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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/dist/lib/adapters/roster-account-store.d.mts +9 -8
  2. package/dist/lib/adapters/roster-account-store.d.ts +9 -8
  3. package/dist/lib/adapters/roster-account-store.d.ts.map +1 -1
  4. package/dist/lib/adapters/roster-account-store.js +2 -1
  5. package/dist/lib/adapters/roster-account-store.js.map +1 -1
  6. package/dist/lib/adapters/roster-account-store.mjs +2 -1
  7. package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
  8. package/dist/lib/net/address-guards.d.ts.map +1 -1
  9. package/dist/lib/net/address-guards.js +6 -0
  10. package/dist/lib/net/address-guards.js.map +1 -1
  11. package/dist/lib/net/address-guards.mjs +6 -0
  12. package/dist/lib/net/address-guards.mjs.map +1 -1
  13. package/dist/lib/net/ssrf-fetch.d.ts.map +1 -1
  14. package/dist/lib/net/ssrf-fetch.js +66 -53
  15. package/dist/lib/net/ssrf-fetch.js.map +1 -1
  16. package/dist/lib/net/ssrf-fetch.mjs +66 -53
  17. package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
  18. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  19. package/dist/lib/server/account-mode.d.mts +2 -1
  20. package/dist/lib/server/account-mode.d.ts +2 -1
  21. package/dist/lib/server/account-mode.d.ts.map +1 -1
  22. package/dist/lib/server/account-mode.js +1 -0
  23. package/dist/lib/server/account-mode.js.map +1 -1
  24. package/dist/lib/server/account-mode.mjs +1 -0
  25. package/dist/lib/server/account-mode.mjs.map +1 -1
  26. package/dist/lib/server/create-adcp-server.d.mts +10 -6
  27. package/dist/lib/server/create-adcp-server.d.ts +10 -6
  28. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  29. package/dist/lib/server/create-adcp-server.js +2 -1
  30. package/dist/lib/server/create-adcp-server.js.map +1 -1
  31. package/dist/lib/server/create-adcp-server.mjs +2 -1
  32. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  33. package/dist/lib/server/decisioning/account.d.mts +16 -11
  34. package/dist/lib/server/decisioning/account.d.ts +16 -11
  35. package/dist/lib/server/decisioning/account.d.ts.map +1 -1
  36. package/dist/lib/server/decisioning/account.js.map +1 -1
  37. package/dist/lib/server/decisioning/account.mjs.map +1 -1
  38. package/dist/lib/server/decisioning/pagination.d.mts +2 -0
  39. package/dist/lib/server/decisioning/pagination.d.ts +2 -0
  40. package/dist/lib/server/decisioning/pagination.d.ts.map +1 -1
  41. package/dist/lib/server/decisioning/pagination.js.map +1 -1
  42. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +20 -14
  43. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +20 -14
  44. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  45. package/dist/lib/server/decisioning/runtime/from-platform.js +32 -6
  46. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  47. package/dist/lib/server/decisioning/runtime/from-platform.mjs +32 -6
  48. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  49. package/dist/lib/server/decisioning/specialisms/sales.d.mts +16 -4
  50. package/dist/lib/server/decisioning/specialisms/sales.d.ts +16 -4
  51. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
  52. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
  53. package/dist/lib/server/index.d.ts.map +1 -1
  54. package/dist/lib/server/index.js.map +1 -1
  55. package/dist/lib/server/index.mjs.map +1 -1
  56. package/dist/lib/server/legacy/v5/index.d.mts +2 -1
  57. package/dist/lib/server/legacy/v5/index.d.ts +2 -1
  58. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
  59. package/dist/lib/server/legacy/v5/index.js.map +1 -1
  60. package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
  61. package/dist/lib/testing/compliance/comply.d.mts +2 -0
  62. package/dist/lib/testing/compliance/comply.d.ts +2 -0
  63. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  64. package/dist/lib/testing/compliance/comply.js +45 -14
  65. package/dist/lib/testing/compliance/comply.js.map +1 -1
  66. package/dist/lib/testing/compliance/comply.mjs +45 -14
  67. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  68. package/dist/lib/testing/compliance/index.d.mts +1 -1
  69. package/dist/lib/testing/compliance/index.d.ts +1 -1
  70. package/dist/lib/testing/compliance/index.d.ts.map +1 -1
  71. package/dist/lib/testing/compliance/index.js.map +1 -1
  72. package/dist/lib/testing/compliance/index.mjs.map +1 -1
  73. package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -1
  74. package/dist/lib/testing/compliance/storyboard-tracks.js +9 -1
  75. package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -1
  76. package/dist/lib/testing/compliance/storyboard-tracks.mjs +9 -1
  77. package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
  78. package/dist/lib/testing/compliance/types.d.mts +26 -25
  79. package/dist/lib/testing/compliance/types.d.ts +26 -25
  80. package/dist/lib/testing/compliance/types.d.ts.map +1 -1
  81. package/dist/lib/testing/compliance/types.js.map +1 -1
  82. package/dist/lib/testing/index.d.mts +2 -2
  83. package/dist/lib/testing/index.d.ts +2 -2
  84. package/dist/lib/testing/index.d.ts.map +1 -1
  85. package/dist/lib/testing/index.js +16 -0
  86. package/dist/lib/testing/index.js.map +1 -1
  87. package/dist/lib/testing/index.mjs +16 -0
  88. package/dist/lib/testing/index.mjs.map +1 -1
  89. package/dist/lib/testing/scenarios/media-buy.d.ts.map +1 -1
  90. package/dist/lib/testing/scenarios/media-buy.js +20 -12
  91. package/dist/lib/testing/scenarios/media-buy.js.map +1 -1
  92. package/dist/lib/testing/scenarios/media-buy.mjs +20 -12
  93. package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
  94. package/dist/lib/testing/storyboard/creative-assets.d.mts +23 -0
  95. package/dist/lib/testing/storyboard/creative-assets.d.ts +23 -0
  96. package/dist/lib/testing/storyboard/creative-assets.d.ts.map +1 -1
  97. package/dist/lib/testing/storyboard/creative-assets.js +322 -45
  98. package/dist/lib/testing/storyboard/creative-assets.js.map +1 -1
  99. package/dist/lib/testing/storyboard/creative-assets.mjs +321 -45
  100. package/dist/lib/testing/storyboard/creative-assets.mjs.map +1 -1
  101. package/dist/lib/testing/storyboard/index.d.mts +4 -1
  102. package/dist/lib/testing/storyboard/index.d.ts +4 -1
  103. package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
  104. package/dist/lib/testing/storyboard/index.js +20 -0
  105. package/dist/lib/testing/storyboard/index.js.map +1 -1
  106. package/dist/lib/testing/storyboard/index.mjs +19 -0
  107. package/dist/lib/testing/storyboard/index.mjs.map +1 -1
  108. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.mts +21 -0
  109. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.ts +22 -0
  110. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.ts.map +1 -0
  111. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.js +668 -0
  112. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.js.map +1 -0
  113. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.mjs +638 -0
  114. package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.mjs.map +1 -0
  115. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.mts +5 -0
  116. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.ts +6 -0
  117. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.d.ts.map +1 -0
  118. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.js +44 -0
  119. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.js.map +1 -0
  120. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.mjs +20 -0
  121. package/dist/lib/testing/storyboard/oauth-metadata-graph/index.mjs.map +1 -0
  122. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.mts +38 -0
  123. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.ts +39 -0
  124. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.d.ts.map +1 -0
  125. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.js +17 -0
  126. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.js.map +1 -0
  127. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.mjs +1 -0
  128. package/dist/lib/testing/storyboard/oauth-metadata-graph/types.mjs.map +1 -0
  129. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.mts +32 -0
  130. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.ts +33 -0
  131. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.d.ts.map +1 -0
  132. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.js +105 -0
  133. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.js.map +1 -0
  134. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.mjs +80 -0
  135. package/dist/lib/testing/storyboard/oauth-metadata-graph/vector-loader.mjs.map +1 -0
  136. package/dist/lib/testing/storyboard/probes.d.ts.map +1 -1
  137. package/dist/lib/testing/storyboard/probes.js +2 -1
  138. package/dist/lib/testing/storyboard/probes.js.map +1 -1
  139. package/dist/lib/testing/storyboard/probes.mjs +2 -1
  140. package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
  141. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  142. package/dist/lib/testing/storyboard/runner.js +382 -69
  143. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  144. package/dist/lib/testing/storyboard/runner.mjs +387 -70
  145. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  146. package/dist/lib/testing/storyboard/seeding.js +3 -1
  147. package/dist/lib/testing/storyboard/seeding.js.map +1 -1
  148. package/dist/lib/testing/storyboard/seeding.mjs +3 -1
  149. package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
  150. package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
  151. package/dist/lib/testing/storyboard/task-map.js +16 -2
  152. package/dist/lib/testing/storyboard/task-map.js.map +1 -1
  153. package/dist/lib/testing/storyboard/task-map.mjs +16 -2
  154. package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
  155. package/dist/lib/testing/storyboard/trusted-match-context-replay.d.mts +11 -0
  156. package/dist/lib/testing/storyboard/trusted-match-context-replay.d.ts +12 -0
  157. package/dist/lib/testing/storyboard/trusted-match-context-replay.d.ts.map +1 -0
  158. package/dist/lib/testing/storyboard/trusted-match-context-replay.js +340 -0
  159. package/dist/lib/testing/storyboard/trusted-match-context-replay.js.map +1 -0
  160. package/dist/lib/testing/storyboard/trusted-match-context-replay.mjs +316 -0
  161. package/dist/lib/testing/storyboard/trusted-match-context-replay.mjs.map +1 -0
  162. package/dist/lib/testing/storyboard/types.d.mts +84 -15
  163. package/dist/lib/testing/storyboard/types.d.ts +84 -15
  164. package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
  165. package/dist/lib/testing/storyboard/types.js +2 -0
  166. package/dist/lib/testing/storyboard/types.js.map +1 -1
  167. package/dist/lib/testing/storyboard/types.mjs +2 -0
  168. package/dist/lib/testing/storyboard/types.mjs.map +1 -1
  169. package/dist/lib/testing/storyboard/validations.d.mts +3 -0
  170. package/dist/lib/testing/storyboard/validations.d.ts +3 -0
  171. package/dist/lib/testing/storyboard/validations.d.ts.map +1 -1
  172. package/dist/lib/testing/storyboard/validations.js +64 -24
  173. package/dist/lib/testing/storyboard/validations.js.map +1 -1
  174. package/dist/lib/testing/storyboard/validations.mjs +64 -24
  175. package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
  176. package/dist/lib/types/server-payload-aliases.d.mts +8 -2
  177. package/dist/lib/types/server-payload-aliases.d.ts +8 -2
  178. package/dist/lib/types/server-payload-aliases.d.ts.map +1 -1
  179. package/dist/lib/types/server-payload-aliases.js.map +1 -1
  180. package/dist/lib/upstream-recorder/recorder.d.mts +7 -18
  181. package/dist/lib/upstream-recorder/recorder.d.ts +7 -18
  182. package/dist/lib/upstream-recorder/recorder.d.ts.map +1 -1
  183. package/dist/lib/upstream-recorder/recorder.js +17 -10
  184. package/dist/lib/upstream-recorder/recorder.js.map +1 -1
  185. package/dist/lib/upstream-recorder/recorder.mjs +12 -5
  186. package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
  187. package/dist/lib/utils/redact-secrets.d.ts.map +1 -1
  188. package/dist/lib/utils/redact-secrets.js +7 -1
  189. package/dist/lib/utils/redact-secrets.js.map +1 -1
  190. package/dist/lib/utils/redact-secrets.mjs +7 -1
  191. package/dist/lib/utils/redact-secrets.mjs.map +1 -1
  192. package/dist/lib/version.d.mts +3 -3
  193. package/dist/lib/version.d.ts +3 -3
  194. package/dist/lib/version.js +3 -3
  195. package/dist/lib/version.js.map +1 -1
  196. package/dist/lib/version.mjs +3 -3
  197. package/dist/lib/version.mjs.map +1 -1
  198. package/docs/guides/BUILD-AN-AGENT.md +4 -2
  199. package/docs/llms.txt +1 -1
  200. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/storyboard/seeding.ts"],"sourcesContent":["/**\n * Pre-flight `comply_test_controller` seeding.\n *\n * Spec: adcontextprotocol/adcp#2585 (fixtures block + `controller_seeding`\n * flag) + adcontextprotocol/adcp#2584 (seed_* scenarios on\n * `comply_test_controller`). Storyboards such as `sales_non_guaranteed`,\n * `creative_ad_server`, `governance_delivery_monitor`,\n * `media_buy_governance_escalation`, and `governance_spend_authority`\n * reference fixture IDs (product_ids, pricing_option_ids, creative_ids,\n * plan_ids, media_buy_ids) that the seller must already hold before the\n * buyer-side flow runs. This module fires the `seed_*` scenarios derived\n * from the storyboard's top-level `fixtures:` block before the first real\n * phase, so the seller's buyer-agent ledger and catalog are populated ahead\n * of any `sync_accounts` / `create_media_buy` / `sync_creatives` / etc. call\n * that would otherwise fail or route through the wrong commercial-state gate.\n *\n * Failures here surface as a dedicated synthetic phase (`__controller_seeding__`)\n * so an implementor reading the report can distinguish \"setup broke\" from\n * \"buyer did something wrong\" — the runner short-circuits the rest of the\n * phases on any seed failure, emitting a cascade skip with reason\n * `controller_seeding_failed`.\n */\n\nimport { resolveAccount, resolveBrand, validateResponseSchema, type TestClient } from '../client';\nimport { getValidator } from '../../validation/schema-loader';\nimport { ADCP_VERSION } from '../../version';\nimport { injectLegacyEnvelopeStatus } from '../../utils/envelope-status-compat';\nimport { callControllerRaw } from '../test-controller';\nimport { executeStoryboardTask } from './task-map';\nimport {\n buildFixtureResolutionSpecs,\n applyFixtureBindingsToRequest,\n FixtureBindingRegistry,\n matchesFixtureRequirements,\n type FixtureResolutionSpec,\n} from './fixture-resolution';\nimport type {\n FixtureResolutionAttempt,\n FixtureResolutionRecord,\n Storyboard,\n StoryboardContext,\n StoryboardFixtures,\n StoryboardPhaseResult,\n StoryboardRunOptions,\n StoryboardStepResult,\n} from './types';\n\n/** Synthetic phase id used in `StoryboardResult.phases[]` for the seed pass. */\nexport const CONTROLLER_SEEDING_PHASE_ID = '__controller_seeding__';\n\n/** Seed scenario names. Kept local — the server-side `SEED_SCENARIOS`\n * constant from `src/lib/server/test-controller.ts` is authoritative, but\n * importing it here would cross the testing ⇄ server module boundary. */\ntype SeedScenario =\n | 'seed_account'\n | 'seed_product'\n | 'seed_pricing_option'\n | 'seed_creative_format'\n | 'seed_creative'\n | 'seed_plan'\n | 'seed_media_buy';\ntype BuyerAgentSeedScenario = 'seed_buyer_agent';\n\ninterface SeedCall {\n step_id: string;\n title: string;\n scenario: SeedScenario | BuyerAgentSeedScenario;\n params: Record<string, unknown>;\n /** Authoring error (e.g. missing required id). When set, the call fails at\n * build time — no controller request is issued. */\n authoring_error?: string;\n}\n\n/**\n * Translate a storyboard `fixtures:` block into an ordered list of seed\n * calls. Each entry's id field(s) are lifted into the scenario params; every\n * remaining field rides in `params.fixture` verbatim. Missing required ids\n * produce an authoring-error marker the runner surfaces as a failed seed\n * step (rather than crashing or silently skipping).\n */\n// Top-level fixture keys are forwarded to the server verbatim inside\n// `params.fixture`. Prototype-pollution rejection (`__proto__`, `constructor`,\n// `prototype`) is enforced by the server-side `dispatchSeed` at a single\n// canonical point (`src/lib/server/test-controller.ts`), NOT re-guarded here:\n// surfacing the rejection through the normal seed-error path keeps one source\n// of truth for the check, and the server-side handler is where a seed request\n// can actually land from any client implementation. A future refactor that\n// removes the server check must add the client guard before removing it.\nexport function buildSeedCalls(fixtures: StoryboardFixtures | undefined): SeedCall[] {\n if (!fixtures) return [];\n const calls: SeedCall[] = [];\n\n (fixtures.accounts ?? []).forEach((entry, i) => {\n const { account_id, ...fixtureFields } = entry;\n const label = account_id ?? `#${i}`;\n if (typeof account_id !== 'string' || account_id.length === 0) {\n calls.push({\n step_id: `seed_account.${label}`,\n title: `Seed account ${label}`,\n scenario: 'seed_account',\n params: { fixture: seedFixtureFromFields(fixtureFields) },\n authoring_error: `fixtures.accounts[${i}] requires a non-empty string 'account_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_account.${account_id}`,\n title: `Seed account ${account_id}`,\n scenario: 'seed_account',\n params: { account_id, fixture: seedFixtureFromFields(fixtureFields) },\n });\n });\n\n (fixtures.buyer_agents ?? []).forEach((entry, i) => {\n const { agent_url, ...params } = entry;\n const label = agent_url ?? `#${i}`;\n if (typeof agent_url !== 'string' || agent_url.length === 0) {\n calls.push({\n step_id: `seed_buyer_agent.${label}`,\n title: `Seed buyer agent ${label}`,\n scenario: 'seed_buyer_agent',\n params,\n authoring_error: `fixtures.buyer_agents[${i}] requires a non-empty string 'agent_url'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_buyer_agent.${agent_url}`,\n title: `Seed buyer agent ${agent_url}`,\n scenario: 'seed_buyer_agent',\n params: { agent_url, ...params },\n });\n });\n\n (fixtures.products ?? []).forEach((entry, i) => {\n const { product_id, ...fixture } = entry;\n const label = product_id ?? `#${i}`;\n if (typeof product_id !== 'string' || product_id.length === 0) {\n calls.push({\n step_id: `seed_product.${label}`,\n title: `Seed product ${label}`,\n scenario: 'seed_product',\n params: { fixture },\n authoring_error: `fixtures.products[${i}] requires a non-empty string 'product_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_product.${product_id}`,\n title: `Seed product ${product_id}`,\n scenario: 'seed_product',\n params: { product_id, fixture },\n });\n });\n\n (fixtures.pricing_options ?? []).forEach((entry, i) => {\n const { product_id, pricing_option_id, ...fixture } = entry;\n const label =\n pricing_option_id && product_id\n ? `${product_id}:${pricing_option_id}`\n : (pricing_option_id ?? product_id ?? `#${i}`);\n const missing: string[] = [];\n if (typeof product_id !== 'string' || product_id.length === 0) missing.push('product_id');\n if (typeof pricing_option_id !== 'string' || pricing_option_id.length === 0) missing.push('pricing_option_id');\n if (missing.length > 0) {\n calls.push({\n step_id: `seed_pricing_option.${label}`,\n title: `Seed pricing option ${label}`,\n scenario: 'seed_pricing_option',\n params: { ...(product_id && { product_id }), ...(pricing_option_id && { pricing_option_id }), fixture },\n authoring_error: `fixtures.pricing_options[${i}] requires non-empty string(s) for: ${missing.join(', ')}`,\n });\n return;\n }\n calls.push({\n step_id: `seed_pricing_option.${product_id}.${pricing_option_id}`,\n title: `Seed pricing option ${pricing_option_id} on ${product_id}`,\n scenario: 'seed_pricing_option',\n params: { product_id, pricing_option_id, fixture },\n });\n });\n\n (fixtures.creative_formats ?? []).forEach((entry, i) => {\n const { format_id, ...fixtureFields } = entry;\n const label = format_id ?? `#${i}`;\n if (typeof format_id !== 'string' || format_id.length === 0) {\n calls.push({\n step_id: `seed_creative_format.${label}`,\n title: `Seed creative format ${label}`,\n scenario: 'seed_creative_format',\n params: { fixture: seedFixtureFromFields(fixtureFields) },\n authoring_error: `fixtures.creative_formats[${i}] requires a non-empty string 'format_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_creative_format.${format_id}`,\n title: `Seed creative format ${format_id}`,\n scenario: 'seed_creative_format',\n params: { format_id, fixture: seedFixtureFromFields(fixtureFields) },\n });\n });\n\n (fixtures.creatives ?? []).forEach((entry, i) => {\n const { creative_id, ...fixture } = entry;\n const label = creative_id ?? `#${i}`;\n if (typeof creative_id !== 'string' || creative_id.length === 0) {\n calls.push({\n step_id: `seed_creative.${label}`,\n title: `Seed creative ${label}`,\n scenario: 'seed_creative',\n params: { fixture },\n authoring_error: `fixtures.creatives[${i}] requires a non-empty string 'creative_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_creative.${creative_id}`,\n title: `Seed creative ${creative_id}`,\n scenario: 'seed_creative',\n params: { creative_id, fixture },\n });\n });\n\n (fixtures.plans ?? []).forEach((entry, i) => {\n const { plan_id, ...fixture } = entry;\n const label = plan_id ?? `#${i}`;\n if (typeof plan_id !== 'string' || plan_id.length === 0) {\n calls.push({\n step_id: `seed_plan.${label}`,\n title: `Seed plan ${label}`,\n scenario: 'seed_plan',\n params: { fixture },\n authoring_error: `fixtures.plans[${i}] requires a non-empty string 'plan_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_plan.${plan_id}`,\n title: `Seed plan ${plan_id}`,\n scenario: 'seed_plan',\n params: { plan_id, fixture },\n });\n });\n\n (fixtures.media_buys ?? []).forEach((entry, i) => {\n const { media_buy_id, ...fixture } = entry;\n const label = media_buy_id ?? `#${i}`;\n if (typeof media_buy_id !== 'string' || media_buy_id.length === 0) {\n calls.push({\n step_id: `seed_media_buy.${label}`,\n title: `Seed media buy ${label}`,\n scenario: 'seed_media_buy',\n params: { fixture },\n authoring_error: `fixtures.media_buys[${i}] requires a non-empty string 'media_buy_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_media_buy.${media_buy_id}`,\n title: `Seed media buy ${media_buy_id}`,\n scenario: 'seed_media_buy',\n params: { media_buy_id, fixture },\n });\n });\n\n return calls;\n}\n\nfunction seedFixtureFromFields(fields: Record<string, unknown>): unknown {\n if (Object.keys(fields).length === 1 && Object.hasOwn(fields, 'fixture')) {\n return fields.fixture;\n }\n return fields;\n}\n\nexport interface ControllerSeedingResult {\n /** Synthetic pre-flight phase to prepend to `StoryboardResult.phases[]`. */\n phase: StoryboardPhaseResult;\n /** True when every seed call succeeded; false means downstream phases must cascade-skip. */\n allPassed: boolean;\n /** Step counts to fold into the storyboard-level totals. */\n passedCount: number;\n failedCount: number;\n /**\n * Agent didn't advertise `comply_test_controller` — the storyboard can't\n * be graded against this seller. The runner cascade-skips real phases\n * with canonical `missing_test_controller` instead of the seeding-failed\n * path. Implements the spec's `fixture_seed_unsupported` not_applicable\n * grade (storyboard-schema.yaml `skip_reasons`).\n */\n missingController?: boolean;\n /**\n * Agent advertised `comply_test_controller`, but not one of the generated\n * seed_* scenarios this storyboard requires. This is a coverage gap, not\n * a failed agent behavior.\n */\n seedUnsupported?: boolean;\n /** At least one declared strategy ladder exhausted without a binding. */\n fixtureUnsatisfied?: boolean;\n /** Run-scoped bindings pinned for all subsequent storyboard phases. */\n bindings?: FixtureBindingRegistry;\n /** Machine-readable AdCP 3.2 resolution evidence. */\n resolutionRecords?: FixtureResolutionRecord[];\n}\n\n/**\n * Fire every seed call for this storyboard. Returns `null` when seeding is\n * not applicable (opt-out, no declaration, empty fixtures) so the runner can\n * treat a no-op identically to a non-seeding storyboard.\n */\nexport async function runControllerSeeding(\n client: TestClient,\n storyboard: Storyboard,\n options: StoryboardRunOptions,\n context: StoryboardContext,\n discoveryClient: TestClient = client\n): Promise<ControllerSeedingResult | null> {\n if (options.skip_controller_seeding === true) return null;\n const calls = buildSeedCalls(storyboard.fixtures);\n if (calls.length === 0) return null;\n if (storyboard.fixture_resolution !== undefined) {\n const resolutionCalls =\n storyboard.prerequisites?.controller_seeding === true\n ? calls\n : calls.filter(call => call.scenario === 'seed_product' || call.scenario === 'seed_pricing_option');\n if (resolutionCalls.length === 0) return null;\n return runDeclaredFixtureResolution(client, discoveryClient, storyboard, options, context, resolutionCalls);\n }\n if (storyboard.prerequisites?.controller_seeding !== true) return null;\n\n // If we can see the agent's tool list and `comply_test_controller` is\n // absent, grade as not_applicable rather than issuing calls that are\n // guaranteed to fail on the wire. Spec: `fixture_seed_unsupported` in\n // storyboard-schema.yaml — missing test-controller is a coverage gap, not\n // a setup break. `options.agentTools` is discovered from the agent profile\n // or passed explicitly by the caller; we don't enforce when it's absent\n // because some harnesses skip tool discovery.\n if (options.agentTools && !options.agentTools.includes('comply_test_controller')) {\n return buildMissingControllerResult(storyboard, calls, context);\n }\n\n const start = Date.now();\n const steps: StoryboardStepResult[] = [];\n let passedCount = 0;\n let failedCount = 0;\n let allPassed = true;\n const seedContext = { correlation_id: `${storyboardCorrelationPrefix(storyboard)}--__seeding__` };\n const authoringErrorResult = buildAuthoringErrorResult(storyboard, calls, context, start);\n if (authoringErrorResult) return authoringErrorResult;\n const unsupportedScenario = await findUnsupportedSeedScenario(client, calls, options, seedContext);\n if (unsupportedScenario) {\n return buildUnsupportedSeedResult(\n storyboard,\n calls,\n context,\n unsupportedScenario.scenario,\n unsupportedScenario.detail\n );\n }\n\n for (const call of calls) {\n const stepStart = Date.now();\n let passed = false;\n let error: string | undefined;\n\n if (call.authoring_error) {\n error = call.authoring_error;\n } else {\n try {\n const raw = await callControllerRaw(\n client,\n { scenario: call.scenario, params: call.params, context: seedContext },\n options\n );\n const data = raw.data as { success?: boolean; error?: string; error_detail?: string } | undefined;\n if (raw.success && data?.success === true) {\n passed = true;\n } else if (raw.success && data?.success === false && data.error === 'UNKNOWN_SCENARIO') {\n return buildUnsupportedSeedResult(storyboard, calls, context, call.scenario, data.error_detail);\n } else {\n error = formatControllerError(call.scenario, raw, data);\n }\n } catch (err) {\n error = err instanceof Error ? err.message : String(err);\n }\n }\n\n const step: StoryboardStepResult = {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed,\n duration_ms: Date.now() - stepStart,\n validations: [],\n context,\n extraction: { path: 'none' },\n ...(error !== undefined && { error }),\n };\n steps.push(step);\n if (passed) {\n passedCount++;\n } else {\n failedCount++;\n allPassed = false;\n }\n }\n\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight)',\n passed: allPassed,\n steps,\n duration_ms: Date.now() - start,\n },\n allPassed,\n passedCount,\n failedCount,\n };\n}\n\ninterface DiscoveryCatalog {\n products: Array<Record<string, unknown>>;\n evidence: { page_count: number; product_count: number; cursors: string[] };\n}\n\ntype DiscoveryCatalogResult =\n | { ok: true; catalog: DiscoveryCatalog }\n | { ok: false; error: string; evidence?: unknown };\n\n/** AdCP 3.2 ordered per-handle seed/discover state machine. */\nasync function runDeclaredFixtureResolution(\n seedClient: TestClient,\n discoveryClient: TestClient,\n storyboard: Storyboard,\n options: StoryboardRunOptions,\n context: StoryboardContext,\n calls: SeedCall[]\n): Promise<ControllerSeedingResult> {\n const start = Date.now();\n const authoringErrorResult = buildAuthoringErrorResult(storyboard, calls, context, start);\n if (authoringErrorResult) return authoringErrorResult;\n\n const specs = buildFixtureResolutionSpecs(storyboard);\n const specByKey = new Map<string, FixtureResolutionSpec>();\n for (const spec of specs) {\n specByKey.set(\n spec.entityType === 'product'\n ? `seed_product\\0${spec.handle}`\n : `seed_pricing_option\\0${spec.parentProductHandle}\\0${spec.handle}`,\n spec\n );\n }\n const declaredCalls = new Map<string, SeedCall>();\n for (const call of calls) {\n const spec = resolutionSpecForCall(call, specByKey);\n if (spec) declaredCalls.set(resolutionSpecKey(spec), call);\n }\n const orderedDeclaredCalls = specs\n .map(spec => declaredCalls.get(resolutionSpecKey(spec)))\n .filter((call): call is SeedCall => call !== undefined);\n let declaredCallIndex = 0;\n const orderedCalls = calls.map(call =>\n resolutionSpecForCall(call, specByKey) ? orderedDeclaredCalls[declaredCallIndex++]! : call\n );\n\n const bindings = new FixtureBindingRegistry();\n const records: FixtureResolutionRecord[] = [];\n const steps: StoryboardStepResult[] = [];\n const claimedProducts = new Map<string, boolean>();\n const claimedPricingOptions = new Map<string, boolean>();\n const productStatuses = new Map<string, FixtureResolutionRecord['status']>();\n const seedContext = { correlation_id: `${storyboardCorrelationPrefix(storyboard)}--__seeding__` };\n const controllerMissing = options.agentTools?.includes('comply_test_controller') === false;\n let advertisedScenarios = controllerMissing ? new Set<string>() : controllerScenarioSetFromOptions(options);\n let scenarioLookupAttempted = advertisedScenarios !== null;\n const legacyCalls = calls.filter(call => resolutionSpecForCall(call, specByKey) === undefined);\n if (legacyCalls.length > 0) {\n if (controllerMissing) return buildMissingControllerResult(storyboard, legacyCalls, context);\n if (!advertisedScenarios) {\n advertisedScenarios = await fetchControllerScenarioSet(seedClient, options, seedContext);\n scenarioLookupAttempted = true;\n }\n if (advertisedScenarios) {\n const unsupported = legacyCalls.find(call => !call.authoring_error && !advertisedScenarios!.has(call.scenario));\n if (unsupported) {\n return buildUnsupportedSeedResult(\n storyboard,\n legacyCalls,\n context,\n unsupported.scenario,\n `list_scenarios did not advertise required seed scenario \"${unsupported.scenario}\".`\n );\n }\n }\n }\n const needsSeedStrategy = orderedCalls.some(call => {\n const spec = resolutionSpecForCall(call, specByKey);\n return !spec || spec.strategies.includes('seed');\n });\n if (needsSeedStrategy && !controllerMissing && !advertisedScenarios && !scenarioLookupAttempted) {\n advertisedScenarios = await fetchControllerScenarioSet(seedClient, options, seedContext);\n }\n let catalogPromise: Promise<DiscoveryCatalogResult> | undefined;\n const catalog = () => (catalogPromise ??= discoverProductCatalog(discoveryClient, options, context));\n\n let passedCount = 0;\n let failedCount = 0;\n let fixtureUnsatisfied = false;\n\n for (const call of orderedCalls) {\n const spec = resolutionSpecForCall(call, specByKey);\n // The first production slice only changes product and product-pricing\n // handles. Every other entity keeps the legacy seed-only behavior.\n if (!spec) {\n const legacy = await executeLegacySeedCall(seedClient, storyboard, call, options, context, seedContext);\n if (legacy.step.skip_reason === 'fixture_unsatisfied') {\n return buildUnsupportedSeedResult(storyboard, legacyCalls, context, call.scenario, legacy.step.skip?.detail);\n }\n steps.push(legacy.step);\n if (legacy.step.passed) passedCount++;\n else failedCount++;\n continue;\n }\n\n const attempts: FixtureResolutionAttempt[] = [];\n let boundIds: FixtureResolutionRecord['seller_ids'];\n let chosenStrategy: FixtureResolutionRecord['strategy'];\n let failure: string | undefined;\n const stepStart = Date.now();\n const parentStatus = spec.parentProductHandle ? productStatuses.get(spec.parentProductHandle) : undefined;\n const parentUnavailable = spec.entityType === 'product_pricing_option' && parentStatus !== 'resolved';\n if (parentUnavailable) {\n const strategy = spec.strategies[0]!;\n const detail =\n parentStatus === 'failed'\n ? `parent product handle \"${spec.parentProductHandle}\" failed resolution`\n : `parent product handle \"${spec.parentProductHandle}\" is unavailable`;\n attempts.push({ strategy, disposition: parentStatus === 'failed' ? 'failed' : 'unavailable', detail });\n if (parentStatus === 'failed') failure = detail;\n }\n\n for (const strategy of parentUnavailable ? [] : spec.strategies) {\n if (strategy === 'seed') {\n const advertised = advertisedScenarios?.has(call.scenario);\n if (controllerMissing || advertised === false) {\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: controllerMissing\n ? 'comply_test_controller is not advertised'\n : `list_scenarios did not advertise ${call.scenario}`,\n });\n continue;\n }\n try {\n const controllerRequest = applyFixtureBindingsToRequest(\n { scenario: call.scenario, params: call.params },\n 'comply_test_controller',\n bindings,\n options.adcpVersion ?? ADCP_VERSION\n );\n const raw = await callControllerRaw(\n seedClient,\n {\n scenario: call.scenario,\n params: isPlainRecord(controllerRequest.params) ? controllerRequest.params : call.params,\n context: seedContext,\n },\n options\n );\n const data = raw.data as { success?: boolean; error?: string; error_detail?: string } | undefined;\n if (raw.success && data?.success === true) {\n boundIds = bindSeededFixture(spec, bindings);\n if (spec.entityType === 'product') {\n recordIdentityClaim(claimedProducts, boundIds.product_id!, spec.allowReuse);\n } else {\n recordIdentityClaim(\n claimedPricingOptions,\n `${boundIds.product_id}\\0${boundIds.pricing_option_id}`,\n spec.allowReuse\n );\n }\n chosenStrategy = strategy;\n attempts.push({\n strategy,\n disposition: 'resolved',\n detail: `${call.scenario} accepted the authored literal id`,\n });\n break;\n }\n if (raw.success && data?.success === false && data.error === 'UNKNOWN_SCENARIO' && advertised !== true) {\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: data.error_detail ?? `${call.scenario} returned UNKNOWN_SCENARIO`,\n });\n continue;\n }\n failure = formatControllerError(call.scenario, raw, data);\n attempts.push({ strategy, disposition: 'failed', detail: failure });\n break;\n } catch (err) {\n failure = err instanceof Error ? err.message : String(err);\n attempts.push({ strategy, disposition: 'failed', detail: failure });\n break;\n }\n }\n\n if (strategy === 'discover') {\n if (options.agentTools && !options.agentTools.includes('get_products')) {\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: 'agent did not advertise get_products',\n });\n continue;\n }\n const discovered = await catalog();\n if (!discovered.ok) {\n failure = discovered.error;\n attempts.push({ strategy, disposition: 'failed', detail: failure, response: discovered.evidence });\n break;\n }\n const selected = selectDiscoveredFixture(\n spec,\n discovered.catalog.products,\n bindings,\n claimedProducts,\n claimedPricingOptions\n );\n if (!selected.ok) {\n if (selected.failed) {\n failure = selected.detail;\n attempts.push({\n strategy,\n disposition: 'failed',\n detail: selected.detail,\n response: discovered.catalog.evidence,\n });\n break;\n }\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: selected.detail,\n response: discovered.catalog.evidence,\n });\n continue;\n }\n boundIds = selected.boundIds;\n chosenStrategy = strategy;\n attempts.push({\n strategy,\n disposition: 'resolved',\n detail: selected.detail,\n response: { ...discovered.catalog.evidence, selected: selected.boundIds },\n });\n break;\n }\n }\n\n const status: FixtureResolutionRecord['status'] = boundIds ? 'resolved' : failure ? 'failed' : 'unsatisfied';\n if (spec.entityType === 'product') productStatuses.set(spec.handle, status);\n const record: FixtureResolutionRecord = {\n fixture_type: spec.entityType === 'product' ? 'product' : 'pricing_option',\n handle: spec.handle,\n ...(spec.parentProductHandle && { product_handle: spec.parentProductHandle }),\n requirements: spec.clauses,\n strategies_attempted: attempts,\n status,\n ...(chosenStrategy && { strategy: chosenStrategy }),\n ...(boundIds && { seller_ids: boundIds }),\n };\n records.push(record);\n\n if (status !== 'unsatisfied') {\n steps.push({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: chosenStrategy === 'discover' ? 'get_products' : 'comply_test_controller',\n passed: status !== 'failed',\n duration_ms: Date.now() - stepStart,\n validations: [],\n context,\n extraction: { path: 'none' },\n ...(failure && { error: failure }),\n });\n }\n if (status === 'failed') failedCount++;\n else if (status === 'unsatisfied') fixtureUnsatisfied = true;\n else passedCount++;\n }\n\n const allPassed = failedCount === 0;\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Fixture resolution (pre-flight)',\n passed: allPassed,\n steps,\n duration_ms: Date.now() - start,\n },\n allPassed,\n passedCount,\n failedCount,\n fixtureUnsatisfied,\n bindings,\n resolutionRecords: records,\n };\n}\n\nfunction resolutionSpecKey(spec: FixtureResolutionSpec): string {\n return spec.entityType === 'product'\n ? `seed_product\\0${spec.handle}`\n : `seed_pricing_option\\0${spec.parentProductHandle}\\0${spec.handle}`;\n}\n\nfunction resolutionSpecForCall(\n call: SeedCall,\n specs: ReadonlyMap<string, FixtureResolutionSpec>\n): FixtureResolutionSpec | undefined {\n if (call.scenario === 'seed_product') {\n return specs.get(`seed_product\\0${String(call.params.product_id ?? '')}`);\n }\n if (call.scenario === 'seed_pricing_option') {\n return specs.get(\n `seed_pricing_option\\0${String(call.params.product_id ?? '')}\\0${String(call.params.pricing_option_id ?? '')}`\n );\n }\n return undefined;\n}\n\nfunction bindSeededFixture(\n spec: FixtureResolutionSpec,\n bindings: FixtureBindingRegistry\n): NonNullable<FixtureResolutionRecord['seller_ids']> {\n if (spec.entityType === 'product') {\n bindings.bindProduct(spec.handle, spec.handle);\n return { product_id: spec.handle };\n }\n const parent = spec.parentProductHandle!;\n bindings.bindPricingOption(parent, spec.handle, spec.handle);\n return { product_id: bindings.productId(parent) ?? parent, pricing_option_id: spec.handle };\n}\n\nasync function executeLegacySeedCall(\n client: TestClient,\n storyboard: Storyboard,\n call: SeedCall,\n options: StoryboardRunOptions,\n context: StoryboardContext,\n seedContext: Record<string, unknown>\n): Promise<{ step: StoryboardStepResult }> {\n const started = Date.now();\n try {\n const raw = await callControllerRaw(\n client,\n { scenario: call.scenario, params: call.params, context: seedContext },\n options\n );\n const data = raw.data as { success?: boolean; error?: string; error_detail?: string } | undefined;\n if (raw.success && data?.success === true) {\n return {\n step: {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: true,\n duration_ms: Date.now() - started,\n validations: [],\n context,\n extraction: { path: 'none' },\n },\n };\n }\n const unknown = raw.success && data?.success === false && data.error === 'UNKNOWN_SCENARIO';\n const detail = unknown\n ? `fixture_unsatisfied: ${call.scenario} is unavailable and no alternate strategy is declared`\n : formatControllerError(call.scenario, raw, data);\n return {\n step: {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: unknown,\n ...(unknown && {\n skipped: true,\n skip_reason: 'fixture_unsatisfied' as const,\n skip: { reason: 'not_applicable' as const, detail },\n }),\n duration_ms: Date.now() - started,\n validations: [],\n context,\n extraction: { path: 'none' },\n ...(!unknown && { error: detail }),\n },\n };\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n return {\n step: {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: false,\n duration_ms: Date.now() - started,\n validations: [],\n context,\n extraction: { path: 'none' },\n error: detail,\n },\n };\n }\n}\n\nasync function discoverProductCatalog(\n client: TestClient,\n options: StoryboardRunOptions,\n context: StoryboardContext\n): Promise<DiscoveryCatalogResult> {\n const contextAccount = isPlainRecord(context.account) ? context.account : undefined;\n const baseAccount = contextAccount ?? resolveAccount(options);\n const account: Record<string, unknown> = { ...baseAccount };\n if (!('account_id' in account)) {\n account.sandbox = options.disable_sandbox === true || options.sandbox === false ? false : true;\n }\n const accountBrand = isPlainRecord(account.brand) ? account.brand : undefined;\n const brand = isPlainRecord(context.brand) ? context.brand : (accountBrand ?? resolveBrand(options));\n const products: Array<Record<string, unknown>> = [];\n const seenProductIds = new Set<string>();\n const cursors: string[] = [];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n let pageCount = 0;\n do {\n if (pageCount >= 1_000) {\n return { ok: false, error: 'fixture discovery pagination exceeded the 1,000-page safety limit' };\n }\n const request: Record<string, unknown> = {\n buying_mode: 'wholesale',\n brand,\n account,\n pagination: { max_results: 100, ...(cursor && { cursor }) },\n };\n let result;\n try {\n result = await executeStoryboardTask(client, 'get_products', request, { signal: options.signal });\n } catch (err) {\n return {\n ok: false,\n error: `fixture discovery transport failure: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n pageCount++;\n if (!result.success) {\n return {\n ok: false,\n error: `fixture discovery get_products rejected: ${result.error ?? result.adcp_error?.code ?? 'unknown error'}`,\n evidence: { page_count: pageCount, request },\n };\n }\n let schemaFailure: string | undefined;\n try {\n const validator = getValidator('get_products', 'sync', options.adcpVersion ?? ADCP_VERSION);\n if (validator) {\n const responseData: unknown = result.data;\n const schemaData = isPlainRecord(responseData)\n ? injectLegacyEnvelopeStatus(responseData, { toolName: 'get_products' })\n : responseData;\n if (!validator(schemaData)) {\n schemaFailure = (validator.errors ?? [])\n .map(error => `${error.instancePath || '/'} ${error.message ?? error.keyword}`)\n .join('; ');\n }\n } else {\n const schema = validateResponseSchema('get_products', result.data, options.adcpVersion);\n if (!schema.passed) schemaFailure = schema.error ?? schema.details ?? 'schema validation failed';\n }\n } catch (err) {\n schemaFailure = `response schema unavailable: ${err instanceof Error ? err.message : String(err)}`;\n }\n if (schemaFailure) {\n return {\n ok: false,\n error: `fixture discovery returned malformed get_products response: ${schemaFailure}`,\n evidence: { page_count: pageCount },\n };\n }\n if (!isPlainRecord(result.data)) {\n return { ok: false, error: 'fixture discovery returned a non-object get_products response' };\n }\n const pageProducts = result.data.products;\n if (pageProducts !== undefined && !Array.isArray(pageProducts)) {\n return { ok: false, error: 'fixture discovery get_products.products is not an array' };\n }\n for (const product of pageProducts ?? []) {\n if (!isPlainRecord(product) || typeof product.product_id !== 'string' || product.product_id.length === 0) {\n return { ok: false, error: 'fixture discovery returned a product without a non-empty product_id' };\n }\n if (seenProductIds.has(product.product_id)) {\n return {\n ok: false,\n error: `fixture discovery returned duplicate product_id \"${product.product_id}\"; response order cannot resolve duplicate identities`,\n };\n }\n seenProductIds.add(product.product_id);\n if (Array.isArray(product.pricing_options)) {\n const seenPricingIds = new Set<string>();\n for (const option of product.pricing_options) {\n if (!isPlainRecord(option) || typeof option.pricing_option_id !== 'string') continue;\n if (seenPricingIds.has(option.pricing_option_id)) {\n return {\n ok: false,\n error: `fixture discovery returned duplicate pricing option identity \"${product.product_id}\\u0000${option.pricing_option_id}\"`,\n };\n }\n seenPricingIds.add(option.pricing_option_id);\n }\n }\n products.push(product);\n if (products.length > 100_000) {\n return { ok: false, error: 'fixture discovery exceeded the 100,000-product safety limit' };\n }\n }\n const pagination = isPlainRecord(result.data.pagination) ? result.data.pagination : undefined;\n if (pagination?.has_more === true) {\n const next = pagination.cursor;\n if (typeof next !== 'string' || next.length === 0) {\n return { ok: false, error: 'fixture discovery pagination is broken: has_more=true without cursor' };\n }\n if (seenCursors.has(next)) {\n return { ok: false, error: `fixture discovery pagination is broken: repeated cursor \"${next}\"` };\n }\n seenCursors.add(next);\n cursors.push(next);\n cursor = next;\n } else {\n cursor = undefined;\n }\n } while (cursor);\n return {\n ok: true,\n catalog: { products, evidence: { page_count: pageCount, product_count: products.length, cursors } },\n };\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction utf8Compare(a: string, b: string): number {\n return Buffer.compare(Buffer.from(a, 'utf8'), Buffer.from(b, 'utf8'));\n}\n\ntype SelectedFixture =\n | { ok: true; boundIds: NonNullable<FixtureResolutionRecord['seller_ids']>; detail: string }\n | { ok: false; failed: boolean; detail: string };\n\nfunction selectDiscoveredFixture(\n spec: FixtureResolutionSpec,\n products: Array<Record<string, unknown>>,\n bindings: FixtureBindingRegistry,\n claimedProducts: Map<string, boolean>,\n claimedPricingOptions: Map<string, boolean>\n): SelectedFixture {\n if (spec.entityType === 'product') {\n const candidates = products\n .filter(product => matchesFixtureRequirements(product, spec.clauses))\n .filter(product => identityCanBeClaimed(claimedProducts, product.product_id as string, spec.allowReuse))\n .sort((a, b) => utf8Compare(a.product_id as string, b.product_id as string));\n const selected = candidates[0];\n if (!selected)\n return { ok: false, failed: false, detail: 'no discovered product satisfied the authored requirements' };\n const productId = selected.product_id as string;\n bindings.bindProduct(spec.handle, productId);\n recordIdentityClaim(claimedProducts, productId, spec.allowReuse);\n return {\n ok: true,\n boundIds: { product_id: productId },\n detail: `selected product_id \"${productId}\" by UTF-8 bytewise order`,\n };\n }\n\n const parentHandle = spec.parentProductHandle!;\n const sellerProductId = bindings.productId(parentHandle);\n if (!sellerProductId) {\n return {\n ok: false,\n failed: true,\n detail: `pricing-option discovery requires bound parent product handle \"${parentHandle}\"`,\n };\n }\n const product = products.find(candidate => candidate.product_id === sellerProductId);\n if (!product) {\n return {\n ok: false,\n failed: true,\n detail: `bound parent product_id \"${sellerProductId}\" was absent from the completed discovery catalog`,\n };\n }\n const options = Array.isArray(product.pricing_options) ? product.pricing_options : [];\n const candidates = options\n .filter(isPlainRecord)\n .filter(option => typeof option.pricing_option_id === 'string' && option.pricing_option_id.length > 0)\n .filter(option => matchesFixtureRequirements(option, spec.clauses))\n .filter(option => {\n const identity = `${sellerProductId}\\0${option.pricing_option_id as string}`;\n return identityCanBeClaimed(claimedPricingOptions, identity, spec.allowReuse);\n })\n .sort((a, b) =>\n utf8Compare(\n `${sellerProductId}\\0${a.pricing_option_id as string}`,\n `${sellerProductId}\\0${b.pricing_option_id as string}`\n )\n );\n const selected = candidates[0];\n if (!selected) {\n return {\n ok: false,\n failed: false,\n detail: 'no pricing option on the bound product satisfied the authored requirements',\n };\n }\n const pricingOptionId = selected.pricing_option_id as string;\n bindings.bindPricingOption(parentHandle, spec.handle, pricingOptionId);\n recordIdentityClaim(claimedPricingOptions, `${sellerProductId}\\0${pricingOptionId}`, spec.allowReuse);\n return {\n ok: true,\n boundIds: { product_id: sellerProductId, pricing_option_id: pricingOptionId },\n detail: `selected pricing option \"${sellerProductId}\\u0000${pricingOptionId}\" by UTF-8 bytewise order`,\n };\n}\n\n/** A seller identity may be shared only when every claimant opts into reuse. */\nfunction identityCanBeClaimed(claims: ReadonlyMap<string, boolean>, identity: string, allowReuse: boolean): boolean {\n const existingAllowsReuse = claims.get(identity);\n return existingAllowsReuse === undefined || (existingAllowsReuse && allowReuse);\n}\n\nfunction recordIdentityClaim(claims: Map<string, boolean>, identity: string, allowReuse: boolean): void {\n claims.set(identity, (claims.get(identity) ?? true) && allowReuse);\n}\n\nfunction storyboardCorrelationPrefix(storyboard: Storyboard): string {\n for (const phase of storyboard.phases) {\n for (const step of phase.steps) {\n const requestContext = step.sample_request?.context;\n if (!requestContext || typeof requestContext !== 'object' || Array.isArray(requestContext)) continue;\n const correlationId = (requestContext as { correlation_id?: unknown }).correlation_id;\n if (typeof correlationId !== 'string' || correlationId.length === 0) continue;\n const suffixSeparator = correlationId.lastIndexOf('--');\n return suffixSeparator > 0 ? correlationId.slice(0, suffixSeparator) : correlationId;\n }\n }\n return storyboard.id;\n}\n\nfunction buildAuthoringErrorResult(\n storyboard: Storyboard,\n calls: SeedCall[],\n context: StoryboardContext,\n start: number\n): ControllerSeedingResult | null {\n const authoringErrors = calls.filter((call): call is SeedCall & { authoring_error: string } =>\n Boolean(call.authoring_error)\n );\n if (authoringErrors.length === 0) return null;\n const steps: StoryboardStepResult[] = authoringErrors.map(call => ({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: false,\n duration_ms: 0,\n validations: [],\n context,\n extraction: { path: 'none' },\n error: call.authoring_error,\n }));\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight) — invalid storyboard fixtures',\n passed: false,\n steps,\n duration_ms: Date.now() - start,\n },\n allPassed: false,\n passedCount: 0,\n failedCount: steps.length,\n };\n}\n\nasync function findUnsupportedSeedScenario(\n client: TestClient,\n calls: SeedCall[],\n options: StoryboardRunOptions,\n seedContext: Record<string, unknown>\n): Promise<{ scenario: SeedScenario | BuyerAgentSeedScenario; detail: string } | null> {\n const requiredScenarios = [...new Set(calls.filter(call => !call.authoring_error).map(call => call.scenario))];\n if (requiredScenarios.length === 0) return null;\n\n let advertisedScenarios = controllerScenarioSetFromOptions(options);\n if (!advertisedScenarios) {\n advertisedScenarios = await fetchControllerScenarioSet(client, options, seedContext);\n }\n if (!advertisedScenarios) return null;\n\n for (const scenario of requiredScenarios) {\n if (!advertisedScenarios.has(scenario)) {\n return {\n scenario,\n detail: `list_scenarios did not advertise required seed scenario \"${scenario}\".`,\n };\n }\n }\n return null;\n}\n\nfunction controllerScenarioSetFromOptions(options: StoryboardRunOptions): Set<string> | null {\n const capabilities = options._controllerCapabilities;\n if (capabilities?.detected !== true) return null;\n return new Set((capabilities.scenarios as readonly string[]).filter(scenario => typeof scenario === 'string'));\n}\n\nasync function fetchControllerScenarioSet(\n client: TestClient,\n options: StoryboardRunOptions,\n seedContext: Record<string, unknown>\n): Promise<Set<string> | null> {\n try {\n const raw = await callControllerRaw(client, { scenario: 'list_scenarios', context: seedContext }, options);\n const data = raw.data as { success?: boolean; scenarios?: unknown } | undefined;\n if (!raw.success || data?.success !== true) return null;\n if (Array.isArray(data.scenarios)) {\n return new Set(data.scenarios.filter((scenario): scenario is string => typeof scenario === 'string'));\n }\n if (data.scenarios && typeof data.scenarios === 'object') {\n return new Set(Object.keys(data.scenarios));\n }\n return null;\n } catch {\n return null;\n }\n}\n\nconst UNSUPPORTED_SEED_DETAIL =\n 'Skipped: agent advertised comply_test_controller, but does not implement a seed_* scenario required by this storyboard (`fixture_seed_unsupported`). Storyboard grades not_applicable — the buyer-side flow depends on pre-seeded state the agent has no way to accept.';\n\nfunction buildUnsupportedSeedResult(\n storyboard: Storyboard,\n calls: Array<{ step_id: string; title: string }>,\n context: StoryboardContext,\n scenario: SeedScenario | BuyerAgentSeedScenario,\n detail?: string\n): ControllerSeedingResult {\n const skipDetail = detail\n ? `${UNSUPPORTED_SEED_DETAIL} Unsupported scenario ${scenario}: ${detail}`\n : `${UNSUPPORTED_SEED_DETAIL} Unsupported scenario: ${scenario}.`;\n const steps: StoryboardStepResult[] = calls.map(call => ({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: true,\n skipped: true,\n skip_reason: 'fixture_seed_unsupported',\n skip: { reason: 'not_applicable', detail: skipDetail },\n duration_ms: 0,\n validations: [],\n context,\n extraction: { path: 'none' },\n }));\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight) — agent lacks required seed scenario',\n passed: true,\n steps,\n duration_ms: 0,\n },\n allPassed: true,\n passedCount: 0,\n failedCount: 0,\n seedUnsupported: true,\n };\n}\n\nfunction formatControllerError(\n scenario: SeedScenario | BuyerAgentSeedScenario,\n raw: { success: boolean; error?: string },\n data: { success?: boolean; error?: string; error_detail?: string } | undefined\n): string {\n if (data?.error_detail) return data.error ? `${data.error}: ${data.error_detail}` : data.error_detail;\n if (data?.error) return data.error;\n return raw.error ?? `comply_test_controller ${scenario} call failed`;\n}\n\nconst MISSING_CONTROLLER_DETAIL =\n 'Skipped: agent did not advertise comply_test_controller, so fixture seeding (`fixture_seed_unsupported`) cannot run. Storyboard grades not_applicable — the buyer-side flow depends on pre-seeded state the agent has no way to accept.';\n\nfunction buildMissingControllerResult(\n storyboard: Storyboard,\n calls: Array<{ step_id: string; title: string }>,\n context: StoryboardContext\n): ControllerSeedingResult {\n const steps: StoryboardStepResult[] = calls.map(call => ({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: true,\n skipped: true,\n skip_reason: 'missing_test_controller',\n skip: { reason: 'missing_test_controller', detail: MISSING_CONTROLLER_DETAIL },\n duration_ms: 0,\n validations: [],\n context,\n extraction: { path: 'none' },\n }));\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight) — agent lacks comply_test_controller',\n passed: true,\n steps,\n duration_ms: 0,\n },\n allPassed: true,\n passedCount: 0,\n failedCount: 0,\n missingController: true,\n };\n}\n"],"mappings":"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","names":["candidates","product","selected"]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/seeding.ts"],"sourcesContent":["/**\n * Pre-flight `comply_test_controller` seeding.\n *\n * Spec: adcontextprotocol/adcp#2585 (fixtures block + `controller_seeding`\n * flag) + adcontextprotocol/adcp#2584 (seed_* scenarios on\n * `comply_test_controller`). Storyboards such as `sales_non_guaranteed`,\n * `creative_ad_server`, `governance_delivery_monitor`,\n * `media_buy_governance_escalation`, and `governance_spend_authority`\n * reference fixture IDs (product_ids, pricing_option_ids, creative_ids,\n * plan_ids, media_buy_ids) that the seller must already hold before the\n * buyer-side flow runs. This module fires the `seed_*` scenarios derived\n * from the storyboard's top-level `fixtures:` block before the first real\n * phase, so the seller's buyer-agent ledger and catalog are populated ahead\n * of any `sync_accounts` / `create_media_buy` / `sync_creatives` / etc. call\n * that would otherwise fail or route through the wrong commercial-state gate.\n *\n * Failures here surface as a dedicated synthetic phase (`__controller_seeding__`)\n * so an implementor reading the report can distinguish \"setup broke\" from\n * \"buyer did something wrong\" — the runner short-circuits the rest of the\n * phases on any seed failure, emitting a cascade skip with reason\n * `controller_seeding_failed`.\n */\n\nimport { resolveAccount, resolveBrand, validateResponseSchema, type TestClient } from '../client';\nimport { getValidator } from '../../validation/schema-loader';\nimport { ADCP_VERSION } from '../../version';\nimport { injectLegacyEnvelopeStatus } from '../../utils/envelope-status-compat';\nimport { callControllerRaw } from '../test-controller';\nimport { executeStoryboardTask } from './task-map';\nimport {\n buildFixtureResolutionSpecs,\n applyFixtureBindingsToRequest,\n FixtureBindingRegistry,\n matchesFixtureRequirements,\n type FixtureResolutionSpec,\n} from './fixture-resolution';\nimport type {\n FixtureResolutionAttempt,\n FixtureResolutionRecord,\n Storyboard,\n StoryboardContext,\n StoryboardFixtures,\n StoryboardPhaseResult,\n StoryboardRunOptions,\n StoryboardStepResult,\n} from './types';\n\n/** Synthetic phase id used in `StoryboardResult.phases[]` for the seed pass. */\nexport const CONTROLLER_SEEDING_PHASE_ID = '__controller_seeding__';\n\n/** Seed scenario names. Kept local — the server-side `SEED_SCENARIOS`\n * constant from `src/lib/server/test-controller.ts` is authoritative, but\n * importing it here would cross the testing ⇄ server module boundary. */\ntype SeedScenario =\n | 'seed_account'\n | 'seed_product'\n | 'seed_pricing_option'\n | 'seed_creative_format'\n | 'seed_creative'\n | 'seed_plan'\n | 'seed_media_buy';\ntype BuyerAgentSeedScenario = 'seed_buyer_agent';\n\ninterface SeedCall {\n step_id: string;\n title: string;\n scenario: SeedScenario | BuyerAgentSeedScenario;\n params: Record<string, unknown>;\n /** Authoring error (e.g. missing required id). When set, the call fails at\n * build time — no controller request is issued. */\n authoring_error?: string;\n}\n\n/**\n * Translate a storyboard `fixtures:` block into an ordered list of seed\n * calls. Each entry's id field(s) are lifted into the scenario params; every\n * remaining field rides in `params.fixture` verbatim. Missing required ids\n * produce an authoring-error marker the runner surfaces as a failed seed\n * step (rather than crashing or silently skipping).\n */\n// Top-level fixture keys are forwarded to the server verbatim inside\n// `params.fixture`. Prototype-pollution rejection (`__proto__`, `constructor`,\n// `prototype`) is enforced by the server-side `dispatchSeed` at a single\n// canonical point (`src/lib/server/test-controller.ts`), NOT re-guarded here:\n// surfacing the rejection through the normal seed-error path keeps one source\n// of truth for the check, and the server-side handler is where a seed request\n// can actually land from any client implementation. A future refactor that\n// removes the server check must add the client guard before removing it.\nexport function buildSeedCalls(fixtures: StoryboardFixtures | undefined): SeedCall[] {\n if (!fixtures) return [];\n const calls: SeedCall[] = [];\n\n (fixtures.accounts ?? []).forEach((entry, i) => {\n const { account_id, ...fixtureFields } = entry;\n const label = account_id ?? `#${i}`;\n if (typeof account_id !== 'string' || account_id.length === 0) {\n calls.push({\n step_id: `seed_account.${label}`,\n title: `Seed account ${label}`,\n scenario: 'seed_account',\n params: { fixture: seedFixtureFromFields(fixtureFields) },\n authoring_error: `fixtures.accounts[${i}] requires a non-empty string 'account_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_account.${account_id}`,\n title: `Seed account ${account_id}`,\n scenario: 'seed_account',\n params: { account_id, fixture: seedFixtureFromFields(fixtureFields) },\n });\n });\n\n (fixtures.buyer_agents ?? []).forEach((entry, i) => {\n const { agent_url, ...params } = entry;\n const label = agent_url ?? `#${i}`;\n if (typeof agent_url !== 'string' || agent_url.length === 0) {\n calls.push({\n step_id: `seed_buyer_agent.${label}`,\n title: `Seed buyer agent ${label}`,\n scenario: 'seed_buyer_agent',\n params,\n authoring_error: `fixtures.buyer_agents[${i}] requires a non-empty string 'agent_url'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_buyer_agent.${agent_url}`,\n title: `Seed buyer agent ${agent_url}`,\n scenario: 'seed_buyer_agent',\n params: { agent_url, ...params },\n });\n });\n\n (fixtures.products ?? []).forEach((entry, i) => {\n const { product_id, ...fixture } = entry;\n const label = product_id ?? `#${i}`;\n if (typeof product_id !== 'string' || product_id.length === 0) {\n calls.push({\n step_id: `seed_product.${label}`,\n title: `Seed product ${label}`,\n scenario: 'seed_product',\n params: { fixture },\n authoring_error: `fixtures.products[${i}] requires a non-empty string 'product_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_product.${product_id}`,\n title: `Seed product ${product_id}`,\n scenario: 'seed_product',\n params: { product_id, fixture },\n });\n });\n\n (fixtures.pricing_options ?? []).forEach((entry, i) => {\n const { product_id, pricing_option_id, ...fixture } = entry;\n const label =\n pricing_option_id && product_id\n ? `${product_id}:${pricing_option_id}`\n : (pricing_option_id ?? product_id ?? `#${i}`);\n const missing: string[] = [];\n if (typeof product_id !== 'string' || product_id.length === 0) missing.push('product_id');\n if (typeof pricing_option_id !== 'string' || pricing_option_id.length === 0) missing.push('pricing_option_id');\n if (missing.length > 0) {\n calls.push({\n step_id: `seed_pricing_option.${label}`,\n title: `Seed pricing option ${label}`,\n scenario: 'seed_pricing_option',\n params: { ...(product_id && { product_id }), ...(pricing_option_id && { pricing_option_id }), fixture },\n authoring_error: `fixtures.pricing_options[${i}] requires non-empty string(s) for: ${missing.join(', ')}`,\n });\n return;\n }\n calls.push({\n step_id: `seed_pricing_option.${product_id}.${pricing_option_id}`,\n title: `Seed pricing option ${pricing_option_id} on ${product_id}`,\n scenario: 'seed_pricing_option',\n params: { product_id, pricing_option_id, fixture },\n });\n });\n\n (fixtures.creative_formats ?? []).forEach((entry, i) => {\n const { format_id, ...fixtureFields } = entry;\n const label = format_id ?? `#${i}`;\n if (typeof format_id !== 'string' || format_id.length === 0) {\n calls.push({\n step_id: `seed_creative_format.${label}`,\n title: `Seed creative format ${label}`,\n scenario: 'seed_creative_format',\n params: { fixture: seedFixtureFromFields(fixtureFields) },\n authoring_error: `fixtures.creative_formats[${i}] requires a non-empty string 'format_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_creative_format.${format_id}`,\n title: `Seed creative format ${format_id}`,\n scenario: 'seed_creative_format',\n params: { format_id, fixture: seedFixtureFromFields(fixtureFields) },\n });\n });\n\n (fixtures.creatives ?? []).forEach((entry, i) => {\n const { creative_id, ...fixture } = entry;\n const label = creative_id ?? `#${i}`;\n if (typeof creative_id !== 'string' || creative_id.length === 0) {\n calls.push({\n step_id: `seed_creative.${label}`,\n title: `Seed creative ${label}`,\n scenario: 'seed_creative',\n params: { fixture },\n authoring_error: `fixtures.creatives[${i}] requires a non-empty string 'creative_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_creative.${creative_id}`,\n title: `Seed creative ${creative_id}`,\n scenario: 'seed_creative',\n params: { creative_id, fixture },\n });\n });\n\n (fixtures.plans ?? []).forEach((entry, i) => {\n const { plan_id, ...fixture } = entry;\n const label = plan_id ?? `#${i}`;\n if (typeof plan_id !== 'string' || plan_id.length === 0) {\n calls.push({\n step_id: `seed_plan.${label}`,\n title: `Seed plan ${label}`,\n scenario: 'seed_plan',\n params: { fixture },\n authoring_error: `fixtures.plans[${i}] requires a non-empty string 'plan_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_plan.${plan_id}`,\n title: `Seed plan ${plan_id}`,\n scenario: 'seed_plan',\n params: { plan_id, fixture },\n });\n });\n\n (fixtures.media_buys ?? []).forEach((entry, i) => {\n const { media_buy_id, ...fixture } = entry;\n const label = media_buy_id ?? `#${i}`;\n if (typeof media_buy_id !== 'string' || media_buy_id.length === 0) {\n calls.push({\n step_id: `seed_media_buy.${label}`,\n title: `Seed media buy ${label}`,\n scenario: 'seed_media_buy',\n params: { fixture },\n authoring_error: `fixtures.media_buys[${i}] requires a non-empty string 'media_buy_id'`,\n });\n return;\n }\n calls.push({\n step_id: `seed_media_buy.${media_buy_id}`,\n title: `Seed media buy ${media_buy_id}`,\n scenario: 'seed_media_buy',\n params: { media_buy_id, fixture },\n });\n });\n\n return calls;\n}\n\nfunction seedFixtureFromFields(fields: Record<string, unknown>): unknown {\n if (Object.keys(fields).length === 1 && Object.hasOwn(fields, 'fixture')) {\n return fields.fixture;\n }\n return fields;\n}\n\nexport interface ControllerSeedingResult {\n /** Synthetic pre-flight phase to prepend to `StoryboardResult.phases[]`. */\n phase: StoryboardPhaseResult;\n /** True when every seed call succeeded; false means downstream phases must cascade-skip. */\n allPassed: boolean;\n /** Step counts to fold into the storyboard-level totals. */\n passedCount: number;\n failedCount: number;\n /**\n * Agent didn't advertise `comply_test_controller` — the storyboard can't\n * be graded against this seller. The runner cascade-skips real phases\n * with canonical `missing_test_controller` instead of the seeding-failed\n * path. Implements the spec's `fixture_seed_unsupported` not_applicable\n * grade (storyboard-schema.yaml `skip_reasons`).\n */\n missingController?: boolean;\n /**\n * Agent advertised `comply_test_controller`, but not one of the generated\n * seed_* scenarios this storyboard requires. This is a coverage gap, not\n * a failed agent behavior.\n */\n seedUnsupported?: boolean;\n /** At least one declared strategy ladder exhausted without a binding. */\n fixtureUnsatisfied?: boolean;\n /** Run-scoped bindings pinned for all subsequent storyboard phases. */\n bindings?: FixtureBindingRegistry;\n /** Machine-readable AdCP 3.2 resolution evidence. */\n resolutionRecords?: FixtureResolutionRecord[];\n}\n\n/**\n * Fire every seed call for this storyboard. Returns `null` when seeding is\n * not applicable (opt-out, no declaration, empty fixtures) so the runner can\n * treat a no-op identically to a non-seeding storyboard.\n */\nexport async function runControllerSeeding(\n client: TestClient,\n storyboard: Storyboard,\n options: StoryboardRunOptions,\n context: StoryboardContext,\n discoveryClient: TestClient = client\n): Promise<ControllerSeedingResult | null> {\n if (options.skip_controller_seeding === true) return null;\n const calls = buildSeedCalls(storyboard.fixtures);\n if (calls.length === 0) return null;\n if (storyboard.fixture_resolution !== undefined) {\n const resolutionCalls =\n storyboard.prerequisites?.controller_seeding === true\n ? calls\n : calls.filter(call => call.scenario === 'seed_product' || call.scenario === 'seed_pricing_option');\n if (resolutionCalls.length === 0) return null;\n return runDeclaredFixtureResolution(client, discoveryClient, storyboard, options, context, resolutionCalls);\n }\n if (storyboard.prerequisites?.controller_seeding !== true) return null;\n\n // If we can see the agent's tool list and `comply_test_controller` is\n // absent, grade as not_applicable rather than issuing calls that are\n // guaranteed to fail on the wire. Spec: `fixture_seed_unsupported` in\n // storyboard-schema.yaml — missing test-controller is a coverage gap, not\n // a setup break. `options.agentTools` is discovered from the agent profile\n // or passed explicitly by the caller; we don't enforce when it's absent\n // because some harnesses skip tool discovery.\n if (options.agentTools && !options.agentTools.includes('comply_test_controller')) {\n return buildMissingControllerResult(storyboard, calls, context);\n }\n\n const start = Date.now();\n const steps: StoryboardStepResult[] = [];\n let passedCount = 0;\n let failedCount = 0;\n let allPassed = true;\n const seedContext = { correlation_id: `${storyboardCorrelationPrefix(storyboard)}--__seeding__` };\n const authoringErrorResult = buildAuthoringErrorResult(storyboard, calls, context, start);\n if (authoringErrorResult) return authoringErrorResult;\n const unsupportedScenario = await findUnsupportedSeedScenario(client, calls, options, seedContext);\n if (unsupportedScenario) {\n return buildUnsupportedSeedResult(\n storyboard,\n calls,\n context,\n unsupportedScenario.scenario,\n unsupportedScenario.detail\n );\n }\n\n for (const call of calls) {\n const stepStart = Date.now();\n let passed = false;\n let error: string | undefined;\n\n if (call.authoring_error) {\n error = call.authoring_error;\n } else {\n try {\n const raw = await callControllerRaw(\n client,\n { scenario: call.scenario, params: call.params, context: seedContext },\n options\n );\n const data = raw.data as { success?: boolean; error?: string; error_detail?: string } | undefined;\n if (raw.success && data?.success === true) {\n passed = true;\n } else if (raw.success && data?.success === false && data.error === 'UNKNOWN_SCENARIO') {\n return buildUnsupportedSeedResult(storyboard, calls, context, call.scenario, data.error_detail);\n } else {\n error = formatControllerError(call.scenario, raw, data);\n }\n } catch (err) {\n error = err instanceof Error ? err.message : String(err);\n }\n }\n\n const step: StoryboardStepResult = {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed,\n duration_ms: Date.now() - stepStart,\n validations: [],\n context,\n extraction: { path: 'none' },\n ...(error !== undefined && { error }),\n };\n steps.push(step);\n if (passed) {\n passedCount++;\n } else {\n failedCount++;\n allPassed = false;\n }\n }\n\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight)',\n passed: allPassed,\n steps,\n duration_ms: Date.now() - start,\n },\n allPassed,\n passedCount,\n failedCount,\n };\n}\n\ninterface DiscoveryCatalog {\n products: Array<Record<string, unknown>>;\n evidence: { page_count: number; product_count: number; cursors: string[] };\n}\n\ntype DiscoveryCatalogResult =\n | { ok: true; catalog: DiscoveryCatalog }\n | { ok: false; error: string; evidence?: unknown };\n\n/** AdCP 3.2 ordered per-handle seed/discover state machine. */\nasync function runDeclaredFixtureResolution(\n seedClient: TestClient,\n discoveryClient: TestClient,\n storyboard: Storyboard,\n options: StoryboardRunOptions,\n context: StoryboardContext,\n calls: SeedCall[]\n): Promise<ControllerSeedingResult> {\n const start = Date.now();\n const authoringErrorResult = buildAuthoringErrorResult(storyboard, calls, context, start);\n if (authoringErrorResult) return authoringErrorResult;\n\n const specs = buildFixtureResolutionSpecs(storyboard);\n const specByKey = new Map<string, FixtureResolutionSpec>();\n for (const spec of specs) {\n specByKey.set(\n spec.entityType === 'product'\n ? `seed_product\\0${spec.handle}`\n : `seed_pricing_option\\0${spec.parentProductHandle}\\0${spec.handle}`,\n spec\n );\n }\n const declaredCalls = new Map<string, SeedCall>();\n for (const call of calls) {\n const spec = resolutionSpecForCall(call, specByKey);\n if (spec) declaredCalls.set(resolutionSpecKey(spec), call);\n }\n const orderedDeclaredCalls = specs\n .map(spec => declaredCalls.get(resolutionSpecKey(spec)))\n .filter((call): call is SeedCall => call !== undefined);\n let declaredCallIndex = 0;\n const orderedCalls = calls.map(call =>\n resolutionSpecForCall(call, specByKey) ? orderedDeclaredCalls[declaredCallIndex++]! : call\n );\n\n const bindings = new FixtureBindingRegistry();\n const records: FixtureResolutionRecord[] = [];\n const steps: StoryboardStepResult[] = [];\n const claimedProducts = new Map<string, boolean>();\n const claimedPricingOptions = new Map<string, boolean>();\n const productStatuses = new Map<string, FixtureResolutionRecord['status']>();\n const seedContext = { correlation_id: `${storyboardCorrelationPrefix(storyboard)}--__seeding__` };\n const controllerMissing = options.agentTools?.includes('comply_test_controller') === false;\n let advertisedScenarios = controllerMissing ? new Set<string>() : controllerScenarioSetFromOptions(options);\n let scenarioLookupAttempted = advertisedScenarios !== null;\n const legacyCalls = calls.filter(call => resolutionSpecForCall(call, specByKey) === undefined);\n if (legacyCalls.length > 0) {\n if (controllerMissing) return buildMissingControllerResult(storyboard, legacyCalls, context);\n if (!advertisedScenarios) {\n advertisedScenarios = await fetchControllerScenarioSet(seedClient, options, seedContext);\n scenarioLookupAttempted = true;\n }\n if (advertisedScenarios) {\n const unsupported = legacyCalls.find(call => !call.authoring_error && !advertisedScenarios!.has(call.scenario));\n if (unsupported) {\n return buildUnsupportedSeedResult(\n storyboard,\n legacyCalls,\n context,\n unsupported.scenario,\n `list_scenarios did not advertise required seed scenario \"${unsupported.scenario}\".`\n );\n }\n }\n }\n const needsSeedStrategy = orderedCalls.some(call => {\n const spec = resolutionSpecForCall(call, specByKey);\n return !spec || spec.strategies.includes('seed');\n });\n if (needsSeedStrategy && !controllerMissing && !advertisedScenarios && !scenarioLookupAttempted) {\n advertisedScenarios = await fetchControllerScenarioSet(seedClient, options, seedContext);\n }\n let catalogPromise: Promise<DiscoveryCatalogResult> | undefined;\n const catalog = () => (catalogPromise ??= discoverProductCatalog(discoveryClient, options, context));\n\n let passedCount = 0;\n let failedCount = 0;\n let fixtureUnsatisfied = false;\n\n for (const call of orderedCalls) {\n const spec = resolutionSpecForCall(call, specByKey);\n // The first production slice only changes product and product-pricing\n // handles. Every other entity keeps the legacy seed-only behavior.\n if (!spec) {\n const legacy = await executeLegacySeedCall(seedClient, storyboard, call, options, context, seedContext);\n if (legacy.step.skip_reason === 'fixture_unsatisfied') {\n return buildUnsupportedSeedResult(storyboard, legacyCalls, context, call.scenario, legacy.step.skip?.detail);\n }\n steps.push(legacy.step);\n if (legacy.step.passed) passedCount++;\n else failedCount++;\n continue;\n }\n\n const attempts: FixtureResolutionAttempt[] = [];\n let boundIds: FixtureResolutionRecord['seller_ids'];\n let chosenStrategy: FixtureResolutionRecord['strategy'];\n let failure: string | undefined;\n const stepStart = Date.now();\n const parentStatus = spec.parentProductHandle ? productStatuses.get(spec.parentProductHandle) : undefined;\n const parentUnavailable = spec.entityType === 'product_pricing_option' && parentStatus !== 'resolved';\n if (parentUnavailable) {\n const strategy = spec.strategies[0]!;\n const detail =\n parentStatus === 'failed'\n ? `parent product handle \"${spec.parentProductHandle}\" failed resolution`\n : `parent product handle \"${spec.parentProductHandle}\" is unavailable`;\n attempts.push({ strategy, disposition: parentStatus === 'failed' ? 'failed' : 'unavailable', detail });\n if (parentStatus === 'failed') failure = detail;\n }\n\n for (const strategy of parentUnavailable ? [] : spec.strategies) {\n if (strategy === 'seed') {\n const advertised = advertisedScenarios?.has(call.scenario);\n if (controllerMissing || advertised === false) {\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: controllerMissing\n ? 'comply_test_controller is not advertised'\n : `list_scenarios did not advertise ${call.scenario}`,\n });\n continue;\n }\n try {\n const controllerRequest = applyFixtureBindingsToRequest(\n { scenario: call.scenario, params: call.params },\n 'comply_test_controller',\n bindings,\n options.adcpVersion ?? ADCP_VERSION\n );\n const raw = await callControllerRaw(\n seedClient,\n {\n scenario: call.scenario,\n params: isPlainRecord(controllerRequest.params) ? controllerRequest.params : call.params,\n context: seedContext,\n },\n options\n );\n const data = raw.data as { success?: boolean; error?: string; error_detail?: string } | undefined;\n if (raw.success && data?.success === true) {\n boundIds = bindSeededFixture(spec, bindings);\n if (spec.entityType === 'product') {\n recordIdentityClaim(claimedProducts, boundIds.product_id!, spec.allowReuse);\n } else {\n recordIdentityClaim(\n claimedPricingOptions,\n `${boundIds.product_id}\\0${boundIds.pricing_option_id}`,\n spec.allowReuse\n );\n }\n chosenStrategy = strategy;\n attempts.push({\n strategy,\n disposition: 'resolved',\n detail: `${call.scenario} accepted the authored literal id`,\n });\n break;\n }\n if (raw.success && data?.success === false && data.error === 'UNKNOWN_SCENARIO' && advertised !== true) {\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: data.error_detail ?? `${call.scenario} returned UNKNOWN_SCENARIO`,\n });\n continue;\n }\n failure = formatControllerError(call.scenario, raw, data);\n attempts.push({ strategy, disposition: 'failed', detail: failure });\n break;\n } catch (err) {\n failure = err instanceof Error ? err.message : String(err);\n attempts.push({ strategy, disposition: 'failed', detail: failure });\n break;\n }\n }\n\n if (strategy === 'discover') {\n if (options.agentTools && !options.agentTools.includes('get_products')) {\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: 'agent did not advertise get_products',\n });\n continue;\n }\n const discovered = await catalog();\n if (!discovered.ok) {\n failure = discovered.error;\n attempts.push({ strategy, disposition: 'failed', detail: failure, response: discovered.evidence });\n break;\n }\n const selected = selectDiscoveredFixture(\n spec,\n discovered.catalog.products,\n bindings,\n claimedProducts,\n claimedPricingOptions\n );\n if (!selected.ok) {\n if (selected.failed) {\n failure = selected.detail;\n attempts.push({\n strategy,\n disposition: 'failed',\n detail: selected.detail,\n response: discovered.catalog.evidence,\n });\n break;\n }\n attempts.push({\n strategy,\n disposition: 'unavailable',\n detail: selected.detail,\n response: discovered.catalog.evidence,\n });\n continue;\n }\n boundIds = selected.boundIds;\n chosenStrategy = strategy;\n attempts.push({\n strategy,\n disposition: 'resolved',\n detail: selected.detail,\n response: { ...discovered.catalog.evidence, selected: selected.boundIds },\n });\n break;\n }\n }\n\n const status: FixtureResolutionRecord['status'] = boundIds ? 'resolved' : failure ? 'failed' : 'unsatisfied';\n if (spec.entityType === 'product') productStatuses.set(spec.handle, status);\n const record: FixtureResolutionRecord = {\n fixture_type: spec.entityType === 'product' ? 'product' : 'pricing_option',\n handle: spec.handle,\n ...(spec.parentProductHandle && { product_handle: spec.parentProductHandle }),\n requirements: spec.clauses,\n strategies_attempted: attempts,\n status,\n ...(chosenStrategy && { strategy: chosenStrategy }),\n ...(boundIds && { seller_ids: boundIds }),\n };\n records.push(record);\n\n if (status !== 'unsatisfied') {\n steps.push({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: chosenStrategy === 'discover' ? 'get_products' : 'comply_test_controller',\n passed: status !== 'failed',\n duration_ms: Date.now() - stepStart,\n validations: [],\n context,\n extraction: { path: 'none' },\n ...(failure && { error: failure }),\n });\n }\n if (status === 'failed') failedCount++;\n else if (status === 'unsatisfied') fixtureUnsatisfied = true;\n else passedCount++;\n }\n\n const allPassed = failedCount === 0;\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Fixture resolution (pre-flight)',\n passed: allPassed,\n steps,\n duration_ms: Date.now() - start,\n },\n allPassed,\n passedCount,\n failedCount,\n fixtureUnsatisfied,\n bindings,\n resolutionRecords: records,\n };\n}\n\nfunction resolutionSpecKey(spec: FixtureResolutionSpec): string {\n return spec.entityType === 'product'\n ? `seed_product\\0${spec.handle}`\n : `seed_pricing_option\\0${spec.parentProductHandle}\\0${spec.handle}`;\n}\n\nfunction resolutionSpecForCall(\n call: SeedCall,\n specs: ReadonlyMap<string, FixtureResolutionSpec>\n): FixtureResolutionSpec | undefined {\n if (call.scenario === 'seed_product') {\n return specs.get(`seed_product\\0${String(call.params.product_id ?? '')}`);\n }\n if (call.scenario === 'seed_pricing_option') {\n return specs.get(\n `seed_pricing_option\\0${String(call.params.product_id ?? '')}\\0${String(call.params.pricing_option_id ?? '')}`\n );\n }\n return undefined;\n}\n\nfunction bindSeededFixture(\n spec: FixtureResolutionSpec,\n bindings: FixtureBindingRegistry\n): NonNullable<FixtureResolutionRecord['seller_ids']> {\n if (spec.entityType === 'product') {\n bindings.bindProduct(spec.handle, spec.handle);\n return { product_id: spec.handle };\n }\n const parent = spec.parentProductHandle!;\n bindings.bindPricingOption(parent, spec.handle, spec.handle);\n return { product_id: bindings.productId(parent) ?? parent, pricing_option_id: spec.handle };\n}\n\nasync function executeLegacySeedCall(\n client: TestClient,\n storyboard: Storyboard,\n call: SeedCall,\n options: StoryboardRunOptions,\n context: StoryboardContext,\n seedContext: Record<string, unknown>\n): Promise<{ step: StoryboardStepResult }> {\n const started = Date.now();\n try {\n const raw = await callControllerRaw(\n client,\n { scenario: call.scenario, params: call.params, context: seedContext },\n options\n );\n const data = raw.data as { success?: boolean; error?: string; error_detail?: string } | undefined;\n if (raw.success && data?.success === true) {\n return {\n step: {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: true,\n duration_ms: Date.now() - started,\n validations: [],\n context,\n extraction: { path: 'none' },\n },\n };\n }\n const unknown = raw.success && data?.success === false && data.error === 'UNKNOWN_SCENARIO';\n const detail = unknown\n ? `fixture_unsatisfied: ${call.scenario} is unavailable and no alternate strategy is declared`\n : formatControllerError(call.scenario, raw, data);\n return {\n step: {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: unknown,\n ...(unknown && {\n skipped: true,\n skip_reason: 'fixture_unsatisfied' as const,\n skip: { reason: 'not_applicable' as const, detail },\n }),\n duration_ms: Date.now() - started,\n validations: [],\n context,\n extraction: { path: 'none' },\n ...(!unknown && { error: detail }),\n },\n };\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n return {\n step: {\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: false,\n duration_ms: Date.now() - started,\n validations: [],\n context,\n extraction: { path: 'none' },\n error: detail,\n },\n };\n }\n}\n\nasync function discoverProductCatalog(\n client: TestClient,\n options: StoryboardRunOptions,\n context: StoryboardContext\n): Promise<DiscoveryCatalogResult> {\n const contextAccount = isPlainRecord(context.account) ? context.account : undefined;\n const baseAccount = contextAccount ?? resolveAccount(options);\n const account: Record<string, unknown> = { ...baseAccount };\n if (!('account_id' in account)) {\n account.sandbox = options.disable_sandbox === true || options.sandbox === false ? false : true;\n }\n const accountBrand = isPlainRecord(account.brand) ? account.brand : undefined;\n const brand = isPlainRecord(context.brand) ? context.brand : (accountBrand ?? resolveBrand(options));\n const products: Array<Record<string, unknown>> = [];\n const seenProductIds = new Set<string>();\n const cursors: string[] = [];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n let pageCount = 0;\n do {\n if (pageCount >= 1_000) {\n return { ok: false, error: 'fixture discovery pagination exceeded the 1,000-page safety limit' };\n }\n const request: Record<string, unknown> = {\n buying_mode: 'wholesale',\n brand,\n account,\n pagination: { max_results: 100, ...(cursor && { cursor }) },\n // Fixture match declarations target the canonical product shape.\n ext: { adcp: { creative_wire: 'canonical' } },\n };\n let result;\n try {\n result = await executeStoryboardTask(client, 'get_products', request, { signal: options.signal });\n } catch (err) {\n return {\n ok: false,\n error: `fixture discovery transport failure: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n pageCount++;\n if (!result.success) {\n return {\n ok: false,\n error: `fixture discovery get_products rejected: ${result.error ?? result.adcp_error?.code ?? 'unknown error'}`,\n evidence: { page_count: pageCount, request },\n };\n }\n let schemaFailure: string | undefined;\n try {\n const validator = getValidator('get_products', 'sync', options.adcpVersion ?? ADCP_VERSION);\n if (validator) {\n const responseData: unknown = result.data;\n const schemaData = isPlainRecord(responseData)\n ? injectLegacyEnvelopeStatus(responseData, { toolName: 'get_products' })\n : responseData;\n if (!validator(schemaData)) {\n schemaFailure = (validator.errors ?? [])\n .map(error => `${error.instancePath || '/'} ${error.message ?? error.keyword}`)\n .join('; ');\n }\n } else {\n const schema = validateResponseSchema('get_products', result.data, options.adcpVersion);\n if (!schema.passed) schemaFailure = schema.error ?? schema.details ?? 'schema validation failed';\n }\n } catch (err) {\n schemaFailure = `response schema unavailable: ${err instanceof Error ? err.message : String(err)}`;\n }\n if (schemaFailure) {\n return {\n ok: false,\n error: `fixture discovery returned malformed get_products response: ${schemaFailure}`,\n evidence: { page_count: pageCount },\n };\n }\n if (!isPlainRecord(result.data)) {\n return { ok: false, error: 'fixture discovery returned a non-object get_products response' };\n }\n const pageProducts = result.data.products;\n if (pageProducts !== undefined && !Array.isArray(pageProducts)) {\n return { ok: false, error: 'fixture discovery get_products.products is not an array' };\n }\n for (const product of pageProducts ?? []) {\n if (!isPlainRecord(product) || typeof product.product_id !== 'string' || product.product_id.length === 0) {\n return { ok: false, error: 'fixture discovery returned a product without a non-empty product_id' };\n }\n if (seenProductIds.has(product.product_id)) {\n return {\n ok: false,\n error: `fixture discovery returned duplicate product_id \"${product.product_id}\"; response order cannot resolve duplicate identities`,\n };\n }\n seenProductIds.add(product.product_id);\n if (Array.isArray(product.pricing_options)) {\n const seenPricingIds = new Set<string>();\n for (const option of product.pricing_options) {\n if (!isPlainRecord(option) || typeof option.pricing_option_id !== 'string') continue;\n if (seenPricingIds.has(option.pricing_option_id)) {\n return {\n ok: false,\n error: `fixture discovery returned duplicate pricing option identity \"${product.product_id}\\u0000${option.pricing_option_id}\"`,\n };\n }\n seenPricingIds.add(option.pricing_option_id);\n }\n }\n products.push(product);\n if (products.length > 100_000) {\n return { ok: false, error: 'fixture discovery exceeded the 100,000-product safety limit' };\n }\n }\n const pagination = isPlainRecord(result.data.pagination) ? result.data.pagination : undefined;\n if (pagination?.has_more === true) {\n const next = pagination.cursor;\n if (typeof next !== 'string' || next.length === 0) {\n return { ok: false, error: 'fixture discovery pagination is broken: has_more=true without cursor' };\n }\n if (seenCursors.has(next)) {\n return { ok: false, error: `fixture discovery pagination is broken: repeated cursor \"${next}\"` };\n }\n seenCursors.add(next);\n cursors.push(next);\n cursor = next;\n } else {\n cursor = undefined;\n }\n } while (cursor);\n return {\n ok: true,\n catalog: { products, evidence: { page_count: pageCount, product_count: products.length, cursors } },\n };\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction utf8Compare(a: string, b: string): number {\n return Buffer.compare(Buffer.from(a, 'utf8'), Buffer.from(b, 'utf8'));\n}\n\ntype SelectedFixture =\n | { ok: true; boundIds: NonNullable<FixtureResolutionRecord['seller_ids']>; detail: string }\n | { ok: false; failed: boolean; detail: string };\n\nfunction selectDiscoveredFixture(\n spec: FixtureResolutionSpec,\n products: Array<Record<string, unknown>>,\n bindings: FixtureBindingRegistry,\n claimedProducts: Map<string, boolean>,\n claimedPricingOptions: Map<string, boolean>\n): SelectedFixture {\n if (spec.entityType === 'product') {\n const candidates = products\n .filter(product => matchesFixtureRequirements(product, spec.clauses))\n .filter(product => identityCanBeClaimed(claimedProducts, product.product_id as string, spec.allowReuse))\n .sort((a, b) => utf8Compare(a.product_id as string, b.product_id as string));\n const selected = candidates[0];\n if (!selected)\n return { ok: false, failed: false, detail: 'no discovered product satisfied the authored requirements' };\n const productId = selected.product_id as string;\n bindings.bindProduct(spec.handle, productId);\n recordIdentityClaim(claimedProducts, productId, spec.allowReuse);\n return {\n ok: true,\n boundIds: { product_id: productId },\n detail: `selected product_id \"${productId}\" by UTF-8 bytewise order`,\n };\n }\n\n const parentHandle = spec.parentProductHandle!;\n const sellerProductId = bindings.productId(parentHandle);\n if (!sellerProductId) {\n return {\n ok: false,\n failed: true,\n detail: `pricing-option discovery requires bound parent product handle \"${parentHandle}\"`,\n };\n }\n const product = products.find(candidate => candidate.product_id === sellerProductId);\n if (!product) {\n return {\n ok: false,\n failed: true,\n detail: `bound parent product_id \"${sellerProductId}\" was absent from the completed discovery catalog`,\n };\n }\n const options = Array.isArray(product.pricing_options) ? product.pricing_options : [];\n const candidates = options\n .filter(isPlainRecord)\n .filter(option => typeof option.pricing_option_id === 'string' && option.pricing_option_id.length > 0)\n .filter(option => matchesFixtureRequirements(option, spec.clauses))\n .filter(option => {\n const identity = `${sellerProductId}\\0${option.pricing_option_id as string}`;\n return identityCanBeClaimed(claimedPricingOptions, identity, spec.allowReuse);\n })\n .sort((a, b) =>\n utf8Compare(\n `${sellerProductId}\\0${a.pricing_option_id as string}`,\n `${sellerProductId}\\0${b.pricing_option_id as string}`\n )\n );\n const selected = candidates[0];\n if (!selected) {\n return {\n ok: false,\n failed: false,\n detail: 'no pricing option on the bound product satisfied the authored requirements',\n };\n }\n const pricingOptionId = selected.pricing_option_id as string;\n bindings.bindPricingOption(parentHandle, spec.handle, pricingOptionId);\n recordIdentityClaim(claimedPricingOptions, `${sellerProductId}\\0${pricingOptionId}`, spec.allowReuse);\n return {\n ok: true,\n boundIds: { product_id: sellerProductId, pricing_option_id: pricingOptionId },\n detail: `selected pricing option \"${sellerProductId}\\u0000${pricingOptionId}\" by UTF-8 bytewise order`,\n };\n}\n\n/** A seller identity may be shared only when every claimant opts into reuse. */\nfunction identityCanBeClaimed(claims: ReadonlyMap<string, boolean>, identity: string, allowReuse: boolean): boolean {\n const existingAllowsReuse = claims.get(identity);\n return existingAllowsReuse === undefined || (existingAllowsReuse && allowReuse);\n}\n\nfunction recordIdentityClaim(claims: Map<string, boolean>, identity: string, allowReuse: boolean): void {\n claims.set(identity, (claims.get(identity) ?? true) && allowReuse);\n}\n\nfunction storyboardCorrelationPrefix(storyboard: Storyboard): string {\n for (const phase of storyboard.phases) {\n for (const step of phase.steps) {\n const requestContext = step.sample_request?.context;\n if (!requestContext || typeof requestContext !== 'object' || Array.isArray(requestContext)) continue;\n const correlationId = (requestContext as { correlation_id?: unknown }).correlation_id;\n if (typeof correlationId !== 'string' || correlationId.length === 0) continue;\n const suffixSeparator = correlationId.lastIndexOf('--');\n return suffixSeparator > 0 ? correlationId.slice(0, suffixSeparator) : correlationId;\n }\n }\n return storyboard.id;\n}\n\nfunction buildAuthoringErrorResult(\n storyboard: Storyboard,\n calls: SeedCall[],\n context: StoryboardContext,\n start: number\n): ControllerSeedingResult | null {\n const authoringErrors = calls.filter((call): call is SeedCall & { authoring_error: string } =>\n Boolean(call.authoring_error)\n );\n if (authoringErrors.length === 0) return null;\n const steps: StoryboardStepResult[] = authoringErrors.map(call => ({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: false,\n duration_ms: 0,\n validations: [],\n context,\n extraction: { path: 'none' },\n error: call.authoring_error,\n }));\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight) — invalid storyboard fixtures',\n passed: false,\n steps,\n duration_ms: Date.now() - start,\n },\n allPassed: false,\n passedCount: 0,\n failedCount: steps.length,\n };\n}\n\nasync function findUnsupportedSeedScenario(\n client: TestClient,\n calls: SeedCall[],\n options: StoryboardRunOptions,\n seedContext: Record<string, unknown>\n): Promise<{ scenario: SeedScenario | BuyerAgentSeedScenario; detail: string } | null> {\n const requiredScenarios = [...new Set(calls.filter(call => !call.authoring_error).map(call => call.scenario))];\n if (requiredScenarios.length === 0) return null;\n\n let advertisedScenarios = controllerScenarioSetFromOptions(options);\n if (!advertisedScenarios) {\n advertisedScenarios = await fetchControllerScenarioSet(client, options, seedContext);\n }\n if (!advertisedScenarios) return null;\n\n for (const scenario of requiredScenarios) {\n if (!advertisedScenarios.has(scenario)) {\n return {\n scenario,\n detail: `list_scenarios did not advertise required seed scenario \"${scenario}\".`,\n };\n }\n }\n return null;\n}\n\nfunction controllerScenarioSetFromOptions(options: StoryboardRunOptions): Set<string> | null {\n const capabilities = options._controllerCapabilities;\n if (capabilities?.detected !== true) return null;\n return new Set((capabilities.scenarios as readonly string[]).filter(scenario => typeof scenario === 'string'));\n}\n\nasync function fetchControllerScenarioSet(\n client: TestClient,\n options: StoryboardRunOptions,\n seedContext: Record<string, unknown>\n): Promise<Set<string> | null> {\n try {\n const raw = await callControllerRaw(client, { scenario: 'list_scenarios', context: seedContext }, options);\n const data = raw.data as { success?: boolean; scenarios?: unknown } | undefined;\n if (!raw.success || data?.success !== true) return null;\n if (Array.isArray(data.scenarios)) {\n return new Set(data.scenarios.filter((scenario): scenario is string => typeof scenario === 'string'));\n }\n if (data.scenarios && typeof data.scenarios === 'object') {\n return new Set(Object.keys(data.scenarios));\n }\n return null;\n } catch {\n return null;\n }\n}\n\nconst UNSUPPORTED_SEED_DETAIL =\n 'Skipped: agent advertised comply_test_controller, but does not implement a seed_* scenario required by this storyboard (`fixture_seed_unsupported`). Storyboard grades not_applicable — the buyer-side flow depends on pre-seeded state the agent has no way to accept.';\n\nfunction buildUnsupportedSeedResult(\n storyboard: Storyboard,\n calls: Array<{ step_id: string; title: string }>,\n context: StoryboardContext,\n scenario: SeedScenario | BuyerAgentSeedScenario,\n detail?: string\n): ControllerSeedingResult {\n const skipDetail = detail\n ? `${UNSUPPORTED_SEED_DETAIL} Unsupported scenario ${scenario}: ${detail}`\n : `${UNSUPPORTED_SEED_DETAIL} Unsupported scenario: ${scenario}.`;\n const steps: StoryboardStepResult[] = calls.map(call => ({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: true,\n skipped: true,\n skip_reason: 'fixture_seed_unsupported',\n skip: { reason: 'not_applicable', detail: skipDetail },\n duration_ms: 0,\n validations: [],\n context,\n extraction: { path: 'none' },\n }));\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight) — agent lacks required seed scenario',\n passed: true,\n steps,\n duration_ms: 0,\n },\n allPassed: true,\n passedCount: 0,\n failedCount: 0,\n seedUnsupported: true,\n };\n}\n\nfunction formatControllerError(\n scenario: SeedScenario | BuyerAgentSeedScenario,\n raw: { success: boolean; error?: string },\n data: { success?: boolean; error?: string; error_detail?: string } | undefined\n): string {\n if (data?.error_detail) return data.error ? `${data.error}: ${data.error_detail}` : data.error_detail;\n if (data?.error) return data.error;\n return raw.error ?? `comply_test_controller ${scenario} call failed`;\n}\n\nconst MISSING_CONTROLLER_DETAIL =\n 'Skipped: agent did not advertise comply_test_controller, so fixture seeding (`fixture_seed_unsupported`) cannot run. Storyboard grades not_applicable — the buyer-side flow depends on pre-seeded state the agent has no way to accept.';\n\nfunction buildMissingControllerResult(\n storyboard: Storyboard,\n calls: Array<{ step_id: string; title: string }>,\n context: StoryboardContext\n): ControllerSeedingResult {\n const steps: StoryboardStepResult[] = calls.map(call => ({\n storyboard_id: storyboard.id,\n step_id: call.step_id,\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n title: call.title,\n task: 'comply_test_controller',\n passed: true,\n skipped: true,\n skip_reason: 'missing_test_controller',\n skip: { reason: 'missing_test_controller', detail: MISSING_CONTROLLER_DETAIL },\n duration_ms: 0,\n validations: [],\n context,\n extraction: { path: 'none' },\n }));\n return {\n phase: {\n phase_id: CONTROLLER_SEEDING_PHASE_ID,\n phase_title: 'Controller seeding (pre-flight) — agent lacks comply_test_controller',\n passed: true,\n steps,\n duration_ms: 0,\n },\n allPassed: true,\n passedCount: 0,\n failedCount: 0,\n missingController: true,\n };\n}\n"],"mappings":"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","names":["candidates","product","selected"]}
