@adcp/sdk 14.0.0-rc.37 → 14.0.0-rc.39

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 (622) hide show
  1. package/bin/adcp-storyboard-summary.js +286 -0
  2. package/bin/adcp.js +221 -10
  3. package/dist/lib/conformance/schemaLoader.d.mts +1 -1
  4. package/dist/lib/conformance/schemaLoader.d.ts +1 -1
  5. package/dist/lib/core/AgentClient.d.mts +6 -1
  6. package/dist/lib/core/AgentClient.d.ts +6 -1
  7. package/dist/lib/core/AgentClient.js +9 -0
  8. package/dist/lib/core/AgentClient.mjs +9 -0
  9. package/dist/lib/core/ConversationTypes.d.mts +29 -0
  10. package/dist/lib/core/ConversationTypes.d.ts +29 -0
  11. package/dist/lib/core/SingleAgentClient.d.mts +3 -1
  12. package/dist/lib/core/SingleAgentClient.d.ts +3 -1
  13. package/dist/lib/core/SingleAgentClient.js +9 -1
  14. package/dist/lib/core/SingleAgentClient.mjs +9 -1
  15. package/dist/lib/core/TaskExecutor.d.mts +13 -1
  16. package/dist/lib/core/TaskExecutor.d.ts +13 -1
  17. package/dist/lib/core/TaskExecutor.js +216 -18
  18. package/dist/lib/core/TaskExecutor.mjs +216 -19
  19. package/dist/lib/index.d.mts +5 -2
  20. package/dist/lib/index.d.ts +5 -2
  21. package/dist/lib/index.js +10 -1
  22. package/dist/lib/index.mjs +10 -1
  23. package/dist/lib/media-buy/action-assessment.d.mts +77 -0
  24. package/dist/lib/media-buy/action-assessment.d.ts +77 -0
  25. package/dist/lib/media-buy/action-assessment.js +300 -0
  26. package/dist/lib/media-buy/action-assessment.mjs +284 -0
  27. package/dist/lib/media-buy/action-constraints.d.mts +9 -0
  28. package/dist/lib/media-buy/action-constraints.d.ts +9 -0
  29. package/dist/lib/media-buy/action-constraints.js +170 -0
  30. package/dist/lib/media-buy/action-constraints.mjs +146 -0
  31. package/dist/lib/media-buy/action-contracts.d.mts +40 -0
  32. package/dist/lib/media-buy/action-contracts.d.ts +40 -0
  33. package/dist/lib/media-buy/action-contracts.js +304 -0
  34. package/dist/lib/media-buy/action-contracts.mjs +267 -0
  35. package/dist/lib/media-buy/action-metadata.generated.d.mts +37 -0
  36. package/dist/lib/media-buy/action-metadata.generated.d.ts +37 -0
  37. package/dist/lib/media-buy/action-metadata.generated.js +128 -0
  38. package/dist/lib/media-buy/action-metadata.generated.mjs +101 -0
  39. package/dist/lib/media-buy/action-types.d.mts +106 -0
  40. package/dist/lib/media-buy/action-types.d.ts +106 -0
  41. package/dist/lib/{types/v3-1-beta/tools.generated.js → media-buy/action-types.js} +2 -2
  42. package/dist/lib/media-buy/actions.d.mts +6 -0
  43. package/dist/lib/media-buy/actions.d.ts +6 -0
  44. package/dist/lib/media-buy/actions.js +38 -0
  45. package/dist/lib/media-buy/actions.mjs +9 -0
  46. package/dist/lib/media-buy/available-actions.d.mts +2 -1
  47. package/dist/lib/media-buy/available-actions.d.ts +2 -1
  48. package/dist/lib/media-buy/available-actions.js +4 -3
  49. package/dist/lib/media-buy/available-actions.mjs +4 -3
  50. package/dist/lib/media-buy/compatibility.js +3 -0
  51. package/dist/lib/media-buy/compatibility.mjs +3 -0
  52. package/dist/lib/media-buy/index.d.mts +4 -0
  53. package/dist/lib/media-buy/index.d.ts +4 -0
  54. package/dist/lib/media-buy/index.js +3 -1
  55. package/dist/lib/media-buy/index.mjs +1 -0
  56. package/dist/lib/media-buy/legacy-action-ids.d.mts +1 -0
  57. package/dist/lib/media-buy/legacy-action-ids.d.ts +1 -0
  58. package/dist/lib/media-buy/legacy-action-ids.js +50 -0
  59. package/dist/lib/media-buy/legacy-action-ids.mjs +26 -0
  60. package/dist/lib/media-buy/mutations.d.mts +70 -0
  61. package/dist/lib/media-buy/mutations.d.ts +70 -0
  62. package/dist/lib/media-buy/mutations.js +525 -0
  63. package/dist/lib/media-buy/mutations.mjs +498 -0
  64. package/dist/lib/media-buy/preflight.d.mts +20 -69
  65. package/dist/lib/media-buy/preflight.d.ts +20 -69
  66. package/dist/lib/media-buy/preflight.js +100 -336
  67. package/dist/lib/media-buy/preflight.mjs +111 -333
  68. package/dist/lib/media-buy/targeting-input.d.mts +7 -4
  69. package/dist/lib/media-buy/targeting-input.d.ts +7 -4
  70. package/dist/lib/media-buy/types.d.mts +55 -7
  71. package/dist/lib/media-buy/types.d.ts +55 -7
  72. package/dist/lib/protocols/rawResponseCapture.d.mts +12 -0
  73. package/dist/lib/protocols/rawResponseCapture.d.ts +12 -0
  74. package/dist/lib/protocols/rawResponseCapture.js +33 -3
  75. package/dist/lib/protocols/rawResponseCapture.mjs +32 -3
  76. package/dist/lib/registry/types.generated.d.mts +377 -9
  77. package/dist/lib/registry/types.generated.d.ts +377 -9
  78. package/dist/lib/reporting/content-mismatch.d.mts +126 -0
  79. package/dist/lib/reporting/content-mismatch.d.ts +126 -0
  80. package/dist/lib/reporting/content-mismatch.js +90 -0
  81. package/dist/lib/reporting/content-mismatch.mjs +66 -0
  82. package/dist/lib/reporting/evidence.d.mts +1 -0
  83. package/dist/lib/reporting/evidence.d.ts +1 -0
  84. package/dist/lib/reporting/evidence.js +32 -3
  85. package/dist/lib/reporting/evidence.mjs +31 -3
  86. package/dist/lib/reporting/index.d.mts +3 -1
  87. package/dist/lib/reporting/index.d.ts +3 -1
  88. package/dist/lib/reporting/index.js +3 -0
  89. package/dist/lib/reporting/index.mjs +2 -0
  90. package/dist/lib/reporting/ledger/handler.d.mts +51 -1
  91. package/dist/lib/reporting/ledger/handler.d.ts +51 -1
  92. package/dist/lib/reporting/ledger/handler.js +306 -38
  93. package/dist/lib/reporting/ledger/handler.mjs +304 -37
  94. package/dist/lib/reporting/ledger/health.d.mts +12 -0
  95. package/dist/lib/reporting/ledger/health.d.ts +12 -0
  96. package/dist/lib/reporting/ledger/health.js +15 -2
  97. package/dist/lib/reporting/ledger/health.mjs +13 -1
  98. package/dist/lib/reporting/ledger/index.d.mts +3 -0
  99. package/dist/lib/reporting/ledger/index.d.ts +3 -0
  100. package/dist/lib/reporting/ledger/index.js +7 -1
  101. package/dist/lib/reporting/ledger/index.mjs +3 -0
  102. package/dist/lib/reporting/ledger/lifecycle.d.mts +31 -4
  103. package/dist/lib/reporting/ledger/lifecycle.d.ts +31 -4
  104. package/dist/lib/reporting/ledger/lifecycle.js +244 -37
  105. package/dist/lib/reporting/ledger/lifecycle.mjs +244 -37
  106. package/dist/lib/reporting/ledger/managed-postgres.d.mts +231 -0
  107. package/dist/lib/reporting/ledger/managed-postgres.d.ts +231 -0
  108. package/dist/lib/reporting/ledger/managed-postgres.js +1797 -0
  109. package/dist/lib/reporting/ledger/managed-postgres.mjs +1776 -0
  110. package/dist/lib/reporting/ledger/managed.d.mts +355 -0
  111. package/dist/lib/reporting/ledger/managed.d.ts +355 -0
  112. package/dist/lib/reporting/ledger/managed.js +661 -0
  113. package/dist/lib/reporting/ledger/managed.mjs +633 -0
  114. package/dist/lib/reporting/ledger/notification-activity.d.mts +222 -0
  115. package/dist/lib/reporting/ledger/notification-activity.d.ts +222 -0
  116. package/dist/lib/reporting/ledger/notification-activity.js +1139 -0
  117. package/dist/lib/reporting/ledger/notification-activity.mjs +1110 -0
  118. package/dist/lib/reporting/ledger/postgres.d.mts +161 -1
  119. package/dist/lib/reporting/ledger/postgres.d.ts +161 -1
  120. package/dist/lib/reporting/ledger/postgres.js +1153 -21
  121. package/dist/lib/reporting/ledger/postgres.mjs +1152 -21
  122. package/dist/lib/reporting/ledger/producer.d.mts +8 -0
  123. package/dist/lib/reporting/ledger/producer.d.ts +8 -0
  124. package/dist/lib/reporting/ledger/producer.js +146 -52
  125. package/dist/lib/reporting/ledger/producer.mjs +146 -51
  126. package/dist/lib/reporting/ledger/types.d.mts +358 -1
  127. package/dist/lib/reporting/ledger/types.d.ts +358 -1
  128. package/dist/lib/reporting/ledger/types.js +3 -0
  129. package/dist/lib/reporting/ledger/types.mjs +2 -0
  130. package/dist/lib/reporting/reconciliation.d.mts +362 -2
  131. package/dist/lib/reporting/reconciliation.d.ts +362 -2
  132. package/dist/lib/reporting/reconciliation.js +1051 -7
  133. package/dist/lib/reporting/reconciliation.mjs +1053 -7
  134. package/dist/lib/reporting/service/conformance.d.mts +35 -0
  135. package/dist/lib/reporting/service/conformance.d.ts +35 -0
  136. package/dist/lib/reporting/service/conformance.js +89 -0
  137. package/dist/lib/reporting/service/conformance.mjs +68 -0
  138. package/dist/lib/reporting/service/index.d.mts +182 -0
  139. package/dist/lib/reporting/service/index.d.ts +182 -0
  140. package/dist/lib/reporting/service/index.js +793 -0
  141. package/dist/lib/reporting/service/index.mjs +787 -0
  142. package/dist/lib/reporting/source/index.d.mts +2 -1
  143. package/dist/lib/reporting/source/index.d.ts +2 -1
  144. package/dist/lib/reporting/source/index.js +16 -3
  145. package/dist/lib/reporting/source/index.mjs +12 -1
  146. package/dist/lib/reporting/source/inline.d.mts +88 -1
  147. package/dist/lib/reporting/source/inline.d.ts +88 -1
  148. package/dist/lib/reporting/source/inline.js +1161 -163
  149. package/dist/lib/reporting/source/inline.mjs +1166 -163
  150. package/dist/lib/reporting/source/manifest.js +12 -7
  151. package/dist/lib/reporting/source/manifest.mjs +12 -7
  152. package/dist/lib/reporting/source/source.d.mts +26 -0
  153. package/dist/lib/reporting/source/source.d.ts +26 -0
  154. package/dist/lib/reporting/source/source.js +71 -2
  155. package/dist/lib/reporting/source/source.mjs +65 -1
  156. package/dist/lib/schemas/index.d.mts +22 -1
  157. package/dist/lib/schemas/index.d.ts +22 -1
  158. package/dist/lib/schemas/index.js +7 -0
  159. package/dist/lib/schemas/index.mjs +7 -0
  160. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  161. package/dist/lib/server/create-adcp-server.d.mts +18 -0
  162. package/dist/lib/server/create-adcp-server.d.ts +18 -0
  163. package/dist/lib/server/create-adcp-server.js +52 -2
  164. package/dist/lib/server/create-adcp-server.mjs +52 -2
  165. package/dist/lib/server/decisioning/account.d.mts +1 -1
  166. package/dist/lib/server/decisioning/account.d.ts +1 -1
  167. package/dist/lib/server/decisioning/index.d.mts +1 -0
  168. package/dist/lib/server/decisioning/index.d.ts +1 -0
  169. package/dist/lib/server/decisioning/platform.d.mts +3 -0
  170. package/dist/lib/server/decisioning/platform.d.ts +3 -0
  171. package/dist/lib/server/decisioning/runtime/from-platform.js +88 -10
  172. package/dist/lib/server/decisioning/runtime/from-platform.mjs +88 -10
  173. package/dist/lib/server/decisioning/specialisms/reporting.d.mts +38 -0
  174. package/dist/lib/server/decisioning/specialisms/reporting.d.ts +38 -0
  175. package/dist/lib/{types/v3-1-beta/index.js → server/decisioning/specialisms/reporting.js} +2 -8
  176. package/dist/lib/server/decisioning/specialisms/reporting.mjs +0 -0
  177. package/dist/lib/server/index.d.mts +4 -2
  178. package/dist/lib/server/index.d.ts +4 -2
  179. package/dist/lib/server/index.js +5 -0
  180. package/dist/lib/server/index.mjs +4 -0
  181. package/dist/lib/server/media-buy-action-resolver.d.mts +63 -0
  182. package/dist/lib/server/media-buy-action-resolver.d.ts +63 -0
  183. package/dist/lib/server/media-buy-action-resolver.js +297 -0
  184. package/dist/lib/server/media-buy-action-resolver.mjs +285 -0
  185. package/dist/lib/server/media-buy-actions.d.mts +7 -8
  186. package/dist/lib/server/media-buy-actions.d.ts +7 -8
  187. package/dist/lib/server/media-buy-actions.js +57 -14
  188. package/dist/lib/server/media-buy-actions.mjs +63 -14
  189. package/dist/lib/server/notification-subscriptions/index.d.mts +2 -2
  190. package/dist/lib/server/notification-subscriptions/index.d.ts +2 -2
  191. package/dist/lib/server/notification-subscriptions/index.js +2 -0
  192. package/dist/lib/server/notification-subscriptions/index.mjs +2 -0
  193. package/dist/lib/server/notification-subscriptions/postgres-runtime.d.mts +3 -1
  194. package/dist/lib/server/notification-subscriptions/postgres-runtime.d.ts +3 -1
  195. package/dist/lib/server/notification-subscriptions/postgres-runtime.js +1 -0
  196. package/dist/lib/server/notification-subscriptions/postgres-runtime.mjs +1 -0
  197. package/dist/lib/server/notification-subscriptions/runtime.d.mts +12 -1
  198. package/dist/lib/server/notification-subscriptions/runtime.d.ts +12 -1
  199. package/dist/lib/server/notification-subscriptions/runtime.js +102 -16
  200. package/dist/lib/server/notification-subscriptions/runtime.mjs +101 -16
  201. package/dist/lib/server/notification-subscriptions/types.d.mts +104 -1
  202. package/dist/lib/server/notification-subscriptions/types.d.ts +104 -1
  203. package/dist/lib/server/webhook-emitter.d.mts +40 -5
  204. package/dist/lib/server/webhook-emitter.d.ts +40 -5
  205. package/dist/lib/server/webhook-emitter.js +23 -12
  206. package/dist/lib/server/webhook-emitter.mjs +23 -12
  207. package/dist/lib/storage/interfaces.d.mts +14 -2
  208. package/dist/lib/storage/interfaces.d.ts +14 -2
  209. package/dist/lib/testing/compliance/comply.d.mts +9 -3
  210. package/dist/lib/testing/compliance/comply.d.ts +9 -3
  211. package/dist/lib/testing/compliance/comply.js +158 -3
  212. package/dist/lib/testing/compliance/comply.mjs +159 -4
  213. package/dist/lib/testing/compliance/storyboard-tracks.js +7 -5
  214. package/dist/lib/testing/compliance/storyboard-tracks.mjs +7 -5
  215. package/dist/lib/testing/compliance/summary.js +10 -1
  216. package/dist/lib/testing/compliance/summary.mjs +10 -1
  217. package/dist/lib/testing/index.d.mts +1 -1
  218. package/dist/lib/testing/index.d.ts +1 -1
  219. package/dist/lib/testing/index.js +2 -0
  220. package/dist/lib/testing/index.mjs +3 -1
  221. package/dist/lib/testing/storyboard/agent-routing.d.mts +12 -43
  222. package/dist/lib/testing/storyboard/agent-routing.d.ts +12 -43
  223. package/dist/lib/testing/storyboard/agent-routing.js +75 -13
  224. package/dist/lib/testing/storyboard/agent-routing.mjs +70 -12
  225. package/dist/lib/testing/storyboard/index.d.mts +1 -0
  226. package/dist/lib/testing/storyboard/index.d.ts +1 -0
  227. package/dist/lib/testing/storyboard/index.js +3 -0
  228. package/dist/lib/testing/storyboard/index.mjs +2 -0
  229. package/dist/lib/testing/storyboard/junit.d.mts +1 -1
  230. package/dist/lib/testing/storyboard/junit.d.ts +1 -1
  231. package/dist/lib/testing/storyboard/junit.js +21 -2
  232. package/dist/lib/testing/storyboard/junit.mjs +21 -2
  233. package/dist/lib/testing/storyboard/probes.d.mts +130 -0
  234. package/dist/lib/testing/storyboard/probes.d.ts +130 -0
  235. package/dist/lib/testing/storyboard/probes.js +682 -10
  236. package/dist/lib/testing/storyboard/probes.mjs +683 -3
  237. package/dist/lib/testing/storyboard/request-signing/builder.d.mts +16 -5
  238. package/dist/lib/testing/storyboard/request-signing/builder.d.ts +16 -5
  239. package/dist/lib/testing/storyboard/request-signing/grader.d.mts +44 -1
  240. package/dist/lib/testing/storyboard/request-signing/grader.d.ts +44 -1
  241. package/dist/lib/testing/storyboard/request-signing/grader.js +46 -22
  242. package/dist/lib/testing/storyboard/request-signing/grader.mjs +43 -21
  243. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.mts +86 -11
  244. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts +86 -11
  245. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js +119 -25
  246. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +117 -26
  247. package/dist/lib/testing/storyboard/request-signing/synthesize.js +22 -2
  248. package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +22 -2
  249. package/dist/lib/testing/storyboard/runner.d.mts +103 -0
  250. package/dist/lib/testing/storyboard/runner.d.ts +103 -0
  251. package/dist/lib/testing/storyboard/runner.js +1090 -268
  252. package/dist/lib/testing/storyboard/runner.mjs +1096 -261
  253. package/dist/lib/testing/storyboard/seeding.d.mts +4 -1
  254. package/dist/lib/testing/storyboard/seeding.d.ts +4 -1
  255. package/dist/lib/testing/storyboard/seeding.js +55 -24
  256. package/dist/lib/testing/storyboard/seeding.mjs +55 -24
  257. package/dist/lib/testing/storyboard/test-kit.d.mts +37 -3
  258. package/dist/lib/testing/storyboard/test-kit.d.ts +37 -3
  259. package/dist/lib/testing/storyboard/test-kit.js +8 -2
  260. package/dist/lib/testing/storyboard/test-kit.mjs +7 -2
  261. package/dist/lib/testing/storyboard/types.d.mts +132 -10
  262. package/dist/lib/testing/storyboard/types.d.ts +132 -10
  263. package/dist/lib/testing/storyboard/types.js +17 -0
  264. package/dist/lib/testing/storyboard/types.mjs +16 -0
  265. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  266. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  267. package/dist/lib/testing/storyboard/validations.js +16 -0
  268. package/dist/lib/testing/storyboard/validations.mjs +16 -0
  269. package/dist/lib/testing/test-controller.d.mts +1 -1
  270. package/dist/lib/testing/test-controller.d.ts +1 -1
  271. package/dist/lib/types/buy-products.d.ts +71 -6
  272. package/dist/lib/types/control-media-buy.d.ts +25 -11
  273. package/dist/lib/types/core.generated.d.mts +69 -10
  274. package/dist/lib/types/core.generated.d.ts +69 -10
  275. package/dist/lib/types/create-media-buy.d.ts +71 -6
  276. package/dist/lib/types/forward-compat-error-codes.d.mts +7 -6
  277. package/dist/lib/types/forward-compat-error-codes.d.ts +7 -6
  278. package/dist/lib/types/index.d.mts +2 -2
  279. package/dist/lib/types/index.d.ts +2 -2
  280. package/dist/lib/types/schemas.generated.d.ts +8040 -8116
  281. package/dist/lib/types/schemas.generated.js +1074 -309
  282. package/dist/lib/types/schemas.generated.mjs +1068 -309
  283. package/dist/lib/types/tools.generated.d.mts +65 -6
  284. package/dist/lib/types/tools.generated.d.ts +65 -6
  285. package/dist/lib/types/update-media-buy.d.ts +71 -6
  286. package/dist/lib/utils/redact-secrets.d.mts +1 -1
  287. package/dist/lib/utils/redact-secrets.d.ts +1 -1
  288. package/dist/lib/utils/redact-secrets.js +1 -1
  289. package/dist/lib/utils/redact-secrets.mjs +1 -1
  290. package/dist/lib/v2/projection/cache-versions.d.mts +0 -1
  291. package/dist/lib/v2/projection/cache-versions.d.ts +0 -1
  292. package/dist/lib/v2/projection/cache-versions.js +1 -15
  293. package/dist/lib/v2/projection/cache-versions.mjs +1 -14
  294. package/dist/lib/v2/projection/canonical-properties.js +2 -2
  295. package/dist/lib/v2/projection/canonical-properties.mjs +3 -3
  296. package/dist/lib/v2/projection/registry.d.mts +1 -1
  297. package/dist/lib/v2/projection/registry.d.ts +1 -1
  298. package/dist/lib/v2/projection/registry.js +2 -2
  299. package/dist/lib/v2/projection/registry.mjs +3 -3
  300. package/dist/lib/validation/schema-loader.d.mts +9 -1
  301. package/dist/lib/validation/schema-loader.d.ts +9 -1
  302. package/dist/lib/validation/schema-loader.js +65 -8
  303. package/dist/lib/validation/schema-loader.mjs +64 -8
  304. package/dist/lib/version.d.mts +5 -5
  305. package/dist/lib/version.d.ts +5 -5
  306. package/dist/lib/version.js +3 -8
  307. package/dist/lib/version.mjs +3 -8
  308. package/dist/lib/wholesale-feed-sync/index.d.mts +1 -0
  309. package/dist/lib/wholesale-feed-sync/index.d.ts +1 -0
  310. package/dist/lib/wholesale-feed-sync/protocol-types.d.mts +42 -0
  311. package/dist/lib/wholesale-feed-sync/protocol-types.d.ts +42 -0
  312. package/dist/lib/wholesale-feed-sync/protocol-types.js +16 -0
  313. package/dist/lib/wholesale-feed-sync/protocol-types.mjs +0 -0
  314. package/dist/lib/wholesale-feed-sync/sync.d.mts +6 -6
  315. package/dist/lib/wholesale-feed-sync/sync.d.ts +6 -6
  316. package/dist/lib/wholesale-feed-sync/sync.js +3 -1
  317. package/dist/lib/wholesale-feed-sync/sync.mjs +3 -1
  318. package/dist/lib/wholesale-feed-sync/types.d.mts +15 -14
  319. package/dist/lib/wholesale-feed-sync/types.d.ts +15 -14
  320. package/dist/lib/wholesale-feed-sync/webhook-notification.d.mts +7 -5
  321. package/dist/lib/wholesale-feed-sync/webhook-notification.d.ts +7 -5
  322. package/dist/lib/wholesale-feed-sync/webhook-notification.js +45 -0
  323. package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +44 -0
  324. package/docs/CLI.md +1 -1
  325. package/docs/TYPE-SUMMARY.md +118 -4
  326. package/docs/guides/ASYNC-API-REFERENCE.md +62 -1
  327. package/docs/guides/ASYNC-DEVELOPER-GUIDE.md +25 -0
  328. package/docs/guides/ASYNC-DOCUMENTATION-INDEX.md +3 -0
  329. package/docs/guides/BUYER-QUICKSTART-3.2.md +5 -0
  330. package/docs/guides/DURABLE-BUYER-WRITES.md +337 -0
  331. package/docs/guides/EXISTING-PLATFORM.md +80 -1
  332. package/docs/guides/MEDIA-BUY-3.2-COMPATIBILITY.md +57 -0
  333. package/docs/guides/MEDIA-BUY-ACTION-ASSESSMENT.md +300 -0
  334. package/docs/guides/REPORTING-LEDGER.md +654 -3
  335. package/docs/guides/REPORTING-RECONCILIATION.md +50 -0
  336. package/docs/guides/REPORTING-SOURCE-EXECUTOR.md +63 -1
  337. package/docs/guides/SELLER-QUICKSTART-3.2.md +2 -0
  338. package/docs/guides/VALIDATE-YOUR-AGENT.md +35 -0
  339. package/docs/guides/idempotency-crash-recovery.md +4 -0
  340. package/docs/llms.txt +4 -2
  341. package/docs/migration-14.x-rc-worksheet.md +60 -5
  342. package/docs/migration-7.9-to-7.10.md +7 -5
  343. package/examples/README.md +17 -0
  344. package/examples/durable-buyer-writes/caller.ts +745 -0
  345. package/examples/durable-buyer-writes/worker.ts +240 -0
  346. package/examples/reliable-reporting-service/README.md +100 -0
  347. package/examples/seller-3.2-starter.ts +7 -8
  348. package/examples/targeting-input-existing-platform.ts +153 -0
  349. package/package.json +41 -29
  350. package/skills/build-seller-agent/SKILL.md +2 -0
  351. package/skills/build-seller-agent/specialisms/signed-requests.md +11 -1
  352. package/skills/cross-cutting.md +28 -11
  353. package/compliance/cache/3.1.0-beta.7/domains/brand/index.yaml +0 -160
  354. package/compliance/cache/3.1.0-beta.7/domains/brand/scenarios/distributed_brand_resolution.yaml +0 -415
  355. package/compliance/cache/3.1.0-beta.7/domains/brand/scenarios/single_side_trust_extension.yaml +0 -454
  356. package/compliance/cache/3.1.0-beta.7/domains/creative/index.yaml +0 -339
  357. package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/billing_out_of_band.yaml +0 -153
  358. package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/creative_lifecycle_webhooks.yaml +0 -389
  359. package/compliance/cache/3.1.0-beta.7/domains/creative/scenarios/native_in_feed.yaml +0 -543
  360. package/compliance/cache/3.1.0-beta.7/domains/governance/index.yaml +0 -682
  361. package/compliance/cache/3.1.0-beta.7/domains/media-buy/index.yaml +0 -781
  362. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/audience_buy_flow.yaml +0 -380
  363. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/available_actions.yaml +0 -565
  364. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/billing_finality_delivery.yaml +0 -354
  365. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/canonical_formats.yaml +0 -711
  366. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/clicks_buy_flow.yaml +0 -264
  367. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/completed_views_buy_flow.yaml +0 -344
  368. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/create_media_buy_async.yaml +0 -234
  369. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/creative_fate_after_cancellation.yaml +0 -419
  370. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/creative_reception.yaml +0 -247
  371. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/delivery_reporting.yaml +0 -357
  372. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/dependency_impairment.yaml +0 -633
  373. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/dependency_impairment_cardinality.yaml +0 -800
  374. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/event_dedup_flow.yaml +0 -399
  375. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/frequency_cap_enforcement.yaml +0 -309
  376. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_approved.yaml +0 -214
  377. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_conditions.yaml +0 -199
  378. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_denied.yaml +0 -204
  379. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/governance_denied_recovery.yaml +0 -252
  380. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/invalid_transitions.yaml +0 -289
  381. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/inventory_list_no_match.yaml +0 -148
  382. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/inventory_list_targeting.yaml +0 -276
  383. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/measurement_accountability.yaml +0 -244
  384. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/measurement_terms_rejected.yaml +0 -203
  385. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/pending_creatives_to_start.yaml +0 -274
  386. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/per_creative_conversion_attribution.yaml +0 -500
  387. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/performance_buy_flow.yaml +0 -428
  388. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/performance_buy_flow_roas.yaml +0 -470
  389. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/product_signal_targeting.yaml +0 -373
  390. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_finalize.yaml +0 -399
  391. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_finalize_asap_timing.yaml +0 -264
  392. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/proposal_not_found_errors.yaml +0 -257
  393. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_audit_observation.yaml +0 -333
  394. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_enforcement.yaml +0 -517
  395. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/provenance_truth_of_claim.yaml +0 -294
  396. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/reach_buy_flow.yaml +0 -823
  397. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/refine_finalize_exclusivity.yaml +0 -360
  398. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/refine_products.yaml +0 -148
  399. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_accountability.yaml +0 -293
  400. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +0 -307
  401. package/compliance/cache/3.1.0-beta.7/domains/media-buy/scenarios/vendor_metric_optimization_flow.yaml +0 -576
  402. package/compliance/cache/3.1.0-beta.7/domains/media-buy/state-machine.yaml +0 -442
  403. package/compliance/cache/3.1.0-beta.7/domains/signals/index.yaml +0 -266
  404. package/compliance/cache/3.1.0-beta.7/domains/sponsored-intelligence/index.yaml +0 -256
  405. package/compliance/cache/3.1.0-beta.7/index.json +0 -356
  406. package/compliance/cache/3.1.0-beta.7/protocols/brand/index.yaml +0 -160
  407. package/compliance/cache/3.1.0-beta.7/protocols/brand/scenarios/distributed_brand_resolution.yaml +0 -415
  408. package/compliance/cache/3.1.0-beta.7/protocols/brand/scenarios/single_side_trust_extension.yaml +0 -454
  409. package/compliance/cache/3.1.0-beta.7/protocols/creative/index.yaml +0 -339
  410. package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/billing_out_of_band.yaml +0 -153
  411. package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/creative_lifecycle_webhooks.yaml +0 -389
  412. package/compliance/cache/3.1.0-beta.7/protocols/creative/scenarios/native_in_feed.yaml +0 -543
  413. package/compliance/cache/3.1.0-beta.7/protocols/governance/index.yaml +0 -682
  414. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/index.yaml +0 -781
  415. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/audience_buy_flow.yaml +0 -380
  416. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/available_actions.yaml +0 -565
  417. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/billing_finality_delivery.yaml +0 -354
  418. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/canonical_formats.yaml +0 -711
  419. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/clicks_buy_flow.yaml +0 -264
  420. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/completed_views_buy_flow.yaml +0 -344
  421. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/create_media_buy_async.yaml +0 -234
  422. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/creative_fate_after_cancellation.yaml +0 -419
  423. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/creative_reception.yaml +0 -247
  424. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/delivery_reporting.yaml +0 -357
  425. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/dependency_impairment.yaml +0 -633
  426. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/dependency_impairment_cardinality.yaml +0 -800
  427. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/event_dedup_flow.yaml +0 -399
  428. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/frequency_cap_enforcement.yaml +0 -309
  429. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_approved.yaml +0 -214
  430. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_conditions.yaml +0 -199
  431. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_denied.yaml +0 -204
  432. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/governance_denied_recovery.yaml +0 -252
  433. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/invalid_transitions.yaml +0 -289
  434. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/inventory_list_no_match.yaml +0 -148
  435. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/inventory_list_targeting.yaml +0 -276
  436. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/measurement_accountability.yaml +0 -244
  437. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/measurement_terms_rejected.yaml +0 -203
  438. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/pending_creatives_to_start.yaml +0 -274
  439. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/per_creative_conversion_attribution.yaml +0 -500
  440. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/performance_buy_flow.yaml +0 -428
  441. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/performance_buy_flow_roas.yaml +0 -470
  442. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/product_signal_targeting.yaml +0 -373
  443. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_finalize.yaml +0 -399
  444. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_finalize_asap_timing.yaml +0 -264
  445. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/proposal_not_found_errors.yaml +0 -257
  446. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_audit_observation.yaml +0 -333
  447. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_enforcement.yaml +0 -517
  448. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/provenance_truth_of_claim.yaml +0 -294
  449. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/reach_buy_flow.yaml +0 -823
  450. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/refine_finalize_exclusivity.yaml +0 -360
  451. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/refine_products.yaml +0 -148
  452. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_accountability.yaml +0 -293
  453. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_catalog_precondition.yaml +0 -307
  454. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/scenarios/vendor_metric_optimization_flow.yaml +0 -576
  455. package/compliance/cache/3.1.0-beta.7/protocols/media-buy/state-machine.yaml +0 -442
  456. package/compliance/cache/3.1.0-beta.7/protocols/signals/index.yaml +0 -266
  457. package/compliance/cache/3.1.0-beta.7/protocols/sponsored-intelligence/index.yaml +0 -256
  458. package/compliance/cache/3.1.0-beta.7/specialisms/audience-sync/index.yaml +0 -313
  459. package/compliance/cache/3.1.0-beta.7/specialisms/brand-rights/index.yaml +0 -350
  460. package/compliance/cache/3.1.0-beta.7/specialisms/brand-rights/scenarios/governance_denied.yaml +0 -226
  461. package/compliance/cache/3.1.0-beta.7/specialisms/collection-lists/index.yaml +0 -359
  462. package/compliance/cache/3.1.0-beta.7/specialisms/content-standards/index.yaml +0 -572
  463. package/compliance/cache/3.1.0-beta.7/specialisms/creative-ad-server/index.yaml +0 -409
  464. package/compliance/cache/3.1.0-beta.7/specialisms/creative-generative/generative-seller.yaml +0 -807
  465. package/compliance/cache/3.1.0-beta.7/specialisms/creative-generative/index.yaml +0 -758
  466. package/compliance/cache/3.1.0-beta.7/specialisms/creative-template/index.yaml +0 -510
  467. package/compliance/cache/3.1.0-beta.7/specialisms/governance-aware-seller/index.yaml +0 -143
  468. package/compliance/cache/3.1.0-beta.7/specialisms/governance-aware-seller/scenarios/governance_multi_agent_rejected.yaml +0 -117
  469. package/compliance/cache/3.1.0-beta.7/specialisms/governance-delivery-monitor/index.yaml +0 -441
  470. package/compliance/cache/3.1.0-beta.7/specialisms/governance-spend-authority/denied.yaml +0 -221
  471. package/compliance/cache/3.1.0-beta.7/specialisms/governance-spend-authority/index.yaml +0 -330
  472. package/compliance/cache/3.1.0-beta.7/specialisms/property-lists/index.yaml +0 -482
  473. package/compliance/cache/3.1.0-beta.7/specialisms/sales-broadcast-tv/index.yaml +0 -738
  474. package/compliance/cache/3.1.0-beta.7/specialisms/sales-catalog-driven/index.yaml +0 -840
  475. package/compliance/cache/3.1.0-beta.7/specialisms/sales-guaranteed/index.yaml +0 -601
  476. package/compliance/cache/3.1.0-beta.7/specialisms/sales-non-guaranteed/index.yaml +0 -546
  477. package/compliance/cache/3.1.0-beta.7/specialisms/sales-proposal-mode/index.yaml +0 -586
  478. package/compliance/cache/3.1.0-beta.7/specialisms/sales-social/index.yaml +0 -919
  479. package/compliance/cache/3.1.0-beta.7/specialisms/signal-marketplace/index.yaml +0 -424
  480. package/compliance/cache/3.1.0-beta.7/specialisms/signal-marketplace/scenarios/governance_denied.yaml +0 -211
  481. package/compliance/cache/3.1.0-beta.7/specialisms/signal-owned/index.yaml +0 -317
  482. package/compliance/cache/3.1.0-beta.7/specialisms/sponsored-intelligence/index.yaml +0 -59
  483. package/compliance/cache/3.1.0-beta.7/test-kits/acme-outdoor-live.yaml +0 -78
  484. package/compliance/cache/3.1.0-beta.7/test-kits/acme-outdoor.yaml +0 -223
  485. package/compliance/cache/3.1.0-beta.7/test-kits/billing-gate-runner.yaml +0 -115
  486. package/compliance/cache/3.1.0-beta.7/test-kits/bistro-oranje.yaml +0 -126
  487. package/compliance/cache/3.1.0-beta.7/test-kits/distributed-brand-runner.yaml +0 -281
  488. package/compliance/cache/3.1.0-beta.7/test-kits/nova-motors.yaml +0 -262
  489. package/compliance/cache/3.1.0-beta.7/test-kits/osei-natural.yaml +0 -126
  490. package/compliance/cache/3.1.0-beta.7/test-kits/parallel-dispatch-runner.yaml +0 -196
  491. package/compliance/cache/3.1.0-beta.7/test-kits/rate-limit-trip-runner.yaml +0 -172
  492. package/compliance/cache/3.1.0-beta.7/test-kits/signed-requests-runner.yaml +0 -155
  493. package/compliance/cache/3.1.0-beta.7/test-kits/single-side-trust-runner.yaml +0 -294
  494. package/compliance/cache/3.1.0-beta.7/test-kits/substitution-observer-runner.yaml +0 -688
  495. package/compliance/cache/3.1.0-beta.7/test-kits/summit-foods.yaml +0 -125
  496. package/compliance/cache/3.1.0-beta.7/test-kits/webhook-receiver-runner.yaml +0 -265
  497. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/001-minimal-plan.json +0 -43
  498. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/002-full-plan.json +0 -217
  499. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/003-bookkeeping-stripped.json +0 -60
  500. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/004a-human-review-omitted.json +0 -43
  501. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/004b-human-review-explicit-null.json +0 -49
  502. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/005a-policy-categories-order-1.json +0 -53
  503. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/005b-policy-categories-order-2.json +0 -57
  504. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/006a-ext-trace-v1.json +0 -49
  505. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/006b-ext-trace-v2.json +0 -53
  506. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/007-unicode-objectives.json +0 -43
  507. package/compliance/cache/3.1.0-beta.7/test-vectors/plan-hash/008-numeric-canonicalization.json +0 -65
  508. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/README.md +0 -220
  509. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/canonicalization.json +0 -241
  510. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/keys.json +0 -60
  511. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/001-no-signature-header.json +0 -24
  512. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/002-wrong-tag.json +0 -26
  513. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/003-expired-signature.json +0 -26
  514. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/004-window-too-long.json +0 -26
  515. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/005-alg-not-allowed.json +0 -26
  516. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/006-missing-covered-component.json +0 -26
  517. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/007-missing-content-digest.json +0 -26
  518. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/008-unknown-keyid.json +0 -26
  519. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/009-key-ops-missing-verify.json +0 -27
  520. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/010-content-digest-mismatch.json +0 -33
  521. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/011-malformed-header.json +0 -27
  522. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/012-missing-expires-param.json +0 -26
  523. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/013-expires-le-created.json +0 -27
  524. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/014-missing-nonce-param.json +0 -27
  525. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/015-signature-invalid.json +0 -28
  526. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/016-replayed-nonce.json +0 -35
  527. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/017-key-revoked.json +0 -38
  528. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/018-digest-covered-when-forbidden.json +0 -28
  529. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/019-signature-without-signature-input.json +0 -26
  530. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/020-rate-abuse.json +0 -34
  531. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/021-duplicate-signature-input-label.json +0 -31
  532. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/022-multi-valued-content-type.json +0 -31
  533. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/023-multi-valued-content-digest.json +0 -32
  534. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/024-unquoted-string-param.json +0 -31
  535. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/025-jwk-alg-crv-mismatch.json +0 -43
  536. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/026-non-ascii-host.json +0 -31
  537. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/027-webhook-registration-authentication-unsigned.json +0 -25
  538. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/negative/028-unsigned-protocol-method-required.json +0 -26
  539. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/001-basic-post.json +0 -30
  540. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/002-post-with-content-digest.json +0 -31
  541. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/003-es256-post.json +0 -30
  542. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/004-multiple-signature-labels.json +0 -26
  543. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/005-default-port-stripped.json +0 -30
  544. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/006-dot-segment-path.json +0 -30
  545. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/007-query-byte-preserved.json +0 -30
  546. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/008-percent-encoded-path.json +0 -30
  547. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/009-percent-encoded-unreserved-decoded.json +0 -30
  548. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/010-percent-encoded-slash-preserved.json +0 -30
  549. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/011-ipv6-authority.json +0 -30
  550. package/compliance/cache/3.1.0-beta.7/test-vectors/request-signing/positive/012-ipv6-authority-default-port-stripped.json +0 -30
  551. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/README.md +0 -211
  552. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/keys.json +0 -61
  553. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/001-wrong-tag.json +0 -26
  554. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/002-expired-signature.json +0 -26
  555. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/003-window-too-long.json +0 -26
  556. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/004-alg-not-allowed.json +0 -26
  557. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/005-missing-authority-component.json +0 -26
  558. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/006-missing-content-digest.json +0 -25
  559. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/007-unknown-keyid.json +0 -26
  560. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/008-wrong-adcp-use.json +0 -26
  561. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/009-content-digest-mismatch.json +0 -26
  562. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/010-malformed-signature-input.json +0 -26
  563. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/011-signature-without-input.json +0 -25
  564. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/012-missing-expires-param.json +0 -26
  565. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/013-expires-le-created.json +0 -26
  566. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/014-missing-nonce-param.json +0 -26
  567. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/015-signature-invalid.json +0 -26
  568. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/016-replayed-nonce.json +0 -37
  569. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/017-key-revoked.json +0 -32
  570. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/018-rate-abuse.json +0 -33
  571. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/019-revocation-stale.json +0 -32
  572. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/020-key-ops-missing-verify.json +0 -41
  573. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/negative/021-base64-alphabet-mixing.json +0 -26
  574. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/001-basic-post.json +0 -24
  575. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/002-es256-post.json +0 -24
  576. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/003-multiple-signature-labels.json +0 -24
  577. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/004-default-port-stripped.json +0 -24
  578. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/005-percent-encoded-path.json +0 -24
  579. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/006-query-byte-preserved.json +0 -24
  580. package/compliance/cache/3.1.0-beta.7/test-vectors/webhook-signing/positive/007-body-without-idempotency-key.json +0 -25
  581. package/compliance/cache/3.1.0-beta.7/universal/billing-gate-dispatch.yaml +0 -450
  582. package/compliance/cache/3.1.0-beta.7/universal/canonical-format-validate-input.yaml +0 -640
  583. package/compliance/cache/3.1.0-beta.7/universal/capability-discovery.yaml +0 -125
  584. package/compliance/cache/3.1.0-beta.7/universal/collection-lists-pagination-integrity.yaml +0 -306
  585. package/compliance/cache/3.1.0-beta.7/universal/comply-controller-mode-gate.yaml +0 -141
  586. package/compliance/cache/3.1.0-beta.7/universal/content-standards-pagination-integrity.yaml +0 -326
  587. package/compliance/cache/3.1.0-beta.7/universal/deterministic-testing.yaml +0 -1430
  588. package/compliance/cache/3.1.0-beta.7/universal/error-compliance-signals.yaml +0 -377
  589. package/compliance/cache/3.1.0-beta.7/universal/error-compliance.yaml +0 -528
  590. package/compliance/cache/3.1.0-beta.7/universal/fictional-entities.yaml +0 -307
  591. package/compliance/cache/3.1.0-beta.7/universal/get-media-buys-pagination-integrity.yaml +0 -160
  592. package/compliance/cache/3.1.0-beta.7/universal/get-signals-pagination-integrity.yaml +0 -211
  593. package/compliance/cache/3.1.0-beta.7/universal/idempotency.yaml +0 -861
  594. package/compliance/cache/3.1.0-beta.7/universal/notification-config-event-scope.yaml +0 -119
  595. package/compliance/cache/3.1.0-beta.7/universal/notification-config-lifecycle.yaml +0 -337
  596. package/compliance/cache/3.1.0-beta.7/universal/notification-config-rejections.yaml +0 -107
  597. package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity-creative-formats.yaml +0 -265
  598. package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity-list-accounts.yaml +0 -245
  599. package/compliance/cache/3.1.0-beta.7/universal/pagination-integrity.yaml +0 -263
  600. package/compliance/cache/3.1.0-beta.7/universal/property-lists-pagination-integrity.yaml +0 -307
  601. package/compliance/cache/3.1.0-beta.7/universal/read-tool-idempotency.yaml +0 -405
  602. package/compliance/cache/3.1.0-beta.7/universal/runner-output-contract.yaml +0 -1266
  603. package/compliance/cache/3.1.0-beta.7/universal/schema-validation-signals.yaml +0 -181
  604. package/compliance/cache/3.1.0-beta.7/universal/schema-validation.yaml +0 -548
  605. package/compliance/cache/3.1.0-beta.7/universal/security.yaml +0 -539
  606. package/compliance/cache/3.1.0-beta.7/universal/signed-requests.yaml +0 -217
  607. package/compliance/cache/3.1.0-beta.7/universal/stale-response-advisory.yaml +0 -295
  608. package/compliance/cache/3.1.0-beta.7/universal/storyboard-schema.yaml +0 -2136
  609. package/compliance/cache/3.1.0-beta.7/universal/v3-envelope-integrity.yaml +0 -117
  610. package/compliance/cache/3.1.0-beta.7/universal/version-negotiation.yaml +0 -130
  611. package/compliance/cache/3.1.0-beta.7/universal/webhook-emission.yaml +0 -411
  612. package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-bulk-webhooks.yaml +0 -82
  613. package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-product-webhooks.yaml +0 -83
  614. package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-products.yaml +0 -151
  615. package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-signal-webhooks.yaml +0 -83
  616. package/compliance/cache/3.1.0-beta.7/universal/wholesale-feed-signals.yaml +0 -149
  617. package/dist/lib/types/v3-1-beta/index.d.mts +0 -1
  618. package/dist/lib/types/v3-1-beta/index.d.ts +0 -1
  619. package/dist/lib/types/v3-1-beta/index.mjs +0 -1
  620. package/dist/lib/types/v3-1-beta/tools.generated.d.mts +0 -26788
  621. package/dist/lib/types/v3-1-beta/tools.generated.d.ts +0 -26788
  622. /package/dist/lib/{types/v3-1-beta/tools.generated.mjs → media-buy/action-types.mjs} +0 -0
