@adcp/sdk 13.0.0-rc.8 → 13.0.0-rc.9

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 (200) hide show
  1. package/dist/lib/adapters/roster-account-store.d.mts +9 -8
  2. package/dist/lib/adapters/roster-account-store.d.ts +9 -8
  3. package/dist/lib/adapters/roster-account-store.d.ts.map +1 -1
  4. package/dist/lib/adapters/roster-account-store.js +2 -1
  5. package/dist/lib/adapters/roster-account-store.js.map +1 -1
  6. package/dist/lib/adapters/roster-account-store.mjs +2 -1
  7. package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
  8. package/dist/lib/net/address-guards.d.ts.map +1 -1
  9. package/dist/lib/net/address-guards.js +6 -0
  10. package/dist/lib/net/address-guards.js.map +1 -1
  11. package/dist/lib/net/address-guards.mjs +6 -0
  12. package/dist/lib/net/address-guards.mjs.map +1 -1
  13. package/dist/lib/net/ssrf-fetch.d.ts.map +1 -1
  14. package/dist/lib/net/ssrf-fetch.js +66 -53
  15. package/dist/lib/net/ssrf-fetch.js.map +1 -1
  16. package/dist/lib/net/ssrf-fetch.mjs +66 -53
  17. package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
  18. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  19. package/dist/lib/server/account-mode.d.mts +2 -1
  20. package/dist/lib/server/account-mode.d.ts +2 -1
  21. package/dist/lib/server/account-mode.d.ts.map +1 -1
  22. package/dist/lib/server/account-mode.js +1 -0
  23. package/dist/lib/server/account-mode.js.map +1 -1
  24. package/dist/lib/server/account-mode.mjs +1 -0
  25. package/dist/lib/server/account-mode.mjs.map +1 -1
  26. package/dist/lib/server/create-adcp-server.d.mts +10 -6
  27. package/dist/lib/server/create-adcp-server.d.ts +10 -6
  28. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  29. package/dist/lib/server/create-adcp-server.js +2 -1
  30. package/dist/lib/server/create-adcp-server.js.map +1 -1
  31. package/dist/lib/server/create-adcp-server.mjs +2 -1
  32. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  33. package/dist/lib/server/decisioning/account.d.mts +16 -11
  34. package/dist/lib/server/decisioning/account.d.ts +16 -11
  35. package/dist/lib/server/decisioning/account.d.ts.map +1 -1
  36. package/dist/lib/server/decisioning/account.js.map +1 -1
  37. package/dist/lib/server/decisioning/account.mjs.map +1 -1
  38. package/dist/lib/server/decisioning/pagination.d.mts +2 -0
  39. package/dist/lib/server/decisioning/pagination.d.ts +2 -0
  40. package/dist/lib/server/decisioning/pagination.d.ts.map +1 -1
  41. package/dist/lib/server/decisioning/pagination.js.map +1 -1
  42. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +20 -14
  43. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +20 -14
  44. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  45. package/dist/lib/server/decisioning/runtime/from-platform.js +32 -6
  46. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  47. package/dist/lib/server/decisioning/runtime/from-platform.mjs +32 -6
  48. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  49. package/dist/lib/server/decisioning/specialisms/sales.d.mts +16 -4
  50. package/dist/lib/server/decisioning/specialisms/sales.d.ts +16 -4
  51. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
  52. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
  53. package/dist/lib/server/index.d.ts.map +1 -1
  54. package/dist/lib/server/index.js.map +1 -1
  55. package/dist/lib/server/index.mjs.map +1 -1
  56. package/dist/lib/server/legacy/v5/index.d.mts +2 -1
  57. package/dist/lib/server/legacy/v5/index.d.ts +2 -1
  58. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
  59. package/dist/lib/server/legacy/v5/index.js.map +1 -1
  60. package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
  61. package/dist/lib/testing/compliance/comply.d.mts +2 -0
  62. package/dist/lib/testing/compliance/comply.d.ts +2 -0
  63. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  64. package/dist/lib/testing/compliance/comply.js +45 -14
  65. package/dist/lib/testing/compliance/comply.js.map +1 -1
  66. package/dist/lib/testing/compliance/comply.mjs +45 -14
  67. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  68. package/dist/lib/testing/compliance/index.d.mts +1 -1
  69. package/dist/lib/testing/compliance/index.d.ts +1 -1
  70. package/dist/lib/testing/compliance/index.d.ts.map +1 -1
  71. package/dist/lib/testing/compliance/index.js.map +1 -1
  72. package/dist/lib/testing/compliance/index.mjs.map +1 -1
  73. package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -1
  74. package/dist/lib/testing/compliance/storyboard-tracks.js +9 -1
  75. package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -1
  76. package/dist/lib/testing/compliance/storyboard-tracks.mjs +9 -1
  77. package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
  78. package/dist/lib/testing/compliance/types.d.mts +26 -25
  79. package/dist/lib/testing/compliance/types.d.ts +26 -25
  80. package/dist/lib/testing/compliance/types.d.ts.map +1 -1
  81. package/dist/lib/testing/compliance/types.js.map +1 -1
  82. package/dist/lib/testing/index.d.mts +2 -2
  83. package/dist/lib/testing/index.d.ts +2 -2
  84. package/dist/lib/testing/index.d.ts.map +1 -1
  85. package/dist/lib/testing/index.js +16 -0
  86. package/dist/lib/testing/index.js.map +1 -1
  87. package/dist/lib/testing/index.mjs +16 -0
  88. package/dist/lib/testing/index.mjs.map +1 -1
  89. package/dist/lib/testing/scenarios/media-buy.d.ts.map +1 -1
  90. package/dist/lib/testing/scenarios/media-buy.js +20 -12
  91. package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
  92. package/dist/lib/testing/scenarios/media-buy.mjs +20 -12
  93. package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
  94. package/dist/lib/testing/storyboard/creative-assets.d.mts +23 -0
  95. package/dist/lib/testing/storyboard/creative-assets.d.ts +23 -0
  96. package/dist/lib/testing/storyboard/creative-assets.d.ts.map +1 -1
  97. package/dist/lib/testing/storyboard/creative-assets.js +322 -45
  98. package/dist/lib/testing/storyboard/creative-assets.js.map +1 -1
  99. package/dist/lib/testing/storyboard/creative-assets.mjs +321 -45
  100. package/dist/lib/testing/storyboard/creative-assets.mjs.map +1 -1
  101. package/dist/lib/testing/storyboard/index.d.mts +4 -1
  102. package/dist/lib/testing/storyboard/index.d.ts +4 -1
  103. package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
  104. package/dist/lib/testing/storyboard/index.js +20 -0
  105. package/dist/lib/testing/storyboard/index.js.map +1 -1
  106. package/dist/lib/testing/storyboard/index.mjs +19 -0
  107. package/dist/lib/testing/storyboard/index.mjs.map +1 -1
  108. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.mts +21 -0
  109. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.ts +22 -0
  110. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.ts.map +1 -0
  111. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.js +668 -0
  112. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.js.map +1 -0
  113. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.mjs +638 -0
  114. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.mjs.map +1 -0
  115. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.mts +5 -0
  116. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.ts +6 -0
  117. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.ts.map +1 -0
  118. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.js +44 -0
  119. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.js.map +1 -0
  120. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.mjs +20 -0
  121. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.mjs.map +1 -0
  122. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.mts +38 -0
  123. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.ts +39 -0
  124. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.ts.map +1 -0
  125. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.js +17 -0
  126. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.js.map +1 -0
  127. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.mjs +1 -0
  128. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.mjs.map +1 -0
  129. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.mts +32 -0
  130. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.ts +33 -0
  131. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.ts.map +1 -0
  132. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.js +105 -0
  133. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.js.map +1 -0
  134. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.mjs +80 -0
  135. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.mjs.map +1 -0
  136. package/dist/lib/testing/storyboard/probes.d.ts.map +1 -1
  137. package/dist/lib/testing/storyboard/probes.js +2 -1
  138. package/dist/lib/testing/storyboard/probes.js.map +1 -1
  139. package/dist/lib/testing/storyboard/probes.mjs +2 -1
  140. package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
  141. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  142. package/dist/lib/testing/storyboard/runner.js +382 -69
  143. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  144. package/dist/lib/testing/storyboard/runner.mjs +387 -70
  145. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  146. package/dist/lib/testing/storyboard/seeding.js +3 -1
  147. package/dist/lib/testing/storyboard/seeding.js.map +1 -1
  148. package/dist/lib/testing/storyboard/seeding.mjs +3 -1
  149. package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
  150. package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
  151. package/dist/lib/testing/storyboard/task-map.js +16 -2
  152. package/dist/lib/testing/storyboard/task-map.js.map +1 -1
  153. package/dist/lib/testing/storyboard/task-map.mjs +16 -2
  154. package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
  155. package/dist/lib/testing/storyboard/trusted-match-context-replay.d.mts +11 -0
  156. package/dist/lib/testing/storyboard/trusted-match-context-replay.d.ts +12 -0
  157. package/dist/lib/testing/storyboard/trusted-match-context-replay.d.ts.map +1 -0
  158. package/dist/lib/testing/storyboard/trusted-match-context-replay.js +340 -0
  159. package/dist/lib/testing/storyboard/trusted-match-context-replay.js.map +1 -0
  160. package/dist/lib/testing/storyboard/trusted-match-context-replay.mjs +316 -0
  161. package/dist/lib/testing/storyboard/trusted-match-context-replay.mjs.map +1 -0
  162. package/dist/lib/testing/storyboard/types.d.mts +84 -15
  163. package/dist/lib/testing/storyboard/types.d.ts +84 -15
  164. package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
  165. package/dist/lib/testing/storyboard/types.js +2 -0
  166. package/dist/lib/testing/storyboard/types.js.map +1 -1
  167. package/dist/lib/testing/storyboard/types.mjs +2 -0
  168. package/dist/lib/testing/storyboard/types.mjs.map +1 -1
  169. package/dist/lib/testing/storyboard/validations.d.mts +3 -0
  170. package/dist/lib/testing/storyboard/validations.d.ts +3 -0
  171. package/dist/lib/testing/storyboard/validations.d.ts.map +1 -1
  172. package/dist/lib/testing/storyboard/validations.js +64 -24
  173. package/dist/lib/testing/storyboard/validations.js.map +1 -1
  174. package/dist/lib/testing/storyboard/validations.mjs +64 -24
  175. package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
  176. package/dist/lib/types/server-payload-aliases.d.mts +8 -2
  177. package/dist/lib/types/server-payload-aliases.d.ts +8 -2
  178. package/dist/lib/types/server-payload-aliases.d.ts.map +1 -1
  179. package/dist/lib/types/server-payload-aliases.js.map +1 -1
  180. package/dist/lib/upstream-recorder/recorder.d.mts +7 -18
  181. package/dist/lib/upstream-recorder/recorder.d.ts +7 -18
  182. package/dist/lib/upstream-recorder/recorder.d.ts.map +1 -1
  183. package/dist/lib/upstream-recorder/recorder.js +17 -10
  184. package/dist/lib/upstream-recorder/recorder.js.map +1 -1
  185. package/dist/lib/upstream-recorder/recorder.mjs +12 -5
  186. package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
  187. package/dist/lib/utils/redact-secrets.d.ts.map +1 -1
  188. package/dist/lib/utils/redact-secrets.js +7 -1
  189. package/dist/lib/utils/redact-secrets.js.map +1 -1
  190. package/dist/lib/utils/redact-secrets.mjs +7 -1
  191. package/dist/lib/utils/redact-secrets.mjs.map +1 -1
  192. package/dist/lib/version.d.mts +3 -3
  193. package/dist/lib/version.d.ts +3 -3
  194. package/dist/lib/version.js +3 -3
  195. package/dist/lib/version.js.map +1 -1
  196. package/dist/lib/version.mjs +3 -3
  197. package/dist/lib/version.mjs.map +1 -1
  198. package/docs/guides/BUILD-AN-AGENT.md +4 -2
  199. package/docs/llms.txt +1 -1
  200. package/package.json +2 -2
