@adcp/sdk 14.0.0-beta.12 → 14.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/index.d.mts +3 -3
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +3 -1
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +2 -2
- package/dist/lib/server/create-adcp-server.d.ts +2 -2
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +6 -1
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +6 -1
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.d.mts +3 -3
- package/dist/lib/server/decisioning/index.d.ts +3 -3
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +24 -17
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +24 -17
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +71 -42
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +75 -43
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.mts +15 -21
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +15 -21
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +100 -30
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +100 -30
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.d.mts +30 -16
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts +30 -16
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.js +40 -20
- package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +38 -19
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.d.mts +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.d.ts +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.js +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.mts +3 -2
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +3 -2
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.d.mts +10 -10
- package/dist/lib/server/decisioning/specialisms/creative.d.ts +10 -10
- package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.js +11 -2
- package/dist/lib/testing/storyboard/default-invariants.js.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +11 -2
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.d.mts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/loader.js +14 -0
- package/dist/lib/testing/storyboard/loader.js.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +14 -0
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/phase-condition.d.mts +41 -0
- package/dist/lib/testing/storyboard/phase-condition.d.ts +42 -0
- package/dist/lib/testing/storyboard/phase-condition.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/phase-condition.js +215 -0
- package/dist/lib/testing/storyboard/phase-condition.js.map +1 -0
- package/dist/lib/testing/storyboard/phase-condition.mjs +189 -0
- package/dist/lib/testing/storyboard/phase-condition.mjs.map +1 -0
- package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.js +15 -2
- package/dist/lib/testing/storyboard/request-builder.js.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +15 -2
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +57 -23
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +57 -23
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/task-map.js +6 -2
- package/dist/lib/testing/storyboard/task-map.js.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +6 -2
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.d.mts +5 -4
- package/dist/lib/testing/storyboard/types.d.ts +5 -4
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.js +60 -4
- package/dist/lib/testing/storyboard/webhook-assertions.js.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +60 -4
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.d.mts +15 -0
- package/dist/lib/testing/storyboard/webhook-receiver.d.ts +15 -0
- package/dist/lib/testing/storyboard/webhook-receiver.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.js +57 -6
- package/dist/lib/testing/storyboard/webhook-receiver.js.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +57 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/types.d.mts +2 -0
- package/dist/lib/testing/types.d.ts +2 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/testing/types.js.map +1 -1
- package/dist/lib/types/core.generated.d.mts +5 -2
- package/dist/lib/types/core.generated.d.ts +5 -2
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js.map +1 -1
- package/dist/lib/types/index.d.mts +1 -1
- package/dist/lib/types/index.d.ts +1 -1
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/list-transformers.d.ts +9 -5
- package/dist/lib/types/schemas.generated.d.ts +21 -298
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +5 -2
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +4 -2
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.d.mts +2 -1
- package/dist/lib/types/server-payload-aliases.d.ts +2 -1
- package/dist/lib/types/server-payload-aliases.d.ts.map +1 -1
- package/dist/lib/types/server-payload-aliases.js.map +1 -1
- package/dist/lib/types/tools.generated.d.mts +5 -2
- package/dist/lib/types/tools.generated.d.ts +5 -2
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.d.mts +5 -1
- package/dist/lib/utils/build-creative-return-builders.d.ts +5 -1
- package/dist/lib/utils/build-creative-return-builders.d.ts.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.js +9 -3
- package/dist/lib/utils/build-creative-return-builders.js.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +7 -2
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.js +1 -1
- package/dist/lib/utils/response-unwrapper.js.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +1 -1
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.d.ts.map +1 -1
- package/dist/lib/validation/schema-loader.js +16 -7
- package/dist/lib/validation/schema-loader.js.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +16 -7
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/llms.txt +2 -2
- package/docs/migration-5.x-to-6.x.md +3 -2
- package/docs/migration-task-registry-scoping.md +61 -0
- package/examples/hello_seller_adapter_guaranteed.ts +1 -1
- package/package.json +4 -4
- package/skills/build-decisioning-creative-template/SKILL.md +2 -2
- package/skills/build-decisioning-platform/SKILL.md +4 -2
- package/skills/build-decisioning-platform/advanced/REFERENCE.md +7 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/storyboard/request-builder.ts"],"sourcesContent":["/**\n * Request enrichers for storyboard steps.\n *\n * Contract (see issue #820):\n * - `sample_request` (when authored) is the authoritative base payload.\n * The runner injects context placeholders into it and passes it through\n * to the agent under test.\n * - An enricher fills top-level fields the fixture didn't specify —\n * typically discovery-derived identifiers (`product_id`, `format_id`,\n * `account`, `media_buy_id`) or envelope fields that only the harness\n * knows.\n * - For conflicts at the top level, the fixture wins — storyboard authors'\n * intent is not silently overridden.\n *\n * A short list of tasks need to splice discovery-derived fields INTO\n * nested structures in the fixture (e.g. `create_media_buy` injects\n * `product_id` into `packages[0]`) and can't be expressed by a top-level\n * overlay. Those enrichers declare themselves fixture-aware via\n * `FIXTURE_AWARE_ENRICHERS` below and the runner uses their output as-is.\n *\n * `sample_request` from YAML, when a task has no enricher, is used directly\n * after context injection — preserves the \"no handler, fixture is the wire\n * payload\" pattern.\n */\n\nimport { createHash } from 'node:crypto';\nimport { resolveBrand, resolveAccount } from '../client';\nimport type { TestOptions } from '../types';\nimport type { StoryboardContext, StoryboardStep } from './types';\nimport { injectContext, type RunnerVariables } from './context';\n\ntype RequestEnricher = (\n step: StoryboardStep,\n context: StoryboardContext,\n options: TestOptions,\n runnerVars?: RunnerVariables\n) => Record<string, unknown>;\n\n/** Legacy alias kept for external consumers pinned to the old terminology. */\ntype RequestBuilder = RequestEnricher;\n\n/**\n * Placeholder `format_id` used when neither `list_creative_formats` discovery\n * nor accumulated `context.format_id` supplied one. Schema\n * (core/format-id.json) requires `agent_url` in URI form, so a bare\n * `\"unknown\"` string fails validation. `example.com` is reserved for\n * documentation per RFC 2606 — an obvious fixture that strict JSON-schema\n * validators accept and that downstream handlers resolve to a clean\n * format-not-found error rather than an unrelated crash. Frozen so a\n * builder that accidentally spread-mutates the shared constant hits a\n * TypeError instead of silently corrupting sibling calls.\n */\nconst UNKNOWN_FORMAT_ID = Object.freeze({ agent_url: 'https://unknown.example.com/', id: 'unknown' });\n\n/**\n * Placeholder `caller` URL for tasks whose schema names the CALLER-AGENT's\n * URL (not the brand or the seller). `check_governance.caller` is the canonical\n * case: governance agents bind this field to agent identity for rate limiting,\n * audit trails, and (with `signed-requests`) JWS issuer correlation — emitting\n * the brand domain here names the wrong entity and will confuse strict\n * governance agents. Storyboards that care about a specific caller identity\n * author sample_request; this is the fallback when neither fixture nor\n * harness-supplied agent URL is present.\n */\nconst FALLBACK_CALLER_AGENT_URL = 'https://e2e-orchestrator.adcontextprotocol.org/';\n\n/**\n * Tasks whose enricher must see `sample_request` to produce the final\n * payload — typically because it needs to splice discovery-derived fields\n * INTO nested structures the fixture owns (arrays, object trees). For\n * these, the runner uses the enricher's output verbatim and does not\n * layer the fixture on top; the enricher is responsible for fixture\n * precedence internally.\n */\nconst FIXTURE_AWARE_ENRICHERS = new Set<string>([\n 'create_media_buy', // merges discovery-derived product_id / pricing_option_id INTO fixture packages[0]\n 'comply_test_controller', // forces account.sandbox: true regardless of fixture\n 'get_products', // preserves wholesale fixture fields while keeping resolved account scope authoritative\n 'update_media_buy', // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy\n 'get_media_buys', // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy\n 'get_media_buy_delivery', // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy\n]);\n\nfunction hasUnresolvedContextReference(value: unknown): boolean {\n if (typeof value === 'string') return /^\\$context\\.\\w+$/.test(value);\n if (Array.isArray(value)) return value.some(hasUnresolvedContextReference);\n if (value && typeof value === 'object') {\n return Object.values(value as Record<string, unknown>).some(hasUnresolvedContextReference);\n }\n return false;\n}\n\n/**\n * Placeholder identifiers that the upstream universal compliance\n * storyboards ship inside `create_media_buy.packages[0]` expecting the\n * runner to substitute the seller's discovered identifiers. The fixtures\n * live in `adcontextprotocol/adcp` and can't be rewritten from the SDK,\n * so the enricher treats these literals as \"defer to discovery\" while\n * real seller ids (e.g. `cpm_guaranteed`) win over discovery per the\n * fixture-authoritative contract. If a future storyboard wants\n * placeholder-then-discovery semantics for another value, author it as\n * a `$context.<key>` substitution rather than a magic literal so the\n * intent is explicit at the fixture level.\n */\nconst PRODUCT_ID_SENTINELS = new Set(['test-product']);\nconst PRICING_OPTION_ID_SENTINELS = new Set(['test-pricing']);\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst DEFAULT_MEDIA_BUY_WINDOW_MS = 7 * DAY_MS;\n\nfunction asNonSentinel(value: unknown, sentinels: Set<string>): string | undefined {\n if (typeof value !== 'string') return undefined;\n return sentinels.has(value) ? undefined : value;\n}\n\nfunction parseTime(value: string | undefined): number | undefined {\n if (value === undefined) return undefined;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction resolveMediaBuyWindow(\n sampleStart: string | undefined,\n sampleEnd: string | undefined,\n nowMs?: number\n): {\n startTime: string;\n endTime: string;\n} {\n const now = nowMs ?? Date.now();\n const defaultStart = new Date(now + DAY_MS).toISOString();\n const defaultEnd = new Date(now + 8 * DAY_MS).toISOString();\n const sampleStartMs = parseTime(sampleStart);\n const sampleEndMs = parseTime(sampleEnd);\n const startIsAsap = sampleStart === 'asap';\n\n const startTime = startIsAsap\n ? 'asap'\n : sampleStart && sampleStartMs !== undefined && sampleStartMs >= now\n ? sampleStart\n : defaultStart;\n let endTime = sampleEnd && sampleEndMs !== undefined && sampleEndMs >= now ? sampleEnd : defaultEnd;\n\n const startTimeMs = startIsAsap ? now : Date.parse(startTime);\n if (Date.parse(endTime) <= startTimeMs) {\n const sampleDurationMs =\n sampleStartMs !== undefined && sampleEndMs !== undefined && sampleEndMs > sampleStartMs\n ? sampleEndMs - sampleStartMs\n : DEFAULT_MEDIA_BUY_WINDOW_MS;\n endTime = new Date(startTimeMs + sampleDurationMs).toISOString();\n }\n\n return { startTime, endTime };\n}\n\nfunction runClockMs(runnerVars: RunnerVariables | undefined): number {\n return runnerVars?.runStartMs ?? Date.now();\n}\n\nfunction resolveMediaBuyReadAccount(fixtureAccount: unknown, contextAccount: unknown, options: TestOptions): unknown {\n const resolvedAccount = contextAccount ?? resolveAccount(options);\n // Preserve a fixture-authored natural-key operator: it identifies the\n // buyer acting for the brand and is not interchangeable with brand.domain.\n // A context account remains authoritative, while the harness still owns\n // sandbox routing for fixture-authored natural keys.\n if (\n contextAccount === undefined &&\n fixtureAccount !== null &&\n typeof fixtureAccount === 'object' &&\n !Array.isArray(fixtureAccount) &&\n typeof (fixtureAccount as Record<string, unknown>).operator === 'string' &&\n typeof (fixtureAccount as Record<string, unknown>).account_id !== 'string'\n ) {\n const sandbox = (resolvedAccount as { sandbox?: boolean }).sandbox;\n return {\n ...(fixtureAccount as Record<string, unknown>),\n ...(sandbox !== undefined && { sandbox }),\n };\n }\n return resolvedAccount;\n}\n\nfunction generatedIdSuffix(step: StoryboardStep, runnerVars: RunnerVariables | undefined, nowMs?: number): string {\n const timestamp = nowMs ?? runClockMs(runnerVars);\n if (runnerVars?.runStartMs === undefined) return String(timestamp);\n const stepHash = createHash('sha256').update(step.id).digest('hex').slice(0, 12);\n return `${timestamp}-${stepHash}`;\n}\n\n/**\n * Envelope fields that live on every AdCP request and are owned by the\n * storyboard author — `context.correlation_id`, runner-supplied\n * `idempotency_key` aliases, webhook pointers, per-request extensions.\n * Fixture-aware enrichers must NOT spread these from their internal\n * `injectContext(sample_request, context)` call: that internal call\n * doesn't receive `runnerVars`, so mustache tokens (`{{runner.webhook_url:<step_id>}}`)\n * would ship to the wire literally. The outer `enrichRequest` overlays\n * envelope fields from a `runnerVars`-aware fixture re-injection.\n */\nconst ENVELOPE_FIELDS = ['context', 'ext', 'push_notification_config', 'idempotency_key'] as const;\n\nfunction omitEnvelopeFields(obj: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (!(ENVELOPE_FIELDS as readonly string[]).includes(k)) out[k] = v;\n }\n return out;\n}\n\nconst REQUEST_ENRICHERS: Record<string, RequestEnricher> = {\n // ── Account & Audience ─────────────────────────────────\n\n sync_accounts(_step, _context, options) {\n return {\n accounts: [\n {\n brand: resolveBrand(options),\n operator: resolveBrand(options).domain,\n billing: 'operator',\n payment_terms: 'net_30',\n },\n ],\n };\n },\n\n sync_audiences(step, context, options, runnerVars) {\n // Honor hand-authored sample_request so storyboards can register a\n // specific audience_id that downstream steps reference. Without this,\n // add-shaped sample_request blocks (authored with audience_id + add[])\n // fell through to the generated fallback id, and a later delete_audience\n // or context-substitution step would hit AUDIENCE_NOT_FOUND because the\n // sync had registered a different id. Matches the pattern used by\n // sync_event_sources, sync_catalogs, and sync_creatives.\n if (step.sample_request) {\n return injectContext({ ...step.sample_request, account: context.account ?? resolveAccount(options) }, context);\n }\n return {\n account: context.account ?? resolveAccount(options),\n audiences: [\n {\n audience_id: context.audience_id ?? `test-audience-${generatedIdSuffix(step, runnerVars)}`,\n name: 'E2E Test Audience',\n add: [\n {\n external_id: 'user-001',\n hashed_email: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',\n },\n ],\n },\n ],\n };\n },\n\n // ── Brand & Rights ───────────────────────────────────────\n\n get_brand_identity(step, context, options) {\n const brand = resolveBrand(options);\n return {\n brand_id: context.brand_id ?? (step.sample_request?.brand_id as string) ?? brand.brand_id ?? brand.domain,\n };\n },\n\n get_rights(step, context, options) {\n // Honor hand-authored sample_request so storyboards can specify\n // scenario-specific query text, uses, countries, or buyer_brand.\n // Peer builders (sync_plans, check_governance, list_creative_formats,\n // create_content_standards, etc.) follow the same pattern.\n //\n // Without this, any get_rights step hits the wire with the generic\n // fallback and a brand_id derived from the caller's domain — which\n // rights-holder rosters reject as unknown, so rights[0] is undefined,\n // $context.rights_id doesn't resolve, and downstream acquire_rights\n // steps fail with rights_not_found instead of the error the\n // storyboard is actually asserting (e.g., GOVERNANCE_DENIED).\n const brand = resolveBrand(options);\n return {\n query: 'available rights for advertising',\n uses: ['ai_generated_image'],\n brand_id: context.brand_id ?? brand.brand_id ?? brand.domain,\n };\n },\n\n // ── Product Discovery ──────────────────────────────────\n\n get_products(step, context, options) {\n // Fixture-aware: wholesale storyboards author cache validators, filters,\n // and account identities that must survive enrichment together. Resolve\n // placeholders before selecting the account. A fully resolved fixture\n // account remains authoritative (scope-isolation storyboards deliberately\n // switch accounts between steps); only an unresolved fixture reference\n // falls back to the context/run account (#2654).\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const fixtureAccount = fixtureFields.account;\n const resolvedAccount =\n fixtureAccount !== undefined && !hasUnresolvedContextReference(fixtureAccount)\n ? fixtureAccount\n : (context.account ?? resolveAccount(options));\n\n if (fixtureFields.buying_mode === 'wholesale') {\n return {\n ...fixtureFields,\n account: resolvedAccount,\n };\n }\n\n // If the step is a \"refine\" step, build a refine request\n if (step.sample_request?.buying_mode === 'refine' && context.products) {\n return {\n ...fixtureFields,\n buying_mode: 'refine',\n refine: fixtureFields.refine ?? [\n {\n scope: 'request',\n ask: 'Only guaranteed packages with premium placement.',\n },\n ],\n brand: fixtureFields.brand ?? resolveBrand(options),\n account: resolvedAccount,\n };\n }\n\n return {\n buying_mode: 'brief',\n brief: options.brief || 'Show me all available advertising products across all channels',\n brand: resolveBrand(options),\n ...fixtureFields,\n account: resolvedAccount,\n };\n },\n\n // ── Media Buy ──────────────────────────────────────────\n\n create_media_buy(step, context, options, runnerVars) {\n const product = selectProduct(context);\n const pricingOption = selectPricingOption(product);\n\n // Respect sample_request dates when they're future-dated — needed for\n // storyboards that test replay semantics where initial + replay must\n // produce byte-for-byte identical canonical payloads. Two calls\n // generated 5ms apart with `Date.now()` would hash differently,\n // triggering IDEMPOTENCY_CONFLICT on replay. Stale sample dates\n // (authored before the run date) fall back to the run-start-relative\n // default. Resolve the pair together so a stale start and same-day\n // future end cannot produce start_time > end_time.\n const sampleStart =\n typeof step.sample_request?.start_time === 'string' ? step.sample_request.start_time : undefined;\n const sampleEnd = typeof step.sample_request?.end_time === 'string' ? step.sample_request.end_time : undefined;\n const { startTime, endTime } = resolveMediaBuyWindow(sampleStart, sampleEnd, runnerVars?.runStartMs);\n\n // Merge hand-authored package fields from sample_request (targeting_overlay,\n // measurement_terms, creative_assignments, performance_standards, etc.) so\n // scenario-specific behaviors are exercised. The first package's\n // identifiers (product_id, pricing_option_id) follow a two-tier rule:\n //\n // - Real seller ids in the fixture win over discovery — storyboards\n // that name `cpm_guaranteed` (or any seller-specific identifier)\n // are asserting that specific id reaches the wire. Discovery must\n // not override.\n // - Well-known sentinel placeholders (`test-product`, `test-pricing`)\n // from the upstream universal compliance storyboards defer to\n // discovery. Those storyboards ship package fixtures with\n // `product_id: \"test-product\"` expecting the runner to substitute\n // the seller's discovered product — they'd fail against every\n // seller that doesn't literally ship a \"test-product\" catalog\n // entry if the fixture value survived to the wire.\n //\n // The sentinel list is conservative. If a future storyboard wants\n // placeholder-then-discovery semantics for another field, author it\n // as `$context.<key>` substitution instead of a magic literal.\n const samplePackages = (step.sample_request?.packages as Array<Record<string, unknown>> | undefined) ?? [];\n const baseSample = samplePackages[0]\n ? (injectContext({ ...samplePackages[0] }, context) as Record<string, unknown>)\n : {};\n\n const fixtureProductId = asNonSentinel(baseSample.product_id, PRODUCT_ID_SENTINELS);\n const fixturePricingOptionId = asNonSentinel(baseSample.pricing_option_id, PRICING_OPTION_ID_SENTINELS);\n\n const firstPkg: Record<string, unknown> = {\n ...baseSample,\n product_id: fixtureProductId ?? product?.product_id ?? context.product_id ?? 'test-product',\n budget:\n (typeof baseSample.budget === 'number' ? baseSample.budget : undefined) ??\n options.budget ??\n Math.max(1000, (pricingOption?.min_spend_per_package as number) ?? 1000),\n pricing_option_id:\n fixturePricingOptionId ?? pricingOption?.pricing_option_id ?? context.pricing_option_id ?? 'default',\n };\n\n // Synthesize a bid_price for auction/cpm pricing only when the fixture\n // didn't author one. Storyboards that test auction flows (e.g.\n // sales-non-guaranteed) author explicit bid_prices the seller validates\n // against floor_price; discovery-synthesized values would silently\n // override intentional bid-floor-boundary tests.\n if (\n baseSample.bid_price === undefined &&\n (pricingOption?.pricing_model === 'auction' || pricingOption?.pricing_model === 'cpm')\n ) {\n const floor = Number(pricingOption?.floor_price) || 5;\n firstPkg.bid_price = Math.round(floor * 1.5 * 100) / 100;\n }\n\n const additionalPkgs = samplePackages\n .slice(1)\n .map(p => injectContext({ ...p }, context) as Record<string, unknown>);\n\n // Proposal-mode: when context carries a proposal_id (captured from\n // `proposals[0]` in a prior brief/refine/finalize step), forward it\n // and omit `packages`. The schema disallows synthesising packages\n // alongside `proposal_id` — `dependencies.proposal_id` requires\n // `total_budget` and the seller derives packages from the committed\n // allocation.\n //\n // Spread the fixture (after $context injection) so proposal-mode-\n // required fields like `total_budget` flow through. Prefer the\n // fixture's account/brand when supplied — proposal-mode storyboards\n // author a non-default brand (e.g. `acmeoutdoor.example`) that the\n // adapter resolves end-to-end through brief/refine/finalize, and\n // the harness-default `test.example` would fail account resolution\n // at the accept step (adcp-client#1600). Dates and proposal_id\n // are still normalised by the enricher.\n const fixture =\n step.sample_request !== undefined\n ? (injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>)\n : {};\n // Drop envelope fields from the local spread — the outer enrichRequest\n // re-injects them with `runnerVars` so `{{runner.webhook_url:<step_id>}}`\n // tokens inside push_notification_config expand. Spreading them here\n // would carry through unexpanded mustache strings.\n const fixtureBody = omitEnvelopeFields(fixture);\n\n // Proposal-mode applies only when the storyboard's fixture explicitly\n // names a `proposal_id`. `context.proposal_id` is auto-captured from\n // any prior `get_products` response that returned `proposals[0]` (see\n // context.ts), which is essentially every brief flow — using it as a\n // fallback would override a fixture's explicit `packages` direction\n // and force every sales storyboard through proposal-mode validation,\n // including ones that intentionally exercise package-mode (sales-\n // guaranteed, schema_validation, media_buy_seller/*). Fixture is the\n // storyboard author's intent; respect it.\n const fixtureHasPackages = Array.isArray(fixture.packages) && (fixture.packages as unknown[]).length > 0;\n const proposalId: unknown =\n fixture.proposal_id !== undefined ? fixture.proposal_id : fixtureHasPackages ? undefined : context.proposal_id;\n if (typeof proposalId === 'string') {\n const { packages: _droppedPackages, ...fixtureWithoutPackages } = fixtureBody;\n return {\n ...fixtureWithoutPackages,\n account: fixtureWithoutPackages.account ?? context.account ?? resolveAccount(options),\n brand: fixtureWithoutPackages.brand ?? resolveBrand(options),\n start_time: startTime,\n end_time: endTime,\n proposal_id: proposalId,\n };\n }\n\n // Spread the fixture (after $context injection) so any sample_request\n // fields the enricher doesn't explicitly normalise (total_budget,\n // buyer_ref, currency, scenario-specific extensions) reach the wire.\n // The enricher then layers its own substitutions on top: packages is\n // replaced (the enricher merged samplePackages internally with\n // discovery-derived identifiers above), account/brand/start_time/\n // end_time are normalised. Per issue #1604, build-from-scratch dropped\n // every fixture field outside this enumerated set — fixture-aware\n // enrichers must spread sample_request first, then override. Envelope\n // fields are omitted here and re-applied by the outer enrichRequest\n // with `runnerVars` so mustache tokens expand correctly.\n return {\n ...fixtureBody,\n account: context.account ?? resolveAccount(options),\n brand: resolveBrand(options),\n start_time: startTime,\n end_time: endTime,\n packages: [firstPkg, ...additionalPkgs],\n };\n },\n\n update_media_buy(step, context, options) {\n // Fixture-aware: spread the storyboard's sample_request first so hand-authored\n // intent (targeting_overlay swaps, creative assignments, pause/resume/cancel)\n // is preserved verbatim, then force `account` to the harness-resolved value so\n // sandbox routing matches create_media_buy's namespace on every round-trip\n // (otherwise the fixture's account silently routes update writes to a different\n // partition than the create wrote to, and a subsequent get_media_buys reading\n // from the create-time partition surfaces stale data — see adcp-client#1505).\n // Envelope fields are dropped from the local spread; the outer enrichRequest\n // re-injects them with `runnerVars` so mustache substitutions expand.\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const request: Record<string, unknown> = { ...fixtureFields };\n request.account = context.account ?? resolveAccount(options);\n if (request.media_buy_id === undefined) {\n request.media_buy_id = context.media_buy_id ?? 'unknown';\n }\n\n // No sample_request: fall back to step-id keyword inference so legacy\n // storyboards without an authored fixture still exercise sensible flows.\n if (!step.sample_request) {\n if (step.id.includes('pause')) {\n request.paused = true;\n } else if (step.id.includes('resume')) {\n request.paused = false;\n } else if (step.id.includes('cancel')) {\n request.canceled = true;\n } else {\n request.packages = [\n {\n package_id: (context.package_id as string | undefined) ?? 'unknown',\n budget: 2000,\n },\n ];\n }\n }\n\n return request;\n },\n\n get_media_buys(step, context, options) {\n // Spread fixture fields so storyboards can author filters, status, pagination, etc.\n // account is always overridden by the harness-resolved value so sandbox routing\n // matches create_media_buy's namespace on every round-trip. Envelope fields are\n // dropped from the local spread so the outer enrichRequest re-injects them with\n // `runnerVars` (mustache substitutions expand against the runner's webhook base).\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const result: Record<string, unknown> = { ...fixtureFields };\n result.account = resolveMediaBuyReadAccount(fixtureFields.account, context.account, options);\n if (context.media_buy_id != null && result.media_buy_ids === undefined) {\n result.media_buy_ids = [context.media_buy_id];\n }\n return result;\n },\n\n get_media_buy_delivery(step, context, options) {\n // Same account-resolution rule as get_media_buys — fixture fields preserved,\n // account overridden by harness so sandbox routing matches create_media_buy.\n // Envelope fields dropped from the local spread; outer enrichRequest re-applies\n // them with `runnerVars` so mustache substitutions expand.\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const result: Record<string, unknown> = { ...fixtureFields };\n result.account = resolveMediaBuyReadAccount(fixtureFields.account, context.account, options);\n if (context.media_buy_id != null && result.media_buy_ids === undefined) {\n result.media_buy_ids = [context.media_buy_id];\n }\n return result;\n },\n\n // provide_performance_feedback intentionally has no builder — storyboard\n // sample_request is authoritative because the spec's oneOf requires a\n // performance_index variant that only the storyboard author knows the\n // shape of. A synthesized payload here would emit non-spec fields\n // (feedback/satisfaction/notes) and get rejected with INVALID_REQUEST.\n\n // ── Catalogs & Events ─────────────────────────────────\n\n sync_catalogs(step, context, options, runnerVars) {\n // Prefer the fixture's sample_request — it's the authoritative request\n // shape for the storyboard step. The fallback's hardcoded feed_format\n // ('json') is NOT in the spec's 5-literal union and its `type` is\n // missing entirely, so any agent running the generated Zod schema\n // rejects the fallback with -32602 on both fields.\n return {\n account: context.account ?? resolveAccount(options),\n catalogs: [\n {\n catalog_id: `test-catalog-${generatedIdSuffix(step, runnerVars)}`,\n name: 'E2E Test Catalog',\n type: 'product',\n feed_url: 'https://test-assets.adcontextprotocol.org/feeds/test-catalog.json',\n feed_format: 'custom',\n },\n ],\n };\n },\n\n sync_event_sources(step, context, options, runnerVars) {\n return {\n account: context.account ?? resolveAccount(options),\n event_sources: [\n {\n event_source_id: `test-source-${generatedIdSuffix(step, runnerVars)}`,\n name: 'E2E Test Event Source',\n event_types: ['purchase', 'add_to_cart'],\n },\n ],\n };\n },\n\n log_event(step, context, _options, runnerVars) {\n // Storyboards routinely ship spec-conformant event payloads with\n // event_time, content_ids, and custom_data siblings that only the\n // author knows. Honor sample_request when present.\n return {\n event_source_id: context.event_source_id ?? 'test-source',\n events: [\n {\n event_id: `evt-${generatedIdSuffix(step, runnerVars)}`,\n event_type: 'purchase',\n event_time: new Date(runClockMs(runnerVars)).toISOString(),\n custom_data: { value: 49.99, currency: 'USD' },\n },\n ],\n };\n },\n\n report_usage(step, context, options, runnerVars) {\n // Prefer the fixture's sample_request — creative-ad-server and other\n // specialisms carry per-usage-entry fields (vendor_cost, currency,\n // pricing_option_id) that the hardcoded fallback here omits, causing\n // agents running the generated Zod schema to reject every step.\n const now = new Date(runClockMs(runnerVars));\n const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n return {\n account: context.account ?? resolveAccount(options),\n reporting_period: {\n start: monthAgo.toISOString(),\n end: now.toISOString(),\n },\n usage: [\n {\n account: context.account ?? resolveAccount(options),\n creative_id: context.creative_id ?? 'unknown',\n impressions: 10000,\n vendor_cost: 500,\n currency: 'USD',\n },\n ],\n };\n },\n\n // ── Creative ───────────────────────────────────────────\n\n list_creative_formats(step, context) {\n // Mirror the pattern used by peer builders (build_creative, sync_creatives,\n // etc.): honor hand-authored sample_request so storyboards can exercise\n // format_ids filters and other query params. Without this, any step that\n // declares `format_ids: [\"...\"]` in sample_request hits the wire as an\n // empty request and the agent returns unfiltered results — failing\n // round-trip / substitution-observer assertions silently.\n return {};\n },\n\n build_creative(step, context, options) {\n // Hand-authored sample_request can exercise slot-specific briefs, target\n // format overrides, or multi-format requests — honor it when present.\n const format = selectFormat(context);\n const sample = step.sample_request;\n const sampleRecord =\n sample !== undefined && typeof sample === 'object' && !Array.isArray(sample)\n ? (sample as Record<string, unknown>)\n : undefined;\n const hasAuthoredTarget =\n sampleRecord?.target_format_id !== undefined ||\n sampleRecord?.target_capability_id !== undefined ||\n Array.isArray(sampleRecord?.target_format_ids) ||\n Array.isArray(sampleRecord?.target_capability_ids) ||\n sampleRecord?.refine_from_build_variant_id !== undefined;\n return {\n ...(hasAuthoredTarget ? {} : { target_format_id: format?.format_id ?? context.format_id ?? UNKNOWN_FORMAT_ID }),\n brand: resolveBrand(options),\n message: 'Create a test advertisement for an e-commerce brand promoting a summer sale.',\n quality: 'draft',\n include_preview: true,\n };\n },\n\n preview_creative(_step, context, _options) {\n const format = selectFormat(context);\n return {\n request_type: 'single',\n creative_manifest: {\n format_id: format?.format_id ?? context.format_id ?? UNKNOWN_FORMAT_ID,\n name: 'E2E Test Creative',\n assets: {},\n },\n };\n },\n\n sync_creatives(step, context, options, runnerVars) {\n // Honor hand-authored sample_request for scenarios that require specific\n // creative shapes (delete/patch flows, format-scoped uploads, etc).\n const formats = (context.formats as Array<Record<string, unknown>> | undefined) ?? [];\n const idSuffix = generatedIdSuffix(step, runnerVars);\n\n // Send one creative per discovered format so downstream steps\n // (e.g., build_video_tag) can find creatives in every format.\n const creatives =\n formats.length > 0\n ? formats.map((fmt, i) => ({\n creative_id: `test-creative-${idSuffix}-${i}`,\n name: `E2E Test Creative ${i + 1}`,\n format_id: fmt.format_id ?? context.format_id ?? UNKNOWN_FORMAT_ID,\n assets: buildAssetsForFormat(fmt),\n }))\n : [\n {\n creative_id: `test-creative-${idSuffix}`,\n name: 'E2E Test Creative',\n format_id: context.format_id ?? UNKNOWN_FORMAT_ID,\n assets: {\n primary: {\n asset_type: 'image',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n width: 1200,\n height: 628,\n format: 'image/jpeg',\n },\n },\n },\n ];\n\n return {\n account: context.account ?? resolveAccount(options),\n creatives,\n };\n },\n\n list_creatives(_step, context, options) {\n return {\n account: context.account ?? resolveAccount(options),\n };\n },\n\n // ── Signals ────────────────────────────────────────────\n\n get_signals(step, context, options) {\n if (options.brief) return { signal_spec: options.brief };\n if (step.sample_request?.signal_ids) {\n return injectContext({ signal_ids: step.sample_request.signal_ids }, context);\n }\n // `anyOf: [{required: [signal_spec]}, {required: [signal_ids]}]` — the\n // schema rejects an empty object. Default to a discovery-style\n // `signal_spec` so storyboards that omit `options.brief` still send a\n // conforming request. A real test should author sample_request or pass\n // options.brief; this is the minimally valid fallback.\n return { signal_spec: 'E2E fallback signal discovery' };\n },\n\n activate_signal(step, context, _options) {\n const signal = selectSignal(context);\n const destinations = step.sample_request?.destinations as Array<Record<string, unknown>> | undefined;\n const request: Record<string, unknown> = {\n signal_agent_segment_id: signal?.signal_agent_segment_id ?? context.signal_id ?? 'test-signal',\n pricing_option_id:\n (signal?.pricing_options as Array<Record<string, unknown>> | undefined)?.[0]?.pricing_option_id ??\n context.pricing_option_id,\n };\n request.destinations = destinations\n ? (injectContext({ destinations }, context) as Record<string, unknown>).destinations\n : [{ type: 'agent', agent_url: 'https://test.example/signals' }];\n return request;\n },\n\n // ── Capabilities ───────────────────────────────────────\n\n get_adcp_capabilities() {\n return {};\n },\n\n // ── Governance ─────────────────────────────────────────\n\n sync_governance(step, context, options) {\n // `governance_agents[]` items are `additionalProperties: false` per\n // AdCP 3.1.0-beta.3 (the single-agent-owns-full-lifecycle clarification\n // dropped per-agent `categories`). Only `url` + `authentication` are\n // permitted on the wire.\n return {\n accounts: [\n {\n account: context.account ?? resolveAccount(options),\n governance_agents: [\n {\n url: 'https://governance.test.example',\n authentication: {\n schemes: ['Bearer'],\n credentials: 'test-governance-token-padded-to-meet-min-length-32',\n },\n },\n ],\n },\n ],\n };\n },\n\n list_content_standards() {\n return {};\n },\n\n get_content_standards(_step, context, _options) {\n // `standards_id` is required by GetContentStandardsRequestSchema (no optional()).\n // Unlike `get_media_buys` / `get_media_buy_delivery` (where the id field is\n // optional), we cannot return {} here — that would fail the schema round-trip\n // test. `'unknown'` triggers a clean NOT_FOUND when context lacks a real id,\n // surfacing the authoring gap (\"wire context_outputs from create_content_standards\").\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n };\n },\n\n calibrate_content(step, context, _options) {\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n artifact: {\n property_rid: 'test-publisher.example',\n artifact_id: context.creative_id ?? 'unknown',\n assets: [],\n },\n };\n },\n\n sync_plans(step, context, options, runnerVars) {\n // Governance storyboards define scenario-specific plans in sample_request\n // (e.g., custom_policies for conditions, reallocation_threshold for denied).\n // Delegate to sample_request when present.\n const now = runClockMs(runnerVars);\n const startDate = new Date(now + 24 * 60 * 60 * 1000).toISOString();\n const endDate = new Date(now + 90 * 24 * 60 * 60 * 1000).toISOString();\n const idSuffix = generatedIdSuffix(step, runnerVars, now);\n return {\n plans: [\n {\n plan_id: `test-plan-${idSuffix}`,\n brand: resolveBrand(options),\n objectives: 'E2E test campaign — maximize reach across digital channels',\n budget: { total: options.budget ?? 10000, currency: 'USD', reallocation_unlimited: true },\n flight: { start: startDate, end: endDate },\n approved_sellers: null,\n },\n ],\n };\n },\n\n check_governance(step, context, options) {\n // `caller` names the CALLER-AGENT's URL, not the brand — governance agents\n // use it for agent identity (rate limits, audit, JWS issuer correlation).\n // The brand belongs inside `payload`, where governance rules about the\n // advertised entity are evaluated. Using the fallback harness-orchestrator\n // URL keeps the semantics honest when no sample_request is authored.\n return {\n plan_id: context.plan_id ?? 'unknown',\n caller: FALLBACK_CALLER_AGENT_URL,\n tool: 'get_products',\n target_agent: 'https://seller.example/',\n payload: {\n type: 'media_buy',\n account: context.account ?? resolveAccount(options),\n brand: resolveBrand(options),\n total_budget: options.budget ?? 10000,\n },\n };\n },\n\n get_account_financials(_step, context, options) {\n return {\n account: context.account ?? resolveAccount(options),\n };\n },\n\n create_content_standards(step, context, _options, runnerVars) {\n // `anyOf: [{required: [policies]}, {required: [registry_policy_ids]}]` —\n // one must be present. Emit a minimal inline bespoke policy rather than\n // pinning a registry id the agent may not carry; storyboards that want\n // real governance coverage author sample_request.\n //\n // Contamination safeguards for the rare case a fallback hits a shared\n // sandbox: `enforcement: \"should\"` keeps this from hardening into a deny\n // rule against real content, and the ephemeral `policy_id` (timestamped\n // + \"e2e-fallback-\" prefix) guarantees uniqueness per run so a stale\n // policy can't be matched by accident.\n return {\n scope: {\n languages_any: ['en'],\n description: 'E2E fallback content standards — replace via sample_request for real governance coverage',\n },\n policies: [\n {\n policy_id: `e2e-fallback-${generatedIdSuffix(step, runnerVars)}`,\n enforcement: 'should',\n policy: 'E2E fallback policy — storyboard author did not supply sample_request.',\n },\n ],\n };\n },\n\n update_content_standards(step, context, _options) {\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n };\n },\n\n validate_content_delivery(step, context, _options) {\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n records: [\n {\n record_id: 'delivery_001',\n artifact: {\n property_rid: 'test-publisher.example',\n artifact_id: context.creative_id ?? 'unknown',\n assets: [],\n },\n },\n ],\n };\n },\n\n acquire_rights(step, context, options) {\n return {\n rights_id: context.rights_id ?? 'unknown',\n pricing_option_id: 'standard',\n buyer: { domain: resolveBrand(options).domain },\n campaign: {\n description: 'E2E storyboard test campaign',\n uses: ['commercial'],\n },\n revocation_webhook: {\n url: 'https://test.example/webhooks/revocation',\n authentication: {\n schemes: ['Bearer'],\n credentials: 'test-revocation-webhook-secret-token',\n },\n },\n };\n },\n\n update_rights(step, context, _options) {\n return {\n rights_id: context.rights_id ?? 'unknown',\n };\n },\n\n creative_approval(step, context, _options) {\n return {\n rights_id: context.rights_id ?? 'unknown',\n creative_id: context.creative_id ?? 'unknown',\n creative_url:\n (context.creative_url as string | undefined) ??\n 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n };\n },\n\n // ── Sponsored Intelligence ─────────────────────────────\n\n si_get_offering(step, context, options) {\n return {\n offering_id: options.si_offering_id ?? 'e2e-test-offering',\n intent: options.si_context ?? 'E2E testing - checking SI offering availability',\n };\n },\n\n si_initiate_session(step, context, options, runnerVars) {\n // `intent` is required and represents the user's ask. Default to a\n // semantically plausible one so agents that dispatch on intent still\n // behave sensibly; storyboards override via sample_request when\n // testing intent-specific paths.\n return {\n offering_id: context.offering_id ?? options.si_offering_id ?? 'e2e-test-offering',\n offering_token: context.offering_token,\n identity: {\n consent_granted: false,\n anonymous_session_id: `e2e-anon-${generatedIdSuffix(step, runnerVars)}`,\n },\n intent: options.si_context ?? 'Browse available offerings',\n placement: 'e2e-test',\n supported_capabilities: {\n modalities: { conversational: true, rich_media: true },\n },\n };\n },\n\n si_send_message(step, context, _options) {\n return {\n session_id: context.session_id ?? 'unknown',\n message: 'Tell me more about this product.',\n };\n },\n\n si_terminate_session(step, context, _options) {\n return {\n session_id: context.session_id ?? 'unknown',\n reason: 'user_exit',\n };\n },\n\n // ── Test Controller ────────────────────────────────────\n\n comply_test_controller(step, context, options) {\n // The test controller requires account.sandbox: true to be set.\n const account: Record<string, unknown> = {\n ...(context.account ?? resolveAccount(options)),\n sandbox: true,\n };\n // Natural-key arm of AccountReference requires `operator` per the spec\n // schema. If `context.account` came from a sync_accounts response that\n // omitted `operator` (#1419), fall back to brand.domain so the synthetic\n // ref the controller receives is spec-valid.\n if (typeof account.account_id !== 'string' && typeof account.operator !== 'string') {\n const brand = account.brand as { domain?: unknown } | undefined;\n if (brand && typeof brand.domain === 'string') {\n account.operator = brand.domain;\n }\n }\n if (step.sample_request) {\n // Drop envelope fields; outer enrichRequest re-applies them with\n // `runnerVars` so mustache substitutions expand correctly.\n return {\n ...omitEnvelopeFields(injectContext({ ...step.sample_request }, context) as Record<string, unknown>),\n account,\n };\n }\n return {\n account,\n scenario: context.controller_scenario ?? 'list_scenarios',\n };\n },\n};\n\n/**\n * Enrich a storyboard step's request payload.\n *\n * Contract (issue #820):\n * - `sample_request`, when authored, is the authoritative base. The runner\n * injects context placeholders into it before calling here.\n * - An enricher (if registered for the task) produces fields that should\n * fill gaps the fixture left unset — discovery-derived identifiers,\n * envelope fields the author couldn't know at YAML-authoring time.\n * - Top-level merge: fixture wins on key conflicts. Fixture-aware\n * enrichers (see `FIXTURE_AWARE_ENRICHERS`) skip the generic merge and\n * return the final payload themselves.\n *\n * Returns `{}` when the task has no enricher and no `sample_request` — the\n * runner's load-time validator prevents this for mutating tasks, so the\n * empty return is reachable only for read tasks that have no fixture and\n * no registered enricher (rare).\n */\nexport function enrichRequest(\n step: StoryboardStep,\n context: StoryboardContext,\n options: TestOptions,\n runnerVars?: RunnerVariables\n): Record<string, unknown> {\n const enricher = REQUEST_ENRICHERS[step.task];\n const fixture =\n step.sample_request !== undefined\n ? (injectContext({ ...(step.sample_request as Record<string, unknown>) }, context, runnerVars) as Record<\n string,\n unknown\n >)\n : undefined;\n\n if (!enricher) return fixture ?? {};\n\n const enriched = enricher(step, context, options, runnerVars);\n\n // Fixture-aware enrichers already did the body merge internally and know\n // the array/nested shapes better than a generic top-level overlay can.\n // Envelope fields still flow through from sample_request.\n if (FIXTURE_AWARE_ENRICHERS.has(step.task)) {\n if (!fixture) return enriched;\n const out: Record<string, unknown> = { ...enriched };\n for (const field of ENVELOPE_FIELDS) {\n if (fixture[field] !== undefined && out[field] === undefined) out[field] = fixture[field];\n }\n return out;\n }\n\n // Generic fixture-authoritative merge: fixture keys overlay enricher keys.\n return fixture ? { ...enriched, ...fixture } : enriched;\n}\n\n/** True iff a request enricher is registered for this task. */\nexport function hasRequestEnricher(taskName: string): boolean {\n return taskName in REQUEST_ENRICHERS;\n}\n\n// ────────────────────────────────────────────────────────────\n// Legacy aliases — pre-#820 terminology. Kept for one release so\n// external consumers (repo greps found none, but public exports may\n// have downstream users) migrate at their own pace.\n// ────────────────────────────────────────────────────────────\n\n/** @deprecated Renamed to `enrichRequest`. Same behavior. */\nexport const buildRequest = enrichRequest;\n\n/** @deprecated Renamed to `hasRequestEnricher`. Same behavior. */\nexport const hasRequestBuilder = hasRequestEnricher;\n\n// ────────────────────────────────────────────────────────────\n// Selection helpers: pick the best item from discovered data\n// ────────────────────────────────────────────────────────────\n\nfunction selectProduct(context: StoryboardContext): Record<string, unknown> | undefined {\n const products = context.products as Array<Record<string, unknown>> | undefined;\n if (!products?.length) return undefined;\n\n // Prefer products with guaranteed delivery and pricing options\n const withPricing = products.filter(p => {\n const opts = p.pricing_options as unknown[] | undefined;\n return opts && opts.length > 0;\n });\n\n return withPricing[0] ?? products[0];\n}\n\nfunction selectPricingOption(product: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!product) return undefined;\n const options = product.pricing_options as Array<Record<string, unknown>> | undefined;\n if (!options?.length) return undefined;\n\n // Prefer fixed pricing (cpm, flat) over auction\n const fixed = options.filter(o => o.pricing_model === 'cpm' || o.pricing_model === 'flat');\n return fixed[0] ?? options[0];\n}\n\nfunction selectFormat(context: StoryboardContext): Record<string, unknown> | undefined {\n const formats = context.formats as Array<Record<string, unknown>> | undefined;\n if (!formats?.length) return undefined;\n return formats[0];\n}\n\nfunction selectSignal(context: StoryboardContext): Record<string, unknown> | undefined {\n const signals = context.signals as Array<Record<string, unknown>> | undefined;\n if (!signals?.length) return undefined;\n return signals[0];\n}\n\n/**\n * Build placeholder assets appropriate for a format's type.\n * Uses the format name to guess whether it's video, native, or display.\n */\nfunction buildAssetsForFormat(format: Record<string, unknown>): Record<string, unknown> {\n const name = String(format.name ?? format.format_id ?? '').toLowerCase();\n const type = String(format.type ?? '').toLowerCase();\n\n if (type === 'video' || name.includes('video') || name.includes('vast')) {\n return {\n video: {\n asset_type: 'video',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/trail-pro-30s.mp4',\n width: 1920,\n height: 1080,\n duration_ms: 30000,\n container_format: 'video/mp4',\n },\n };\n }\n\n if (type === 'native' || name.includes('native')) {\n return {\n image: {\n asset_type: 'image',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n width: 1200,\n height: 628,\n format: 'image/jpeg',\n },\n headline: {\n asset_type: 'text',\n content: 'Trail Pro 3000 — Built for the Summit',\n },\n };\n }\n\n // Default: display image\n return {\n primary: {\n asset_type: 'image',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n width: 1200,\n height: 628,\n format: 'image/jpeg',\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/request-builder.ts"],"sourcesContent":["/**\n * Request enrichers for storyboard steps.\n *\n * Contract (see issue #820):\n * - `sample_request` (when authored) is the authoritative base payload.\n * The runner injects context placeholders into it and passes it through\n * to the agent under test.\n * - An enricher fills top-level fields the fixture didn't specify —\n * typically discovery-derived identifiers (`product_id`, `format_id`,\n * `account`, `media_buy_id`) or envelope fields that only the harness\n * knows.\n * - For conflicts at the top level, the fixture wins — storyboard authors'\n * intent is not silently overridden.\n *\n * A short list of tasks need to splice discovery-derived fields INTO\n * nested structures in the fixture (e.g. `create_media_buy` injects\n * `product_id` into `packages[0]`) and can't be expressed by a top-level\n * overlay. Those enrichers declare themselves fixture-aware via\n * `FIXTURE_AWARE_ENRICHERS` below and the runner uses their output as-is.\n *\n * `sample_request` from YAML, when a task has no enricher, is used directly\n * after context injection — preserves the \"no handler, fixture is the wire\n * payload\" pattern.\n */\n\nimport { createHash } from 'node:crypto';\nimport { resolveBrand, resolveAccount } from '../client';\nimport type { TestOptions } from '../types';\nimport type { StoryboardContext, StoryboardStep } from './types';\nimport { injectContext, type RunnerVariables } from './context';\n\ntype RequestEnricher = (\n step: StoryboardStep,\n context: StoryboardContext,\n options: TestOptions,\n runnerVars?: RunnerVariables\n) => Record<string, unknown>;\n\n/** Legacy alias kept for external consumers pinned to the old terminology. */\ntype RequestBuilder = RequestEnricher;\n\n/**\n * Placeholder `format_id` used when neither `list_creative_formats` discovery\n * nor accumulated `context.format_id` supplied one. Schema\n * (core/format-id.json) requires `agent_url` in URI form, so a bare\n * `\"unknown\"` string fails validation. `example.com` is reserved for\n * documentation per RFC 2606 — an obvious fixture that strict JSON-schema\n * validators accept and that downstream handlers resolve to a clean\n * format-not-found error rather than an unrelated crash. Frozen so a\n * builder that accidentally spread-mutates the shared constant hits a\n * TypeError instead of silently corrupting sibling calls.\n */\nconst UNKNOWN_FORMAT_ID = Object.freeze({ agent_url: 'https://unknown.example.com/', id: 'unknown' });\n\n/**\n * Placeholder `caller` URL for tasks whose schema names the CALLER-AGENT's\n * URL (not the brand or the seller). `check_governance.caller` is the canonical\n * case: governance agents bind this field to agent identity for rate limiting,\n * audit trails, and (with `signed-requests`) JWS issuer correlation — emitting\n * the brand domain here names the wrong entity and will confuse strict\n * governance agents. Storyboards that care about a specific caller identity\n * author sample_request; this is the fallback when neither fixture nor\n * harness-supplied agent URL is present.\n */\nconst FALLBACK_CALLER_AGENT_URL = 'https://e2e-orchestrator.adcontextprotocol.org/';\n\n/**\n * Tasks whose enricher must see `sample_request` to produce the final\n * payload — typically because it needs to splice discovery-derived fields\n * INTO nested structures the fixture owns (arrays, object trees). For\n * these, the runner uses the enricher's output verbatim and does not\n * layer the fixture on top; the enricher is responsible for fixture\n * precedence internally.\n */\nconst FIXTURE_AWARE_ENRICHERS = new Set<string>([\n 'create_media_buy', // merges discovery-derived product_id / pricing_option_id INTO fixture packages[0]\n 'comply_test_controller', // forces account.sandbox: true regardless of fixture\n 'check_governance', // preserves the authored intent-vs-delivery request shape\n 'get_products', // preserves wholesale fixture fields while keeping resolved account scope authoritative\n 'update_media_buy', // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy\n 'get_media_buys', // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy\n 'get_media_buy_delivery', // resolves account via resolveAccount(options) so sandbox routing matches create_media_buy\n]);\n\nfunction hasUnresolvedContextReference(value: unknown): boolean {\n if (typeof value === 'string') return /^\\$context\\.\\w+$/.test(value);\n if (Array.isArray(value)) return value.some(hasUnresolvedContextReference);\n if (value && typeof value === 'object') {\n return Object.values(value as Record<string, unknown>).some(hasUnresolvedContextReference);\n }\n return false;\n}\n\n/**\n * Placeholder identifiers that the upstream universal compliance\n * storyboards ship inside `create_media_buy.packages[0]` expecting the\n * runner to substitute the seller's discovered identifiers. The fixtures\n * live in `adcontextprotocol/adcp` and can't be rewritten from the SDK,\n * so the enricher treats these literals as \"defer to discovery\" while\n * real seller ids (e.g. `cpm_guaranteed`) win over discovery per the\n * fixture-authoritative contract. If a future storyboard wants\n * placeholder-then-discovery semantics for another value, author it as\n * a `$context.<key>` substitution rather than a magic literal so the\n * intent is explicit at the fixture level.\n */\nconst PRODUCT_ID_SENTINELS = new Set(['test-product']);\nconst PRICING_OPTION_ID_SENTINELS = new Set(['test-pricing']);\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst DEFAULT_MEDIA_BUY_WINDOW_MS = 7 * DAY_MS;\n\nfunction asNonSentinel(value: unknown, sentinels: Set<string>): string | undefined {\n if (typeof value !== 'string') return undefined;\n return sentinels.has(value) ? undefined : value;\n}\n\nfunction parseTime(value: string | undefined): number | undefined {\n if (value === undefined) return undefined;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction resolveMediaBuyWindow(\n sampleStart: string | undefined,\n sampleEnd: string | undefined,\n nowMs?: number\n): {\n startTime: string;\n endTime: string;\n} {\n const now = nowMs ?? Date.now();\n const defaultStart = new Date(now + DAY_MS).toISOString();\n const defaultEnd = new Date(now + 8 * DAY_MS).toISOString();\n const sampleStartMs = parseTime(sampleStart);\n const sampleEndMs = parseTime(sampleEnd);\n const startIsAsap = sampleStart === 'asap';\n\n const startTime = startIsAsap\n ? 'asap'\n : sampleStart && sampleStartMs !== undefined && sampleStartMs >= now\n ? sampleStart\n : defaultStart;\n let endTime = sampleEnd && sampleEndMs !== undefined && sampleEndMs >= now ? sampleEnd : defaultEnd;\n\n const startTimeMs = startIsAsap ? now : Date.parse(startTime);\n if (Date.parse(endTime) <= startTimeMs) {\n const sampleDurationMs =\n sampleStartMs !== undefined && sampleEndMs !== undefined && sampleEndMs > sampleStartMs\n ? sampleEndMs - sampleStartMs\n : DEFAULT_MEDIA_BUY_WINDOW_MS;\n endTime = new Date(startTimeMs + sampleDurationMs).toISOString();\n }\n\n return { startTime, endTime };\n}\n\nfunction runClockMs(runnerVars: RunnerVariables | undefined): number {\n return runnerVars?.runStartMs ?? Date.now();\n}\n\nfunction resolveMediaBuyReadAccount(fixtureAccount: unknown, contextAccount: unknown, options: TestOptions): unknown {\n const resolvedAccount = contextAccount ?? resolveAccount(options);\n // Preserve a fixture-authored natural-key operator: it identifies the\n // buyer acting for the brand and is not interchangeable with brand.domain.\n // A context account remains authoritative, while the harness still owns\n // sandbox routing for fixture-authored natural keys.\n if (\n contextAccount === undefined &&\n fixtureAccount !== null &&\n typeof fixtureAccount === 'object' &&\n !Array.isArray(fixtureAccount) &&\n typeof (fixtureAccount as Record<string, unknown>).operator === 'string' &&\n typeof (fixtureAccount as Record<string, unknown>).account_id !== 'string'\n ) {\n const sandbox = (resolvedAccount as { sandbox?: boolean }).sandbox;\n return {\n ...(fixtureAccount as Record<string, unknown>),\n ...(sandbox !== undefined && { sandbox }),\n };\n }\n return resolvedAccount;\n}\n\nfunction generatedIdSuffix(step: StoryboardStep, runnerVars: RunnerVariables | undefined, nowMs?: number): string {\n const timestamp = nowMs ?? runClockMs(runnerVars);\n if (runnerVars?.runStartMs === undefined) return String(timestamp);\n const stepHash = createHash('sha256').update(step.id).digest('hex').slice(0, 12);\n return `${timestamp}-${stepHash}`;\n}\n\n/**\n * Envelope fields that live on every AdCP request and are owned by the\n * storyboard author — `context.correlation_id`, runner-supplied\n * `idempotency_key` aliases, webhook pointers, per-request extensions.\n * Fixture-aware enrichers must NOT spread these from their internal\n * `injectContext(sample_request, context)` call: that internal call\n * doesn't receive `runnerVars`, so mustache tokens (`{{runner.webhook_url:<step_id>}}`)\n * would ship to the wire literally. The outer `enrichRequest` overlays\n * envelope fields from a `runnerVars`-aware fixture re-injection.\n */\nconst ENVELOPE_FIELDS = ['context', 'ext', 'push_notification_config', 'idempotency_key'] as const;\n\nfunction omitEnvelopeFields(obj: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (!(ENVELOPE_FIELDS as readonly string[]).includes(k)) out[k] = v;\n }\n return out;\n}\n\nconst REQUEST_ENRICHERS: Record<string, RequestEnricher> = {\n // ── Account & Audience ─────────────────────────────────\n\n sync_accounts(_step, _context, options) {\n return {\n accounts: [\n {\n brand: resolveBrand(options),\n operator: resolveBrand(options).domain,\n billing: 'operator',\n payment_terms: 'net_30',\n },\n ],\n };\n },\n\n sync_audiences(step, context, options, runnerVars) {\n // Honor hand-authored sample_request so storyboards can register a\n // specific audience_id that downstream steps reference. Without this,\n // add-shaped sample_request blocks (authored with audience_id + add[])\n // fell through to the generated fallback id, and a later delete_audience\n // or context-substitution step would hit AUDIENCE_NOT_FOUND because the\n // sync had registered a different id. Matches the pattern used by\n // sync_event_sources, sync_catalogs, and sync_creatives.\n if (step.sample_request) {\n return injectContext({ ...step.sample_request, account: context.account ?? resolveAccount(options) }, context);\n }\n return {\n account: context.account ?? resolveAccount(options),\n audiences: [\n {\n audience_id: context.audience_id ?? `test-audience-${generatedIdSuffix(step, runnerVars)}`,\n name: 'E2E Test Audience',\n add: [\n {\n external_id: 'user-001',\n hashed_email: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',\n },\n ],\n },\n ],\n };\n },\n\n // ── Brand & Rights ───────────────────────────────────────\n\n get_brand_identity(step, context, options) {\n const brand = resolveBrand(options);\n return {\n brand_id: context.brand_id ?? (step.sample_request?.brand_id as string) ?? brand.brand_id ?? brand.domain,\n };\n },\n\n get_rights(step, context, options) {\n // Honor hand-authored sample_request so storyboards can specify\n // scenario-specific query text, uses, countries, or buyer_brand.\n // Peer builders (sync_plans, check_governance, list_creative_formats,\n // create_content_standards, etc.) follow the same pattern.\n //\n // Without this, any get_rights step hits the wire with the generic\n // fallback and a brand_id derived from the caller's domain — which\n // rights-holder rosters reject as unknown, so rights[0] is undefined,\n // $context.rights_id doesn't resolve, and downstream acquire_rights\n // steps fail with rights_not_found instead of the error the\n // storyboard is actually asserting (e.g., GOVERNANCE_DENIED).\n const brand = resolveBrand(options);\n return {\n query: 'available rights for advertising',\n uses: ['ai_generated_image'],\n brand_id: context.brand_id ?? brand.brand_id ?? brand.domain,\n };\n },\n\n // ── Product Discovery ──────────────────────────────────\n\n get_products(step, context, options) {\n // Fixture-aware: wholesale storyboards author cache validators, filters,\n // and account identities that must survive enrichment together. Resolve\n // placeholders before selecting the account. A fully resolved fixture\n // account remains authoritative (scope-isolation storyboards deliberately\n // switch accounts between steps); only an unresolved fixture reference\n // falls back to the context/run account (#2654).\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const fixtureAccount = fixtureFields.account;\n const resolvedAccount =\n fixtureAccount !== undefined && !hasUnresolvedContextReference(fixtureAccount)\n ? fixtureAccount\n : (context.account ?? resolveAccount(options));\n\n if (fixtureFields.buying_mode === 'wholesale') {\n return {\n ...fixtureFields,\n account: resolvedAccount,\n };\n }\n\n // If the step is a \"refine\" step, build a refine request\n if (step.sample_request?.buying_mode === 'refine' && context.products) {\n return {\n ...fixtureFields,\n buying_mode: 'refine',\n refine: fixtureFields.refine ?? [\n {\n scope: 'request',\n ask: 'Only guaranteed packages with premium placement.',\n },\n ],\n brand: fixtureFields.brand ?? resolveBrand(options),\n account: resolvedAccount,\n };\n }\n\n return {\n buying_mode: 'brief',\n brief: options.brief || 'Show me all available advertising products across all channels',\n brand: resolveBrand(options),\n ...fixtureFields,\n account: resolvedAccount,\n };\n },\n\n // ── Media Buy ──────────────────────────────────────────\n\n create_media_buy(step, context, options, runnerVars) {\n const product = selectProduct(context);\n const pricingOption = selectPricingOption(product);\n\n // Respect sample_request dates when they're future-dated — needed for\n // storyboards that test replay semantics where initial + replay must\n // produce byte-for-byte identical canonical payloads. Two calls\n // generated 5ms apart with `Date.now()` would hash differently,\n // triggering IDEMPOTENCY_CONFLICT on replay. Stale sample dates\n // (authored before the run date) fall back to the run-start-relative\n // default. Resolve the pair together so a stale start and same-day\n // future end cannot produce start_time > end_time.\n const sampleStart =\n typeof step.sample_request?.start_time === 'string' ? step.sample_request.start_time : undefined;\n const sampleEnd = typeof step.sample_request?.end_time === 'string' ? step.sample_request.end_time : undefined;\n const { startTime, endTime } = resolveMediaBuyWindow(sampleStart, sampleEnd, runnerVars?.runStartMs);\n\n // Merge hand-authored package fields from sample_request (targeting_overlay,\n // measurement_terms, creative_assignments, performance_standards, etc.) so\n // scenario-specific behaviors are exercised. The first package's\n // identifiers (product_id, pricing_option_id) follow a two-tier rule:\n //\n // - Real seller ids in the fixture win over discovery — storyboards\n // that name `cpm_guaranteed` (or any seller-specific identifier)\n // are asserting that specific id reaches the wire. Discovery must\n // not override.\n // - Well-known sentinel placeholders (`test-product`, `test-pricing`)\n // from the upstream universal compliance storyboards defer to\n // discovery. Those storyboards ship package fixtures with\n // `product_id: \"test-product\"` expecting the runner to substitute\n // the seller's discovered product — they'd fail against every\n // seller that doesn't literally ship a \"test-product\" catalog\n // entry if the fixture value survived to the wire.\n //\n // The sentinel list is conservative. If a future storyboard wants\n // placeholder-then-discovery semantics for another field, author it\n // as `$context.<key>` substitution instead of a magic literal.\n const samplePackages = (step.sample_request?.packages as Array<Record<string, unknown>> | undefined) ?? [];\n const baseSample = samplePackages[0]\n ? (injectContext({ ...samplePackages[0] }, context) as Record<string, unknown>)\n : {};\n\n const fixtureProductId = asNonSentinel(baseSample.product_id, PRODUCT_ID_SENTINELS);\n const fixturePricingOptionId = asNonSentinel(baseSample.pricing_option_id, PRICING_OPTION_ID_SENTINELS);\n\n const firstPkg: Record<string, unknown> = {\n ...baseSample,\n product_id: fixtureProductId ?? product?.product_id ?? context.product_id ?? 'test-product',\n budget:\n (typeof baseSample.budget === 'number' ? baseSample.budget : undefined) ??\n options.budget ??\n Math.max(1000, (pricingOption?.min_spend_per_package as number) ?? 1000),\n pricing_option_id:\n fixturePricingOptionId ?? pricingOption?.pricing_option_id ?? context.pricing_option_id ?? 'default',\n };\n\n // Synthesize a bid_price for auction/cpm pricing only when the fixture\n // didn't author one. Storyboards that test auction flows (e.g.\n // sales-non-guaranteed) author explicit bid_prices the seller validates\n // against floor_price; discovery-synthesized values would silently\n // override intentional bid-floor-boundary tests.\n if (\n baseSample.bid_price === undefined &&\n (pricingOption?.pricing_model === 'auction' || pricingOption?.pricing_model === 'cpm')\n ) {\n const floor = Number(pricingOption?.floor_price) || 5;\n firstPkg.bid_price = Math.round(floor * 1.5 * 100) / 100;\n }\n\n const additionalPkgs = samplePackages\n .slice(1)\n .map(p => injectContext({ ...p }, context) as Record<string, unknown>);\n\n // Proposal-mode: when context carries a proposal_id (captured from\n // `proposals[0]` in a prior brief/refine/finalize step), forward it\n // and omit `packages`. The schema disallows synthesising packages\n // alongside `proposal_id` — `dependencies.proposal_id` requires\n // `total_budget` and the seller derives packages from the committed\n // allocation.\n //\n // Spread the fixture (after $context injection) so proposal-mode-\n // required fields like `total_budget` flow through. Prefer the\n // fixture's account/brand when supplied — proposal-mode storyboards\n // author a non-default brand (e.g. `acmeoutdoor.example`) that the\n // adapter resolves end-to-end through brief/refine/finalize, and\n // the harness-default `test.example` would fail account resolution\n // at the accept step (adcp-client#1600). Dates and proposal_id\n // are still normalised by the enricher.\n const fixture =\n step.sample_request !== undefined\n ? (injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>)\n : {};\n // Drop envelope fields from the local spread — the outer enrichRequest\n // re-injects them with `runnerVars` so `{{runner.webhook_url:<step_id>}}`\n // tokens inside push_notification_config expand. Spreading them here\n // would carry through unexpanded mustache strings.\n const fixtureBody = omitEnvelopeFields(fixture);\n\n // Proposal-mode applies only when the storyboard's fixture explicitly\n // names a `proposal_id`. `context.proposal_id` is auto-captured from\n // any prior `get_products` response that returned `proposals[0]` (see\n // context.ts), which is essentially every brief flow — using it as a\n // fallback would override a fixture's explicit `packages` direction\n // and force every sales storyboard through proposal-mode validation,\n // including ones that intentionally exercise package-mode (sales-\n // guaranteed, schema_validation, media_buy_seller/*). Fixture is the\n // storyboard author's intent; respect it.\n const fixtureHasPackages = Array.isArray(fixture.packages) && (fixture.packages as unknown[]).length > 0;\n const proposalId: unknown =\n fixture.proposal_id !== undefined ? fixture.proposal_id : fixtureHasPackages ? undefined : context.proposal_id;\n if (typeof proposalId === 'string') {\n const { packages: _droppedPackages, ...fixtureWithoutPackages } = fixtureBody;\n return {\n ...fixtureWithoutPackages,\n account: fixtureWithoutPackages.account ?? context.account ?? resolveAccount(options),\n brand: fixtureWithoutPackages.brand ?? resolveBrand(options),\n start_time: startTime,\n end_time: endTime,\n proposal_id: proposalId,\n };\n }\n\n // Spread the fixture (after $context injection) so any sample_request\n // fields the enricher doesn't explicitly normalise (total_budget,\n // buyer_ref, currency, scenario-specific extensions) reach the wire.\n // The enricher then layers its own substitutions on top: packages is\n // replaced (the enricher merged samplePackages internally with\n // discovery-derived identifiers above), account/brand/start_time/\n // end_time are normalised. Per issue #1604, build-from-scratch dropped\n // every fixture field outside this enumerated set — fixture-aware\n // enrichers must spread sample_request first, then override. Envelope\n // fields are omitted here and re-applied by the outer enrichRequest\n // with `runnerVars` so mustache tokens expand correctly.\n return {\n ...fixtureBody,\n account: context.account ?? resolveAccount(options),\n brand: resolveBrand(options),\n start_time: startTime,\n end_time: endTime,\n packages: [firstPkg, ...additionalPkgs],\n };\n },\n\n update_media_buy(step, context, options) {\n // Fixture-aware: spread the storyboard's sample_request first so hand-authored\n // intent (targeting_overlay swaps, creative assignments, pause/resume/cancel)\n // is preserved verbatim, then force `account` to the harness-resolved value so\n // sandbox routing matches create_media_buy's namespace on every round-trip\n // (otherwise the fixture's account silently routes update writes to a different\n // partition than the create wrote to, and a subsequent get_media_buys reading\n // from the create-time partition surfaces stale data — see adcp-client#1505).\n // Envelope fields are dropped from the local spread; the outer enrichRequest\n // re-injects them with `runnerVars` so mustache substitutions expand.\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const request: Record<string, unknown> = { ...fixtureFields };\n request.account = context.account ?? resolveAccount(options);\n if (request.media_buy_id === undefined) {\n request.media_buy_id = context.media_buy_id ?? 'unknown';\n }\n\n // No sample_request: fall back to step-id keyword inference so legacy\n // storyboards without an authored fixture still exercise sensible flows.\n if (!step.sample_request) {\n if (step.id.includes('pause')) {\n request.paused = true;\n } else if (step.id.includes('resume')) {\n request.paused = false;\n } else if (step.id.includes('cancel')) {\n request.canceled = true;\n } else {\n request.packages = [\n {\n package_id: (context.package_id as string | undefined) ?? 'unknown',\n budget: 2000,\n },\n ];\n }\n }\n\n return request;\n },\n\n get_media_buys(step, context, options) {\n // Spread fixture fields so storyboards can author filters, status, pagination, etc.\n // account is always overridden by the harness-resolved value so sandbox routing\n // matches create_media_buy's namespace on every round-trip. Envelope fields are\n // dropped from the local spread so the outer enrichRequest re-injects them with\n // `runnerVars` (mustache substitutions expand against the runner's webhook base).\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const result: Record<string, unknown> = { ...fixtureFields };\n result.account = resolveMediaBuyReadAccount(fixtureFields.account, context.account, options);\n if (context.media_buy_id != null && result.media_buy_ids === undefined) {\n result.media_buy_ids = [context.media_buy_id];\n }\n return result;\n },\n\n get_media_buy_delivery(step, context, options) {\n // Same account-resolution rule as get_media_buys — fixture fields preserved,\n // account overridden by harness so sandbox routing matches create_media_buy.\n // Envelope fields dropped from the local spread; outer enrichRequest re-applies\n // them with `runnerVars` so mustache substitutions expand.\n const fixtureFields = step.sample_request\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context) as Record<string, unknown>\n )\n : {};\n const result: Record<string, unknown> = { ...fixtureFields };\n result.account = resolveMediaBuyReadAccount(fixtureFields.account, context.account, options);\n if (context.media_buy_id != null && result.media_buy_ids === undefined) {\n result.media_buy_ids = [context.media_buy_id];\n }\n return result;\n },\n\n // provide_performance_feedback intentionally has no builder — storyboard\n // sample_request is authoritative because the spec's oneOf requires a\n // performance_index variant that only the storyboard author knows the\n // shape of. A synthesized payload here would emit non-spec fields\n // (feedback/satisfaction/notes) and get rejected with INVALID_REQUEST.\n\n // ── Catalogs & Events ─────────────────────────────────\n\n sync_catalogs(step, context, options, runnerVars) {\n // Prefer the fixture's sample_request — it's the authoritative request\n // shape for the storyboard step. The fallback's hardcoded feed_format\n // ('json') is NOT in the spec's 5-literal union and its `type` is\n // missing entirely, so any agent running the generated Zod schema\n // rejects the fallback with -32602 on both fields.\n return {\n account: context.account ?? resolveAccount(options),\n catalogs: [\n {\n catalog_id: `test-catalog-${generatedIdSuffix(step, runnerVars)}`,\n name: 'E2E Test Catalog',\n type: 'product',\n feed_url: 'https://test-assets.adcontextprotocol.org/feeds/test-catalog.json',\n feed_format: 'custom',\n },\n ],\n };\n },\n\n sync_event_sources(step, context, options, runnerVars) {\n return {\n account: context.account ?? resolveAccount(options),\n event_sources: [\n {\n event_source_id: `test-source-${generatedIdSuffix(step, runnerVars)}`,\n name: 'E2E Test Event Source',\n event_types: ['purchase', 'add_to_cart'],\n },\n ],\n };\n },\n\n log_event(step, context, _options, runnerVars) {\n // Storyboards routinely ship spec-conformant event payloads with\n // event_time, content_ids, and custom_data siblings that only the\n // author knows. Honor sample_request when present.\n return {\n event_source_id: context.event_source_id ?? 'test-source',\n events: [\n {\n event_id: `evt-${generatedIdSuffix(step, runnerVars)}`,\n event_type: 'purchase',\n event_time: new Date(runClockMs(runnerVars)).toISOString(),\n custom_data: { value: 49.99, currency: 'USD' },\n },\n ],\n };\n },\n\n report_usage(step, context, options, runnerVars) {\n // Prefer the fixture's sample_request — creative-ad-server and other\n // specialisms carry per-usage-entry fields (vendor_cost, currency,\n // pricing_option_id) that the hardcoded fallback here omits, causing\n // agents running the generated Zod schema to reject every step.\n const now = new Date(runClockMs(runnerVars));\n const monthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n return {\n account: context.account ?? resolveAccount(options),\n reporting_period: {\n start: monthAgo.toISOString(),\n end: now.toISOString(),\n },\n usage: [\n {\n account: context.account ?? resolveAccount(options),\n creative_id: context.creative_id ?? 'unknown',\n impressions: 10000,\n vendor_cost: 500,\n currency: 'USD',\n },\n ],\n };\n },\n\n // ── Creative ───────────────────────────────────────────\n\n list_creative_formats(step, context) {\n // Mirror the pattern used by peer builders (build_creative, sync_creatives,\n // etc.): honor hand-authored sample_request so storyboards can exercise\n // format_ids filters and other query params. Without this, any step that\n // declares `format_ids: [\"...\"]` in sample_request hits the wire as an\n // empty request and the agent returns unfiltered results — failing\n // round-trip / substitution-observer assertions silently.\n return {};\n },\n\n build_creative(step, context, options) {\n // Hand-authored sample_request can exercise slot-specific briefs, target\n // format overrides, or multi-format requests — honor it when present.\n const format = selectFormat(context);\n const sample = step.sample_request;\n const sampleRecord =\n sample !== undefined && typeof sample === 'object' && !Array.isArray(sample)\n ? (sample as Record<string, unknown>)\n : undefined;\n const hasAuthoredTarget =\n sampleRecord?.target_format_id !== undefined ||\n sampleRecord?.target_capability_id !== undefined ||\n Array.isArray(sampleRecord?.target_format_ids) ||\n Array.isArray(sampleRecord?.target_capability_ids) ||\n sampleRecord?.refine_from_build_variant_id !== undefined;\n return {\n ...(hasAuthoredTarget ? {} : { target_format_id: format?.format_id ?? context.format_id ?? UNKNOWN_FORMAT_ID }),\n brand: resolveBrand(options),\n message: 'Create a test advertisement for an e-commerce brand promoting a summer sale.',\n quality: 'draft',\n include_preview: true,\n };\n },\n\n preview_creative(_step, context, _options) {\n const format = selectFormat(context);\n return {\n request_type: 'single',\n creative_manifest: {\n format_id: format?.format_id ?? context.format_id ?? UNKNOWN_FORMAT_ID,\n name: 'E2E Test Creative',\n assets: {},\n },\n };\n },\n\n sync_creatives(step, context, options, runnerVars) {\n // Honor hand-authored sample_request for scenarios that require specific\n // creative shapes (delete/patch flows, format-scoped uploads, etc).\n const formats = (context.formats as Array<Record<string, unknown>> | undefined) ?? [];\n const idSuffix = generatedIdSuffix(step, runnerVars);\n\n // Send one creative per discovered format so downstream steps\n // (e.g., build_video_tag) can find creatives in every format.\n const creatives =\n formats.length > 0\n ? formats.map((fmt, i) => ({\n creative_id: `test-creative-${idSuffix}-${i}`,\n name: `E2E Test Creative ${i + 1}`,\n format_id: fmt.format_id ?? context.format_id ?? UNKNOWN_FORMAT_ID,\n assets: buildAssetsForFormat(fmt),\n }))\n : [\n {\n creative_id: `test-creative-${idSuffix}`,\n name: 'E2E Test Creative',\n format_id: context.format_id ?? UNKNOWN_FORMAT_ID,\n assets: {\n primary: {\n asset_type: 'image',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n width: 1200,\n height: 628,\n format: 'image/jpeg',\n },\n },\n },\n ];\n\n return {\n account: context.account ?? resolveAccount(options),\n creatives,\n };\n },\n\n list_creatives(_step, context, options) {\n return {\n account: context.account ?? resolveAccount(options),\n };\n },\n\n // ── Signals ────────────────────────────────────────────\n\n get_signals(step, context, options) {\n if (options.brief) return { signal_spec: options.brief };\n if (step.sample_request?.signal_ids) {\n return injectContext({ signal_ids: step.sample_request.signal_ids }, context);\n }\n // `anyOf: [{required: [signal_spec]}, {required: [signal_ids]}]` — the\n // schema rejects an empty object. Default to a discovery-style\n // `signal_spec` so storyboards that omit `options.brief` still send a\n // conforming request. A real test should author sample_request or pass\n // options.brief; this is the minimally valid fallback.\n return { signal_spec: 'E2E fallback signal discovery' };\n },\n\n activate_signal(step, context, _options) {\n const signal = selectSignal(context);\n const destinations = step.sample_request?.destinations as Array<Record<string, unknown>> | undefined;\n const request: Record<string, unknown> = {\n signal_agent_segment_id: signal?.signal_agent_segment_id ?? context.signal_id ?? 'test-signal',\n pricing_option_id:\n (signal?.pricing_options as Array<Record<string, unknown>> | undefined)?.[0]?.pricing_option_id ??\n context.pricing_option_id,\n };\n request.destinations = destinations\n ? (injectContext({ destinations }, context) as Record<string, unknown>).destinations\n : [{ type: 'agent', agent_url: 'https://test.example/signals' }];\n return request;\n },\n\n // ── Capabilities ───────────────────────────────────────\n\n get_adcp_capabilities() {\n return {};\n },\n\n // ── Governance ─────────────────────────────────────────\n\n sync_governance(step, context, options) {\n // `governance_agents[]` items are `additionalProperties: false` per\n // AdCP 3.1.0-beta.3 (the single-agent-owns-full-lifecycle clarification\n // dropped per-agent `categories`). Only `url` + `authentication` are\n // permitted on the wire.\n return {\n accounts: [\n {\n account: context.account ?? resolveAccount(options),\n governance_agents: [\n {\n url: 'https://governance.test.example',\n authentication: {\n schemes: ['Bearer'],\n credentials: 'test-governance-token-padded-to-meet-min-length-32',\n },\n },\n ],\n },\n ],\n };\n },\n\n list_content_standards() {\n return {};\n },\n\n get_content_standards(_step, context, _options) {\n // `standards_id` is required by GetContentStandardsRequestSchema (no optional()).\n // Unlike `get_media_buys` / `get_media_buy_delivery` (where the id field is\n // optional), we cannot return {} here — that would fail the schema round-trip\n // test. `'unknown'` triggers a clean NOT_FOUND when context lacks a real id,\n // surfacing the authoring gap (\"wire context_outputs from create_content_standards\").\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n };\n },\n\n calibrate_content(step, context, _options) {\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n artifact: {\n property_rid: 'test-publisher.example',\n artifact_id: context.creative_id ?? 'unknown',\n assets: [],\n },\n };\n },\n\n sync_plans(step, context, options, runnerVars) {\n // Governance storyboards define scenario-specific plans in sample_request\n // (e.g., custom_policies for conditions, reallocation_threshold for denied).\n // Delegate to sample_request when present.\n const now = runClockMs(runnerVars);\n const startDate = new Date(now + 24 * 60 * 60 * 1000).toISOString();\n const endDate = new Date(now + 90 * 24 * 60 * 60 * 1000).toISOString();\n const idSuffix = generatedIdSuffix(step, runnerVars, now);\n return {\n plans: [\n {\n plan_id: `test-plan-${idSuffix}`,\n brand: resolveBrand(options),\n objectives: 'E2E test campaign — maximize reach across digital channels',\n budget: { total: options.budget ?? 10000, currency: 'USD', reallocation_unlimited: true },\n flight: { start: startDate, end: endDate },\n approved_sellers: null,\n },\n ],\n };\n },\n\n check_governance(step, context, options, runnerVars) {\n // `caller` names the CALLER-AGENT's URL, not the brand — governance agents\n // use it for agent identity (rate limits, audit, JWS issuer correlation).\n // The brand belongs inside `payload`, where governance rules about the\n // advertised entity are evaluated. Using the fallback harness-orchestrator\n // URL keeps the semantics honest when no sample_request is authored.\n const fixture =\n step.sample_request !== undefined\n ? omitEnvelopeFields(\n injectContext({ ...(step.sample_request as Record<string, unknown>) }, context, runnerVars) as Record<\n string,\n unknown\n >\n )\n : undefined;\n const isDelivery =\n fixture?.phase === 'delivery' ||\n fixture?.planned_delivery !== undefined ||\n fixture?.delivery_metrics !== undefined ||\n fixture?.governance_context !== undefined;\n\n if (fixture && isDelivery) {\n return {\n ...fixture,\n caller: fixture.caller ?? FALLBACK_CALLER_AGENT_URL,\n };\n }\n\n const fallback = {\n plan_id: context.plan_id ?? 'unknown',\n caller: FALLBACK_CALLER_AGENT_URL,\n tool: 'get_products',\n target_agent: 'https://seller.example/',\n payload: {\n type: 'media_buy',\n account: context.account ?? resolveAccount(options),\n brand: resolveBrand(options),\n total_budget: options.budget ?? 10000,\n },\n };\n return fixture ? { ...fallback, ...fixture } : fallback;\n },\n\n get_account_financials(_step, context, options) {\n return {\n account: context.account ?? resolveAccount(options),\n };\n },\n\n create_content_standards(step, context, _options, runnerVars) {\n // `anyOf: [{required: [policies]}, {required: [registry_policy_ids]}]` —\n // one must be present. Emit a minimal inline bespoke policy rather than\n // pinning a registry id the agent may not carry; storyboards that want\n // real governance coverage author sample_request.\n //\n // Contamination safeguards for the rare case a fallback hits a shared\n // sandbox: `enforcement: \"should\"` keeps this from hardening into a deny\n // rule against real content, and the ephemeral `policy_id` (timestamped\n // + \"e2e-fallback-\" prefix) guarantees uniqueness per run so a stale\n // policy can't be matched by accident.\n return {\n scope: {\n languages_any: ['en'],\n description: 'E2E fallback content standards — replace via sample_request for real governance coverage',\n },\n policies: [\n {\n policy_id: `e2e-fallback-${generatedIdSuffix(step, runnerVars)}`,\n enforcement: 'should',\n policy: 'E2E fallback policy — storyboard author did not supply sample_request.',\n },\n ],\n };\n },\n\n update_content_standards(step, context, _options) {\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n };\n },\n\n validate_content_delivery(step, context, _options) {\n return {\n standards_id: context.content_standards_id ?? 'unknown',\n records: [\n {\n record_id: 'delivery_001',\n artifact: {\n property_rid: 'test-publisher.example',\n artifact_id: context.creative_id ?? 'unknown',\n assets: [],\n },\n },\n ],\n };\n },\n\n acquire_rights(step, context, options) {\n return {\n rights_id: context.rights_id ?? 'unknown',\n pricing_option_id: 'standard',\n buyer: { domain: resolveBrand(options).domain },\n campaign: {\n description: 'E2E storyboard test campaign',\n uses: ['commercial'],\n },\n revocation_webhook: {\n url: 'https://test.example/webhooks/revocation',\n authentication: {\n schemes: ['Bearer'],\n credentials: 'test-revocation-webhook-secret-token',\n },\n },\n };\n },\n\n update_rights(step, context, _options) {\n return {\n rights_id: context.rights_id ?? 'unknown',\n };\n },\n\n creative_approval(step, context, _options) {\n return {\n rights_id: context.rights_id ?? 'unknown',\n creative_id: context.creative_id ?? 'unknown',\n creative_url:\n (context.creative_url as string | undefined) ??\n 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n };\n },\n\n // ── Sponsored Intelligence ─────────────────────────────\n\n si_get_offering(step, context, options) {\n return {\n offering_id: options.si_offering_id ?? 'e2e-test-offering',\n intent: options.si_context ?? 'E2E testing - checking SI offering availability',\n };\n },\n\n si_initiate_session(step, context, options, runnerVars) {\n // `intent` is required and represents the user's ask. Default to a\n // semantically plausible one so agents that dispatch on intent still\n // behave sensibly; storyboards override via sample_request when\n // testing intent-specific paths.\n return {\n offering_id: context.offering_id ?? options.si_offering_id ?? 'e2e-test-offering',\n offering_token: context.offering_token,\n identity: {\n consent_granted: false,\n anonymous_session_id: `e2e-anon-${generatedIdSuffix(step, runnerVars)}`,\n },\n intent: options.si_context ?? 'Browse available offerings',\n placement: 'e2e-test',\n supported_capabilities: {\n modalities: { conversational: true, rich_media: true },\n },\n };\n },\n\n si_send_message(step, context, _options) {\n return {\n session_id: context.session_id ?? 'unknown',\n message: 'Tell me more about this product.',\n };\n },\n\n si_terminate_session(step, context, _options) {\n return {\n session_id: context.session_id ?? 'unknown',\n reason: 'user_exit',\n };\n },\n\n // ── Test Controller ────────────────────────────────────\n\n comply_test_controller(step, context, options) {\n // The test controller requires account.sandbox: true to be set.\n const account: Record<string, unknown> = {\n ...(context.account ?? resolveAccount(options)),\n sandbox: true,\n };\n // Natural-key arm of AccountReference requires `operator` per the spec\n // schema. If `context.account` came from a sync_accounts response that\n // omitted `operator` (#1419), fall back to brand.domain so the synthetic\n // ref the controller receives is spec-valid.\n if (typeof account.account_id !== 'string' && typeof account.operator !== 'string') {\n const brand = account.brand as { domain?: unknown } | undefined;\n if (brand && typeof brand.domain === 'string') {\n account.operator = brand.domain;\n }\n }\n if (step.sample_request) {\n // Drop envelope fields; outer enrichRequest re-applies them with\n // `runnerVars` so mustache substitutions expand correctly.\n return {\n ...omitEnvelopeFields(injectContext({ ...step.sample_request }, context) as Record<string, unknown>),\n account,\n };\n }\n return {\n account,\n scenario: context.controller_scenario ?? 'list_scenarios',\n };\n },\n};\n\n/**\n * Enrich a storyboard step's request payload.\n *\n * Contract (issue #820):\n * - `sample_request`, when authored, is the authoritative base. The runner\n * injects context placeholders into it before calling here.\n * - An enricher (if registered for the task) produces fields that should\n * fill gaps the fixture left unset — discovery-derived identifiers,\n * envelope fields the author couldn't know at YAML-authoring time.\n * - Top-level merge: fixture wins on key conflicts. Fixture-aware\n * enrichers (see `FIXTURE_AWARE_ENRICHERS`) skip the generic merge and\n * return the final payload themselves.\n *\n * Returns `{}` when the task has no enricher and no `sample_request` — the\n * runner's load-time validator prevents this for mutating tasks, so the\n * empty return is reachable only for read tasks that have no fixture and\n * no registered enricher (rare).\n */\nexport function enrichRequest(\n step: StoryboardStep,\n context: StoryboardContext,\n options: TestOptions,\n runnerVars?: RunnerVariables\n): Record<string, unknown> {\n const enricher = REQUEST_ENRICHERS[step.task];\n const fixture =\n step.sample_request !== undefined\n ? (injectContext({ ...(step.sample_request as Record<string, unknown>) }, context, runnerVars) as Record<\n string,\n unknown\n >)\n : undefined;\n\n if (!enricher) return fixture ?? {};\n\n const enriched = enricher(step, context, options, runnerVars);\n\n // Fixture-aware enrichers already did the body merge internally and know\n // the array/nested shapes better than a generic top-level overlay can.\n // Envelope fields still flow through from sample_request.\n if (FIXTURE_AWARE_ENRICHERS.has(step.task)) {\n if (!fixture) return enriched;\n const out: Record<string, unknown> = { ...enriched };\n for (const field of ENVELOPE_FIELDS) {\n if (fixture[field] !== undefined && out[field] === undefined) out[field] = fixture[field];\n }\n return out;\n }\n\n // Generic fixture-authoritative merge: fixture keys overlay enricher keys.\n return fixture ? { ...enriched, ...fixture } : enriched;\n}\n\n/** True iff a request enricher is registered for this task. */\nexport function hasRequestEnricher(taskName: string): boolean {\n return taskName in REQUEST_ENRICHERS;\n}\n\n// ────────────────────────────────────────────────────────────\n// Legacy aliases — pre-#820 terminology. Kept for one release so\n// external consumers (repo greps found none, but public exports may\n// have downstream users) migrate at their own pace.\n// ────────────────────────────────────────────────────────────\n\n/** @deprecated Renamed to `enrichRequest`. Same behavior. */\nexport const buildRequest = enrichRequest;\n\n/** @deprecated Renamed to `hasRequestEnricher`. Same behavior. */\nexport const hasRequestBuilder = hasRequestEnricher;\n\n// ────────────────────────────────────────────────────────────\n// Selection helpers: pick the best item from discovered data\n// ────────────────────────────────────────────────────────────\n\nfunction selectProduct(context: StoryboardContext): Record<string, unknown> | undefined {\n const products = context.products as Array<Record<string, unknown>> | undefined;\n if (!products?.length) return undefined;\n\n // Prefer products with guaranteed delivery and pricing options\n const withPricing = products.filter(p => {\n const opts = p.pricing_options as unknown[] | undefined;\n return opts && opts.length > 0;\n });\n\n return withPricing[0] ?? products[0];\n}\n\nfunction selectPricingOption(product: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!product) return undefined;\n const options = product.pricing_options as Array<Record<string, unknown>> | undefined;\n if (!options?.length) return undefined;\n\n // Prefer fixed pricing (cpm, flat) over auction\n const fixed = options.filter(o => o.pricing_model === 'cpm' || o.pricing_model === 'flat');\n return fixed[0] ?? options[0];\n}\n\nfunction selectFormat(context: StoryboardContext): Record<string, unknown> | undefined {\n const formats = context.formats as Array<Record<string, unknown>> | undefined;\n if (!formats?.length) return undefined;\n return formats[0];\n}\n\nfunction selectSignal(context: StoryboardContext): Record<string, unknown> | undefined {\n const signals = context.signals as Array<Record<string, unknown>> | undefined;\n if (!signals?.length) return undefined;\n return signals[0];\n}\n\n/**\n * Build placeholder assets appropriate for a format's type.\n * Uses the format name to guess whether it's video, native, or display.\n */\nfunction buildAssetsForFormat(format: Record<string, unknown>): Record<string, unknown> {\n const name = String(format.name ?? format.format_id ?? '').toLowerCase();\n const type = String(format.type ?? '').toLowerCase();\n\n if (type === 'video' || name.includes('video') || name.includes('vast')) {\n return {\n video: {\n asset_type: 'video',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/trail-pro-30s.mp4',\n width: 1920,\n height: 1080,\n duration_ms: 30000,\n container_format: 'video/mp4',\n },\n };\n }\n\n if (type === 'native' || name.includes('native')) {\n return {\n image: {\n asset_type: 'image',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n width: 1200,\n height: 628,\n format: 'image/jpeg',\n },\n headline: {\n asset_type: 'text',\n content: 'Trail Pro 3000 — Built for the Summit',\n },\n };\n }\n\n // Default: display image\n return {\n primary: {\n asset_type: 'image',\n url: 'https://test-assets.adcontextprotocol.org/acme-outdoor/hero-master.jpg',\n width: 1200,\n height: 628,\n format: 'image/jpeg',\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,6 +8,8 @@ const FIXTURE_AWARE_ENRICHERS = /* @__PURE__ */ new Set([
|
|
|
8
8
|
// merges discovery-derived product_id / pricing_option_id INTO fixture packages[0]
|
|
9
9
|
"comply_test_controller",
|
|
10
10
|
// forces account.sandbox: true regardless of fixture
|
|
11
|
+
"check_governance",
|
|
12
|
+
// preserves the authored intent-vs-delivery request shape
|
|
11
13
|
"get_products",
|
|
12
14
|
// preserves wholesale fixture fields while keeping resolved account scope authoritative
|
|
13
15
|
"update_media_buy",
|
|
@@ -465,8 +467,18 @@ const REQUEST_ENRICHERS = {
|
|
|
465
467
|
]
|
|
466
468
|
};
|
|
467
469
|
},
|
|
468
|
-
check_governance(step, context, options) {
|
|
469
|
-
|
|
470
|
+
check_governance(step, context, options, runnerVars) {
|
|
471
|
+
const fixture = step.sample_request !== void 0 ? omitEnvelopeFields(
|
|
472
|
+
injectContext({ ...step.sample_request }, context, runnerVars)
|
|
473
|
+
) : void 0;
|
|
474
|
+
const isDelivery = fixture?.phase === "delivery" || fixture?.planned_delivery !== void 0 || fixture?.delivery_metrics !== void 0 || fixture?.governance_context !== void 0;
|
|
475
|
+
if (fixture && isDelivery) {
|
|
476
|
+
return {
|
|
477
|
+
...fixture,
|
|
478
|
+
caller: fixture.caller ?? FALLBACK_CALLER_AGENT_URL
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
const fallback = {
|
|
470
482
|
plan_id: context.plan_id ?? "unknown",
|
|
471
483
|
caller: FALLBACK_CALLER_AGENT_URL,
|
|
472
484
|
tool: "get_products",
|
|
@@ -478,6 +490,7 @@ const REQUEST_ENRICHERS = {
|
|
|
478
490
|
total_budget: options.budget ?? 1e4
|
|
479
491
|
}
|
|
480
492
|
};
|
|
493
|
+
return fixture ? { ...fallback, ...fixture } : fallback;
|
|
481
494
|
},
|
|
482
495
|
get_account_financials(_step, context, options) {
|
|
483
496
|
return {
|