@@ -1 +1 @@
1
- {"version":3,"file":"task-map.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/task-map.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsDjD,CAAC;AAwFF;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAEzC,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,GAAE;IAAE,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GACxG,OAAO,CAAC,UAAU,CAAC,CA0FrB"}
1
+ {"version":3,"file":"task-map.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/task-map.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAK3C;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsDjD,CAAC;AA8FF;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAEzC,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,GAAE;IAAE,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GACxG,OAAO,CAAC,UAAU,CAAC,CAwGrB"}
@@ -23,6 +23,7 @@ __export(task_map_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(task_map_exports);
25
25
  var import_response_unwrapper = require('../../utils/response-unwrapper.js');
26
+ var import_creative_assets = require('./creative-assets.js');
26
27
  const TASK_TO_METHOD = {
27
28
  // Account & audience
28
29
  sync_accounts: "syncAccounts",
@@ -98,10 +99,15 @@ function gradesLegacyCreativeWire(client) {
98
99
  function isRecord(value) {
99
100
  return value !== null && typeof value === "object" && !Array.isArray(value);
100
101
  }
102
+ function readCreativeWireHint(params) {
103
+ if (!isRecord(params.ext) || !isRecord(params.ext.adcp)) return void 0;
104
+ const wire = params.ext.adcp.creative_wire;
105
+ return wire === "legacy" || wire === "canonical" ? wire : void 0;
106
+ }
101
107
  function withLegacyCreativeWireHint(params) {
108
+ if (readCreativeWireHint(params)) return params;
102
109
  const ext = isRecord(params.ext) ? params.ext : {};
103
110
  const adcp = isRecord(ext.adcp) ? ext.adcp : {};
104
- if (adcp.creative_wire === "legacy" || adcp.creative_wire === "canonical") return params;
105
111
  return {
106
112
  ...params,
107
113
  ext: {
@@ -144,7 +150,15 @@ function normalizeStoryboardTaskSuccess(result, taskName, terminalDataError, adc
144
150
  return true;
145
151
  }
146
152
  async function executeStoryboardTask(client, taskName, params, opts = {}) {
147
- const legacyMethodName = gradesLegacyCreativeWire(client) ? LEGACY_CREATIVE_TASK_TO_METHOD[taskName] : void 0;
153
+ const unresolvedAssetDirectives = (0, import_creative_assets.findUnresolvedCreativeAssetDirectives)(params);
154
+ if (unresolvedAssetDirectives.length > 0) {
155
+ return {
156
+ success: false,
157
+ error: `Request contains unexpanded storyboard directive '${import_creative_assets.BUILD_ASSETS_FROM_FORMAT_DIRECTIVE}' at ${unresolvedAssetDirectives.join(", ")}. Call expandCreativeAssetDirectives(params, context, testKit) before passing params to executeStoryboardTask.`
158
+ };
159
+ }
160
+ const useLegacyCreativeMethod = gradesLegacyCreativeWire(client) && readCreativeWireHint(params) !== "canonical";
161
+ const legacyMethodName = useLegacyCreativeMethod ? LEGACY_CREATIVE_TASK_TO_METHOD[taskName] : void 0;
148
162
  const methodName = legacyMethodName ?? (Object.hasOwn(TASK_TO_METHOD, taskName) ? TASK_TO_METHOD[taskName] : void 0);
149
163
  const callParams = legacyMethodName ? withLegacyCreativeWireHint(params) : params;
150
164
  const taskOptions = opts.skipIdempotencyAutoInject || opts.skipAccountValidation ? {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/storyboard/task-map.ts"],"sourcesContent":["/**\n * Maps AdCP task names (from storyboard YAML) to SingleAgentClient method names.\n *\n * Each storyboard step has a `task` field like \"sync_accounts\" or \"get_products\".\n * This map resolves those to the camelCase method on SingleAgentClient.\n *\n * Tasks without a dedicated method fall through to `executeTask()`.\n */\n\nimport type { TaskResult } from '../types';\nimport type { AdcpErrorInfo } from '../../core/ConversationTypes';\nimport { isTerminalAdcpError, readExtractionPath } from '../../utils/response-unwrapper';\n\n/**\n * Map of AdCP task names to SingleAgentClient method names.\n * Only includes tasks that have dedicated typed methods.\n */\nexport const TASK_TO_METHOD: Record<string, string> = {\n // Account & audience\n sync_accounts: 'syncAccounts',\n list_accounts: 'listAccounts',\n sync_audiences: 'syncAudiences',\n\n // Product discovery & media buy\n get_products: 'getProducts',\n create_media_buy: 'createMediaBuy',\n update_media_buy: 'updateMediaBuy',\n get_media_buys: 'getMediaBuys',\n get_media_buy_delivery: 'getMediaBuyDelivery',\n provide_performance_feedback: 'providePerformanceFeedback',\n\n // Creative\n list_creative_formats: 'listCreativeFormats',\n build_creative: 'buildCreativeLegacy',\n preview_creative: 'previewCreativeLegacy',\n sync_creatives: 'syncCreatives',\n list_creatives: 'listCreatives',\n\n // Signals\n get_signals: 'getSignals',\n activate_signal: 'activateSignal',\n\n // Capabilities\n get_adcp_capabilities: 'getAdcpCapabilities',\n\n // Governance\n sync_plans: 'syncPlans',\n check_governance: 'checkGovernance',\n get_plan_audit_logs: 'getPlanAuditLogs',\n create_property_list: 'createPropertyList',\n get_property_list: 'getPropertyList',\n update_property_list: 'updatePropertyList',\n list_property_lists: 'listPropertyLists',\n delete_property_list: 'deletePropertyList',\n list_collection_lists: 'listCollectionLists',\n list_content_standards: 'listContentStandards',\n get_content_standards: 'getContentStandards',\n create_content_standards: 'createContentStandards',\n update_content_standards: 'updateContentStandards',\n calibrate_content: 'calibrateContent',\n validate_content_delivery: 'validateContentDelivery',\n\n // Account\n get_account_financials: 'getAccountFinancials',\n log_event: 'logEvent',\n\n // Sponsored Intelligence\n si_get_offering: 'siGetOffering',\n si_initiate_session: 'siInitiateSession',\n si_send_message: 'siSendMessage',\n si_terminate_session: 'siTerminateSession',\n};\n\n/** Storyboards grade the selected protocol wire, not the SDK's canonical API. */\nconst LEGACY_CREATIVE_TASK_TO_METHOD: Readonly<Record<string, string>> = {\n get_products: 'getProductsLegacy',\n create_media_buy: 'createMediaBuyLegacy',\n update_media_buy: 'updateMediaBuyLegacy',\n sync_creatives: 'syncCreativesLegacy',\n list_creatives: 'listCreativesLegacy',\n};\n\nfunction gradesLegacyCreativeWire(client: unknown): boolean {\n if (client === null || typeof client !== 'object') return false;\n const getAdcpVersion = (client as { getAdcpVersion?: unknown }).getAdcpVersion;\n if (typeof getAdcpVersion !== 'function') return false;\n let version: unknown;\n try {\n version = getAdcpVersion.call(client);\n } catch {\n return false;\n }\n if (typeof version !== 'string') return false;\n const match = /^v?(\\d+)(?:\\.(\\d+))?/.exec(version.trim());\n if (!match) return false;\n const major = Number(match[1]);\n const minor = Number(match[2] ?? 0);\n return major < 3 || (major === 3 && minor < 2);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction withLegacyCreativeWireHint(params: Record<string, unknown>): Record<string, unknown> {\n const ext = isRecord(params.ext) ? params.ext : {};\n const adcp = isRecord(ext.adcp) ? ext.adcp : {};\n if (adcp.creative_wire === 'legacy' || adcp.creative_wire === 'canonical') return params;\n return {\n ...params,\n ext: {\n ...ext,\n adcp: { ...adcp, creative_wire: 'legacy' },\n },\n };\n}\n\nfunction readAdcpError(value: unknown): AdcpErrorInfo | undefined {\n if (!isRecord(value)) return undefined;\n const error = value.adcp_error;\n if (!isRecord(error) || typeof error.code !== 'string') return undefined;\n return error as unknown as AdcpErrorInfo;\n}\n\nfunction readFirstError(value: unknown): AdcpErrorInfo | undefined {\n if (!isRecord(value) || !Array.isArray(value.errors)) return undefined;\n const first = value.errors[0];\n if (!isRecord(first) || typeof first.code !== 'string') return undefined;\n return {\n code: first.code,\n message: typeof first.message === 'string' ? first.message : String(first.code),\n ...(typeof first.recovery === 'string' && { recovery: first.recovery as AdcpErrorInfo['recovery'] }),\n ...(typeof first.field === 'string' && { field: first.field }),\n ...(typeof first.suggestion === 'string' && { suggestion: first.suggestion }),\n ...(typeof first.retry_after === 'number' && { retry_after: first.retry_after }),\n ...(isRecord(first.details) && { details: first.details }),\n };\n}\n\nfunction errorMessageFrom(error: AdcpErrorInfo | undefined, fallback: unknown): string | undefined {\n if (typeof error?.message === 'string' && error.message.length > 0) return error.message;\n if (typeof error?.code === 'string') return error.code;\n return typeof fallback === 'string' && fallback.length > 0 ? fallback : undefined;\n}\n\nfunction normalizeStoryboardTaskSuccess(\n result: unknown,\n taskName: string,\n terminalDataError?: boolean,\n adcpError?: AdcpErrorInfo\n): boolean {\n if (!isRecord(result)) return true;\n if (typeof result.success === 'boolean') return result.success;\n if (result.status === 'failed' || result.status === 'rejected') return false;\n if (adcpError || result.adcpError || result.adcp_error) return false;\n if (terminalDataError ?? isTerminalAdcpError(result.data, taskName)) return false;\n return true;\n}\n\n/**\n * Execute a storyboard task against a SingleAgentClient.\n *\n * Uses the typed method if one exists, otherwise falls back to executeTask().\n * When the agent returns an async status (working/submitted), waits for\n * completion before returning — storyboard steps expect final results.\n */\nexport async function executeStoryboardTask(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic dispatch requires any\n client: any,\n taskName: string,\n params: Record<string, unknown>,\n opts: { skipIdempotencyAutoInject?: boolean; skipAccountValidation?: boolean; signal?: AbortSignal } = {}\n): Promise<TaskResult> {\n const legacyMethodName = gradesLegacyCreativeWire(client) ? LEGACY_CREATIVE_TASK_TO_METHOD[taskName] : undefined;\n const methodName =\n legacyMethodName ?? (Object.hasOwn(TASK_TO_METHOD, taskName) ? TASK_TO_METHOD[taskName] : undefined);\n const callParams = legacyMethodName ? withLegacyCreativeWireHint(params) : params;\n\n // Only pass TaskOptions when a flag is actually set — avoids changing\n // behavior for the common path that relies on method defaults.\n const taskOptions =\n opts.skipIdempotencyAutoInject || opts.skipAccountValidation\n ? {\n ...(opts.skipIdempotencyAutoInject && { skipIdempotencyAutoInject: true }),\n ...(opts.skipAccountValidation && { skipAccountValidation: true }),\n }\n : undefined;\n\n let result;\n const invoke = async () => {\n if (methodName && typeof client[methodName] === 'function') {\n // Typed methods take (params, inputHandler?, options?). Pass options\n // only when set, otherwise they take their defaults.\n return taskOptions ? client[methodName](callParams, undefined, taskOptions) : client[methodName](callParams);\n }\n return client.executeTask(taskName, callParams, undefined, taskOptions);\n };\n\n // Retry with exponential backoff on rate limit errors\n const MAX_RETRIES = 3;\n const BASE_DELAY_MS = 2000;\n for (let attempt = 0; ; attempt++) {\n try {\n result = await raceWithSignal(invoke(), opts.signal);\n break;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const isRateLimit =\n /rate limit/i.test(msg) || (/\"code\":\\s*-32000/.test(msg) && /rate.?limit|too many|throttl/i.test(msg));\n if (isRateLimit && attempt < MAX_RETRIES) {\n const jitter = Math.random() * 1000;\n const delay = BASE_DELAY_MS * 2 ** attempt + jitter;\n await raceWithSignal(new Promise(resolve => setTimeout(resolve, delay)), opts.signal);\n continue;\n }\n throw err;\n }\n }\n\n // If the agent returned an async status but included data in the initial\n // response (common for agents that process synchronously but report as\n // submitted), use that data. Only poll when there's no data at all.\n const hasData = result.data !== undefined && result.data !== null;\n const isAsync = result.status === 'submitted' || result.status === 'working';\n const prePollingDebugLogs = Array.isArray(result.debug_logs) ? [...result.debug_logs] : [];\n let replacedByPolling = false;\n if (!hasData && isAsync && result.submitted?.waitForCompletion) {\n try {\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('Task polling timeout')), 30_000)\n );\n result = await raceWithSignal(\n Promise.race([result.submitted.waitForCompletion(2000, opts.signal), timeout]),\n opts.signal\n );\n replacedByPolling = true;\n } catch (err) {\n if (opts.signal?.aborted) throw err;\n // Polling failed or timed out — return the intermediate result as-is\n }\n }\n\n const terminalDataError = isTerminalAdcpError(result.data, taskName);\n const adcpError =\n result.adcpError ??\n result.adcp_error ??\n readAdcpError(result.data) ??\n (terminalDataError ? readFirstError(result.data) : undefined);\n const data = result.data ?? (adcpError ? { adcp_error: adcpError } : undefined);\n const success = normalizeStoryboardTaskSuccess(result, taskName, terminalDataError, adcpError);\n const error = result.error ?? (!success ? errorMessageFrom(adcpError, undefined) : undefined);\n const extractionPath = readExtractionPath(data);\n const debugLogs = Array.isArray(result.debug_logs) ? result.debug_logs : [];\n const mergedDebugLogs = replacedByPolling ? [...prePollingDebugLogs, ...debugLogs] : debugLogs;\n return {\n success,\n data,\n error,\n ...(adcpError && { adcp_error: adcpError }),\n ...(extractionPath !== undefined && { _extraction_path: extractionPath }),\n ...(mergedDebugLogs.length > 0 && { debug_logs: mergedDebugLogs }),\n };\n}\n\nfunction raceWithSignal<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) return promise;\n if (signal.aborted) return Promise.reject(signal.reason ?? new Error('aborted'));\n\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(signal.reason ?? new Error('aborted'));\n signal.addEventListener('abort', onAbort, { once: true });\n promise.then(\n value => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n err => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n }\n );\n });\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/task-map.ts"],"sourcesContent":["/**\n * Maps AdCP task names (from storyboard YAML) to SingleAgentClient method names.\n *\n * Each storyboard step has a `task` field like \"sync_accounts\" or \"get_products\".\n * This map resolves those to the camelCase method on SingleAgentClient.\n *\n * Tasks without a dedicated method fall through to `executeTask()`.\n */\n\nimport type { TaskResult } from '../types';\nimport type { AdcpErrorInfo } from '../../core/ConversationTypes';\nimport { isTerminalAdcpError, readExtractionPath } from '../../utils/response-unwrapper';\nimport { BUILD_ASSETS_FROM_FORMAT_DIRECTIVE, findUnresolvedCreativeAssetDirectives } from './creative-assets';\n\n/**\n * Map of AdCP task names to SingleAgentClient method names.\n * Only includes tasks that have dedicated typed methods.\n */\nexport const TASK_TO_METHOD: Record<string, string> = {\n // Account & audience\n sync_accounts: 'syncAccounts',\n list_accounts: 'listAccounts',\n sync_audiences: 'syncAudiences',\n\n // Product discovery & media buy\n get_products: 'getProducts',\n create_media_buy: 'createMediaBuy',\n update_media_buy: 'updateMediaBuy',\n get_media_buys: 'getMediaBuys',\n get_media_buy_delivery: 'getMediaBuyDelivery',\n provide_performance_feedback: 'providePerformanceFeedback',\n\n // Creative\n list_creative_formats: 'listCreativeFormats',\n build_creative: 'buildCreativeLegacy',\n preview_creative: 'previewCreativeLegacy',\n sync_creatives: 'syncCreatives',\n list_creatives: 'listCreatives',\n\n // Signals\n get_signals: 'getSignals',\n activate_signal: 'activateSignal',\n\n // Capabilities\n get_adcp_capabilities: 'getAdcpCapabilities',\n\n // Governance\n sync_plans: 'syncPlans',\n check_governance: 'checkGovernance',\n get_plan_audit_logs: 'getPlanAuditLogs',\n create_property_list: 'createPropertyList',\n get_property_list: 'getPropertyList',\n update_property_list: 'updatePropertyList',\n list_property_lists: 'listPropertyLists',\n delete_property_list: 'deletePropertyList',\n list_collection_lists: 'listCollectionLists',\n list_content_standards: 'listContentStandards',\n get_content_standards: 'getContentStandards',\n create_content_standards: 'createContentStandards',\n update_content_standards: 'updateContentStandards',\n calibrate_content: 'calibrateContent',\n validate_content_delivery: 'validateContentDelivery',\n\n // Account\n get_account_financials: 'getAccountFinancials',\n log_event: 'logEvent',\n\n // Sponsored Intelligence\n si_get_offering: 'siGetOffering',\n si_initiate_session: 'siInitiateSession',\n si_send_message: 'siSendMessage',\n si_terminate_session: 'siTerminateSession',\n};\n\n/** Storyboards grade the selected protocol wire, not the SDK's canonical API. */\nconst LEGACY_CREATIVE_TASK_TO_METHOD: Readonly<Record<string, string>> = {\n get_products: 'getProductsLegacy',\n create_media_buy: 'createMediaBuyLegacy',\n update_media_buy: 'updateMediaBuyLegacy',\n sync_creatives: 'syncCreativesLegacy',\n list_creatives: 'listCreativesLegacy',\n};\n\nfunction gradesLegacyCreativeWire(client: unknown): boolean {\n if (client === null || typeof client !== 'object') return false;\n const getAdcpVersion = (client as { getAdcpVersion?: unknown }).getAdcpVersion;\n if (typeof getAdcpVersion !== 'function') return false;\n let version: unknown;\n try {\n version = getAdcpVersion.call(client);\n } catch {\n return false;\n }\n if (typeof version !== 'string') return false;\n const match = /^v?(\\d+)(?:\\.(\\d+))?/.exec(version.trim());\n if (!match) return false;\n const major = Number(match[1]);\n const minor = Number(match[2] ?? 0);\n return major < 3 || (major === 3 && minor < 2);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction readCreativeWireHint(params: Record<string, unknown>): 'legacy' | 'canonical' | undefined {\n if (!isRecord(params.ext) || !isRecord(params.ext.adcp)) return undefined;\n const wire = params.ext.adcp.creative_wire;\n return wire === 'legacy' || wire === 'canonical' ? wire : undefined;\n}\n\nfunction withLegacyCreativeWireHint(params: Record<string, unknown>): Record<string, unknown> {\n if (readCreativeWireHint(params)) return params;\n const ext = isRecord(params.ext) ? params.ext : {};\n const adcp = isRecord(ext.adcp) ? ext.adcp : {};\n return {\n ...params,\n ext: {\n ...ext,\n adcp: { ...adcp, creative_wire: 'legacy' },\n },\n };\n}\n\nfunction readAdcpError(value: unknown): AdcpErrorInfo | undefined {\n if (!isRecord(value)) return undefined;\n const error = value.adcp_error;\n if (!isRecord(error) || typeof error.code !== 'string') return undefined;\n return error as unknown as AdcpErrorInfo;\n}\n\nfunction readFirstError(value: unknown): AdcpErrorInfo | undefined {\n if (!isRecord(value) || !Array.isArray(value.errors)) return undefined;\n const first = value.errors[0];\n if (!isRecord(first) || typeof first.code !== 'string') return undefined;\n return {\n code: first.code,\n message: typeof first.message === 'string' ? first.message : String(first.code),\n ...(typeof first.recovery === 'string' && { recovery: first.recovery as AdcpErrorInfo['recovery'] }),\n ...(typeof first.field === 'string' && { field: first.field }),\n ...(typeof first.suggestion === 'string' && { suggestion: first.suggestion }),\n ...(typeof first.retry_after === 'number' && { retry_after: first.retry_after }),\n ...(isRecord(first.details) && { details: first.details }),\n };\n}\n\nfunction errorMessageFrom(error: AdcpErrorInfo | undefined, fallback: unknown): string | undefined {\n if (typeof error?.message === 'string' && error.message.length > 0) return error.message;\n if (typeof error?.code === 'string') return error.code;\n return typeof fallback === 'string' && fallback.length > 0 ? fallback : undefined;\n}\n\nfunction normalizeStoryboardTaskSuccess(\n result: unknown,\n taskName: string,\n terminalDataError?: boolean,\n adcpError?: AdcpErrorInfo\n): boolean {\n if (!isRecord(result)) return true;\n if (typeof result.success === 'boolean') return result.success;\n if (result.status === 'failed' || result.status === 'rejected') return false;\n if (adcpError || result.adcpError || result.adcp_error) return false;\n if (terminalDataError ?? isTerminalAdcpError(result.data, taskName)) return false;\n return true;\n}\n\n/**\n * Execute a storyboard task against a SingleAgentClient.\n *\n * Uses the typed method if one exists, otherwise falls back to executeTask().\n * When the agent returns an async status (working/submitted), waits for\n * completion before returning — storyboard steps expect final results.\n */\nexport async function executeStoryboardTask(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic dispatch requires any\n client: any,\n taskName: string,\n params: Record<string, unknown>,\n opts: { skipIdempotencyAutoInject?: boolean; skipAccountValidation?: boolean; signal?: AbortSignal } = {}\n): Promise<TaskResult> {\n const unresolvedAssetDirectives = findUnresolvedCreativeAssetDirectives(params);\n if (unresolvedAssetDirectives.length > 0) {\n return {\n success: false,\n error:\n `Request contains unexpanded storyboard directive '${BUILD_ASSETS_FROM_FORMAT_DIRECTIVE}' at ` +\n `${unresolvedAssetDirectives.join(', ')}. ` +\n 'Call expandCreativeAssetDirectives(params, context, testKit) before passing params to executeStoryboardTask.',\n };\n }\n\n // AdCP 3.1 transition storyboards default to the legacy creative wire, but\n // canonical-specific storyboards must be able to opt into the canonical API.\n const useLegacyCreativeMethod = gradesLegacyCreativeWire(client) && readCreativeWireHint(params) !== 'canonical';\n const legacyMethodName = useLegacyCreativeMethod ? LEGACY_CREATIVE_TASK_TO_METHOD[taskName] : undefined;\n const methodName =\n legacyMethodName ?? (Object.hasOwn(TASK_TO_METHOD, taskName) ? TASK_TO_METHOD[taskName] : undefined);\n const callParams = legacyMethodName ? withLegacyCreativeWireHint(params) : params;\n\n // Only pass TaskOptions when a flag is actually set — avoids changing\n // behavior for the common path that relies on method defaults.\n const taskOptions =\n opts.skipIdempotencyAutoInject || opts.skipAccountValidation\n ? {\n ...(opts.skipIdempotencyAutoInject && { skipIdempotencyAutoInject: true }),\n ...(opts.skipAccountValidation && { skipAccountValidation: true }),\n }\n : undefined;\n\n let result;\n const invoke = async () => {\n if (methodName && typeof client[methodName] === 'function') {\n // Typed methods take (params, inputHandler?, options?). Pass options\n // only when set, otherwise they take their defaults.\n return taskOptions ? client[methodName](callParams, undefined, taskOptions) : client[methodName](callParams);\n }\n return client.executeTask(taskName, callParams, undefined, taskOptions);\n };\n\n // Retry with exponential backoff on rate limit errors\n const MAX_RETRIES = 3;\n const BASE_DELAY_MS = 2000;\n for (let attempt = 0; ; attempt++) {\n try {\n result = await raceWithSignal(invoke(), opts.signal);\n break;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const isRateLimit =\n /rate limit/i.test(msg) || (/\"code\":\\s*-32000/.test(msg) && /rate.?limit|too many|throttl/i.test(msg));\n if (isRateLimit && attempt < MAX_RETRIES) {\n const jitter = Math.random() * 1000;\n const delay = BASE_DELAY_MS * 2 ** attempt + jitter;\n await raceWithSignal(new Promise(resolve => setTimeout(resolve, delay)), opts.signal);\n continue;\n }\n throw err;\n }\n }\n\n // If the agent returned an async status but included data in the initial\n // response (common for agents that process synchronously but report as\n // submitted), use that data. Only poll when there's no data at all.\n const hasData = result.data !== undefined && result.data !== null;\n const isAsync = result.status === 'submitted' || result.status === 'working';\n const prePollingDebugLogs = Array.isArray(result.debug_logs) ? [...result.debug_logs] : [];\n let replacedByPolling = false;\n if (!hasData && isAsync && result.submitted?.waitForCompletion) {\n try {\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('Task polling timeout')), 30_000)\n );\n result = await raceWithSignal(\n Promise.race([result.submitted.waitForCompletion(2000, opts.signal), timeout]),\n opts.signal\n );\n replacedByPolling = true;\n } catch (err) {\n if (opts.signal?.aborted) throw err;\n // Polling failed or timed out — return the intermediate result as-is\n }\n }\n\n const terminalDataError = isTerminalAdcpError(result.data, taskName);\n const adcpError =\n result.adcpError ??\n result.adcp_error ??\n readAdcpError(result.data) ??\n (terminalDataError ? readFirstError(result.data) : undefined);\n const data = result.data ?? (adcpError ? { adcp_error: adcpError } : undefined);\n const success = normalizeStoryboardTaskSuccess(result, taskName, terminalDataError, adcpError);\n const error = result.error ?? (!success ? errorMessageFrom(adcpError, undefined) : undefined);\n const extractionPath = readExtractionPath(data);\n const debugLogs = Array.isArray(result.debug_logs) ? result.debug_logs : [];\n const mergedDebugLogs = replacedByPolling ? [...prePollingDebugLogs, ...debugLogs] : debugLogs;\n return {\n success,\n data,\n error,\n ...(adcpError && { adcp_error: adcpError }),\n ...(extractionPath !== undefined && { _extraction_path: extractionPath }),\n ...(mergedDebugLogs.length > 0 && { debug_logs: mergedDebugLogs }),\n };\n}\n\nfunction raceWithSignal<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) return promise;\n if (signal.aborted) return Promise.reject(signal.reason ?? new Error('aborted'));\n\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(signal.reason ?? new Error('aborted'));\n signal.addEventListener('abort', onAbort, { once: true });\n promise.then(\n value => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n err => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n }\n );\n });\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,5 @@
1
1
  import { isTerminalAdcpError, readExtractionPath } from "../../utils/response-unwrapper.mjs";
2
+ import { BUILD_ASSETS_FROM_FORMAT_DIRECTIVE, findUnresolvedCreativeAssetDirectives } from "./creative-assets.mjs";
2
3
  const TASK_TO_METHOD = {
3
4
  // Account & audience
4
5
  sync_accounts: "syncAccounts",
@@ -74,10 +75,15 @@ function gradesLegacyCreativeWire(client) {
74
75
  function isRecord(value) {
75
76
  return value !== null && typeof value === "object" && !Array.isArray(value);
76
77
  }
78
+ function readCreativeWireHint(params) {
79
+ if (!isRecord(params.ext) || !isRecord(params.ext.adcp)) return void 0;
80
+ const wire = params.ext.adcp.creative_wire;
81
+ return wire === "legacy" || wire === "canonical" ? wire : void 0;
82
+ }
77
83
  function withLegacyCreativeWireHint(params) {
84
+ if (readCreativeWireHint(params)) return params;
78
85
  const ext = isRecord(params.ext) ? params.ext : {};
79
86
  const adcp = isRecord(ext.adcp) ? ext.adcp : {};
80
- if (adcp.creative_wire === "legacy" || adcp.creative_wire === "canonical") return params;
81
87
  return {
82
88
  ...params,
83
89
  ext: {
@@ -120,7 +126,15 @@ function normalizeStoryboardTaskSuccess(result, taskName, terminalDataError, adc
120
126
  return true;
121
127
  }
122
128
  async function executeStoryboardTask(client, taskName, params, opts = {}) {
123
- const legacyMethodName = gradesLegacyCreativeWire(client) ? LEGACY_CREATIVE_TASK_TO_METHOD[taskName] : void 0;
129
+ const unresolvedAssetDirectives = findUnresolvedCreativeAssetDirectives(params);
130
+ if (unresolvedAssetDirectives.length > 0) {
131
+ return {
132
+ success: false,
133
+ error: `Request contains unexpanded storyboard directive '${BUILD_ASSETS_FROM_FORMAT_DIRECTIVE}' at ${unresolvedAssetDirectives.join(", ")}. Call expandCreativeAssetDirectives(params, context, testKit) before passing params to executeStoryboardTask.`
134
+ };
135
+ }
136
+ const useLegacyCreativeMethod = gradesLegacyCreativeWire(client) && readCreativeWireHint(params) !== "canonical";
137
+ const legacyMethodName = useLegacyCreativeMethod ? LEGACY_CREATIVE_TASK_TO_METHOD[taskName] : void 0;
124
138
  const methodName = legacyMethodName ?? (Object.hasOwn(TASK_TO_METHOD, taskName) ? TASK_TO_METHOD[taskName] : void 0);
125
139
  const callParams = legacyMethodName ? withLegacyCreativeWireHint(params) : params;
126
140
  const taskOptions = opts.skipIdempotencyAutoInject || opts.skipAccountValidation ? {