@@ -73,6 +73,8 @@ var import_seeding = require('./seeding.js');
73
73
  var import_fixture_resolution = require('./fixture-resolution.js');
74
74
  var import_compliance = require('./compliance.js');
75
75
  var import_client3 = require('../../signing/client.js');
76
+ var import_trusted_match_context_replay = require('./trusted-match-context-replay.js');
77
+ var import_oauth_metadata_graph = require('./oauth-metadata-graph/index.js');
76
78
  var import_agent_routing = require('./agent-routing.js');
77
79
  var import_types = require('./types.js');
78
80
  var import_assertions = require('./assertions.js');
@@ -82,6 +84,7 @@ const SKIP_DETAILS = {
82
84
  prerequisite_failed: "Skipped: a prerequisite step or contract did not pass.",
83
85
  missing_tool: "Skipped: agent did not advertise the required tool.",
84
86
  missing_test_controller: "Skipped: deterministic_testing phase requires comply_test_controller, which the agent did not advertise.",
87
+ fixture_unavailable: "Skipped: the runner test kit cannot synthesize a valid input for the seller-declared contract.",
85
88
  unsatisfied_contract: "Skipped: test-kit contract is out of scope for this grading run.",
86
89
  requirement_unmet: "Skipped: a requires: tag named a runtime requirement that is not available on this run (see RunnerSkipResult.requirement).",
87
90
  peer_branch_taken: "Skipped: a peer branch in the same any_of branch set already contributed the aggregation flag.",
@@ -131,6 +134,7 @@ const DETAILED_SKIP_DETAILS = {
131
134
  rate_limit_not_triggered: "No RATE_LIMITED response was observed within the configured max_attempts."
132
135
  };
133
136
  const REPLAY_WEBHOOK_VECTOR_TASK = "replay_webhook_vector";
137
+ const REPLAY_TRUSTED_MATCH_CONTEXT_VECTOR_TASK = "replay_trusted_match_context_vector";
134
138
  const WEBHOOK_REPLAY_DEFAULT_TIMEOUT_MS = 1e4;
135
139
  function selectionForProbeSkip(reason, detail) {
136
140
  switch (reason) {
@@ -211,6 +215,9 @@ function evaluateRequiresCapabilityGate(predicate, profile, agentTools, adcpVers
211
215
  const actual = resolveCapabilityPathForGate(rawCaps, predicate, adcpVersion);
212
216
  return evaluateCapabilityPredicate(predicate, actual);
213
217
  }
218
+ if ("equals" in predicate && predicate.path === "oauth.supported" && predicate.equals === true) {
219
+ return evaluateCapabilityPredicate(predicate, void 0);
220
+ }
214
221
  const tools = agentTools ?? profile?.tools;
215
222
  if ("equals" in predicate && tools !== void 0 && !tools.includes("get_adcp_capabilities")) {
216
223
  return evaluateCapabilityPredicate(predicate, void 0);
@@ -235,6 +242,24 @@ function allExecutablePhasesCapabilitySkipped(storyboard, phaseCapabilitySkipDet
235
242
  function buildSkip(reason, detail) {
236
243
  return { reason, detail: detail ?? SKIP_DETAILS[reason] };
237
244
  }
245
+ function buildCreativeAssetFixtureUnavailableStep(step, phaseId, context, allSteps, runState, failure, task = step.task) {
246
+ const detail = `creative_asset_fixture_unavailable: slot "${failure.slotId}", asset type "${failure.assetType}", constraint: ${failure.constraint} (${failure.path})`;
247
+ return {
248
+ step_id: step.id,
249
+ phase_id: phaseId,
250
+ title: step.title,
251
+ task,
252
+ passed: true,
253
+ skipped: true,
254
+ skip_reason: "fixture_unavailable",
255
+ skip: buildSkip("fixture_unavailable", detail),
256
+ duration_ms: 0,
257
+ validations: [],
258
+ context,
259
+ next: getNextStepPreview(step.id, allSteps, context, runState.runnerVars),
260
+ extraction: { path: "none" }
261
+ };
262
+ }
238
263
  function detectResponseDerivedNotApplicable(step, request, response, runState, allSteps) {
239
264
  if (response === void 0 || response === null) return null;
240
265
  const gates = [
@@ -518,7 +543,10 @@ function filterResponseHeaders(headers) {
518
543
  if (!headers) return void 0;
519
544
  const out = {};
520
545
  for (const [k, v] of Object.entries(headers)) {
521
- if (RESPONSE_HEADER_ALLOWLIST.has(k.toLowerCase())) out[k] = v;
546
+ const lower = k.toLowerCase();
547
+ if (RESPONSE_HEADER_ALLOWLIST.has(lower)) {
548
+ out[lower] = lower === "location" ? (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(v) : v;
549
+ }
522
550
  }
523
551
  return Object.keys(out).length > 0 ? out : void 0;
524
552
  }
@@ -550,15 +578,6 @@ async function runStoryboardBody(agentUrlOrUrls, storyboard, options) {
550
578
  "runStoryboard: _client override is incompatible with multi-instance mode. Remove _client (or pass a single agent URL) to use round-robin dispatch."
551
579
  );
552
580
  }
553
- const requestedStrategy = options.multi_instance_strategy ?? "round-robin";
554
- if (requestedStrategy === "multi-pass" && isMultiInstance) {
555
- if (options.webhook_receiver) {
556
- throw new Error(
557
- 'runStoryboard: webhook_receiver is incompatible with multi_instance_strategy: "multi-pass". Each pass would bind a fresh receiver URL, so agents caching the pass-1 URL would deliver to a dead port in pass 2. Use round-robin when the storyboard needs a webhook receiver, or run multi-pass on a storyboard without webhook observation.'
558
- );
559
- }
560
- return runMultiPass(agentUrls, storyboard, options);
561
- }
562
581
  const allRequires = resolveStoryboardRequires(storyboard, options);
563
582
  if (allRequires.length) {
564
583
  const unmet = checkRequires(allRequires, storyboard, options, options._profile);
@@ -570,6 +589,15 @@ async function runStoryboardBody(agentUrlOrUrls, storyboard, options) {
570
589
  };
571
590
  }
572
591
  }
592
+ const requestedStrategy = options.multi_instance_strategy ?? "round-robin";
593
+ if (requestedStrategy === "multi-pass" && isMultiInstance) {
594
+ if (options.webhook_receiver) {
595
+ throw new Error(
596
+ 'runStoryboard: webhook_receiver is incompatible with multi_instance_strategy: "multi-pass". Each pass would bind a fresh receiver URL, so agents caching the pass-1 URL would deliver to a dead port in pass 2. Use round-robin when the storyboard needs a webhook receiver, or run multi-pass on a storyboard without webhook observation.'
597
+ );
598
+ }
599
+ return runMultiPass(agentUrls, storyboard, options);
600
+ }
573
601
  if (options.agents) {
574
602
  const projected = Object.values(options.agents).map((e) => e.url);
575
603
  return executeStoryboardPass(projected, storyboard, options, 0);
@@ -648,7 +676,7 @@ function buildCapabilityUnsupportedResult(agentUrls, storyboard, detail) {
648
676
  return {
649
677
  storyboard_id: storyboard.id,
650
678
  storyboard_title: storyboard.title,
651
- agent_url: agentUrls[0],
679
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(agentUrls[0]),
652
680
  overall_passed: true,
653
681
  phases: [
654
682
  {
@@ -703,6 +731,8 @@ const REQUIREMENT_TO_SKIP_REASON = {
703
731
  seeded_state: "requirement_unmet",
704
732
  real_wire: "requirement_unmet",
705
733
  webhook_receiver: "requirement_unmet",
734
+ webhook_replay_receiver: "not_applicable",
735
+ trusted_match_context_router_runner: "not_applicable",
706
736
  request_signer: "not_applicable",
707
737
  multi_agent: "requirement_unmet"
708
738
  };
@@ -729,7 +759,7 @@ function buildRequirementUnmetResult(agentUrls, storyboard, requirement, detail)
729
759
  return {
730
760
  storyboard_id: storyboard.id,
731
761
  storyboard_title: storyboard.title,
732
- agent_url: agentUrls[0],
762
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(agentUrls[0]),
733
763
  overall_passed: true,
734
764
  phases: [
735
765
  {
@@ -779,7 +809,7 @@ function buildRequiredAnyOfToolsMissingResult(agentUrls, storyboard, detail) {
779
809
  return {
780
810
  storyboard_id: storyboard.id,
781
811
  storyboard_title: storyboard.title,
782
- agent_url: agentUrls[0],
812
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(agentUrls[0]),
783
813
  overall_passed: true,
784
814
  phases: [
785
815
  {
@@ -859,6 +889,25 @@ function checkRequires(requires, storyboard, options, profile) {
859
889
  }
860
890
  break;
861
891
  }
892
+ case "webhook_replay_receiver": {
893
+ if (!options.webhook_replay_receiver?.url) {
894
+ return {
895
+ requirement,
896
+ detail: "Storyboard contains a `replay_webhook_vector` step but no webhook replay receiver URL is configured. Pass `webhook_replay_receiver.url` in StoryboardRunOptions to run inbound buyer/orchestrator receiver conformance. Seller agents without an inbound receiver grade not_applicable for this storyboard."
897
+ };
898
+ }
899
+ break;
900
+ }
901
+ case "trusted_match_context_router_runner": {
902
+ const runner = options.trusted_match_context_router_runner;
903
+ if (!runner?.router_url || typeof runner.registerProviders !== "function") {
904
+ return {
905
+ requirement,
906
+ detail: "Storyboard contains a `replay_trusted_match_context_vector` step but no Trusted Match Context router harness is configured. Pass `trusted_match_context_router_runner` with `router_url` and `registerProviders` to run raw POST /context conformance."
907
+ };
908
+ }
909
+ break;
910
+ }
862
911
  case "request_signer": {
863
912
  if (!profile?.raw_capabilities) break;
864
913
  const supported = resolveCapabilityPath(profile.raw_capabilities, "request_signing.supported");
@@ -920,22 +969,32 @@ function valueContainsWebhookToken(value) {
920
969
  function detectImplicitRequires(storyboard, options = {}) {
921
970
  const requires = [];
922
971
  let needsWebhook = false;
972
+ let needsWebhookReplayReceiver = false;
973
+ let needsTrustedMatchContextRouterRunner = false;
923
974
  let needsSigner = storyboard.id === "signed_requests";
924
975
  const contractsInScope = new Set(options.contracts ?? []);
925
976
  for (const phase of storyboard.phases) {
926
977
  for (const step of phase.steps) {
927
- const rateLimitTripInScope = !step.requires_contract || contractsInScope.has(step.requires_contract);
928
- if (!needsWebhook && (step.sample_request && valueContainsWebhookToken(step.sample_request) || step.rate_limit_trip?.trip_target_sample_request && rateLimitTripInScope && valueContainsWebhookToken(step.rate_limit_trip.trip_target_sample_request))) {
978
+ const stepContractInScope = !step.requires_contract || contractsInScope.has(step.requires_contract);
979
+ if (!needsWebhook && (step.sample_request && valueContainsWebhookToken(step.sample_request) || step.rate_limit_trip?.trip_target_sample_request && stepContractInScope && valueContainsWebhookToken(step.rate_limit_trip.trip_target_sample_request))) {
929
980
  needsWebhook = true;
930
981
  }
931
982
  if (!needsSigner && step.task === "request_signing_probe") {
932
983
  needsSigner = true;
933
984
  }
934
- if (needsWebhook && needsSigner) break;
985
+ if (!needsWebhookReplayReceiver && stepContractInScope && step.task === REPLAY_WEBHOOK_VECTOR_TASK) {
986
+ needsWebhookReplayReceiver = true;
987
+ }
988
+ if (!needsTrustedMatchContextRouterRunner && stepContractInScope && step.task === REPLAY_TRUSTED_MATCH_CONTEXT_VECTOR_TASK) {
989
+ needsTrustedMatchContextRouterRunner = true;
990
+ }
991
+ if (needsWebhook && needsWebhookReplayReceiver && needsTrustedMatchContextRouterRunner && needsSigner) break;
935
992
  }
936
- if (needsWebhook && needsSigner) break;
993
+ if (needsWebhook && needsWebhookReplayReceiver && needsTrustedMatchContextRouterRunner && needsSigner) break;
937
994
  }
938
995
  if (needsWebhook) requires.push("webhook_receiver");
996
+ if (needsWebhookReplayReceiver) requires.push("webhook_replay_receiver");
997
+ if (needsTrustedMatchContextRouterRunner) requires.push("trusted_match_context_router_runner");
939
998
  if (needsSigner) requires.push("request_signer");
940
999
  return requires;
941
1000
  }
@@ -958,7 +1017,7 @@ function buildDiscoveryFailedResult(agentUrls, storyboard, discoveryStep) {
958
1017
  return {
959
1018
  storyboard_id: storyboard.id,
960
1019
  storyboard_title: storyboard.title,
961
- agent_url: agentUrls[0],
1020
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(agentUrls[0]),
962
1021
  overall_passed: false,
963
1022
  phases: [
964
1023
  {
@@ -990,7 +1049,7 @@ function buildRequiredToolsMissingResult(agentUrls, storyboard, detail) {
990
1049
  return {
991
1050
  storyboard_id: storyboard.id,
992
1051
  storyboard_title: storyboard.title,
993
- agent_url: agentUrls[0],
1052
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(agentUrls[0]),
994
1053
  overall_passed: true,
995
1054
  phases: [
996
1055
  {
@@ -1332,6 +1391,33 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1332
1391
  storyboard,
1333
1392
  phaseCapabilitySkipDetails
1334
1393
  );
1394
+ const capabilitySkippedPhaseIds = /* @__PURE__ */ new Set([
1395
+ ...phaseCapabilitySkipDetails.keys(),
1396
+ ...storyboard.phases.filter((phase) => shouldSkipPhase(phase, options)).map((phase) => phase.id)
1397
+ ]);
1398
+ let creativeAssetFixtureGap = preflightRemainingCreativeAssetDirectives(
1399
+ allSteps,
1400
+ -1,
1401
+ context,
1402
+ options,
1403
+ {
1404
+ contributions,
1405
+ priorStepResults,
1406
+ priorProbes,
1407
+ agentUrl: agentUrls[0],
1408
+ webhookReceiver,
1409
+ runnerVars,
1410
+ contextProvenance,
1411
+ priorA2aEnvelopes,
1412
+ stepRequestStarts,
1413
+ responseDerivedNotApplicableContextKeys,
1414
+ agentProfile: profile,
1415
+ agentLibraryVersion: profile?.library_version,
1416
+ storyboardRequiresRequestSigner: allRequires.includes("request_signer")
1417
+ },
1418
+ capabilitySkippedPhaseIds
1419
+ );
1420
+ let creativeAssetFixtureGapRecorded = false;
1335
1421
  if (!hasExecutableSteps) {
1336
1422
  const isScenarioComposed = (storyboard.requires_scenarios?.length ?? 0) > 0;
1337
1423
  const detail = isScenarioComposed ? `Storyboard "${storyboard.id}" has no local phases \u2014 its test surface is fully composed from the scenarios listed in \`requires_scenarios\`.` : `Storyboard "${storyboard.id}" has no executable phases \u2014 populate \`phases[].steps\` or remove the storyboard.`;
@@ -1389,7 +1475,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1389
1475
  fixtureDiscoveryClient = dispatch.nextFor(fixtureStep("get_products")).client;
1390
1476
  }
1391
1477
  }
1392
- const seeding = skipControllerSeedingForPhaseGates ? null : preSeeded !== void 0 ? preSeeded.result : await (0, import_seeding.runControllerSeeding)(fixtureSeedClient, storyboard, options, context, fixtureDiscoveryClient);
1478
+ const seeding = creativeAssetFixtureGap ? null : skipControllerSeedingForPhaseGates ? null : preSeeded !== void 0 ? preSeeded.result : await (0, import_seeding.runControllerSeeding)(fixtureSeedClient, storyboard, options, context, fixtureDiscoveryClient);
1393
1479
  if (seeding) {
1394
1480
  const attach = preSeeded === void 0 || preSeeded.attach;
1395
1481
  if (attach) {
@@ -1437,6 +1523,32 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1437
1523
  }
1438
1524
  }
1439
1525
  }
1526
+ const buildExecutionState = (agentUrl = agentUrls[0], agentProfile = profile) => ({
1527
+ contributions,
1528
+ priorStepResults,
1529
+ priorProbes,
1530
+ agentUrl,
1531
+ webhookReceiver,
1532
+ runnerVars,
1533
+ contextProvenance,
1534
+ priorA2aEnvelopes,
1535
+ stepRequestStarts,
1536
+ responseDerivedNotApplicableContextKeys,
1537
+ agentProfile,
1538
+ agentLibraryVersion: agentProfile?.library_version,
1539
+ storyboardRequiresRequestSigner: allRequires.includes("request_signer"),
1540
+ fixtureBindings
1541
+ });
1542
+ if (!creativeAssetFixtureGap && !seedingMissingController && !seedingUnsupported && !seedingFailed && !fixtureUnsatisfied) {
1543
+ creativeAssetFixtureGap = preflightRemainingCreativeAssetDirectives(
1544
+ allSteps,
1545
+ -1,
1546
+ context,
1547
+ options,
1548
+ buildExecutionState(),
1549
+ capabilitySkippedPhaseIds
1550
+ );
1551
+ }
1440
1552
  for (const phase of storyboard.phases) {
1441
1553
  options.signal?.throwIfAborted();
1442
1554
  const phaseStart = Date.now();
@@ -1450,6 +1562,33 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1450
1562
  });
1451
1563
  continue;
1452
1564
  }
1565
+ if (creativeAssetFixtureGap) {
1566
+ const gapSteps = [];
1567
+ if (!creativeAssetFixtureGapRecorded && creativeAssetFixtureGap.target.phaseId === phase.id) {
1568
+ const gapStep = buildCreativeAssetFixtureUnavailableStep(
1569
+ creativeAssetFixtureGap.target.step,
1570
+ phase.id,
1571
+ context,
1572
+ allSteps,
1573
+ buildExecutionState(),
1574
+ creativeAssetFixtureGap.failure
1575
+ );
1576
+ gapStep.storyboard_id = storyboard.id;
1577
+ gapSteps.push(gapStep);
1578
+ priorStepResults.set(gapStep.step_id, gapStep);
1579
+ skippedCount++;
1580
+ creativeAssetFixtureGapRecorded = true;
1581
+ }
1582
+ phaseResults.push({
1583
+ phase_id: phase.id,
1584
+ phase_title: phase.title,
1585
+ passed: true,
1586
+ steps: gapSteps,
1587
+ duration_ms: 0
1588
+ });
1589
+ priorPhaseIds.push(phase.id);
1590
+ continue;
1591
+ }
1453
1592
  const phaseCapabilitySkipDetail = phaseCapabilitySkipDetails.get(phase.id);
1454
1593
  if (phaseCapabilitySkipDetail !== void 0) {
1455
1594
  const skippedSteps = buildPhaseCapabilitySkippedSteps(storyboard, phase, phaseCapabilitySkipDetail, context);
@@ -1633,6 +1772,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1633
1772
  phasePassed = false;
1634
1773
  continue;
1635
1774
  }
1775
+ const stepExecutionState = buildExecutionState(assignment.agentUrl, assignment.profile);
1636
1776
  const rawResult = await executeStep(
1637
1777
  assignment.client,
1638
1778
  step,
@@ -1641,26 +1781,11 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1641
1781
  context,
1642
1782
  allSteps,
1643
1783
  options,
1644
- {
1645
- contributions,
1646
- priorStepResults,
1647
- priorProbes,
1648
- agentUrl: assignment.agentUrl,
1649
- webhookReceiver,
1650
- runnerVars,
1651
- contextProvenance,
1652
- priorA2aEnvelopes,
1653
- stepRequestStarts,
1654
- responseDerivedNotApplicableContextKeys,
1655
- agentProfile: assignment.profile,
1656
- agentLibraryVersion: assignment.profile?.library_version,
1657
- storyboardRequiresRequestSigner: allRequires.includes("request_signer"),
1658
- fixtureBindings
1659
- }
1784
+ stepExecutionState
1660
1785
  );
1661
1786
  const result2 = { ...rawResult, storyboard_id: storyboard.id };
1662
1787
  if (isMultiInstance || useRouting) {
1663
- result2.agent_url = assignment.agentUrl;
1788
+ result2.agent_url = (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(assignment.agentUrl);
1664
1789
  result2.agent_index = assignment.instanceIndex + 1;
1665
1790
  }
1666
1791
  stepResults.push(result2);
@@ -1779,6 +1904,39 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1779
1904
  annotateMultiInstanceFailure(result2, storyboard, stepResults);
1780
1905
  }
1781
1906
  }
1907
+ if (!result2.skipped && result2.passed) {
1908
+ const currentGlobalIndex = allSteps.find(
1909
+ (flat) => flat.phaseId === phase.id && flat.step.id === step.id
1910
+ )?.globalIndex;
1911
+ if (currentGlobalIndex !== void 0) {
1912
+ creativeAssetFixtureGap = preflightRemainingCreativeAssetDirectives(
1913
+ allSteps,
1914
+ currentGlobalIndex,
1915
+ context,
1916
+ options,
1917
+ stepExecutionState,
1918
+ capabilitySkippedPhaseIds
1919
+ );
1920
+ }
1921
+ if (creativeAssetFixtureGap) {
1922
+ if (creativeAssetFixtureGap.target.phaseId === phase.id) {
1923
+ const gapStep = buildCreativeAssetFixtureUnavailableStep(
1924
+ creativeAssetFixtureGap.target.step,
1925
+ phase.id,
1926
+ context,
1927
+ allSteps,
1928
+ stepExecutionState,
1929
+ creativeAssetFixtureGap.failure
1930
+ );
1931
+ gapStep.storyboard_id = storyboard.id;
1932
+ stepResults.push(gapStep);
1933
+ priorStepResults.set(gapStep.step_id, gapStep);
1934
+ skippedCount++;
1935
+ creativeAssetFixtureGapRecorded = true;
1936
+ }
1937
+ break;
1938
+ }
1939
+ }
1782
1940
  }
1783
1941
  if (phasePendingNotApplicable && !phaseEstablishedStatefulState && !phaseStatefulCascades.has(phase.id)) {
1784
1942
  const hadStatefulPeers = phaseStatefulStepIds.some((id) => id !== phasePendingNotApplicable.stepId);
@@ -1822,7 +1980,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1822
1980
  });
1823
1981
  priorPhaseIds.push(phase.id);
1824
1982
  }
1825
- const branchSetDelta = applyBranchSetGrading(
1983
+ const branchSetDelta = creativeAssetFixtureGap ? { skippedDelta: 0 } : applyBranchSetGrading(
1826
1984
  storyboard.phases,
1827
1985
  phaseResults,
1828
1986
  branchSetsByPhaseId,
@@ -1831,12 +1989,14 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1831
1989
  countedAsFailed
1832
1990
  );
1833
1991
  skippedCount += branchSetDelta.skippedDelta;
1834
- for (const spec of assertions) {
1835
- if (!spec.onEnd) continue;
1836
- const raw = await spec.onEnd(assertionContexts.get(spec.id));
1837
- for (const r of raw) {
1838
- assertionResults.push({ ...r, assertion_id: spec.id, scope: "storyboard" });
1839
- if (!r.passed) assertionsFailed = true;
1992
+ if (!creativeAssetFixtureGap) {
1993
+ for (const spec of assertions) {
1994
+ if (!spec.onEnd) continue;
1995
+ const raw = await spec.onEnd(assertionContexts.get(spec.id));
1996
+ for (const r of raw) {
1997
+ assertionResults.push({ ...r, assertion_id: spec.id, scope: "storyboard" });
1998
+ if (!r.passed) assertionsFailed = true;
1999
+ }
1840
2000
  }
1841
2001
  }
1842
2002
  const requiredPhaseHasExecutedPass = phaseResults.some((p, idx) => {
@@ -1845,13 +2005,17 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1845
2005
  return p.steps.some((s) => !s.skipped && s.passed);
1846
2006
  });
1847
2007
  const requiredPhaseDefs = storyboard.phases.filter((phaseDef) => !phaseDef.optional);
2008
+ const requiredPhasesNotApplicable = requiredPhaseDefs.length > 0 && requiredPhaseDefs.every((phaseDef) => {
2009
+ const phaseResult = phaseResults.find((p) => p.phase_id === phaseDef.id);
2010
+ return !!phaseResult && phaseResult.passed && phaseResult.steps.length > 0 && phaseResult.steps.every((step) => step.skipped && step.skip?.reason === "not_applicable");
2011
+ });
1848
2012
  const requiredPhasesCoveredByCapabilityGates = phaseCapabilitySkippedIds.size > 0 && requiredPhaseDefs.length > 0 && requiredPhaseDefs.every((phaseDef) => {
1849
2013
  if (phaseCapabilitySkippedIds.has(phaseDef.id)) return true;
1850
2014
  const phaseResult = phaseResults.find((p) => p.phase_id === phaseDef.id);
1851
2015
  return !!phaseResult && phaseResult.passed && phaseResult.steps.some((s) => !s.skipped && s.passed);
1852
2016
  });
1853
- const requiredPhasesPassed = !hasExecutableSteps || requiredPhaseHasExecutedPass || failedCount === 0 && requiredPhasesCoveredByCapabilityGates;
1854
- const storyboardWideFixtureUnavailable = (seedingUnsupported || fixtureUnsatisfied) && failedCount === 0;
2017
+ const requiredPhasesPassed = !hasExecutableSteps || requiredPhaseHasExecutedPass || requiredPhasesNotApplicable || failedCount === 0 && requiredPhasesCoveredByCapabilityGates;
2018
+ const storyboardWideFixtureUnavailable = (seedingUnsupported || fixtureUnsatisfied || creativeAssetFixtureGap !== void 0) && failedCount === 0;
1855
2019
  if (seedingPhaseResult) phaseResults.unshift(seedingPhaseResult);
1856
2020
  const schemasUsed = collectSchemasUsed(phaseResults);
1857
2021
  const strictSummary = summarizeStrictValidation(phaseResults);
@@ -1863,13 +2027,17 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1863
2027
  const result = {
1864
2028
  storyboard_id: storyboard.id,
1865
2029
  storyboard_title: storyboard.title,
1866
- agent_url: agentUrls[0],
1867
- ...isMultiInstance && { agent_urls: [...agentUrls] },
2030
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(agentUrls[0]),
2031
+ ...isMultiInstance && { agent_urls: agentUrls.map(import_oauth_metadata_graph.redactOAuthUrlForOutput) },
1868
2032
  // Inner multi-pass passes surface as `round-robin` (that's what they are
1869
2033
  // individually); the aggregating wrapper relabels the top-level result
1870
2034
  // `multi-pass`.
1871
2035
  ...isMultiInstance && { multi_instance_strategy: "round-robin" },
1872
- ...routingContext && { agent_map: { ...routingContext.agentMap } },
2036
+ ...routingContext && {
2037
+ agent_map: Object.fromEntries(
2038
+ Object.entries(routingContext.agentMap).map(([specialism, url]) => [specialism, (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(url)])
2039
+ )
2040
+ },
1873
2041
  overall_passed: failedCount === 0 && (requiredPhasesPassed || storyboardWideFixtureUnavailable) && !assertionsFailed,
1874
2042
  phases: phaseResults,
1875
2043
  context,
@@ -1888,12 +2056,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1888
2056
  ...routingContext && routingContext.discoveryFailures.length > 0 ? {
1889
2057
  discovery_failures: routingContext.discoveryFailures.map((f) => ({
1890
2058
  agent_key: f.agentKey,
1891
- // Scrub URL userinfo (`https://user:pass@host/`) before
1892
- // echoing onto the result — an operator may legitimately
1893
- // encode credentials in the URL, and the leaderboard /
1894
- // dashboard surface mustn't carry them.
1895
- url: f.url.replace(/\/\/[^/@\s]+@/, "//[REDACTED]@"),
1896
- error: f.underlying
2059
+ url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(f.url),
2060
+ error: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(f.underlying)
1897
2061
  }))
1898
2062
  } : {}
1899
2063
  };
@@ -1931,7 +2095,24 @@ async function runMultiPass(agentUrls, storyboard, options) {
1931
2095
  options.agentTools,
1932
2096
  options.adcpVersion
1933
2097
  );
1934
- const preSeededResult = allExecutablePhasesCapabilitySkipped(storyboard, phaseCapabilitySkipDetails) ? null : await (0, import_seeding.runControllerSeeding)(preSeedClients[0], storyboard, options, preSeedContext);
2098
+ const preSeedExcludedPhaseIds = /* @__PURE__ */ new Set([
2099
+ ...phaseCapabilitySkipDetails.keys(),
2100
+ ...storyboard.phases.filter((phase) => shouldSkipPhase(phase, options)).map((phase) => phase.id)
2101
+ ]);
2102
+ const preSeedFixtureGap = preflightRemainingCreativeAssetDirectives(
2103
+ flattenSteps(storyboard),
2104
+ -1,
2105
+ preSeedContext,
2106
+ options,
2107
+ {
2108
+ contributions: /* @__PURE__ */ new Set(),
2109
+ priorStepResults: /* @__PURE__ */ new Map(),
2110
+ priorProbes: /* @__PURE__ */ new Map(),
2111
+ agentUrl: agentUrls[0]
2112
+ },
2113
+ preSeedExcludedPhaseIds
2114
+ );
2115
+ const preSeededResult = preSeedFixtureGap || allExecutablePhasesCapabilitySkipped(storyboard, phaseCapabilitySkipDetails) ? null : await (0, import_seeding.runControllerSeeding)(preSeedClients[0], storyboard, options, preSeedContext);
1935
2116
  const passes = [];
1936
2117
  const passResults = [];
1937
2118
  for (let passIdx = 0; passIdx < agentUrls.length; passIdx++) {
@@ -1963,8 +2144,8 @@ async function runMultiPass(agentUrls, storyboard, options) {
1963
2144
  return {
1964
2145
  storyboard_id: storyboard.id,
1965
2146
  storyboard_title: storyboard.title,
1966
- agent_url: agentUrls[0],
1967
- agent_urls: [...agentUrls],
2147
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(agentUrls[0]),
2148
+ agent_urls: agentUrls.map(import_oauth_metadata_graph.redactOAuthUrlForOutput),
1968
2149
  multi_instance_strategy: "multi-pass",
1969
2150
  overall_passed: overallPassed,
1970
2151
  phases: first.phases,
@@ -2289,7 +2470,19 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2289
2470
  };
2290
2471
  }
2291
2472
  request = fixtureBinding.request;
2292
- request = (0, import_creative_assets.expandCreativeAssetDirectives)(request, context, options.test_kit);
2473
+ const creativeAssetExpansion = (0, import_creative_assets.expandCreativeAssetDirectivesWithDiagnostics)(request, context, options.test_kit);
2474
+ request = creativeAssetExpansion.value;
2475
+ if (!creativeAssetExpansion.ok && creativeAssetExpansion.failure.reason === "fixture_unavailable") {
2476
+ return buildCreativeAssetFixtureUnavailableStep(
2477
+ step,
2478
+ phaseId,
2479
+ context,
2480
+ allSteps,
2481
+ runState,
2482
+ creativeAssetExpansion.failure,
2483
+ effectiveStep.task
2484
+ );
2485
+ }
2293
2486
  const unresolvedContextVars = findUnresolvedContextVars(request);
2294
2487
  const unresolvedAssetDirectives = (0, import_creative_assets.findUnresolvedCreativeAssetDirectives)(request).map((path) => ({
2295
2488
  key: path,
@@ -2361,7 +2554,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2361
2554
  transport: options.protocol === "a2a" ? "a2a" : "mcp",
2362
2555
  operation: effectiveStep.task,
2363
2556
  payload: (0, import_redact_secrets.redactSecrets)(request),
2364
- ...runState.agentUrl ? { url: runState.agentUrl } : {}
2557
+ ...runState.agentUrl ? { url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(runState.agentUrl) } : {}
2365
2558
  },
2366
2559
  extraction: { path: "none" }
2367
2560
  };
@@ -2556,7 +2749,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2556
2749
  transport: useRawProbe ? "mcp" : options.protocol === "a2a" ? "a2a" : "mcp",
2557
2750
  operation: effectiveStep.task,
2558
2751
  payload: (0, import_redact_secrets.redactSecrets)(request),
2559
- ...runState.agentUrl ? { url: runState.agentUrl } : {}
2752
+ ...runState.agentUrl ? { url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(runState.agentUrl) } : {}
2560
2753
  };
2561
2754
  const inputSchemaStripNotices = collectInputSchemaFieldStripNotices(
2562
2755
  taskResult?.debug_logs,
@@ -2912,6 +3105,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2912
3105
  async function executeProbeStep(client, step, phaseId, context, allSteps, options, runState) {
2913
3106
  const start = Date.now();
2914
3107
  let httpResult;
3108
+ let oauthMetadataGraph;
2915
3109
  const probeOpts = {
2916
3110
  allowPrivateIp: options.allow_http === true,
2917
3111
  fetchFn: options.transport?.fetchFn
@@ -2933,8 +3127,17 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
2933
3127
  }
2934
3128
  if (httpResult) {
2935
3129
  } else if (step.task === "protected_resource_metadata") {
2936
- httpResult = await (0, import_probes.probeProtectedResourceMetadata)(runState.agentUrl, probeOpts);
2937
- if (!httpResult.error && httpResult.status === 404) {
3130
+ if (step.validations?.some((validation) => validation.check === "oauth_metadata_graph")) {
3131
+ oauthMetadataGraph = await (0, import_oauth_metadata_graph.gradeOAuthMetadataGraph)(runState.agentUrl, {
3132
+ allowHttp: options.allow_http === true,
3133
+ signal: options.signal,
3134
+ trustedFetchFn: options.transport?.fetchFn
3135
+ });
3136
+ httpResult = oauthMetadataGraph.protected_resource_result;
3137
+ } else {
3138
+ httpResult = await (0, import_probes.probeProtectedResourceMetadata)(runState.agentUrl, probeOpts);
3139
+ }
3140
+ if (!oauthMetadataGraph && !httpResult.error && httpResult.status === 404) {
2938
3141
  httpResult.skipped = true;
2939
3142
  httpResult.skip_reason = "oauth_not_advertised";
2940
3143
  }
@@ -2972,6 +3175,16 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
2972
3175
  };
2973
3176
  const targetRequestResult = buildEffectiveStepRequest(targetStep, context, options, runState);
2974
3177
  if (!targetRequestResult.ok) {
3178
+ if ("creativeAssetFailure" in targetRequestResult) {
3179
+ return buildCreativeAssetFixtureUnavailableStep(
3180
+ step,
3181
+ phaseId,
3182
+ context,
3183
+ allSteps,
3184
+ runState,
3185
+ targetRequestResult.creativeAssetFailure
3186
+ );
3187
+ }
2975
3188
  const next = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
2976
3189
  return {
2977
3190
  step_id: step.id,
@@ -3085,7 +3298,34 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
3085
3298
  transport: targetTransport,
3086
3299
  operation: rateLimitTrip.trip_target_task,
3087
3300
  payload: (0, import_redact_secrets.redactSecrets)(observedRequest),
3088
- ...runState.agentUrl ? { url: runState.agentUrl } : {}
3301
+ ...runState.agentUrl ? { url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(runState.agentUrl) } : {}
3302
+ };
3303
+ }
3304
+ } else if (step.task === REPLAY_TRUSTED_MATCH_CONTEXT_VECTOR_TASK) {
3305
+ const routerRunner = options.trusted_match_context_router_runner;
3306
+ if (!routerRunner?.router_url || typeof routerRunner.registerProviders !== "function") {
3307
+ httpResult = {
3308
+ url: routerRunner?.router_url ?? runState.agentUrl,
3309
+ status: 0,
3310
+ headers: {},
3311
+ body: null,
3312
+ skipped: true,
3313
+ skip_reason: "grader_skipped",
3314
+ error: "No Trusted Match Context router harness configured. Pass trusted_match_context_router_runner with router_url and registerProviders; the runner will not dispatch this pseudo-task over MCP/A2A."
3315
+ };
3316
+ } else {
3317
+ const requestOverride = options.request ? (0, import_context.injectContext)({ ...options.request }, context, runState.runnerVars) : step.sample_request ? (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars) : void 0;
3318
+ const replay = await (0, import_trusted_match_context_replay.replayTrustedMatchContextVector)(step, routerRunner, {
3319
+ ...requestOverride && { requestOverride },
3320
+ ...options.adcpVersion && { adcpVersion: options.adcpVersion },
3321
+ ...options.signal && { signal: options.signal }
3322
+ });
3323
+ httpResult = replay.httpResult;
3324
+ requestRecordOverride = {
3325
+ transport: "http",
3326
+ operation: step.task,
3327
+ payload: (0, import_redact_secrets.redactSecrets)(replay.request),
3328
+ url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(replay.httpResult.url)
3089
3329
  };
3090
3330
  }
3091
3331
  }
@@ -3095,7 +3335,7 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
3095
3335
  transport: "http",
3096
3336
  operation: step.task,
3097
3337
  payload: null,
3098
- ...httpResult?.url ? { url: httpResult.url } : runState.agentUrl ? { url: runState.agentUrl } : {}
3338
+ ...httpResult?.url ? { url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(httpResult.url) } : runState.agentUrl ? { url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(runState.agentUrl) } : {}
3099
3339
  };
3100
3340
  const filteredProbeHeaders = filterResponseHeaders(httpResult?.headers);
3101
3341
  const responseTransport = requestRecordOverride?.transport ?? "http";
@@ -3108,6 +3348,7 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
3108
3348
  } : void 0;
3109
3349
  const redactedHttpResult = httpResult ? {
3110
3350
  ...httpResult,
3351
+ headers: filteredProbeHeaders ?? {},
3111
3352
  body: (0, import_redact_secrets.redactSecrets)(httpResult.body),
3112
3353
  ...responseTransport !== "http" && { status: void 0 }
3113
3354
  } : void 0;
@@ -3137,15 +3378,24 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
3137
3378
  };
3138
3379
  }
3139
3380
  const vctx = {
3140
- taskName: step.task,
3381
+ taskName: step.task === REPLAY_TRUSTED_MATCH_CONTEXT_VECTOR_TASK ? "context_match" : step.task,
3141
3382
  ...options.adcpVersion && { adcpVersion: options.adcpVersion },
3142
3383
  ...options._serverAdcpVersion && { responseAdcpVersion: options._serverAdcpVersion },
3143
3384
  httpResult: redactedHttpResult,
3385
+ ...step.task === REPLAY_TRUSTED_MATCH_CONTEXT_VECTOR_TASK && redactedHttpResult && {
3386
+ taskResult: {
3387
+ success: !redactedHttpResult.error && redactedHttpResult.status >= 200 && redactedHttpResult.status < 300,
3388
+ data: redactedHttpResult.body,
3389
+ ...redactedHttpResult.error && { error: redactedHttpResult.error }
3390
+ }
3391
+ },
3144
3392
  agentUrl: runState.agentUrl,
3145
3393
  contributions: runState.contributions,
3394
+ ...step.response_schema_ref && { responseSchemaRef: step.response_schema_ref },
3146
3395
  request: requestRecord,
3147
3396
  ...responseRecord && { response: responseRecord },
3148
- storyboardContext: context
3397
+ storyboardContext: context,
3398
+ ...oauthMetadataGraph && { oauthMetadataGraph }
3149
3399
  };
3150
3400
  const validations = step.validations?.length ? (0, import_validations.runValidations)(step.validations, vctx) : [];
3151
3401
  const allValidationsPassed = validations.every((v) => v.passed);
@@ -3207,13 +3457,73 @@ function buildEffectiveStepRequest(step, context, options, runState) {
3207
3457
  request = applyIdempotencyInvariant(request, step.task, step);
3208
3458
  const fixtureBinding = applyFixtureBindingsSafely(request, step.task, options, runState);
3209
3459
  if (!fixtureBinding.ok) return fixtureBinding;
3460
+ const creativeAssetExpansion = (0, import_creative_assets.expandCreativeAssetDirectivesWithDiagnostics)(
3461
+ fixtureBinding.request,
3462
+ context,
3463
+ options.test_kit
3464
+ );
3465
+ if (!creativeAssetExpansion.ok && creativeAssetExpansion.failure.reason === "fixture_unavailable") {
3466
+ return { ok: false, creativeAssetFailure: creativeAssetExpansion.failure };
3467
+ }
3210
3468
  return {
3211
3469
  ok: true,
3212
- request: (0, import_creative_assets.expandCreativeAssetDirectives)(fixtureBinding.request, context, options.test_kit)
3470
+ request: creativeAssetExpansion.value
3213
3471
  };
3214
3472
  }
3473
+ function preflightRemainingCreativeAssetDirectives(allSteps, afterGlobalIndex, context, options, runState, excludedPhaseIds = /* @__PURE__ */ new Set()) {
3474
+ for (const target of allSteps) {
3475
+ if (target.globalIndex <= afterGlobalIndex) continue;
3476
+ if (excludedPhaseIds.has(target.phaseId)) continue;
3477
+ const resolvedTask = resolveTaskName(target.step, options);
3478
+ if (!resolvedTask) continue;
3479
+ if (target.step.requires_tool && options.agentTools && !options.agentTools.includes(target.step.requires_tool)) {
3480
+ continue;
3481
+ }
3482
+ if (target.step.requires_contract && !new Set(options.contracts ?? []).has(target.step.requires_contract)) {
3483
+ continue;
3484
+ }
3485
+ if (!import_probes.PROBE_TASKS.has(target.step.task) && options.agentTools && !options.agentTools.includes(resolvedTask)) {
3486
+ continue;
3487
+ }
3488
+ let requestStep = resolvedTask === target.step.task ? target.step : { ...target.step, task: resolvedTask };
3489
+ if (target.step.task === "expect_rate_limit_not_replayed") {
3490
+ const rateLimitTrip = target.step.rate_limit_trip;
3491
+ if ((0, import_rate_limit_trip.validateRateLimitTripSpec)(rateLimitTrip) || !rateLimitTrip) continue;
3492
+ requestStep = {
3493
+ ...target.step,
3494
+ task: rateLimitTrip.trip_target_task,
3495
+ sample_request: rateLimitTrip.trip_target_sample_request,
3496
+ omit_idempotency_key: true
3497
+ };
3498
+ }
3499
+ const request = buildEffectiveStepRequest(requestStep, context, options, runState);
3500
+ if (!request.ok && "creativeAssetFailure" in request) {
3501
+ return { target, failure: request.creativeAssetFailure };
3502
+ }
3503
+ }
3504
+ return void 0;
3505
+ }
3215
3506
  async function executeReplayWebhookVectorStep(step, phaseId, context, allSteps, options, runState) {
3216
3507
  const start = Date.now();
3508
+ if (step.requires_contract && !new Set(options.contracts ?? []).has(step.requires_contract)) {
3509
+ const detail = `Test-kit contract "${step.requires_contract}" is not configured on this runner.`;
3510
+ const reason = "missing_test_kit_contract";
3511
+ return {
3512
+ step_id: step.id,
3513
+ phase_id: phaseId,
3514
+ title: step.title,
3515
+ task: step.task,
3516
+ passed: true,
3517
+ skipped: true,
3518
+ skip_reason: reason,
3519
+ skip: buildSkip(import_types.DETAILED_SKIP_TO_CANONICAL[reason], detail),
3520
+ duration_ms: Date.now() - start,
3521
+ validations: [],
3522
+ context,
3523
+ next: getNextStepPreview(step.id, allSteps, context, runState.runnerVars),
3524
+ extraction: { path: "none", note: "test-kit contract not configured" }
3525
+ };
3526
+ }
3217
3527
  const receiver = options.webhook_replay_receiver;
3218
3528
  if (!receiver?.url) {
3219
3529
  const detail = "No webhook replay receiver URL configured. Pass `webhook_replay_receiver.url` in StoryboardRunOptions to run inbound receiver conformance.";
@@ -3791,6 +4101,9 @@ function phaseContainsOauthMetadataProbe(phase) {
3791
4101
  function agentAdvertisesOauth(profile) {
3792
4102
  const rawCaps = profile?.raw_capabilities;
3793
4103
  if (rawCaps === void 0) return true;
4104
+ const oauthSupported = resolveCapabilityPath(rawCaps, "oauth.supported");
4105
+ if (oauthSupported === true) return true;
4106
+ if (oauthSupported === false) return false;
3794
4107
  const endpoint = resolveCapabilityPath(rawCaps, "account.authorization_endpoint");
3795
4108
  return typeof endpoint === "string" && endpoint.length > 0;
3796
4109
  }
@@ -4046,7 +4359,7 @@ async function prefetchUpstreamTraffic(stepId, resolvedValidations, client, opti
4046
4359
  transport: options.protocol === "a2a" ? "a2a" : "mcp",
4047
4360
  operation: "comply_test_controller",
4048
4361
  payload: (0, import_redact_secrets.redactSecrets)({ scenario: "query_upstream_traffic", params }),
4049
- ...runState.agentUrl ? { url: runState.agentUrl } : {}
4362
+ ...runState.agentUrl ? { url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(runState.agentUrl) } : {}
4050
4363
  };
4051
4364
  const startMs = Date.now();
4052
4365
  let payload;