@@ -20,7 +20,10 @@ var runner_exports = {};
20
20
  __export(runner_exports, {
21
21
  __defaultAuthHeadersForRawProbeForTest: () => __defaultAuthHeadersForRawProbeForTest,
22
22
  __filterResponseHeadersForTest: () => __filterResponseHeadersForTest,
23
+ __protectedToolCandidatesForTest: () => __protectedToolCandidatesForTest,
23
24
  __redactSecretsForTest: () => __redactSecretsForTest,
25
+ __selectProtectedToolTargetForTest: () => __selectProtectedToolTargetForTest,
26
+ __sessionControlCredentialsForTest: () => __sessionControlCredentialsForTest,
24
27
  applyAdcpVersionRunOptions: () => applyAdcpVersionRunOptions,
25
28
  applyBrandInvariant: () => applyBrandInvariant,
26
29
  applyDisableSandboxHint: () => applyDisableSandboxHint,
@@ -34,6 +37,9 @@ __export(runner_exports, {
34
37
  resolveCapabilityPath: () => resolveCapabilityPath,
35
38
  runStoryboard: () => runStoryboard,
36
39
  runStoryboardStep: () => runStoryboardStep,
40
+ signingCoverage: () => signingCoverage,
41
+ signingCoverageUnverified: () => signingCoverageUnverified,
42
+ storyboardCapabilityPredicates: () => storyboardCapabilityPredicates,
37
43
  summarizeStrictValidation: () => summarizeStrictValidation
38
44
  });
39
45
  module.exports = __toCommonJS(runner_exports);
@@ -68,13 +74,18 @@ var import_probes = require('./probes.js');
68
74
  var import_capabilities_types = require('../../signing/agent-resolver/capabilities-types.js');
69
75
  var import_select_agent = require('../../signing/agent-resolver/select-agent.js');
70
76
  var import_test_kit = require('./test-kit.js');
77
+ var import_idempotency2 = require('../../utils/idempotency.js');
78
+ var import_tool_request_schemas = require('../../utils/tool-request-schemas.js');
79
+ var import_capabilities = require('../../utils/capabilities.js');
71
80
  var import_loader = require('./loader.js');
72
81
  var import_phase_condition = require('./phase-condition.js');
73
82
  var import_provenance = require('./provenance.js');
74
83
  var import_probe_dispatch = require('./request-signing/probe-dispatch.js');
84
+ var import_synthesize = require('./request-signing/synthesize.js');
75
85
  var import_webhook_receiver = require('./webhook-receiver.js');
76
86
  var import_webhook_assertions = require('./webhook-assertions.js');
77
87
  var import_seeding = require('./seeding.js');
88
+ var import_test_controller2 = require('../test-controller.js');
78
89
  var import_fixture_resolution = require('./fixture-resolution.js');
79
90
  var import_compliance = require('./compliance.js');
80
91
  var import_client3 = require('../../signing/client.js');
@@ -115,7 +126,7 @@ function applyStoryboardVersionOptions(storyboard, options) {
115
126
  function applyReusableProfileOptions(options) {
116
127
  const profile = options.profile ?? options._profile;
117
128
  if (!profile) return options;
118
- const profileTools = options.agents === void 0 ? normalizeAgentToolNames(profile.tools) ?? [] : void 0;
129
+ const profileTools = options.agents === void 0 ? (0, import_agent_routing.normalizeAgentToolNames)(profile.tools) ?? [] : void 0;
119
130
  return {
120
131
  ...options,
121
132
  _profile: profile,
@@ -157,11 +168,26 @@ const DETAILED_SKIP_DETAILS = {
157
168
  rate_abuse_opt_out: "Rate-abuse vector was excluded by request_signing.skipRateAbuse.",
158
169
  capability_profile_mismatch: "Vector is outside the agent capability profile selected for this run.",
159
170
  transport_ungradable: "Vector cannot be graded faithfully by the selected transport.",
171
+ signing_transport_unavailable: "Request-signing vectors have no shape this run's protocol can carry, so no verifier behavior was graded.",
160
172
  rate_limit_not_triggered: "No RATE_LIMITED response was observed within the configured max_attempts."
161
173
  };
162
174
  const CANONICAL_SKIP_DETAILS = {
163
- rate_limit_not_triggered: "rate_limit_not_triggered"
175
+ rate_limit_not_triggered: "rate_limit_not_triggered",
176
+ // Same shape as `rate_limit_not_triggered` above, which
177
+ // runner-output-contract.yaml registers under
178
+ // `canonical_detail_sub_reasons.not_applicable` with a test-kit
179
+ // `spec_source`: emit the sub-reason token *exactly* as `skip.detail`,
180
+ // with empty validations and no pass/fail counter movement. The
181
+ // operator-facing remedy travels on the probe result (`response.error`),
182
+ // which is where the renderers read it.
183
+ //
184
+ // Upstream ask, tracked as the remaining external blocker: register
185
+ // `not_applicable.signing_transport_unavailable` with
186
+ // `spec_source: test-kits/signed-requests-runner.yaml`. Emitting the
187
+ // registered *shape* now means that registration changes nothing here.
188
+ signing_transport_unavailable: "signing_transport_unavailable"
164
189
  };
190
+ const MCP_SESSION_PROBE_REQUEST_TIMEOUT_MS = 5e3;
165
191
  const REPLAY_WEBHOOK_VECTOR_TASK = "replay_webhook_vector";
166
192
  const REPLAY_TRUSTED_MATCH_CONTEXT_VECTOR_TASK = "replay_trusted_match_context_vector";
167
193
  const WEBHOOK_REPLAY_DEFAULT_TIMEOUT_MS = 1e4;
@@ -504,6 +530,42 @@ function resetClientSessions(clients) {
504
530
  if (typeof reset === "function") reset.call(client);
505
531
  }
506
532
  }
533
+ async function resetControllerState(client, storyboard, options) {
534
+ const controller = options._controllerCapabilities;
535
+ if (controller?.detected !== true || !controller.scenarios.includes("reset_state")) return void 0;
536
+ const outcome = await (0, import_client.runStep)(
537
+ "Reset test-controller state",
538
+ "comply_test_controller",
539
+ () => (0, import_test_controller2.callControllerRaw)(
540
+ client,
541
+ {
542
+ scenario: "reset_state",
543
+ context: { correlation_id: `${storyboard.id}--__reset_state__` }
544
+ },
545
+ options
546
+ )
547
+ );
548
+ if (!outcome.step.passed) return outcome.step;
549
+ const raw = outcome.result;
550
+ const data = raw?.data;
551
+ if (raw?.success && data?.success === true) return void 0;
552
+ if (raw?.success && data?.success === false && data.error === "UNKNOWN_SCENARIO") return void 0;
553
+ return {
554
+ ...outcome.step,
555
+ passed: false,
556
+ error: data?.error_detail ?? data?.error ?? raw?.error ?? "comply_test_controller reset_state failed"
557
+ };
558
+ }
559
+ async function resetControllerStates(targets, storyboard) {
560
+ const seen = /* @__PURE__ */ new Set();
561
+ for (const target of targets) {
562
+ if (seen.has(target.client)) continue;
563
+ seen.add(target.client);
564
+ const failure = await resetControllerState(target.client, storyboard, target.options);
565
+ if (failure) return failure;
566
+ }
567
+ return void 0;
568
+ }
507
569
  function isPollEligibleEnvelope(data) {
508
570
  if (data == null || typeof data !== "object") return false;
509
571
  const obj = data;
@@ -623,6 +685,15 @@ function __redactSecretsForTest(value) {
623
685
  function __filterResponseHeadersForTest(headers) {
624
686
  return filterResponseHeaders(headers);
625
687
  }
688
+ function __selectProtectedToolTargetForTest(tools) {
689
+ return selectProtectedToolTarget(tools);
690
+ }
691
+ function __protectedToolCandidatesForTest(tools) {
692
+ return protectedToolCandidates(tools);
693
+ }
694
+ function __sessionControlCredentialsForTest(mechanism, options, client, agentUrl) {
695
+ return sessionControlCredentials(mechanism, options, client, agentUrl);
696
+ }
626
697
  function __defaultAuthHeadersForRawProbeForTest(options) {
627
698
  return defaultAuthHeadersForRawProbe(options);
628
699
  }
@@ -689,7 +760,7 @@ async function runStoryboardBody(agentUrlOrUrls, storyboard, options) {
689
760
  );
690
761
  }
691
762
  const hasCapabilityGate = storyboardCapabilityPredicates(storyboard).length > 0;
692
- const deferCapabilityAndRequires = hasCapabilityGate && options._profile === void 0;
763
+ const deferCapabilityAndRequires = options.agents !== void 0 || hasCapabilityGate && options._profile === void 0;
693
764
  if (hasCapabilityGate && !deferCapabilityAndRequires) {
694
765
  const unmetDetail = evaluateStoryboardCapabilityGates(
695
766
  storyboard,
@@ -706,8 +777,25 @@ async function runStoryboardBody(agentUrlOrUrls, storyboard, options) {
706
777
  }
707
778
  }
708
779
  const allRequires = resolveStoryboardRequires(storyboard, options);
709
- if (allRequires.length && !deferCapabilityAndRequires) {
710
- const requirementCheck = await checkRequires(allRequires, storyboard, options, options._profile);
780
+ const preflightDefersRequirement = (requirement) => {
781
+ switch (requirement) {
782
+ case "controller":
783
+ return options.agents !== void 0 || !options.agentTools;
784
+ case "request_signer":
785
+ return options.agents !== void 0 || !options._profile?.raw_capabilities;
786
+ default:
787
+ return false;
788
+ }
789
+ };
790
+ const firstDeferred = allRequires.findIndex(preflightDefersRequirement);
791
+ const earlyRequires = hasCapabilityGate ? [] : allRequires.slice(0, firstDeferred < 0 ? void 0 : firstDeferred);
792
+ if (earlyRequires.length && (!deferCapabilityAndRequires || options.agents && !hasCapabilityGate)) {
793
+ const requirementCheck = await checkRequires(
794
+ earlyRequires,
795
+ storyboard,
796
+ options,
797
+ options.agents ? void 0 : options._profile
798
+ );
711
799
  if ("requirement" in requirementCheck) {
712
800
  const resultAgentUrls = options.agents ? Object.values(options.agents).map((e) => e.url) : agentUrls;
713
801
  return {
@@ -976,20 +1064,7 @@ function buildRequiredAnyOfToolsMissingResult(agentUrls, storyboard, detail) {
976
1064
  notices: []
977
1065
  };
978
1066
  }
979
- function normalizeAgentToolNames(tools) {
980
- if (!Array.isArray(tools)) return void 0;
981
- const names = [];
982
- for (const tool of tools) {
983
- if (typeof tool === "string") {
984
- names.push(tool);
985
- } else if (tool && typeof tool === "object") {
986
- const name = tool.name;
987
- if (typeof name === "string") names.push(name);
988
- }
989
- }
990
- return names.length > 0 ? names : void 0;
991
- }
992
- async function checkRequires(requires, storyboard, options, profile) {
1067
+ async function checkRequires(requires, storyboard, options, profile, precomputed) {
993
1068
  let preparedPublisherAuthProbes = getPreparedTrustedMatchPublisherAuth(options);
994
1069
  for (const requirement of requires) {
995
1070
  if (!isKnownRequirement(requirement)) {
@@ -998,6 +1073,13 @@ async function checkRequires(requires, storyboard, options, profile) {
998
1073
  detail: `Storyboard requires unknown runtime requirement '${requirement}'. This SDK does not know how to satisfy it, so the requirement is treated as unmet for forward compatibility.`
999
1074
  };
1000
1075
  }
1076
+ const established = precomputed?.get(requirement);
1077
+ if (established) {
1078
+ if (established.status === "unmet") {
1079
+ return { requirement: established.requirement, detail: established.detail };
1080
+ }
1081
+ continue;
1082
+ }
1001
1083
  switch (requirement) {
1002
1084
  case "controller": {
1003
1085
  if (!options.agentTools) continue;
@@ -1159,6 +1241,28 @@ function detectImplicitRequires(storyboard, options = {}) {
1159
1241
  if (needsSigner) requires.push("request_signer");
1160
1242
  return requires;
1161
1243
  }
1244
+ function probeResponseStatus(response) {
1245
+ if (response === null || typeof response !== "object") return 0;
1246
+ const status = response.status;
1247
+ return typeof status === "number" ? status : 0;
1248
+ }
1249
+ function signingCoverage(steps) {
1250
+ const probes = steps.filter((step) => step.task === import_synthesize.REQUEST_SIGNING_PROBE_TASK);
1251
+ if (probes.length === 0) return "not_probed";
1252
+ if (probes.some((step) => step.skipped !== true && probeResponseStatus(step.response) > 0 && !isProbeFault(step.response)))
1253
+ return "graded";
1254
+ if (probes.some((step) => isProbeFault(step.response))) return "probe_errored";
1255
+ if (probes.some((step) => step.skip_reason === "signing_transport_unavailable")) return "transport_unverified";
1256
+ if (probes.every((step) => step.skipped === true)) return "scope_excluded";
1257
+ return "self_check_only";
1258
+ }
1259
+ function isProbeFault(response) {
1260
+ return response !== null && typeof response === "object" && response.probe_error === true;
1261
+ }
1262
+ function signingCoverageUnverified(steps) {
1263
+ const coverage = signingCoverage(steps);
1264
+ return coverage !== "not_probed" && coverage !== "graded";
1265
+ }
1162
1266
  function buildDiscoveryFailedResult(agentUrls, storyboard, discoveryStep) {
1163
1267
  const detail = discoveryStep.error ?? "Discovery failed (no agent tools advertised).";
1164
1268
  const syntheticStep = {
@@ -1378,7 +1482,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1378
1482
  try {
1379
1483
  routingContext = await (0, import_agent_routing.buildRoutingContext)(storyboard, options);
1380
1484
  } catch (err) {
1381
- const detail = err?.message ?? String(err);
1485
+ const detail = (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(err?.message ?? String(err));
1382
1486
  const failedStep = {
1383
1487
  step: err instanceof import_agent_routing.DiscoveryFailure ? `Discover agent capabilities (${err.agentKey})` : "Build agent routing index",
1384
1488
  passed: false,
@@ -1393,13 +1497,9 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1393
1497
  profile = [...routingContext.profiles.values()][0];
1394
1498
  const unionedTools = /* @__PURE__ */ new Set();
1395
1499
  for (const p of routingContext.profiles.values()) {
1396
- for (const t of normalizeAgentToolNames(p.tools) ?? []) unionedTools.add(t);
1397
- }
1398
- if (!options.agentTools) {
1399
- options = { ...options, agentTools: [...unionedTools], _profile: profile };
1400
- } else if (profile && !options._profile) {
1401
- options = { ...options, _profile: profile };
1500
+ for (const t of (0, import_agent_routing.normalizeAgentToolNames)(p.tools) ?? []) unionedTools.add(t);
1402
1501
  }
1502
+ options = { ...options, agentTools: [...unionedTools], _profile: profile };
1403
1503
  } else {
1404
1504
  const clientResolutions = agentUrls.map((url) => (0, import_client.getOrCreateClientResolution)(url, options));
1405
1505
  clients = clientResolutions.map((r) => r.client);
@@ -1412,7 +1512,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1412
1512
  return buildDiscoveryFailedResult(agentUrls, storyboard, discovered.step);
1413
1513
  }
1414
1514
  profile = discovered.profile;
1415
- const profileTools = normalizeAgentToolNames(profile?.tools);
1515
+ const profileTools = (0, import_agent_routing.normalizeAgentToolNames)(profile?.tools);
1416
1516
  if (!options.agentTools && profileTools) {
1417
1517
  options = { ...options, agentTools: profileTools, _profile: profile };
1418
1518
  } else if (profile && !options._profile) {
@@ -1420,7 +1520,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1420
1520
  }
1421
1521
  } else {
1422
1522
  profile = options._profile;
1423
- const profileTools = normalizeAgentToolNames(profile?.tools);
1523
+ const profileTools = (0, import_agent_routing.normalizeAgentToolNames)(profile?.tools);
1424
1524
  if (!options.agentTools && profileTools) {
1425
1525
  options = { ...options, agentTools: profileTools, _profile: profile };
1426
1526
  } else if (!options.agentTools && typeof clients[0]?.getAgentInfo === "function") {
@@ -1429,7 +1529,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1429
1529
  return buildDiscoveryFailedResult(agentUrls, storyboard, discovered.step);
1430
1530
  }
1431
1531
  profile = discovered.profile;
1432
- const discoveredTools = normalizeAgentToolNames(profile?.tools);
1532
+ const discoveredTools = (0, import_agent_routing.normalizeAgentToolNames)(profile?.tools);
1433
1533
  if (discoveredTools) {
1434
1534
  options = { ...options, agentTools: discoveredTools, _profile: profile };
1435
1535
  } else if (profile && !options._profile) {
@@ -1438,9 +1538,126 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1438
1538
  }
1439
1539
  }
1440
1540
  }
1541
+ if (preSeeded === void 0) {
1542
+ const resetTargets = routingContext && options.agents ? [...routingContext.profiles.entries()].map(([key, profile2]) => ({
1543
+ client: routingContext.clients.get(key),
1544
+ options: (0, import_agent_routing.routedAgentOptions)(options.agents[key], options, profile2)
1545
+ })) : clients.map((client) => ({ client, options }));
1546
+ const resetFailure = await resetControllerStates(resetTargets, storyboard);
1547
+ if (resetFailure) {
1548
+ if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
1549
+ return buildDiscoveryFailedResult(agentUrls, storyboard, resetFailure);
1550
+ }
1551
+ }
1552
+ const allRequires = resolveStoryboardRequires(storyboard, options);
1553
+ let dispatch = routingContext && options.agents ? createRoutingDispatcher(routingContext, options, options.agents) : createDispatcher(agentUrls, clients, "round-robin", dispatchOffset, profile);
1554
+ const routedStepCapabilitySkips = /* @__PURE__ */ new Map();
1555
+ const routedPhaseCapabilitySkips = /* @__PURE__ */ new Map();
1556
+ const routedStepRequirements = /* @__PURE__ */ new Map();
1557
+ const routedRootCapabilitySkips = [];
1558
+ const routedRootRequirementSkips = [];
1559
+ const routedControllerRoutes = /* @__PURE__ */ new Map();
1560
+ const routedErrors = /* @__PURE__ */ new Map();
1561
+ const reportedRoutingErrors = /* @__PURE__ */ new Set();
1562
+ let context = { ...storyboard.context, ...options.context };
1563
+ const routingFailedStep = (step, phaseId, err) => {
1564
+ const detail = (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
1565
+ err instanceof import_agent_routing.RoutingError ? err.message : err?.message ?? String(err)
1566
+ );
1567
+ const failedAgentKey = step.agent ?? options.default_agent;
1568
+ const failedAgentUrl = failedAgentKey ? options.agents?.[failedAgentKey]?.url : void 0;
1569
+ const failedAgentIndex = failedAgentKey ? Object.keys(options.agents ?? {}).indexOf(failedAgentKey) : -1;
1570
+ return {
1571
+ storyboard_id: storyboard.id,
1572
+ step_id: step.id,
1573
+ phase_id: phaseId,
1574
+ title: step.title,
1575
+ task: step.task,
1576
+ passed: false,
1577
+ duration_ms: 0,
1578
+ validations: [],
1579
+ context,
1580
+ error: detail,
1581
+ ...failedAgentUrl && { agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(failedAgentUrl) },
1582
+ ...failedAgentIndex >= 0 && { agent_index: failedAgentIndex + 1 },
1583
+ extraction: { path: "none" }
1584
+ };
1585
+ };
1586
+ if (routingContext) {
1587
+ for (const phase of storyboard.phases) {
1588
+ for (const step of phase.steps) {
1589
+ if (step.task === import_loader.VALIDATION_ONLY_TASK) continue;
1590
+ try {
1591
+ const selected = dispatch.nextFor(step);
1592
+ const selectedOptions = selected.options;
1593
+ const rootDetail = evaluateStoryboardCapabilityGates(
1594
+ storyboard,
1595
+ selected.profile,
1596
+ selectedOptions.agentTools,
1597
+ options.adcpVersion
1598
+ );
1599
+ let requirementSkip;
1600
+ if (rootDetail === null && allRequires.includes("request_signer")) {
1601
+ const requirement = await checkRequires(["request_signer"], storyboard, selectedOptions, {
1602
+ ...selected.profile,
1603
+ // Routed discovery is authoritative. A legacy agent without a
1604
+ // capabilities response did not opt into request signing.
1605
+ raw_capabilities: selected.profile.raw_capabilities ?? {}
1606
+ });
1607
+ if ("requirement" in requirement) {
1608
+ requirementSkip = requirement;
1609
+ routedStepRequirements.set(step, requirement.requirement);
1610
+ }
1611
+ }
1612
+ const phaseDetail = phase.requires_capability ? evaluateRequiresCapabilityGate(
1613
+ phase.requires_capability,
1614
+ selected.profile,
1615
+ selectedOptions.agentTools,
1616
+ options.adcpVersion
1617
+ ) : null;
1618
+ if (allRequires.includes("controller") && rootDetail === null && phaseDetail === null) {
1619
+ const routeKey = selected.agentKey ?? selected.agentUrl;
1620
+ const routeTools = selectedOptions.agentTools ?? [];
1621
+ const resolvedTask = (0, import_agent_routing.resolveTaskName)(step, selectedOptions) ?? step.task;
1622
+ const previous = routedControllerRoutes.get(routeKey);
1623
+ routedControllerRoutes.set(routeKey, {
1624
+ tools: routeTools,
1625
+ // A `comply_test_controller` step is the back-channel itself,
1626
+ // not the state under test, so it cannot vouch for the route it
1627
+ // is dispatched to. One state-exercising step is enough to mark
1628
+ // the route, whatever order the steps arrive in.
1629
+ stateExercising: (previous?.stateExercising ?? false) || resolvedTask !== "comply_test_controller"
1630
+ });
1631
+ }
1632
+ if (rootDetail !== null) routedRootCapabilitySkips.push(rootDetail);
1633
+ else if (requirementSkip) routedRootRequirementSkips.push(requirementSkip);
1634
+ const detail = rootDetail ?? requirementSkip?.detail ?? phaseDetail;
1635
+ if (detail !== null) routedStepCapabilitySkips.set(step, detail);
1636
+ } catch (error) {
1637
+ routedErrors.set(step, error);
1638
+ }
1639
+ }
1640
+ const callableSteps = phase.steps.filter((step) => step.task !== import_loader.VALIDATION_ONLY_TASK);
1641
+ if (callableSteps.length && callableSteps.every((step) => routedStepCapabilitySkips.has(step))) {
1642
+ routedPhaseCapabilitySkips.set(phase.id, routedStepCapabilitySkips.get(callableSteps[0]));
1643
+ }
1644
+ }
1645
+ }
1646
+ const routedPreflightAssignment = routingContext ? (step) => {
1647
+ if (routedStepCapabilitySkips.has(step)) return void 0;
1648
+ try {
1649
+ return dispatch.nextFor(step);
1650
+ } catch {
1651
+ return void 0;
1652
+ }
1653
+ } : void 0;
1441
1654
  const preflightNotices = collectCapabilityNotices(storyboard, options._profile);
1655
+ const callableStepCount = storyboard.phases.reduce(
1656
+ (n, phase) => n + phase.steps.filter((step) => step.task !== import_loader.VALIDATION_ONLY_TASK).length,
1657
+ 0
1658
+ );
1442
1659
  if (storyboardCapabilityPredicates(storyboard).length > 0) {
1443
- const unmetDetail = evaluateStoryboardCapabilityGates(storyboard, profile, options.agentTools, options.adcpVersion);
1660
+ const unmetDetail = routingContext ? routedRootCapabilitySkips.length > 0 && routedRootCapabilitySkips.length === callableStepCount ? routedRootCapabilitySkips[0] : null : evaluateStoryboardCapabilityGates(storyboard, profile, options.agentTools, options.adcpVersion);
1444
1661
  if (unmetDetail !== null) {
1445
1662
  if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
1446
1663
  return {
@@ -1449,21 +1666,71 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1449
1666
  };
1450
1667
  }
1451
1668
  }
1452
- const allRequires = resolveStoryboardRequires(storyboard, options);
1669
+ const establishedRequirements = /* @__PURE__ */ new Map();
1670
+ if (routingContext && allRequires.includes("controller")) {
1671
+ const decided = [...routedControllerRoutes].filter(([, route]) => route.stateExercising);
1672
+ const routes = decided.length > 0 ? decided : [...routedControllerRoutes];
1673
+ if (routedErrors.size > 0 || routes.length === 0) {
1674
+ establishedRequirements.set("controller", { status: "unknown" });
1675
+ } else if (routes.some(([, route]) => route.tools.includes("comply_test_controller"))) {
1676
+ establishedRequirements.set("controller", { status: "met" });
1677
+ } else {
1678
+ const exercised = routes.map(([key]) => key);
1679
+ const exercisedKeys = new Set(exercised);
1680
+ const peersWithController = [...routingContext.profiles.entries()].filter(
1681
+ ([key, peer]) => !exercisedKeys.has(key) && (0, import_agent_routing.normalizeAgentToolNames)(peer.tools)?.includes("comply_test_controller")
1682
+ ).map(([key]) => key);
1683
+ establishedRequirements.set("controller", {
1684
+ status: "unmet",
1685
+ requirement: "controller",
1686
+ detail: `Storyboard requires 'controller'; no route serving this storyboard's steps advertises comply_test_controller. Route(s) exercised: [${exercised.join(", ")}]. ` + (peersWithController.length ? `Agent(s) [${peersWithController.join(", ")}] in this map do advertise it, but a peer route's controller cannot seed another route's state \u2014 a run-level tool union does not grant it. ` : "") + `Add comply_test_controller to the route that owns the state, or pin the seeding step to that route with 'agent:'.`
1687
+ });
1688
+ }
1689
+ }
1690
+ if (routingContext && allRequires.includes("request_signer")) {
1691
+ establishedRequirements.set(
1692
+ "request_signer",
1693
+ routedErrors.size === 0 && routedRootRequirementSkips.length > 0 && routedRootRequirementSkips.length === callableStepCount ? { status: "unmet", ...routedRootRequirementSkips[0] } : { status: "unknown" }
1694
+ );
1695
+ }
1453
1696
  if (allRequires.length) {
1454
- const requirementCheck = await checkRequires(allRequires, storyboard, options, profile);
1697
+ const requirementCheck = await checkRequires(
1698
+ allRequires,
1699
+ storyboard,
1700
+ options,
1701
+ routingContext ? void 0 : profile,
1702
+ establishedRequirements
1703
+ );
1455
1704
  if ("requirement" in requirementCheck) {
1456
1705
  if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
1457
- return {
1458
- ...buildRequirementUnmetResult(agentUrls, storyboard, requirementCheck.requirement, requirementCheck.detail),
1459
- notices: preflightNotices
1460
- };
1706
+ const result2 = buildRequirementUnmetResult(
1707
+ agentUrls,
1708
+ storyboard,
1709
+ requirementCheck.requirement,
1710
+ requirementCheck.detail
1711
+ );
1712
+ for (const phase of storyboard.phases) {
1713
+ const failures = phase.steps.filter((step) => routedErrors.has(step)).map((step) => routingFailedStep(step, phase.id, routedErrors.get(step)));
1714
+ if (failures.length) {
1715
+ result2.phases.push({
1716
+ phase_id: phase.id,
1717
+ phase_title: phase.title,
1718
+ passed: false,
1719
+ steps: failures,
1720
+ duration_ms: 0
1721
+ });
1722
+ result2.failed_count += failures.length;
1723
+ result2.overall_passed = false;
1724
+ }
1725
+ }
1726
+ return { ...result2, notices: preflightNotices };
1461
1727
  }
1462
1728
  if (requirementCheck.preparedPublisherAuthProbes) {
1463
1729
  options = withPreparedTrustedMatchPublisherAuth(options, requirementCheck.preparedPublisherAuthProbes);
1730
+ if (routingContext && options.agents) dispatch = createRoutingDispatcher(routingContext, options, options.agents);
1464
1731
  }
1465
1732
  }
1466
- if (storyboard.required_any_of_tools?.length && options.agentTools) {
1733
+ if (storyboard.required_any_of_tools?.length && options.agentTools && !routingContext?.discoveryFailures.length && routedErrors.size === 0) {
1467
1734
  const agentTools = new Set(options.agentTools);
1468
1735
  const missing = storyboard.required_any_of_tools.find((family) => !family.tools.some((tool) => agentTools.has(tool)));
1469
1736
  if (missing) {
@@ -1475,8 +1742,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1475
1742
  };
1476
1743
  }
1477
1744
  }
1478
- if (storyboard.required_tools?.length && options.agentTools) {
1479
- const hasAnyRequired = storyboard.required_tools.some((t) => options.agentTools.includes(t));
1745
+ if (storyboard.required_tools?.length && options.agentTools && !routingContext?.discoveryFailures.length && routedErrors.size === 0) {
1746
+ const hasAnyRequired = (0, import_agent_routing.hasAnyRequiredTool)(storyboard.required_tools, options.agentTools);
1480
1747
  if (!hasAnyRequired) {
1481
1748
  if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
1482
1749
  return {
@@ -1489,18 +1756,26 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1489
1756
  };
1490
1757
  }
1491
1758
  }
1492
- let context = { ...storyboard.context, ...options.context };
1493
1759
  if (storyboard.context) (0, import_context.forwardAliasCache)(storyboard.context, context);
1494
1760
  if (options.context) (0, import_context.forwardAliasCache)(options.context, context);
1495
1761
  const contributions = /* @__PURE__ */ new Set();
1496
1762
  const contributionSources = /* @__PURE__ */ new Map();
1497
1763
  const priorStepResults = /* @__PURE__ */ new Map();
1498
1764
  const priorProbes = /* @__PURE__ */ new Map();
1765
+ const routedPriorProbes = /* @__PURE__ */ new Map();
1499
1766
  const contextProvenance = /* @__PURE__ */ new Map();
1500
1767
  const priorA2aEnvelopes = /* @__PURE__ */ new Map();
1501
1768
  const stepRequestStarts = /* @__PURE__ */ new Map();
1502
1769
  const responseDerivedNotApplicableContextKeys = /* @__PURE__ */ new Map();
1503
1770
  const capabilityUnavailableContextKeysByPhase = /* @__PURE__ */ new Map();
1771
+ const missingPrerequisiteContextKeysByPhase = /* @__PURE__ */ new Map();
1772
+ const recordUnavailableOutputs = (phaseId, step, keysByPhase = capabilityUnavailableContextKeysByPhase) => {
1773
+ const keys = keysByPhase.get(phaseId) ?? /* @__PURE__ */ new Set();
1774
+ for (const output of step.context_outputs ?? []) {
1775
+ if (output.key) keys.add(output.key);
1776
+ }
1777
+ keysByPhase.set(phaseId, keys);
1778
+ };
1504
1779
  const phaseResults = [];
1505
1780
  let passedCount = 0;
1506
1781
  let failedCount = 0;
@@ -1511,28 +1786,31 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1511
1786
  const branchSetsByPhaseId = resolveBranchSets(storyboard);
1512
1787
  const effectiveDependsOn = (phase, prior) => phase.depends_on ?? prior;
1513
1788
  const cascadeForPhase = (phase, prior) => {
1514
- if (phaseStatefulCascades.has(phase.id)) {
1515
- return { tripped: true, trigger: phaseStatefulCascades.get(phase.id) ?? null };
1516
- }
1517
1789
  const ownSpec = branchSetsByPhaseId.get(phase.id);
1518
1790
  const ownAnyOfBranchSet = ownSpec?.semantics === "any_of" ? ownSpec.id : void 0;
1519
- for (const depId of effectiveDependsOn(phase, prior)) {
1520
- if (ownAnyOfBranchSet !== void 0 && branchSetsByPhaseId.get(depId)?.id === ownAnyOfBranchSet) {
1791
+ let capabilityTrigger;
1792
+ let missingStateTrigger;
1793
+ for (const depId of [phase.id, ...effectiveDependsOn(phase, prior)]) {
1794
+ if (depId !== phase.id && ownAnyOfBranchSet !== void 0 && branchSetsByPhaseId.get(depId)?.id === ownAnyOfBranchSet) {
1521
1795
  continue;
1522
1796
  }
1523
1797
  if (phaseStatefulCascades.has(depId)) {
1524
- return { tripped: true, trigger: phaseStatefulCascades.get(depId) ?? null };
1798
+ const trigger2 = phaseStatefulCascades.get(depId) ?? null;
1799
+ if (trigger2 === null) return { tripped: true, trigger: null };
1800
+ if (trigger2.capabilityUnavailable) capabilityTrigger ??= trigger2;
1801
+ else missingStateTrigger ??= trigger2;
1525
1802
  }
1526
1803
  }
1527
- return { tripped: false };
1804
+ const trigger = missingStateTrigger ?? capabilityTrigger;
1805
+ return trigger ? { tripped: true, trigger } : { tripped: false };
1528
1806
  };
1529
- const capabilityUnavailableContextKeysForPhase = (phase, prior) => {
1530
- const keys = /* @__PURE__ */ new Set();
1807
+ const unavailableContextKeysForPhase = (phase, prior, keysByPhase = capabilityUnavailableContextKeysByPhase) => {
1808
+ const keys = new Set(keysByPhase.get(phase.id));
1531
1809
  const ownSpec = branchSetsByPhaseId.get(phase.id);
1532
1810
  const ownAnyOfBranchSet = ownSpec?.semantics === "any_of" ? ownSpec.id : void 0;
1533
1811
  for (const depId of effectiveDependsOn(phase, prior)) {
1534
1812
  if (ownAnyOfBranchSet !== void 0 && branchSetsByPhaseId.get(depId)?.id === ownAnyOfBranchSet) continue;
1535
- for (const key of capabilityUnavailableContextKeysByPhase.get(depId) ?? []) keys.add(key);
1813
+ for (const key of keysByPhase.get(depId) ?? []) keys.add(key);
1536
1814
  }
1537
1815
  return keys;
1538
1816
  };
@@ -1550,7 +1828,6 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1550
1828
  });
1551
1829
  if (webhookReceiver) (0, import_webhook_assertions.armWebhookAssertions)(storyboard, runnerVars, webhookReceiver);
1552
1830
  const allSteps = flattenSteps(storyboard);
1553
- const dispatch = routingContext && options.agents ? createRoutingDispatcher(routingContext, options, options.agents) : createDispatcher(agentUrls, clients, "round-robin", dispatchOffset, profile);
1554
1831
  const assertions = (0, import_assertions.resolveAssertions)(storyboard.invariants);
1555
1832
  (0, import_assertions.validateStepInvariants)(storyboard, assertions);
1556
1833
  const assertionContexts = /* @__PURE__ */ new Map();
@@ -1568,12 +1845,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1568
1845
  if (spec.onStart) await spec.onStart(assertionContexts.get(spec.id));
1569
1846
  }
1570
1847
  const hasExecutableSteps = storyboard.phases.some((p) => p.steps.length > 0);
1571
- const phaseCapabilitySkipDetails = collectPhaseCapabilitySkipDetails(
1572
- storyboard,
1573
- profile,
1574
- options.agentTools,
1575
- options.adcpVersion
1576
- );
1848
+ const phaseCapabilitySkipDetails = routingContext ? routedPhaseCapabilitySkips : collectPhaseCapabilitySkipDetails(storyboard, profile, options.agentTools, options.adcpVersion);
1577
1849
  const skipControllerSeedingForPhaseGates = allExecutablePhasesCapabilitySkipped(
1578
1850
  storyboard,
1579
1851
  phaseCapabilitySkipDetails
@@ -1604,7 +1876,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1604
1876
  storyboardRequiresRequestSigner: allRequires.includes("request_signer"),
1605
1877
  storyboardRequiresPublisherAuthRunner: storyboard.requires?.includes("trusted_match_publisher_auth_runner") === true
1606
1878
  },
1607
- preflightExcludedPhaseIds
1879
+ preflightExcludedPhaseIds,
1880
+ routedPreflightAssignment
1608
1881
  );
1609
1882
  let creativeAssetFixtureGapRecorded = false;
1610
1883
  if (!hasExecutableSteps) {
@@ -1649,22 +1922,36 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1649
1922
  let fixtureResolutionRecords;
1650
1923
  let fixtureCoverageGap;
1651
1924
  {
1652
- let fixtureSeedClient = clients[0];
1653
- let fixtureDiscoveryClient = clients[0];
1654
- if (routingContext && options.agents) {
1655
- const fixtureStep = (task) => ({
1656
- id: `__fixture_resolution_${task}__`,
1657
- title: `Fixture resolution via ${task}`,
1658
- task
1925
+ let seeding;
1926
+ try {
1927
+ seeding = creativeAssetFixtureGap || skipControllerSeedingForPhaseGates ? null : preSeeded !== void 0 ? preSeeded.result : await (0, import_seeding.runControllerSeeding)(
1928
+ clients[0],
1929
+ storyboard,
1930
+ options,
1931
+ context,
1932
+ clients[0],
1933
+ routingContext ? (task) => {
1934
+ if (!options.agentTools?.includes(task))
1935
+ return { client: clients[0], options: { ...options, agentTools: [] } };
1936
+ const selected = dispatch.nextFor({
1937
+ id: `__fixture_resolution_${task}__`,
1938
+ title: `Fixture resolution via ${task}`,
1939
+ task
1940
+ });
1941
+ return { client: selected.client, options: selected.options };
1942
+ } : void 0
1943
+ );
1944
+ } catch (error) {
1945
+ if (webhookReceiver) await webhookReceiver.close();
1946
+ if (!(error instanceof import_agent_routing.RoutingError)) throw error;
1947
+ if (!callerOwnsClients) await (0, import_protocols.closeScopedConnections)(options.protocol);
1948
+ return buildDiscoveryFailedResult(agentUrls, storyboard, {
1949
+ step: "Resolve fixture agent routes",
1950
+ passed: false,
1951
+ duration_ms: 0,
1952
+ error: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(error.message)
1659
1953
  });
1660
- if (options.agentTools?.includes("comply_test_controller")) {
1661
- fixtureSeedClient = dispatch.nextFor(fixtureStep("comply_test_controller")).client;
1662
- }
1663
- if (options.agentTools?.includes("get_products")) {
1664
- fixtureDiscoveryClient = dispatch.nextFor(fixtureStep("get_products")).client;
1665
- }
1666
1954
  }
1667
- const seeding = creativeAssetFixtureGap ? null : skipControllerSeedingForPhaseGates ? null : preSeeded !== void 0 ? preSeeded.result : await (0, import_seeding.runControllerSeeding)(fixtureSeedClient, storyboard, options, context, fixtureDiscoveryClient);
1668
1955
  if (seeding) {
1669
1956
  const attach = preSeeded === void 0 || preSeeded.attach;
1670
1957
  if (attach) {
@@ -1736,7 +2023,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1736
2023
  context,
1737
2024
  options,
1738
2025
  buildExecutionState(),
1739
- preflightExcludedPhaseIds
2026
+ preflightExcludedPhaseIds,
2027
+ routedPreflightAssignment
1740
2028
  );
1741
2029
  }
1742
2030
  for (const phase of storyboard.phases) {
@@ -1781,7 +2069,25 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1781
2069
  }
1782
2070
  const phaseCapabilitySkipDetail = phaseCapabilitySkipDetails.get(phase.id);
1783
2071
  if (phaseCapabilitySkipDetail !== void 0) {
1784
- const skippedSteps = buildPhaseCapabilitySkippedSteps(storyboard, phase, phaseCapabilitySkipDetail, context);
2072
+ const skippedSteps = routingContext ? phase.steps.map((step) => {
2073
+ const selected = step.task === import_loader.VALIDATION_ONLY_TASK ? void 0 : dispatch.nextFor(step);
2074
+ const skipped = buildPhaseCapabilitySkippedSteps(
2075
+ storyboard,
2076
+ { ...phase, steps: [step] },
2077
+ routedStepCapabilitySkips.get(step) ?? phaseCapabilitySkipDetail,
2078
+ context
2079
+ )[0];
2080
+ return {
2081
+ ...skipped,
2082
+ ...routedStepRequirements.has(step) && {
2083
+ skip: { ...skipped.skip, requirement: routedStepRequirements.get(step) }
2084
+ },
2085
+ ...selected && {
2086
+ agent_url: (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(selected.agentUrl),
2087
+ agent_index: selected.instanceIndex + 1
2088
+ }
2089
+ };
2090
+ }) : buildPhaseCapabilitySkippedSteps(storyboard, phase, phaseCapabilitySkipDetail, context);
1785
2091
  phaseResults.push({
1786
2092
  phase_id: phase.id,
1787
2093
  phase_title: phase.title,
@@ -1791,13 +2097,9 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1791
2097
  });
1792
2098
  skippedCount += skippedSteps.length;
1793
2099
  phaseCapabilitySkippedIds.add(phase.id);
1794
- const unavailableKeys = /* @__PURE__ */ new Set();
1795
2100
  for (const step of phase.steps) {
1796
- for (const output of step.context_outputs ?? []) {
1797
- if (output.key) unavailableKeys.add(output.key);
1798
- }
2101
+ recordUnavailableOutputs(phase.id, step);
1799
2102
  }
1800
- capabilityUnavailableContextKeysByPhase.set(phase.id, unavailableKeys);
1801
2103
  if (phase.steps.some((s) => s.stateful)) {
1802
2104
  phaseStatefulCascades.set(phase.id, {
1803
2105
  stepId: phase.steps.find((s) => s.stateful).id,
@@ -1811,6 +2113,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1811
2113
  const stepResults = [];
1812
2114
  let phasePassed = true;
1813
2115
  let phasePendingNotApplicable = null;
2116
+ let phaseInheritedCapabilityTrigger;
1814
2117
  let phaseEstablishedStatefulState = false;
1815
2118
  const phaseSubstitutes = /* @__PURE__ */ new Map();
1816
2119
  for (const declaringStep of phase.steps) {
@@ -1823,13 +2126,27 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1823
2126
  phaseSubstitutes.set(target, arr);
1824
2127
  }
1825
2128
  }
1826
- let phasePendingMissingTool = null;
2129
+ const phasePendingMissingTool = { trigger: null };
1827
2130
  const phaseRescuedTargets = /* @__PURE__ */ new Set();
1828
2131
  const phaseRescueSource = /* @__PURE__ */ new Map();
1829
2132
  const phaseStatefulStepIds = phase.steps.filter((s) => s.stateful).map((s) => s.id);
1830
2133
  let phaseAbsent = false;
2134
+ const routedOauthAbsent = /* @__PURE__ */ new Set();
1831
2135
  let presenceDetected = false;
2136
+ const routedOauthPresent = /* @__PURE__ */ new Set();
1832
2137
  if (shouldSkipPhase(phase, options, context)) {
2138
+ const skippedRoutingFailures = routingContext ? phase.steps.filter((step) => routedErrors.has(step)) : [];
2139
+ const skippedCapabilitySteps = routingContext ? phase.steps.filter((step) => routedStepCapabilitySkips.has(step)) : [];
2140
+ for (const step of skippedCapabilitySteps) recordUnavailableOutputs(phase.id, step);
2141
+ if (skippedRoutingFailures.length > 0) {
2142
+ for (const step of skippedRoutingFailures) {
2143
+ recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
2144
+ }
2145
+ if (skippedRoutingFailures.some((step) => step.stateful)) phaseStatefulCascades.set(phase.id, null);
2146
+ }
2147
+ if (skippedRoutingFailures.length > 0 || skippedCapabilitySteps.length > 0) {
2148
+ priorPhaseIds.push(phase.id);
2149
+ }
1833
2150
  phaseResults.push({
1834
2151
  phase_id: phase.id,
1835
2152
  phase_title: phase.title,
@@ -1849,7 +2166,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1849
2166
  context,
1850
2167
  options,
1851
2168
  buildExecutionState(),
1852
- preflightExcludedPhaseIds
2169
+ preflightExcludedPhaseIds,
2170
+ routedPreflightAssignment
1853
2171
  );
1854
2172
  if (creativeAssetFixtureGap?.target.phaseId === phase.id) {
1855
2173
  const gapStep = buildCreativeAssetFixtureUnavailableStep(
@@ -1875,7 +2193,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1875
2193
  continue;
1876
2194
  }
1877
2195
  }
1878
- if (!phaseAbsent && phaseContainsOauthMetadataProbe(phase) && !agentAdvertisesOauth(profile)) {
2196
+ if (!routingContext && phaseContainsOauthMetadataProbe(phase) && !agentAdvertisesOauth(profile)) {
1879
2197
  phaseAbsent = true;
1880
2198
  }
1881
2199
  context = { ...context };
@@ -1917,9 +2235,66 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1917
2235
  skippedCount += cascadeSteps.length;
1918
2236
  continue;
1919
2237
  }
2238
+ const recordHardPrerequisiteFailure = (step, realFailure = false) => {
2239
+ if (realFailure) {
2240
+ phaseStatefulCascades.set(phase.id, null);
2241
+ } else if (!phaseStatefulCascades.has(phase.id) || phaseStatefulCascades.get(phase.id)?.capabilityUnavailable === true) {
2242
+ phaseStatefulCascades.set(phase.id, { stepId: step.id, reason: "prerequisite_failed" });
2243
+ }
2244
+ };
2245
+ const recordHardMissingState = (step, result2) => {
2246
+ const substitutes = phaseSubstitutes.get(step.id);
2247
+ if (substitutes && substitutes.length > 0) {
2248
+ if (phasePendingMissingTool.trigger === null) {
2249
+ phasePendingMissingTool.trigger = {
2250
+ stepId: step.id,
2251
+ reason: result2.skip_reason ?? "missing_tool",
2252
+ substitutes
2253
+ };
2254
+ }
2255
+ } else {
2256
+ const hasStatefulPeers = phaseStatefulStepIds.length > 1;
2257
+ if (hasStatefulPeers && !phaseStatefulCascades.has(phase.id)) {
2258
+ phaseStatefulCascades.set(phase.id, {
2259
+ stepId: step.id,
2260
+ reason: result2.skip_reason ?? "missing_tool"
2261
+ });
2262
+ } else if (!hasStatefulPeers && result2.skip) {
2263
+ result2.skip = {
2264
+ ...result2.skip,
2265
+ detail: result2.skip.detail + soleStatefulExemptionDetail(phase.id)
2266
+ };
2267
+ }
2268
+ }
2269
+ };
1920
2270
  for (const step of phase.steps) {
1921
2271
  options.signal?.throwIfAborted();
1922
- if (phaseAbsent) {
2272
+ if (routingContext && step.task === import_loader.VALIDATION_ONLY_TASK) {
2273
+ const result3 = validationOnlyCoverageGap(step, phase.id, context, allSteps, runnerVars, storyboard.id);
2274
+ stepResults.push(result3);
2275
+ priorStepResults.set(step.id, result3);
2276
+ skippedCount++;
2277
+ continue;
2278
+ }
2279
+ let assignment;
2280
+ try {
2281
+ if (routingContext) assignment = dispatch.nextFor(step);
2282
+ } catch (err) {
2283
+ const failed = routingFailedStep(step, phase.id, err);
2284
+ reportedRoutingErrors.add(step);
2285
+ stepResults.push(failed);
2286
+ countedAsFailed.add(failed);
2287
+ priorStepResults.set(step.id, failed);
2288
+ failedCount++;
2289
+ phasePassed = false;
2290
+ recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
2291
+ if (step.stateful) phaseStatefulCascades.set(phase.id, null);
2292
+ continue;
2293
+ }
2294
+ if (routingContext && assignment && phaseContainsOauthMetadataProbe(phase) && !agentAdvertisesOauth(assignment.profile)) {
2295
+ routedOauthAbsent.add(assignment.instanceIndex);
2296
+ }
2297
+ if ((phaseAbsent || assignment && routedOauthAbsent.has(assignment.instanceIndex)) && !routedStepCapabilitySkips.has(step)) {
1923
2298
  const cascadeResult = {
1924
2299
  storyboard_id: storyboard.id,
1925
2300
  step_id: step.id,
@@ -1940,21 +2315,25 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1940
2315
  skippedCount++;
1941
2316
  continue;
1942
2317
  }
2318
+ const selectedOptions = assignment?.options ?? options;
2319
+ const routedCapabilityDetail = routedStepCapabilitySkips.get(step);
1943
2320
  const cascade = step.stateful ? cascadeForPhase(phase, priorPhaseIds) : { tripped: false };
1944
- if (cascade.tripped && step.stateful) {
1945
- const resolvedTask = resolveTaskName(step, options);
1946
- if (options.agentTools && resolvedTask && !options.agentTools.includes(resolvedTask)) {
1947
- const toolDetail = `Agent did not advertise tool "${resolvedTask}"; agent tools: [${options.agentTools.join(", ")}].`;
2321
+ if (cascade.tripped && step.stateful && routedCapabilityDetail === void 0) {
2322
+ const resolvedTask = (0, import_agent_routing.resolveTaskName)(step, selectedOptions);
2323
+ const missingTool = selectedOptions.agentTools && (routingContext && step.requires_tool && !selectedOptions.agentTools.includes(step.requires_tool) ? step.requires_tool : resolvedTask && resolvedTask !== import_types.MCP_SESSION_PROBE_TASK && !selectedOptions.agentTools.includes(resolvedTask) ? resolvedTask : void 0);
2324
+ if (missingTool) {
2325
+ const missingReason = routingContext && missingTool === "comply_test_controller" ? "missing_test_controller" : "missing_tool";
2326
+ const toolDetail = `Agent did not advertise tool "${missingTool}"; agent tools: [${selectedOptions.agentTools.join(", ")}].`;
1948
2327
  const missingToolResult = {
1949
2328
  storyboard_id: storyboard.id,
1950
2329
  step_id: step.id,
1951
2330
  phase_id: phase.id,
1952
2331
  title: step.title,
1953
- task: resolvedTask,
2332
+ task: resolvedTask ?? step.task,
1954
2333
  passed: true,
1955
2334
  skipped: true,
1956
- skip_reason: "missing_tool",
1957
- skip: buildSkip("missing_tool", toolDetail),
2335
+ skip_reason: missingReason,
2336
+ skip: buildSkip(missingReason, toolDetail),
1958
2337
  duration_ms: 0,
1959
2338
  validations: [],
1960
2339
  context,
@@ -1962,12 +2341,42 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1962
2341
  };
1963
2342
  stepResults.push(missingToolResult);
1964
2343
  priorStepResults.set(step.id, missingToolResult);
2344
+ if (routingContext) {
2345
+ recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
2346
+ recordHardMissingState(step, missingToolResult);
2347
+ }
1965
2348
  skippedCount++;
1966
2349
  continue;
1967
2350
  }
1968
2351
  const trigger = cascade.trigger;
1969
- const detail = trigger ? trigger.substitution_chain ? `Skipped: prior stateful step "${trigger.stepId}" skipped (${trigger.reason}); ${trigger.substitution_chain}; state never materialized.` : `Skipped: prior stateful step "${trigger.stepId}" skipped (${trigger.reason}); state never materialized.` : "Skipped: prior stateful step failed.";
1970
- const capabilityUnavailable = trigger?.capabilityUnavailable === true;
2352
+ let detail = trigger ? trigger.substitution_chain ? `Skipped: prior stateful step "${trigger.stepId}" skipped (${trigger.reason}); ${trigger.substitution_chain}; state never materialized.` : `Skipped: prior stateful step "${trigger.stepId}" skipped (${trigger.reason}); state never materialized.` : "Skipped: prior stateful step failed.";
2353
+ let capabilityUnavailable = trigger?.capabilityUnavailable === true;
2354
+ if (capabilityUnavailable && routingContext && !import_trusted_match_publisher_auth.TRUSTED_MATCH_PUBLISHER_AUTH_TASKS.has(step.task) && !import_probes.PROBE_TASKS.has(step.task) && !import_webhook_assertions.WEBHOOK_ASSERTION_TASKS.has(step.task) && step.task !== REPLAY_WEBHOOK_VECTOR_TASK && (!step.requires_contract || (selectedOptions.contracts ?? []).includes(step.requires_contract))) {
2355
+ const hardKeys = unavailableContextKeysForPhase(phase, priorPhaseIds, missingPrerequisiteContextKeysByPhase);
2356
+ if (hardKeys.size > 0) {
2357
+ const effectiveRequest = buildEffectiveStepRequest(
2358
+ { ...step, task: resolvedTask ?? step.task },
2359
+ context,
2360
+ selectedOptions,
2361
+ buildExecutionState(assignment?.agentUrl, assignment?.profile)
2362
+ );
2363
+ const missingKeys = /* @__PURE__ */ new Set([
2364
+ ...(effectiveRequest.ok ? findUnresolvedContextVars(effectiveRequest.request) : []).filter((v) => hardKeys.has(v.key)).map((v) => v.key),
2365
+ ...(step.context_inputs ?? []).filter((input) => !(input.key in context) && hardKeys.has(input.key)).map((input) => input.key)
2366
+ ]);
2367
+ if (missingKeys.size > 0) {
2368
+ capabilityUnavailable = false;
2369
+ detail = `Skipped: context required from a failed or unavailable prerequisite is missing: ${[...missingKeys].join(", ")}.`;
2370
+ }
2371
+ }
2372
+ }
2373
+ if (capabilityUnavailable) {
2374
+ recordUnavailableOutputs(phase.id, step);
2375
+ if (routingContext) phaseInheritedCapabilityTrigger ??= trigger ?? void 0;
2376
+ } else if (routingContext) {
2377
+ recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
2378
+ recordHardPrerequisiteFailure(step, trigger === null);
2379
+ }
1971
2380
  stepResults.push({
1972
2381
  storyboard_id: storyboard.id,
1973
2382
  step_id: step.id,
@@ -1995,46 +2404,47 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
1995
2404
  skippedCount++;
1996
2405
  continue;
1997
2406
  }
1998
- let assignment;
1999
- try {
2000
- assignment = dispatch.nextFor(step);
2001
- } catch (err) {
2002
- const detail = err instanceof import_agent_routing.RoutingError ? err.message : err?.message ?? String(err);
2003
- const failed = {
2004
- storyboard_id: storyboard.id,
2005
- step_id: step.id,
2006
- phase_id: phase.id,
2007
- title: step.title,
2008
- task: step.task,
2009
- passed: false,
2010
- duration_ms: 0,
2011
- validations: [],
2012
- context,
2013
- error: detail,
2014
- extraction: { path: "none" }
2015
- };
2016
- stepResults.push(failed);
2017
- priorStepResults.set(step.id, failed);
2018
- failedCount++;
2019
- phasePassed = false;
2020
- continue;
2021
- }
2407
+ assignment ??= dispatch.nextFor(step);
2022
2408
  const stepExecutionState = buildExecutionState(assignment.agentUrl, assignment.profile);
2023
- stepExecutionState.capabilityUnavailableContextKeys = capabilityUnavailableContextKeysForPhase(
2024
- phase,
2025
- priorPhaseIds
2026
- );
2027
- const rawResult = await executeStep(
2409
+ if (routingContext) {
2410
+ let probes = routedPriorProbes.get(assignment.instanceIndex);
2411
+ if (!probes) {
2412
+ probes = /* @__PURE__ */ new Map();
2413
+ routedPriorProbes.set(assignment.instanceIndex, probes);
2414
+ }
2415
+ stepExecutionState.priorProbes = probes;
2416
+ stepExecutionState.allowPriorProbeFallback = false;
2417
+ }
2418
+ stepExecutionState.capabilityUnavailableContextKeys = unavailableContextKeysForPhase(phase, priorPhaseIds);
2419
+ if (routingContext) {
2420
+ stepExecutionState.missingPrerequisiteContextKeys = unavailableContextKeysForPhase(
2421
+ phase,
2422
+ priorPhaseIds,
2423
+ missingPrerequisiteContextKeysByPhase
2424
+ );
2425
+ }
2426
+ const rawResult = routedCapabilityDetail !== void 0 ? buildPhaseCapabilitySkippedSteps(
2427
+ storyboard,
2428
+ { ...phase, steps: [step] },
2429
+ routedCapabilityDetail,
2430
+ context
2431
+ )[0] : await executeStep(
2028
2432
  assignment.client,
2029
2433
  step,
2030
2434
  storyboard.id,
2031
2435
  phase.id,
2032
2436
  context,
2033
2437
  allSteps,
2034
- options,
2438
+ assignment.options ?? options,
2035
2439
  stepExecutionState
2036
2440
  );
2037
2441
  const result2 = { ...rawResult, storyboard_id: storyboard.id };
2442
+ if (routedCapabilityDetail !== void 0 || result2.skip_reason === "capability_prerequisite_unavailable") {
2443
+ recordUnavailableOutputs(phase.id, step);
2444
+ }
2445
+ if (routedCapabilityDetail !== void 0 && routedStepRequirements.has(step)) {
2446
+ result2.skip = { ...result2.skip, requirement: routedStepRequirements.get(step) };
2447
+ }
2038
2448
  if (isMultiInstance || useRouting) {
2039
2449
  result2.agent_url = (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(assignment.agentUrl);
2040
2450
  result2.agent_index = assignment.instanceIndex + 1;
@@ -2080,11 +2490,13 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2080
2490
  }
2081
2491
  if (step.task === "protected_resource_metadata") {
2082
2492
  if (result2.skipped && result2.skip_reason === "oauth_not_advertised") {
2083
- phaseAbsent = true;
2493
+ if (routingContext) routedOauthAbsent.add(assignment.instanceIndex);
2494
+ else phaseAbsent = true;
2084
2495
  } else {
2085
2496
  const status = result2.response?.status;
2086
2497
  if (typeof status === "number" && status >= 200 && status < 300) {
2087
- presenceDetected = true;
2498
+ if (routingContext) routedOauthPresent.add(assignment.instanceIndex);
2499
+ else presenceDetected = true;
2088
2500
  }
2089
2501
  }
2090
2502
  }
@@ -2100,34 +2512,26 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2100
2512
  if (result2.skipped) {
2101
2513
  skippedCount++;
2102
2514
  context = result2.context;
2515
+ const hardPrerequisite = isHardMissingStateSkipReason(result2.skip_reason) || result2.skip_reason === "prerequisite_failed";
2516
+ if (result2.skip_reason === "prerequisite_failed" && !result2.passed) phasePassed = false;
2517
+ if (routingContext && hardPrerequisite) {
2518
+ recordUnavailableOutputs(phase.id, step, missingPrerequisiteContextKeysByPhase);
2519
+ if (!result2.passed) {
2520
+ phasePassed = false;
2521
+ if (step.stateful) recordHardPrerequisiteFailure(step);
2522
+ }
2523
+ }
2103
2524
  if (step.stateful) {
2104
2525
  if (isHardMissingStateSkipReason(result2.skip_reason)) {
2105
- const substitutes = phaseSubstitutes.get(step.id);
2106
- if (substitutes && substitutes.length > 0) {
2107
- if (phasePendingMissingTool === null) {
2108
- phasePendingMissingTool = {
2109
- stepId: step.id,
2110
- reason: result2.skip_reason ?? "missing_tool",
2111
- substitutes
2112
- };
2113
- }
2114
- } else {
2115
- const hasStatefulPeers = phaseStatefulStepIds.length > 1;
2116
- if (hasStatefulPeers && !phaseStatefulCascades.has(phase.id)) {
2117
- phaseStatefulCascades.set(phase.id, {
2118
- stepId: step.id,
2119
- reason: result2.skip_reason ?? "missing_tool"
2120
- });
2121
- } else if (!hasStatefulPeers && result2.skip) {
2122
- result2.skip = {
2123
- ...result2.skip,
2124
- detail: result2.skip.detail + soleStatefulExemptionDetail(phase.id)
2125
- };
2126
- }
2127
- }
2128
- } else if (result2.skip_reason === "not_applicable") {
2129
- if (phasePendingNotApplicable === null) {
2130
- phasePendingNotApplicable = { stepId: step.id, reason: "not_applicable" };
2526
+ recordHardMissingState(step, result2);
2527
+ } else if (result2.skip_reason === "not_applicable" || result2.skip_reason === "capability_prerequisite_unavailable") {
2528
+ const capabilityUnavailable = routedCapabilityDetail !== void 0 || result2.skip_reason === "capability_prerequisite_unavailable";
2529
+ if (phasePendingNotApplicable === null || phasePendingNotApplicable.capabilityUnavailable === true && !capabilityUnavailable) {
2530
+ phasePendingNotApplicable = {
2531
+ stepId: step.id,
2532
+ reason: result2.skip_reason,
2533
+ ...capabilityUnavailable ? { capabilityUnavailable: true } : {}
2534
+ };
2131
2535
  }
2132
2536
  }
2133
2537
  }
@@ -2149,7 +2553,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2149
2553
  }
2150
2554
  } else {
2151
2555
  phasePassed = false;
2152
- if (!phase.optional || presenceDetected) {
2556
+ if (!phase.optional || (routingContext ? routedOauthPresent.has(assignment.instanceIndex) : presenceDetected)) {
2153
2557
  failedCount++;
2154
2558
  countedAsFailed.add(result2);
2155
2559
  }
@@ -2171,7 +2575,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2171
2575
  context,
2172
2576
  options,
2173
2577
  stepExecutionState,
2174
- preflightExcludedPhaseIds
2578
+ preflightExcludedPhaseIds,
2579
+ routedPreflightAssignment
2175
2580
  );
2176
2581
  }
2177
2582
  if (creativeAssetFixtureGap) {
@@ -2194,6 +2599,15 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2194
2599
  }
2195
2600
  }
2196
2601
  }
2602
+ if (phasePendingMissingTool.trigger && !phaseRescuedTargets.has(phasePendingMissingTool.trigger.stepId) && !phaseStatefulCascades.has(phase.id)) {
2603
+ const subs = phasePendingMissingTool.trigger.substitutes;
2604
+ const subsList = subs.length === 1 ? `"${subs[0]}"` : subs.map((s) => `"${s}"`).join(", ");
2605
+ phaseStatefulCascades.set(phase.id, {
2606
+ stepId: phasePendingMissingTool.trigger.stepId,
2607
+ reason: phasePendingMissingTool.trigger.reason,
2608
+ substitution_chain: `declared substitute ${subsList} did not pass`
2609
+ });
2610
+ }
2197
2611
  if (phasePendingNotApplicable && !phaseEstablishedStatefulState && !phaseStatefulCascades.has(phase.id)) {
2198
2612
  const hadStatefulPeers = phaseStatefulStepIds.some((id) => id !== phasePendingNotApplicable.stepId);
2199
2613
  if (hadStatefulPeers) {
@@ -2208,14 +2622,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2208
2622
  }
2209
2623
  }
2210
2624
  }
2211
- if (phasePendingMissingTool && !phaseRescuedTargets.has(phasePendingMissingTool.stepId) && !phaseStatefulCascades.has(phase.id)) {
2212
- const subs = phasePendingMissingTool.substitutes;
2213
- const subsList = subs.length === 1 ? `"${subs[0]}"` : subs.map((s) => `"${s}"`).join(", ");
2214
- phaseStatefulCascades.set(phase.id, {
2215
- stepId: phasePendingMissingTool.stepId,
2216
- reason: phasePendingMissingTool.reason,
2217
- substitution_chain: `declared substitute ${subsList} did not pass`
2218
- });
2625
+ if (phaseInheritedCapabilityTrigger && !phaseStatefulCascades.has(phase.id)) {
2626
+ phaseStatefulCascades.set(phase.id, phaseInheritedCapabilityTrigger);
2219
2627
  }
2220
2628
  for (const target of phaseRescuedTargets) {
2221
2629
  const sourceId = phaseRescueSource.get(target);
@@ -2236,6 +2644,27 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2236
2644
  });
2237
2645
  priorPhaseIds.push(phase.id);
2238
2646
  }
2647
+ for (const phase of storyboard.phases) {
2648
+ const result2 = phaseResults.find((p) => p.phase_id === phase.id);
2649
+ for (const step of phase.steps) {
2650
+ if (!routedErrors.has(step) || reportedRoutingErrors.has(step)) continue;
2651
+ const failed = routingFailedStep(step, phase.id, routedErrors.get(step));
2652
+ const existingIndex = result2.steps.findIndex((row) => row.step_id === step.id);
2653
+ if (existingIndex >= 0) {
2654
+ const existing = result2.steps[existingIndex];
2655
+ if (existing.skipped) skippedCount--;
2656
+ if (countedAsFailed.delete(existing)) failedCount--;
2657
+ result2.steps[existingIndex] = failed;
2658
+ } else {
2659
+ result2.steps.push(failed);
2660
+ }
2661
+ reportedRoutingErrors.add(step);
2662
+ countedAsFailed.add(failed);
2663
+ result2.passed = false;
2664
+ priorStepResults.set(step.id, failed);
2665
+ failedCount++;
2666
+ }
2667
+ }
2239
2668
  const branchSetDelta = creativeAssetFixtureGap ? { skippedDelta: 0 } : applyBranchSetGrading(
2240
2669
  storyboard.phases,
2241
2670
  phaseResults,
@@ -2272,8 +2701,9 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2272
2701
  const phaseResult = phaseResults.find((p) => p.phase_id === phaseDef.id);
2273
2702
  return !!phaseResult && phaseResult.passed && phaseResult.steps.some((s) => !s.skipped && s.passed);
2274
2703
  });
2275
- const requiredPhasesPassed = !hasExecutableSteps || requiredPhaseHasExecutedPass || requiredPhasesNonFailingSkipped || failedCount === 0 && requiredPhasesCoveredByCapabilityGates;
2704
+ const requiredPhasesPassed = !hasExecutableSteps || requiredPhaseDefs.every((phaseDef) => phaseResults.find((p) => p.phase_id === phaseDef.id)?.passed === true) && (requiredPhaseHasExecutedPass || requiredPhasesNonFailingSkipped || failedCount === 0 && requiredPhasesCoveredByCapabilityGates);
2276
2705
  const storyboardWideFixtureUnavailable = (seedingUnsupported || fixtureUnsatisfied || creativeAssetFixtureGap !== void 0) && failedCount === 0;
2706
+ const hasUnverifiedCoverage = signingCoverageUnverified(phaseResults.flatMap((phase) => phase.steps));
2277
2707
  if (seedingPhaseResult) phaseResults.unshift(seedingPhaseResult);
2278
2708
  const schemasUsed = collectSchemasUsed(phaseResults);
2279
2709
  const strictSummary = summarizeStrictValidation(phaseResults);
@@ -2297,7 +2727,7 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2297
2727
  Object.entries(routingContext.agentMap).map(([specialism, url]) => [specialism, (0, import_oauth_metadata_graph.redactOAuthUrlForOutput)(url)])
2298
2728
  )
2299
2729
  },
2300
- overall_passed: failedCount === 0 && (requiredPhasesPassed || storyboardWideFixtureUnavailable) && !assertionsFailed,
2730
+ overall_passed: failedCount === 0 && (requiredPhasesPassed || storyboardWideFixtureUnavailable) && !assertionsFailed && !hasUnverifiedCoverage,
2301
2731
  phases: phaseResults,
2302
2732
  context,
2303
2733
  total_duration_ms: Date.now() - start,
@@ -2347,9 +2777,17 @@ async function runMultiPass(agentUrls, storyboard, options) {
2347
2777
  options = {
2348
2778
  ...options,
2349
2779
  _profile: preSeedProfile,
2350
- ...options.agentTools ? {} : { agentTools: normalizeAgentToolNames(preSeedProfile.tools) }
2780
+ ...options.agentTools ? {} : { agentTools: (0, import_agent_routing.normalizeAgentToolNames)(preSeedProfile.tools) }
2351
2781
  };
2352
2782
  }
2783
+ const resetFailure = await resetControllerStates(
2784
+ preSeedClients.map((client) => ({ client, options })),
2785
+ storyboard
2786
+ );
2787
+ if (resetFailure) {
2788
+ await (0, import_protocols.closeScopedConnections)(options.protocol);
2789
+ return buildDiscoveryFailedResult(agentUrls, storyboard, resetFailure);
2790
+ }
2353
2791
  if (storyboardCapabilityPredicates(storyboard).length > 0) {
2354
2792
  const unmetDetail = evaluateStoryboardCapabilityGates(
2355
2793
  storyboard,
@@ -2594,7 +3032,7 @@ async function runStoryboardStepBody(agentUrl, storyboard, stepId, options) {
2594
3032
  options = {
2595
3033
  ...options,
2596
3034
  ...!options._profile && { _profile: profile },
2597
- ...!options.agentTools && { agentTools: normalizeAgentToolNames(profile.tools) }
3035
+ ...!options.agentTools && { agentTools: (0, import_agent_routing.normalizeAgentToolNames)(profile.tools) }
2598
3036
  };
2599
3037
  }
2600
3038
  } else {
@@ -2682,6 +3120,38 @@ async function runStoryboardStepBody(agentUrl, storyboard, stepId, options) {
2682
3120
  if (ownsWebhookReceiver && webhookReceiver) await webhookReceiver.close();
2683
3121
  return { ...result, contributions: Array.from(contributions) };
2684
3122
  }
3123
+ function unresolvedStepContextVars(step, request, context, runState) {
3124
+ const unavailableInputs = (step.context_inputs ?? []).filter(
3125
+ (input) => !(input.key in context) && (runState.capabilityUnavailableContextKeys?.has(input.key) === true || runState.missingPrerequisiteContextKeys?.has(input.key) === true)
3126
+ );
3127
+ return [
3128
+ ...findUnresolvedContextVars(request),
3129
+ ...unavailableInputs.map((input) => ({ key: input.key, token: `$context.${input.key}` }))
3130
+ ];
3131
+ }
3132
+ function buildStepRequest(step, effectiveStep, context, options, runnerVars) {
3133
+ let request;
3134
+ if (options.request) {
3135
+ request = (0, import_context.injectContext)({ ...options.request }, context, runnerVars);
3136
+ } else if (step.expect_error && step.sample_request) {
3137
+ request = (0, import_context.injectContext)({ ...step.sample_request }, context, runnerVars);
3138
+ } else if ((0, import_request_builder.hasRequestEnricher)(effectiveStep.task)) {
3139
+ request = (0, import_request_builder.enrichRequest)(effectiveStep, context, options, runnerVars);
3140
+ } else if (step.sample_request) {
3141
+ request = (0, import_context.injectContext)({ ...step.sample_request }, context, runnerVars);
3142
+ } else {
3143
+ request = {};
3144
+ }
3145
+ if (step.context_inputs?.length) {
3146
+ request = (0, import_context.applyContextInputs)(request, step.context_inputs, context);
3147
+ }
3148
+ request = applyBrandInvariant(request, options, effectiveStep.task, { omit_account: step.omit_account });
3149
+ if (options.disable_sandbox === true) {
3150
+ request = applyDisableSandboxHint(request, effectiveStep.task);
3151
+ }
3152
+ request = applyIdempotencyInvariant(request, effectiveStep.task, step);
3153
+ return request;
3154
+ }
2685
3155
  async function executeStep(client, step, storyboardId, phaseId, context, allSteps, options, state) {
2686
3156
  const runState = state ?? {
2687
3157
  contributions: /* @__PURE__ */ new Set(),
@@ -2731,7 +3201,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2731
3201
  extraction: { path: "none", note: "test-kit contract not configured" }
2732
3202
  };
2733
3203
  }
2734
- const resolvedTask = resolveTaskName(step, options);
3204
+ const resolvedTask = (0, import_agent_routing.resolveTaskName)(step, options);
2735
3205
  if (!resolvedTask) {
2736
3206
  if (step.task === "$test_kit.auth.probe_task" && options.agentTools) {
2737
3207
  const detail = `Agent does not advertise an auth-required, read-only tool that accepts an empty request body; security auth probes are not applicable to tools [${options.agentTools.join(", ")}].`;
@@ -2785,6 +3255,9 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2785
3255
  extraction: { path: "none" }
2786
3256
  };
2787
3257
  }
3258
+ if (effectiveStep.task === import_types.MCP_SESSION_PROBE_TASK) {
3259
+ return executeProbeStep(client, effectiveStep, phaseId, context, allSteps, options, runState);
3260
+ }
2788
3261
  if (effectiveStep.task === "sync_accounts") {
2789
3262
  const rawCaps = options._profile?.raw_capabilities;
2790
3263
  if (rawCaps !== void 0) {
@@ -2830,47 +3303,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2830
3303
  extraction: { path: "none" }
2831
3304
  };
2832
3305
  }
2833
- let request;
2834
- if (options.request) {
2835
- request = (0, import_context.injectContext)({ ...options.request }, context, runState.runnerVars);
2836
- } else if (step.expect_error && step.sample_request) {
2837
- request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
2838
- } else if ((0, import_request_builder.hasRequestEnricher)(effectiveStep.task)) {
2839
- request = (0, import_request_builder.enrichRequest)(effectiveStep, context, options, runState.runnerVars);
2840
- } else if (step.sample_request) {
2841
- request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
2842
- } else {
2843
- request = {};
2844
- }
2845
- if (step.context_inputs?.length) {
2846
- request = (0, import_context.applyContextInputs)(request, step.context_inputs, context);
2847
- }
2848
- const unavailableContextInputs = (step.context_inputs ?? []).filter(
2849
- (input) => !(input.key in context) && runState.capabilityUnavailableContextKeys?.has(input.key) === true
2850
- );
2851
- if (unavailableContextInputs.length > 0) {
2852
- const detail = "Skipped: context required by a capability-gated phase is unavailable: " + unavailableContextInputs.map((input) => input.key).join(", ") + ".";
2853
- return {
2854
- step_id: step.id,
2855
- phase_id: phaseId,
2856
- title: step.title,
2857
- task: step.task,
2858
- passed: true,
2859
- skipped: true,
2860
- skip_reason: "capability_prerequisite_unavailable",
2861
- skip: buildSkip("not_applicable", detail),
2862
- duration_ms: 0,
2863
- validations: [],
2864
- context,
2865
- next: getNextStepPreview(step.id, allSteps, context, runState.runnerVars),
2866
- extraction: { path: "none" }
2867
- };
2868
- }
2869
- request = applyBrandInvariant(request, options, effectiveStep.task, { omit_account: step.omit_account });
2870
- if (options.disable_sandbox === true) {
2871
- request = applyDisableSandboxHint(request, effectiveStep.task);
2872
- }
2873
- request = applyIdempotencyInvariant(request, effectiveStep.task, step);
3306
+ let request = buildStepRequest(step, effectiveStep, context, options, runState.runnerVars);
2874
3307
  const fixtureBinding = applyFixtureBindingsSafely(request, effectiveStep.task, options, runState);
2875
3308
  if (!fixtureBinding.ok) {
2876
3309
  const next2 = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
@@ -2913,7 +3346,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2913
3346
  effectiveStep.task
2914
3347
  );
2915
3348
  }
2916
- const unresolvedContextVars = findUnresolvedContextVars(request);
3349
+ const unresolvedContextVars = unresolvedStepContextVars(step, request, context, runState);
2917
3350
  const unresolvedAssetDirectives = (0, import_creative_assets.findUnresolvedCreativeAssetDirectives)(request).map((path) => ({
2918
3351
  key: path,
2919
3352
  token: import_creative_assets.BUILD_ASSETS_FROM_FORMAT_DIRECTIVE
@@ -2922,11 +3355,14 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
2922
3355
  const hasCapabilityUnavailableContext = unresolvedContextVars.some(
2923
3356
  (v) => runState.capabilityUnavailableContextKeys?.has(v.key) === true
2924
3357
  );
2925
- if (unresolvedAssetDirectives.length > 0 || unresolvedContextVars.length > 0 && (!step.expect_error || hasCapabilityUnavailableContext)) {
3358
+ const hasMissingToolUnavailableContext = unresolvedContextVars.some(
3359
+ (v) => runState.missingPrerequisiteContextKeys?.has(v.key) === true
3360
+ );
3361
+ if (unresolvedAssetDirectives.length > 0 || unresolvedContextVars.length > 0 && (!step.expect_error || hasCapabilityUnavailableContext || hasMissingToolUnavailableContext)) {
2926
3362
  const next2 = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
2927
3363
  const responseDerivedDetails = unresolvedVars.map((v) => runState.responseDerivedNotApplicableContextKeys?.get(v.key)).filter((d) => typeof d === "string");
2928
- const allResponseDerived = responseDerivedDetails.length === unresolvedVars.length && responseDerivedDetails.length > 0;
2929
- const allCapabilityUnavailable = unresolvedContextVars.length === unresolvedVars.length && unresolvedContextVars.length > 0 && unresolvedContextVars.every((v) => runState.capabilityUnavailableContextKeys?.has(v.key) === true);
3364
+ const allResponseDerived = !hasMissingToolUnavailableContext && responseDerivedDetails.length === unresolvedVars.length && responseDerivedDetails.length > 0;
3365
+ const allCapabilityUnavailable = !hasMissingToolUnavailableContext && unresolvedContextVars.length === unresolvedVars.length && unresolvedContextVars.length > 0 && unresolvedContextVars.every((v) => runState.capabilityUnavailableContextKeys?.has(v.key) === true);
2930
3366
  const detail = allResponseDerived ? [...new Set(responseDerivedDetails)].join("; ") : allCapabilityUnavailable ? `Skipped: context required by a capability-gated phase is unavailable: ${unresolvedVars.map((v) => v.key).join(", ")}.` : `Skipped: unresolved context variables from prior steps: ${unresolvedVars.map((v) => v.key).join(", ")}.`;
2931
3367
  const synthesized = [];
2932
3368
  if (!allResponseDerived && !allCapabilityUnavailable) {
@@ -3792,6 +4228,9 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
3792
4228
  fetchFn: options.transport?.trustedFetchFn
3793
4229
  };
3794
4230
  let requestRecordOverride;
4231
+ let sessionProbeStage;
4232
+ let sessionProbeDetail;
4233
+ let sessionProbeTool;
3795
4234
  const contractsInScope = new Set(options.contracts ?? []);
3796
4235
  if (step.requires_contract) {
3797
4236
  if (!contractsInScope.has(step.requires_contract)) {
@@ -3873,10 +4312,48 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
3873
4312
  httpResult.skip_reason = "oauth_not_advertised";
3874
4313
  }
3875
4314
  } else if (step.task === "oauth_auth_server_metadata") {
3876
- const prior = runState.priorProbes.get("protected_resource_metadata") ?? findPriorProbe(runState.priorStepResults);
4315
+ const prior = runState.priorProbes.get("protected_resource_metadata") ?? (runState.allowPriorProbeFallback !== false ? findPriorProbe(runState.priorStepResults) : void 0);
3877
4316
  httpResult = await (0, import_probes.probeOauthAuthServerMetadata)(prior, probeOpts);
3878
4317
  } else if (step.task === "assert_contribution") {
3879
4318
  httpResult = void 0;
4319
+ } else if (step.task === import_types.MCP_SESSION_PROBE_TASK) {
4320
+ const plan = planMcpSessionSentinel(step, options, client, runState.agentUrl);
4321
+ if (plan.kind === "error") {
4322
+ httpResult = { url: runState.agentUrl, status: 0, headers: {}, body: null, error: plan.error };
4323
+ } else if (plan.kind === "skip") {
4324
+ httpResult = {
4325
+ url: runState.agentUrl,
4326
+ status: 0,
4327
+ headers: {},
4328
+ body: null,
4329
+ skipped: true,
4330
+ skip_reason: plan.reason,
4331
+ error: plan.detail
4332
+ };
4333
+ } else {
4334
+ const probe = await (0, import_probes.rawMcpSessionProbe)({
4335
+ agentUrl: runState.agentUrl,
4336
+ headers: plan.headers,
4337
+ toolName: plan.toolNames,
4338
+ control: plan.control,
4339
+ // Values the probe withholds but the run's ordinary steps do send, so
4340
+ // a stateful agent's echo cannot land them in this step's evidence.
4341
+ redactValues: runCredentialValues(options),
4342
+ allowPrivateIp: options.allow_http === true,
4343
+ // Honour run cancellation and cap each request well under the shared
4344
+ // 10 s `ssrfSafeFetch` default. The probe additionally bounds the
4345
+ // whole step — candidate walk included — with one shared request /
4346
+ // byte / wall-clock budget, so a tarpitting agent cannot multiply this
4347
+ // per-request cap by the length of its own tool list.
4348
+ ...options.signal && { signal: options.signal },
4349
+ timeoutMs: MCP_SESSION_PROBE_REQUEST_TIMEOUT_MS,
4350
+ ...options.transport?.trustedFetchFn && { fetchFn: options.transport.trustedFetchFn }
4351
+ });
4352
+ httpResult = probe.httpResult;
4353
+ sessionProbeStage = probe.stage;
4354
+ sessionProbeDetail = probe.detail;
4355
+ sessionProbeTool = probe.gradedTool;
4356
+ }
3880
4357
  } else if (step.task === "request_signing_probe") {
3881
4358
  httpResult = await (0, import_probe_dispatch.probeRequestSigningVector)(step.id, runState.agentUrl, options);
3882
4359
  } else if (step.task === "fetch_brand_jwks") {
@@ -3953,30 +4430,35 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
3953
4430
  };
3954
4431
  }
3955
4432
  const resolvedTargetRequest = targetRequestResult.request;
3956
- const unresolvedContextVars = findUnresolvedContextVars(resolvedTargetRequest);
4433
+ const advertisedTools = resolveAdvertisedTools(options);
4434
+ const routedPrerequisites = runState.missingPrerequisiteContextKeys !== void 0 && (!advertisedTools || advertisedTools.includes(rateLimitTrip.trip_target_task));
4435
+ const unresolvedContextVars = routedPrerequisites ? unresolvedStepContextVars(targetStep, resolvedTargetRequest, context, runState) : findUnresolvedContextVars(resolvedTargetRequest);
3957
4436
  const unresolvedAssetDirectives = (0, import_creative_assets.findUnresolvedCreativeAssetDirectives)(resolvedTargetRequest).map((path) => ({
3958
4437
  key: path,
3959
4438
  token: import_creative_assets.BUILD_ASSETS_FROM_FORMAT_DIRECTIVE
3960
4439
  }));
3961
4440
  const unresolvedVars = [...unresolvedContextVars, ...unresolvedAssetDirectives];
3962
- if (unresolvedAssetDirectives.length > 0 || unresolvedContextVars.length > 0 && !targetStep.expect_error) {
4441
+ const hardUnavailable = routedPrerequisites && unresolvedContextVars.some((v) => runState.missingPrerequisiteContextKeys?.has(v.key));
4442
+ const capabilityUnavailable = routedPrerequisites && unresolvedContextVars.some((v) => runState.capabilityUnavailableContextKeys?.has(v.key));
4443
+ if (unresolvedAssetDirectives.length > 0 || unresolvedContextVars.length > 0 && (!targetStep.expect_error || hardUnavailable || capabilityUnavailable)) {
3963
4444
  const next = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
3964
- const detail = `Skipped: unresolved context variables from rate_limit_trip.trip_target_sample_request: ${unresolvedVars.map((v) => v.key).join(", ")}.`;
4445
+ const allCapabilityUnavailable = capabilityUnavailable && !hardUnavailable && unresolvedAssetDirectives.length === 0 && unresolvedContextVars.every((v) => runState.capabilityUnavailableContextKeys?.has(v.key));
4446
+ const detail = allCapabilityUnavailable ? `Skipped: context required by a capability-gated phase is unavailable: ${unresolvedVars.map((v) => v.key).join(", ")}.` : `Skipped: unresolved context variables from rate_limit_trip.trip_target_sample_request: ${unresolvedVars.map((v) => v.key).join(", ")}.`;
3965
4447
  return {
3966
4448
  step_id: step.id,
3967
4449
  phase_id: phaseId,
3968
4450
  title: step.title,
3969
4451
  task: step.task,
3970
- passed: false,
4452
+ passed: allCapabilityUnavailable,
3971
4453
  skipped: true,
3972
- skip_reason: "prerequisite_failed",
3973
- skip: buildSkip("prerequisite_failed", detail),
4454
+ skip_reason: allCapabilityUnavailable ? "capability_prerequisite_unavailable" : "prerequisite_failed",
4455
+ skip: buildSkip(allCapabilityUnavailable ? "not_applicable" : "prerequisite_failed", detail),
3974
4456
  duration_ms: Date.now() - start,
3975
4457
  validations: [],
3976
4458
  context,
3977
4459
  next,
3978
4460
  extraction: { path: "none" },
3979
- error: detail
4461
+ ...!allCapabilityUnavailable && { error: detail }
3980
4462
  };
3981
4463
  }
3982
4464
  const unresolvedRunnerTokens = findUnresolvedRunnerTokens(resolvedTargetRequest);
@@ -4002,7 +4484,6 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
4002
4484
  ...isPrerequisiteFailure ? { error: detail } : {}
4003
4485
  };
4004
4486
  }
4005
- const advertisedTools = resolveAdvertisedTools(options);
4006
4487
  if (advertisedTools && !advertisedTools.includes(rateLimitTrip.trip_target_task)) {
4007
4488
  const next = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
4008
4489
  const detail = `Agent did not advertise tool "${rateLimitTrip.trip_target_task}"; agent tools: [${advertisedTools.join(", ")}].`;
@@ -4098,7 +4579,7 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
4098
4579
  if (httpResult?.skipped) {
4099
4580
  const detailedReason = httpResult.skip_reason ?? "probe_skipped";
4100
4581
  const canonicalReason = import_types.DETAILED_SKIP_TO_CANONICAL[detailedReason] ?? "not_applicable";
4101
- const detail = CANONICAL_SKIP_DETAILS[detailedReason] ?? httpResult.error ?? DETAILED_SKIP_DETAILS[detailedReason] ?? SKIP_DETAILS[canonicalReason];
4582
+ const detail = CANONICAL_SKIP_DETAILS[detailedReason] ?? redactedHttpResult?.error ?? DETAILED_SKIP_DETAILS[detailedReason] ?? SKIP_DETAILS[canonicalReason];
4102
4583
  const selectionResult = selectionForProbeSkip(detailedReason, detail);
4103
4584
  return {
4104
4585
  step_id: step.id,
@@ -4145,7 +4626,8 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
4145
4626
  const allValidationsPassed = validations.every((v) => !(0, import_validations.validationFailsStep)(v));
4146
4627
  const fetchOk = httpResult ? !httpResult.error : true;
4147
4628
  const passed = fetchOk && allValidationsPassed;
4148
- const extraction = httpResult ? httpResult.error ? { path: "error" } : { path: "structured_content", note: "http-probe body parsed as JSON" } : { path: "none" };
4629
+ const probeNote = sessionProbeStage !== void 0 ? `MCP session probe graded ${sessionProbeTool ?? "unknown tool"} at ${sessionProbeStage} (${sessionProbeDetail ?? "no detail"})` : "http-probe body parsed as JSON";
4630
+ const extraction = httpResult ? httpResult.error ? { path: "error" } : { path: "structured_content", note: probeNote } : { path: "none" };
4149
4631
  return {
4150
4632
  step_id: step.id,
4151
4633
  phase_id: phaseId,
@@ -4156,7 +4638,9 @@ async function executeProbeStep(client, step, phaseId, context, allSteps, option
4156
4638
  response: redactedHttpResult ?? void 0,
4157
4639
  validations,
4158
4640
  context,
4159
- error: httpResult?.error ?? (passed ? void 0 : "Probe validations failed."),
4641
+ // Redacted copy on both branches: the sibling skip branch reads the same
4642
+ // seam, and a probe error can carry an agent URL with OAuth params.
4643
+ error: redactedHttpResult?.error ?? (passed ? void 0 : "Probe validations failed."),
4160
4644
  next: getNextStepPreview(step.id, allSteps, context, runState.runnerVars),
4161
4645
  request: requestRecord,
4162
4646
  ...responseRecord && { response_record: responseRecord },
@@ -4179,26 +4663,7 @@ function applyFixtureBindingsSafely(request, task, options, runState) {
4179
4663
  }
4180
4664
  }
4181
4665
  function buildEffectiveStepRequest(step, context, options, runState) {
4182
- let request;
4183
- if (options.request) {
4184
- request = (0, import_context.injectContext)({ ...options.request }, context, runState.runnerVars);
4185
- } else if (step.expect_error && step.sample_request) {
4186
- request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
4187
- } else if ((0, import_request_builder.hasRequestEnricher)(step.task)) {
4188
- request = (0, import_request_builder.enrichRequest)(step, context, options, runState.runnerVars);
4189
- } else if (step.sample_request) {
4190
- request = (0, import_context.injectContext)({ ...step.sample_request }, context, runState.runnerVars);
4191
- } else {
4192
- request = {};
4193
- }
4194
- if (step.context_inputs?.length) {
4195
- request = (0, import_context.applyContextInputs)(request, step.context_inputs, context);
4196
- }
4197
- request = applyBrandInvariant(request, options, step.task, { omit_account: step.omit_account });
4198
- if (options.disable_sandbox === true) {
4199
- request = applyDisableSandboxHint(request, step.task);
4200
- }
4201
- request = applyIdempotencyInvariant(request, step.task, step);
4666
+ const request = buildStepRequest(step, step, context, options, runState.runnerVars);
4202
4667
  const fixtureBinding = applyFixtureBindingsSafely(request, step.task, options, runState);
4203
4668
  if (!fixtureBinding.ok) return fixtureBinding;
4204
4669
  const creativeAssetExpansion = (0, import_creative_assets.expandCreativeAssetDirectivesWithDiagnostics)(
@@ -4214,23 +4679,32 @@ function buildEffectiveStepRequest(step, context, options, runState) {
4214
4679
  request: creativeAssetExpansion.value
4215
4680
  };
4216
4681
  }
4217
- function preflightRemainingCreativeAssetDirectives(allSteps, afterGlobalIndex, context, options, runState, excludedPhaseIds = /* @__PURE__ */ new Set()) {
4682
+ function preflightRemainingCreativeAssetDirectives(allSteps, afterGlobalIndex, context, options, runState, excludedPhaseIds = /* @__PURE__ */ new Set(), resolveAssignment) {
4218
4683
  const contractsInScope = new Set(options.contracts ?? []);
4219
4684
  for (const target of allSteps) {
4220
4685
  if (target.globalIndex <= afterGlobalIndex) continue;
4221
4686
  if (excludedPhaseIds.has(target.phaseId)) continue;
4222
- const resolvedTask = resolveTaskName(target.step, options);
4687
+ const assignment = resolveAssignment?.(target.step);
4688
+ if (resolveAssignment && !assignment) continue;
4689
+ const selectedOptions = assignment?.options ?? options;
4690
+ const selectedState = assignment ? {
4691
+ ...runState,
4692
+ agentUrl: assignment.agentUrl,
4693
+ agentProfile: assignment.profile,
4694
+ agentLibraryVersion: assignment.profile?.library_version
4695
+ } : runState;
4696
+ const resolvedTask = (0, import_agent_routing.resolveTaskName)(target.step, selectedOptions);
4223
4697
  if (!resolvedTask) continue;
4224
- if (target.step.requires_tool && options.agentTools && !options.agentTools.includes(target.step.requires_tool)) {
4698
+ if (target.step.requires_tool && selectedOptions.agentTools && !selectedOptions.agentTools.includes(target.step.requires_tool)) {
4225
4699
  continue;
4226
4700
  }
4227
4701
  if (target.step.requires_contract && !contractsInScope.has(target.step.requires_contract)) {
4228
4702
  continue;
4229
4703
  }
4230
- if (target.step.task === "expect_rate_limit_not_replayed" && (!contractsInScope.has(import_rate_limit_trip.RATE_LIMIT_TRIP_CONTRACT) || options.allowLiveSideEffects !== true)) {
4704
+ if (target.step.task === "expect_rate_limit_not_replayed" && (!contractsInScope.has(import_rate_limit_trip.RATE_LIMIT_TRIP_CONTRACT) || selectedOptions.allowLiveSideEffects !== true)) {
4231
4705
  continue;
4232
4706
  }
4233
- if (!import_probes.PROBE_TASKS.has(target.step.task) && options.agentTools && !options.agentTools.includes(resolvedTask)) {
4707
+ if (!import_probes.PROBE_TASKS.has(target.step.task) && selectedOptions.agentTools && !selectedOptions.agentTools.includes(resolvedTask)) {
4234
4708
  continue;
4235
4709
  }
4236
4710
  let requestStep = resolvedTask === target.step.task ? target.step : { ...target.step, task: resolvedTask };
@@ -4244,7 +4718,7 @@ function preflightRemainingCreativeAssetDirectives(allSteps, afterGlobalIndex, c
4244
4718
  omit_idempotency_key: true
4245
4719
  };
4246
4720
  }
4247
- const request = buildEffectiveStepRequest(requestStep, context, options, runState);
4721
+ const request = buildEffectiveStepRequest(requestStep, context, selectedOptions, selectedState);
4248
4722
  if (!request.ok && "creativeAssetFailure" in request) {
4249
4723
  return { target, failure: request.creativeAssetFailure };
4250
4724
  }
@@ -4679,7 +5153,7 @@ function lowerCaseHeaders(headers) {
4679
5153
  return out;
4680
5154
  }
4681
5155
  function resolveAdvertisedTools(options) {
4682
- return options.agentTools ?? normalizeAgentToolNames(options._profile?.tools);
5156
+ return options.agentTools ?? (0, import_agent_routing.normalizeAgentToolNames)(options._profile?.tools);
4683
5157
  }
4684
5158
  function rateLimitTripObservationToProbeResult(agentUrl, observation) {
4685
5159
  if (observation.status === "not_applicable") {
@@ -4912,23 +5386,6 @@ function phaseUsesRuntimeContext(phase) {
4912
5386
  const expr = phase.skip_if?.trim();
4913
5387
  return expr ? (0, import_phase_condition.phaseConditionUsesContext)(expr) : false;
4914
5388
  }
4915
- function resolveTaskName(step, options) {
4916
- if (!step.task.startsWith("$test_kit.")) return step.task;
4917
- const path = step.task.slice("$test_kit.".length).split(".");
4918
- let value = options.test_kit;
4919
- for (const segment of path) {
4920
- if (value == null || typeof value !== "object") {
4921
- value = void 0;
4922
- break;
4923
- }
4924
- value = value[segment];
4925
- }
4926
- const configured = typeof value === "string" && value.length > 0 ? value : step.task_default;
4927
- if (step.task === "$test_kit.auth.probe_task") {
4928
- return (0, import_test_kit.selectProbeTask)(configured, options.agentTools);
4929
- }
4930
- return configured;
4931
- }
4932
5389
  function defaultAuthHeadersForRawProbe(options) {
4933
5390
  const headers = {};
4934
5391
  if (options.auth) {
@@ -4952,6 +5409,354 @@ function defaultAuthHeadersForRawProbe(options) {
4952
5409
  }
4953
5410
  return headers;
4954
5411
  }
5412
+ function sessionProbeRoutingHeaders(options) {
5413
+ const headers = {};
5414
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
5415
+ if (!SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase())) continue;
5416
+ try {
5417
+ assertSafeAuthHeaderPart(value, `options.headers.${name}`);
5418
+ } catch {
5419
+ continue;
5420
+ }
5421
+ headers[name] = value;
5422
+ }
5423
+ setHeaderIfAbsent(headers, "X-Test-Session-ID", options.test_session_id, "options.test_session_id");
5424
+ setHeaderIfAbsent(headers, "User-Agent", options.userAgent, "options.userAgent");
5425
+ return headers;
5426
+ }
5427
+ function setHeaderIfAbsent(headers, name, value, label) {
5428
+ if (!value) return;
5429
+ const lower = name.toLowerCase();
5430
+ if (Object.keys(headers).some((existing) => existing.toLowerCase() === lower)) return;
5431
+ try {
5432
+ assertSafeAuthHeaderPart(value, label);
5433
+ } catch {
5434
+ return;
5435
+ }
5436
+ headers[name] = value;
5437
+ }
5438
+ function runCredentialValues(options) {
5439
+ const values = [];
5440
+ const auth = options.auth;
5441
+ if (auth?.type === "bearer" && typeof auth.token === "string") values.push(auth.token);
5442
+ if (auth?.type === "basic") {
5443
+ if (typeof auth.password === "string") values.push(auth.password);
5444
+ if (typeof auth.username === "string" && typeof auth.password === "string") {
5445
+ values.push(`${auth.username}:${auth.password}`);
5446
+ }
5447
+ }
5448
+ if (auth?.type === "oauth" || auth?.type === "oauth_client_credentials") {
5449
+ const token = auth.tokens?.access_token;
5450
+ if (typeof token === "string") values.push(token);
5451
+ }
5452
+ const kit = options.test_kit?.auth;
5453
+ if (typeof kit?.api_key === "string") values.push(kit.api_key);
5454
+ const basic = kit?.basic;
5455
+ if (typeof basic?.password === "string") values.push(basic.password);
5456
+ if (typeof basic?.username === "string" && typeof basic?.password === "string") {
5457
+ values.push(`${basic.username}:${basic.password}`);
5458
+ }
5459
+ if (typeof basic?.credentials === "string") values.push(basic.credentials);
5460
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
5461
+ if (typeof value !== "string" || value.length === 0) continue;
5462
+ if (AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) || isCredentialHeaderName(name)) values.push(value);
5463
+ }
5464
+ return values.filter((value) => value.trim().length > 0);
5465
+ }
5466
+ const SESSION_PROBE_ROUTING_HEADERS = /* @__PURE__ */ new Set([
5467
+ "x-tenant-id",
5468
+ "x-tenant",
5469
+ "x-account",
5470
+ "x-account-id",
5471
+ "x-routing-key",
5472
+ "x-partition-key",
5473
+ "x-region",
5474
+ "x-environment",
5475
+ "x-request-id",
5476
+ "x-correlation-id",
5477
+ "x-idempotency-key",
5478
+ "x-test-session-id",
5479
+ "user-agent",
5480
+ "accept-language"
5481
+ ]);
5482
+ function unroutableProbeHeader(options) {
5483
+ const runSecrets = runCredentialValues(options);
5484
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
5485
+ const lower = name.toLowerCase();
5486
+ if (SESSION_PROBE_ROUTING_HEADERS.has(lower)) {
5487
+ try {
5488
+ assertSafeAuthHeaderPart(value, `options.headers.${name}`);
5489
+ } catch {
5490
+ return name;
5491
+ }
5492
+ continue;
5493
+ }
5494
+ if (AUTH_OVERRIDE_HEADER_NAMES.has(lower)) continue;
5495
+ if (runSecrets.some((secret) => value.includes(secret))) continue;
5496
+ return name;
5497
+ }
5498
+ return void 0;
5499
+ }
5500
+ function effectiveOAuthAccessToken(client, options, agentUrl) {
5501
+ const live = liveAgentOAuthAccessToken(client, agentUrl);
5502
+ if (live !== void 0) return live;
5503
+ const auth = options.auth;
5504
+ if (auth?.type !== "oauth" && auth?.type !== "oauth_client_credentials") return void 0;
5505
+ const configured = auth.tokens?.access_token;
5506
+ return typeof configured === "string" && configured.length > 0 ? configured : void 0;
5507
+ }
5508
+ function liveAgentOAuthAccessToken(client, agentUrl) {
5509
+ try {
5510
+ const resolved = client?.getAgent?.(TEST_CLIENT_AGENT_ID);
5511
+ if (resolved == null) return void 0;
5512
+ const candidates = [resolved];
5513
+ if (typeof resolved.getAgent === "function") candidates.push(resolved.getAgent());
5514
+ for (const candidate of candidates) {
5515
+ const token = candidate?.oauth_tokens?.access_token;
5516
+ if (typeof token !== "string" || token.length === 0) continue;
5517
+ const configuredUri = candidate?.agent_uri;
5518
+ if (agentUrl !== void 0 && typeof configuredUri === "string" && configuredUri !== agentUrl) continue;
5519
+ if (agentUrl !== void 0 && typeof configuredUri !== "string") continue;
5520
+ return token;
5521
+ }
5522
+ } catch {
5523
+ }
5524
+ return void 0;
5525
+ }
5526
+ const TEST_CLIENT_AGENT_ID = "test";
5527
+ function withMcpBearerParity(headers) {
5528
+ const authorization = headers.authorization;
5529
+ if (authorization === void 0 || !authorization.startsWith("Bearer ")) return headers;
5530
+ const token = authorization.slice("Bearer ".length);
5531
+ if (token.length === 0) return headers;
5532
+ return { ...headers, "x-adcp-auth": token };
5533
+ }
5534
+ function oauthAccessTokenHeaders(options, client, agentUrl) {
5535
+ const token = effectiveOAuthAccessToken(client, options, agentUrl);
5536
+ if (token === void 0) return void 0;
5537
+ try {
5538
+ assertSafeAuthHeaderPart(token, "options.auth.tokens.access_token");
5539
+ } catch {
5540
+ return void 0;
5541
+ }
5542
+ return { authorization: `Bearer ${token}` };
5543
+ }
5544
+ function staticCredentialHeaders(directive, options) {
5545
+ try {
5546
+ const headers = authHeadersForStep(directive, options);
5547
+ return headers.authorization !== void 0 ? { authorization: headers.authorization } : void 0;
5548
+ } catch {
5549
+ }
5550
+ return void 0;
5551
+ }
5552
+ function sessionControlCredentials(mechanism, options, client, agentUrl) {
5553
+ const oauth = oauthAccessTokenHeaders(options, client, agentUrl);
5554
+ const bearer = options.auth?.type === "bearer" ? staticCredentialHeaders({ type: "api_key", value: options.auth.token }, options) : void 0;
5555
+ const basicFromOptions = options.auth?.type === "basic" ? staticCredentialHeaders(
5556
+ { type: "basic", username: options.auth.username, password: options.auth.password },
5557
+ options
5558
+ ) : void 0;
5559
+ const kitApiKey = typeof options.test_kit?.auth?.api_key === "string" && options.test_kit.auth.api_key.length > 0 ? staticCredentialHeaders({ type: "api_key", from_test_kit: true }, options) : void 0;
5560
+ const kitBasic = options.test_kit?.auth?.basic !== void 0 ? staticCredentialHeaders({ type: "basic", from_test_kit: true }, options) : void 0;
5561
+ switch (mechanism) {
5562
+ case "oauth_bearer": {
5563
+ if (oauth) return { headers: oauth };
5564
+ return {
5565
+ unavailable: {
5566
+ reason: `this run holds no OAuth access token, and a static API key or Basic credential is not evidence about the OAuth path at all \u2014 accepting a shared secret says nothing about whether tokens from the issuer advertised in your protected-resource metadata are what gates this resource`,
5567
+ remedy: `Run the storyboard with OAuth so the runner holds a token minted by that issuer (\`adcp --save-auth <alias> <url> --oauth\`, or pass \`--oauth\` to \`storyboard run\`).`
5568
+ }
5569
+ };
5570
+ }
5571
+ case "api_key": {
5572
+ const headers = bearer ?? kitApiKey;
5573
+ if (headers) return { headers };
5574
+ return {
5575
+ unavailable: {
5576
+ reason: `this run holds no valid API key to prove the endpoint accepts one`,
5577
+ remedy: "Declare `auth.api_key` in the test kit, or pass a bearer `options.auth` (CLI: `--auth`)."
5578
+ }
5579
+ };
5580
+ }
5581
+ case "basic": {
5582
+ const headers = basicFromOptions ?? kitBasic;
5583
+ if (headers) return { headers };
5584
+ return {
5585
+ unavailable: {
5586
+ reason: `this run holds no valid Basic credential to prove the endpoint accepts one`,
5587
+ remedy: "Declare `auth.basic` in the test kit, or pass a basic `options.auth`."
5588
+ }
5589
+ };
5590
+ }
5591
+ case "any": {
5592
+ const headers = oauth ?? bearer ?? basicFromOptions ?? kitApiKey ?? kitBasic;
5593
+ if (headers) return { headers };
5594
+ return {
5595
+ unavailable: {
5596
+ reason: `this run holds no valid credential, so a rejection cannot be told apart from an endpoint that refuses every request`,
5597
+ remedy: "Declare `auth.api_key` or `auth.basic` in the test kit, pass `options.auth`, or run with `--oauth`."
5598
+ }
5599
+ };
5600
+ }
5601
+ }
5602
+ }
5603
+ function summarizeAdvertisedTools(tools) {
5604
+ const names = (tools ?? []).slice(0, 20).map((name) => escapeControlChars(name.slice(0, 64)));
5605
+ const overflow = (tools?.length ?? 0) - names.length;
5606
+ return overflow > 0 ? `${names.join(", ")}, \u2026${overflow} more` : names.join(", ");
5607
+ }
5608
+ function escapeControlChars(value) {
5609
+ return value.replace(
5610
+ /[\u0000-\u001f\u007f-\u009f]/g,
5611
+ (char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`
5612
+ );
5613
+ }
5614
+ const SESSION_PROBE_PUBLIC_TIER = /* @__PURE__ */ new Set([
5615
+ "get_adcp_capabilities",
5616
+ "get_products",
5617
+ "list_products",
5618
+ "list_creative_formats"
5619
+ ]);
5620
+ const CANONICAL_ADCP_TOOLS = /* @__PURE__ */ new Set([
5621
+ ...import_capabilities.MEDIA_BUY_TOOLS,
5622
+ ...import_capabilities.CREATIVE_TOOLS,
5623
+ ...import_capabilities.SIGNALS_TOOLS,
5624
+ ...import_capabilities.GOVERNANCE_TOOLS,
5625
+ ...import_capabilities.ACCOUNT_TOOLS,
5626
+ ...import_capabilities.BRAND_RIGHTS_TOOLS,
5627
+ ...import_capabilities.PROTOCOL_TOOLS,
5628
+ ...import_capabilities.EVENT_TRACKING_TOOLS
5629
+ ]);
5630
+ const PREFERRED_PROBE_TARGET = "get_principal";
5631
+ function hasNoRequiredRequestFields(tool) {
5632
+ const schema = import_tool_request_schemas.TOOL_REQUEST_SCHEMAS[tool];
5633
+ const shape = schema?.shape;
5634
+ if (!shape) return false;
5635
+ return !Object.values(shape).some((field) => {
5636
+ const candidate = field;
5637
+ if (typeof candidate?.safeParse !== "function") return false;
5638
+ return !candidate.safeParse(void 0).success;
5639
+ });
5640
+ }
5641
+ function protectedToolCandidates(tools) {
5642
+ if (!tools) return [];
5643
+ const advertised = new Set(tools);
5644
+ const eligible = (tool) => advertised.has(tool) && !SESSION_PROBE_PUBLIC_TIER.has(tool) && !import_idempotency2.MUTATING_TASKS.has(tool);
5645
+ const allowlisted = import_test_kit.PROBE_TASK_ALLOWLIST.filter(eligible);
5646
+ const canonicalReads = [...CANONICAL_ADCP_TOOLS].filter((tool) => /^(list|get)_/.test(tool)).filter((tool) => !allowlisted.includes(tool)).filter(eligible).filter(hasNoRequiredRequestFields).sort((a, b) => {
5647
+ if (a === PREFERRED_PROBE_TARGET) return -1;
5648
+ if (b === PREFERRED_PROBE_TARGET) return 1;
5649
+ return a.localeCompare(b);
5650
+ });
5651
+ return [...allowlisted, ...canonicalReads];
5652
+ }
5653
+ function signatureBoundTools(options) {
5654
+ if (options.functional_request_signing === void 0) return /* @__PURE__ */ new Set();
5655
+ const raw = options._profile?.raw_capabilities;
5656
+ if (raw === null || typeof raw !== "object") return "unparseable";
5657
+ const advertised = raw.request_signing;
5658
+ if (advertised === void 0) return /* @__PURE__ */ new Set();
5659
+ if (advertised === null || typeof advertised !== "object") return "unparseable";
5660
+ const buckets = advertised;
5661
+ const bound = /* @__PURE__ */ new Set();
5662
+ for (const bucket of [buckets.required_for, buckets.supported_for]) {
5663
+ if (bucket === void 0) continue;
5664
+ if (!Array.isArray(bucket) || bucket.some((entry) => typeof entry !== "string")) return "unparseable";
5665
+ for (const entry of bucket) bound.add(entry);
5666
+ }
5667
+ return bound;
5668
+ }
5669
+ function selectProtectedToolTarget(tools) {
5670
+ return protectedToolCandidates(tools)[0];
5671
+ }
5672
+ function sessionControlMechanismFor(auth) {
5673
+ if (auth === "none") return "any";
5674
+ switch (auth.type) {
5675
+ case "oauth_bearer":
5676
+ return "oauth_bearer";
5677
+ case "basic":
5678
+ return "basic";
5679
+ case "api_key":
5680
+ return "api_key";
5681
+ }
5682
+ }
5683
+ function planMcpSessionSentinel(step, options, client, agentUrl) {
5684
+ if (options.protocol !== "mcp") {
5685
+ const declared = options.protocol === void 0 ? "no transport" : `"${options.protocol}"`;
5686
+ return {
5687
+ kind: "error",
5688
+ error: `"${import_types.MCP_SESSION_PROBE_TASK}" is an MCP session probe and requires an explicit \`protocol: 'mcp'\` on the run; this run declared ${declared}. A2A has no equivalent parameter-free protected operation, so the runner refuses to substitute one.`
5689
+ };
5690
+ }
5691
+ if (step.auth === void 0) {
5692
+ return {
5693
+ kind: "skip",
5694
+ reason: "session_probe_ungradable",
5695
+ detail: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
5696
+ `Agent advertises no auth-required, read-only AdCP tool that accepts an empty request body, so the runner fell back to the MCP "${import_types.MCP_SESSION_PROBE_TASK}" session probe. That probe cannot grade a positive static-credential step: its validations assert an AdCP task response body, which no MCP protocol operation produces, so this mechanism's branch cannot contribute auth_mechanism_verified. Remedy: advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}), or serve RFC 9728 metadata and run with OAuth so the OAuth branch can be verified instead. Advertised tools: [${summarizeAdvertisedTools(options.agentTools)}].`
5697
+ )
5698
+ };
5699
+ }
5700
+ const signatureBound = signatureBoundTools(options);
5701
+ const candidates = protectedToolCandidates(options.agentTools);
5702
+ if (signatureBound === "unparseable") {
5703
+ return {
5704
+ kind: "skip",
5705
+ reason: "session_probe_ungradable",
5706
+ detail: `This run signs functional dispatch (RFC 9421), but the runner could not read which operations your \`request_signing\` capability covers, so it cannot tell whether the session probe's unsigned call would be refused for the signature rather than the credential. Refusing to grade instead of guessing. Remedy: advertise \`request_signing.required_for\` / \`supported_for\` as string arrays, or advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}) so the probe has a protocol-vouched target.`
5707
+ };
5708
+ }
5709
+ const toolNames = candidates.filter((tool) => !signatureBound.has(tool));
5710
+ if (toolNames.length === 0 && candidates.length > 0) {
5711
+ return {
5712
+ kind: "skip",
5713
+ reason: "session_probe_ungradable",
5714
+ detail: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
5715
+ `Every protected read the probe could call (${candidates.join(", ")}) is covered by this agent's \`request_signing\` advertisement, and the session probe mints no RFC 9421 signatures. An unsigned call would be refused for the missing signature, which is not evidence about the credential, so the runner refuses to grade it. Remedy: advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}) outside \`request_signing.required_for\`/\`supported_for\`, or run with OAuth against RFC 9728 metadata so the OAuth branch can be verified instead.`
5716
+ )
5717
+ };
5718
+ }
5719
+ if (toolNames.length === 0) {
5720
+ return {
5721
+ kind: "skip",
5722
+ reason: "session_probe_ungradable",
5723
+ detail: (0, import_oauth_metadata_graph.redactOAuthUrlsInText)(
5724
+ `Agent advertises no auth-required, read-only AdCP tool the probe can call with an empty request body, so there is no protected operation to grade. MCP discovery (\`tools/list\`) is not a protected task and public-tier tools (${[...SESSION_PROBE_PUBLIC_TIER].join(", ")}) are served unauthenticated by design. Remedy: advertise one allowlisted read tool (${import_test_kit.PROBE_TASK_ALLOWLIST_SUMMARY}). Advertised tools: [${summarizeAdvertisedTools(options.agentTools)}].`
5725
+ )
5726
+ };
5727
+ }
5728
+ const unroutable = unroutableProbeHeader(options);
5729
+ if (unroutable !== void 0) {
5730
+ return {
5731
+ kind: "skip",
5732
+ reason: "session_probe_ungradable",
5733
+ detail: `The runner cannot classify run header "${escapeControlChars(unroutable.slice(0, 64))}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`
5734
+ };
5735
+ }
5736
+ const routing = sessionProbeRoutingHeaders(options);
5737
+ let headers;
5738
+ try {
5739
+ headers = { ...routing, ...withMcpBearerParity(authHeadersForStep(step.auth, options)) };
5740
+ } catch (err) {
5741
+ return {
5742
+ kind: "error",
5743
+ error: `Step auth configuration error: ${err instanceof Error ? err.message : String(err)}`
5744
+ };
5745
+ }
5746
+ const control = sessionControlCredentials(sessionControlMechanismFor(step.auth), options, client, agentUrl);
5747
+ if ("unavailable" in control) {
5748
+ return { kind: "probe", headers, toolNames, control: { kind: "unavailable", ...control.unavailable } };
5749
+ }
5750
+ if (headers.authorization !== void 0 && control.headers.authorization === headers.authorization) {
5751
+ return { kind: "probe", headers, toolNames, control: { kind: "probe_is_valid_credential" } };
5752
+ }
5753
+ return {
5754
+ kind: "probe",
5755
+ headers,
5756
+ toolNames,
5757
+ control: { kind: "credential", headers: { ...routing, ...withMcpBearerParity(control.headers) } }
5758
+ };
5759
+ }
4955
5760
  function authHeadersForStep(directive, options) {
4956
5761
  if (directive === "none") return {};
4957
5762
  if (directive.type === "basic") return basicAuthHeadersForStep(directive, options);
@@ -5359,7 +6164,8 @@ function createRoutingDispatcher(ctx, options, agents) {
5359
6164
  const keyToIndex = new Map(keyOrder.map((k, i) => [k, i]));
5360
6165
  return {
5361
6166
  nextFor(step) {
5362
- const key = (0, import_agent_routing.resolveAgentForStep)(step, options, ctx);
6167
+ const task = (0, import_agent_routing.resolveTaskName)(step, { ...options, agentTools: void 0 });
6168
+ const key = (0, import_agent_routing.resolveAgentForStep)(task ? { ...step, task } : step, options, ctx);
5363
6169
  const client = ctx.clients.get(key);
5364
6170
  const profile = ctx.profiles.get(key);
5365
6171
  const url = agents[key]?.url;
@@ -5370,11 +6176,21 @@ function createRoutingDispatcher(ctx, options, agents) {
5370
6176
  `key ${key} unbound`
5371
6177
  );
5372
6178
  }
6179
+ if (!profile) {
6180
+ const failure = ctx.discoveryFailures.find((failure2) => failure2.agentKey === key);
6181
+ throw new import_agent_routing.RoutingError(
6182
+ `Agent "${key}" has no discovered profile; its task contract cannot be established.` + (failure ? ` Discovery failed: ${failure.underlying}. Fix the agent or select a healthy route.` : ""),
6183
+ step.task,
6184
+ `agent "${key}" failed discovery`
6185
+ );
6186
+ }
5373
6187
  return {
5374
6188
  client,
5375
6189
  agentUrl: url,
6190
+ agentKey: key,
5376
6191
  instanceIndex: keyToIndex.get(key) ?? 0,
5377
- profile
6192
+ profile,
6193
+ options: (0, import_agent_routing.routedAgentOptions)(agents[key], options, profile)
5378
6194
  };
5379
6195
  }
5380
6196
  };
@@ -5455,7 +6271,10 @@ function getFirstStepPreview(storyboard, context = {}) {
5455
6271
  0 && (module.exports = {
5456
6272
  __defaultAuthHeadersForRawProbeForTest,
5457
6273
  __filterResponseHeadersForTest,
6274
+ __protectedToolCandidatesForTest,
5458
6275
  __redactSecretsForTest,
6276
+ __selectProtectedToolTargetForTest,
6277
+ __sessionControlCredentialsForTest,
5459
6278
  applyAdcpVersionRunOptions,
5460
6279
  applyBrandInvariant,
5461
6280
  applyDisableSandboxHint,
@@ -5469,5 +6288,8 @@ function getFirstStepPreview(storyboard, context = {}) {
5469
6288
  resolveCapabilityPath,
5470
6289
  runStoryboard,
5471
6290
  runStoryboardStep,
6291
+ signingCoverage,
6292
+ signingCoverageUnverified,
6293
+ storyboardCapabilityPredicates,
5472
6294
  summarizeStrictValidation
5473
6295
  });