diff --git a/.changeset/seed-multi-package-storyboards.md b/.changeset/seed-multi-package-storyboards.md new file mode 100644 index 0000000000..12f26fb9ae --- /dev/null +++ b/.changeset/seed-multi-package-storyboards.md @@ -0,0 +1,36 @@ +--- +--- + +Storyboards: add `controller_seeding: true` + `fixtures:` blocks on six +storyboards whose `create_media_buy` steps author multi-package payloads +referencing products that don't exist in any reasonable seller catalog +by default. After `@adcp/client` 5.12 (adcp-client#794), the storyboard +runner emits every authored package instead of silently dropping +`packages[1+]`. Sellers without these products then hit +`PRODUCT_NOT_FOUND: Package 1: Product not found: ` and cascading +step failures in their conformance runs. + +Wires the SDK's fixture-seeding feature (adcp-client#790) on the six +storyboards so `packages[1+].product_id` / `pricing_option_id` resolve +against seeded fixtures regardless of the seller's default catalog: + +- `protocols/media-buy/index.yaml` — seeds `sports_preroll_q2`, + `lifestyle_display_q2` + pricing. +- `protocols/media-buy/scenarios/delivery_reporting.yaml` — seeds + `outdoor_display_q2`, `outdoor_video_q2` + pricing. +- `protocols/media-buy/scenarios/governance_approved.yaml` — same pair. +- `specialisms/creative-generative/generative-seller.yaml` — same pair. +- `specialisms/sales-broadcast-tv/index.yaml` — seeds `primetime_30s_mf`, + `late_fringe_15s_mf` with broadcast-spot formats + unit pricing. +- `specialisms/sales-guaranteed/index.yaml` — seeds + `sports_preroll_q2_guaranteed`, `outdoor_ctv_q2_guaranteed` with + guaranteed-fixed CPM pricing. + +All pricing uses `fixed_price` (rather than `floor_price`) so the +non-auction bid-price requirement doesn't trip storyboards that omit +`bid_price`. + +Validated by overlaying the edited YAMLs into `@adcp/client`'s +compliance cache and re-running via `adcp storyboard run` — seed phase +fires end-to-end and `create_media_buy` no longer throws +`PRODUCT_NOT_FOUND`. diff --git a/.github/workflows/training-agent-storyboards.yml b/.github/workflows/training-agent-storyboards.yml index 04509657bc..a715ed7514 100644 --- a/.github/workflows/training-agent-storyboards.yml +++ b/.github/workflows/training-agent-storyboards.yml @@ -36,30 +36,23 @@ jobs: flag_value: '0' # Baseline on main — keep in sync with the last clean run reported # in the PR description. Rising is fine; regressing fails CI. - # 46→38 on the @adcp/client 5.12.0 bump: the storyboard runner - # now emits every authored package on create_media_buy - # (adcp-client#794), which exposes that several storyboards - # reference per-package products our catalog does not seed - # (outdoor_video_q2, late_fringe_15s_mf, outdoor_ctv_q2_guaranteed, - # lifestyle_display_q2). Tracked as a separate fixture-seeding - # task — wiring `controller_seeding: true` + `fixtures:` blocks - # on the affected storyboards (adcp-client#790 SDK side already - # shipped). Cascades downstream get_delivery on the same buys. - # Passing-step count is 321 (↑2 vs. main's 319) because the - # log_event builder now emits spec-shaped payloads so - # sales_social / sales_catalog_driven log_event no longer -32602s. - min_clean_storyboards: 38 + # 38→42 after wiring `controller_seeding: true` + `fixtures:` + # blocks on the six multi-package storyboards exposed by + # adcp-client#794 (media_buy_seller, delivery_reporting, + # governance_approved, creative_generative, sales_broadcast_tv, + # sales_guaranteed). The in-repo compliance source overlay step + # ensures CI sees these fixture adds before an SDK republish. + min_clean_storyboards: 42 min_passing_steps: 319 - mode: framework flag_value: '1' - # 42→32 on the @adcp/client 5.12.0 bump: same root cause as - # legacy (multi-package authoring exposes missing seeds). The - # framework-only delta vs. legacy is 5 storyboards / 7 step - # failures (acquire_rights_denied error code, calibrate_content - # verdict, log_event/provide_feedback session lookups, - # report_usage `accepted` field type) — tracked as the residual - # zod-parity follow-up. See PR description for the diff. - min_clean_storyboards: 32 + # 32→37 after the same fixture-seeding work. The framework-only + # delta vs. legacy is 5 storyboards / 7 step failures + # (acquire_rights_denied error code, calibrate_content verdict, + # log_event/provide_feedback session lookups, report_usage + # `accepted` field type) — tracked as the residual zod-parity + # follow-up. See PR description for the diff. + min_clean_storyboards: 37 min_passing_steps: 319 steps: - uses: actions/checkout@v6 @@ -75,6 +68,31 @@ jobs: env: PUPPETEER_SKIP_DOWNLOAD: 'true' + - name: Overlay in-repo compliance source onto SDK cache + # The storyboard runner loads from @adcp/client's bundled + # compliance cache, which is a snapshot synced from this repo's + # static/compliance/source/ on each SDK publish. To validate + # spec changes in this PR before waiting for an SDK republish, + # overlay the current source tree onto the cache. Overlays only + # files that exist in both trees; new top-level additions to + # source/ still require a sync-schemas cycle on the SDK side. + run: | + SRC="static/compliance/source" + DST="node_modules/@adcp/client/compliance/cache/latest" + if [ ! -d "$DST" ]; then + echo "::warning::SDK compliance cache not found at $DST — skipping overlay" + exit 0 + fi + # Copy every file that already exists in the cache. `cp -u` is + # not used because we want the overlay to always win for the + # files we maintain here. + (cd "$SRC" && find . -type f) | while read -r rel; do + if [ -f "$DST/${rel#./}" ]; then + cp "$SRC/${rel#./}" "$DST/${rel#./}" + fi + done + echo "Overlay complete." + - name: Run storyboards (${{ matrix.mode }}) id: run env: diff --git a/static/compliance/source/protocols/media-buy/index.yaml b/static/compliance/source/protocols/media-buy/index.yaml index 1348818606..a12cdd7146 100644 --- a/static/compliance/source/protocols/media-buy/index.yaml +++ b/static/compliance/source/protocols/media-buy/index.yaml @@ -53,6 +53,31 @@ prerequisites: The test kit provides a sample brand (Acme Outdoor) with campaign parameters suitable for testing the full media buy flow. test_kit: "test-kits/acme-outdoor.yaml" + controller_seeding: true + +fixtures: + products: + - product_id: "sports_preroll_q2" + delivery_type: "guaranteed" + channels: ["video"] + format_ids: + - id: "video_30s" + - product_id: "lifestyle_display_q2" + delivery_type: "guaranteed" + channels: ["display"] + format_ids: + - id: "display_300x250" + pricing_options: + - product_id: "sports_preroll_q2" + pricing_option_id: "cpm_guaranteed" + pricing_model: "cpm" + currency: "USD" + fixed_price: 22.0 + - product_id: "lifestyle_display_q2" + pricing_option_id: "cpm_standard" + pricing_model: "cpm" + currency: "USD" + fixed_price: 8.0 phases: - id: capability_discovery diff --git a/static/compliance/source/protocols/media-buy/scenarios/delivery_reporting.yaml b/static/compliance/source/protocols/media-buy/scenarios/delivery_reporting.yaml index c54f3ae8bb..75596a2306 100644 --- a/static/compliance/source/protocols/media-buy/scenarios/delivery_reporting.yaml +++ b/static/compliance/source/protocols/media-buy/scenarios/delivery_reporting.yaml @@ -37,6 +37,31 @@ prerequisites: scenario. This allows the test harness to inject delivery metrics into a media buy so get_media_buy_delivery has data to return. test_kit: "test-kits/acme-outdoor.yaml" + controller_seeding: true + +fixtures: + products: + - product_id: "outdoor_display_q2" + delivery_type: "guaranteed" + channels: ["display"] + format_ids: + - id: "display_300x250" + - product_id: "outdoor_video_q2" + delivery_type: "guaranteed" + channels: ["video"] + format_ids: + - id: "video_15s" + pricing_options: + - product_id: "outdoor_display_q2" + pricing_option_id: "cpm_standard" + pricing_model: "cpm" + currency: "USD" + fixed_price: 8.0 + - product_id: "outdoor_video_q2" + pricing_option_id: "cpm_standard" + pricing_model: "cpm" + currency: "USD" + fixed_price: 12.0 phases: - id: setup diff --git a/static/compliance/source/protocols/media-buy/scenarios/governance_approved.yaml b/static/compliance/source/protocols/media-buy/scenarios/governance_approved.yaml index 5b7ae3c119..1d7a43b041 100644 --- a/static/compliance/source/protocols/media-buy/scenarios/governance_approved.yaml +++ b/static/compliance/source/protocols/media-buy/scenarios/governance_approved.yaml @@ -36,6 +36,31 @@ prerequisites: description: | A governance agent that supports sync_plans and check_governance. test_kit: "test-kits/acme-outdoor.yaml" + controller_seeding: true + +fixtures: + products: + - product_id: "outdoor_display_q2" + delivery_type: "guaranteed" + channels: ["display"] + format_ids: + - id: "display_300x250" + - product_id: "outdoor_video_q2" + delivery_type: "guaranteed" + channels: ["video"] + format_ids: + - id: "video_15s" + pricing_options: + - product_id: "outdoor_display_q2" + pricing_option_id: "cpm_standard" + pricing_model: "cpm" + currency: "USD" + fixed_price: 8.0 + - product_id: "outdoor_video_q2" + pricing_option_id: "cpm_standard" + pricing_model: "cpm" + currency: "USD" + fixed_price: 12.0 phases: - id: governance_plan_setup diff --git a/static/compliance/source/specialisms/creative-generative/generative-seller.yaml b/static/compliance/source/specialisms/creative-generative/generative-seller.yaml index d5a178d10f..d0a4cf69db 100644 --- a/static/compliance/source/specialisms/creative-generative/generative-seller.yaml +++ b/static/compliance/source/specialisms/creative-generative/generative-seller.yaml @@ -65,6 +65,31 @@ prerequisites: tone — that the generative seller uses to produce on-brand creatives. The test kit provides a sample brand with campaign parameters. test_kit: "test-kits/acme-outdoor.yaml" + controller_seeding: true + +fixtures: + products: + - product_id: "outdoor_display_q2" + delivery_type: "guaranteed" + channels: ["display"] + format_ids: + - id: "display_300x250" + - product_id: "outdoor_video_q2" + delivery_type: "guaranteed" + channels: ["video"] + format_ids: + - id: "video_15s" + pricing_options: + - product_id: "outdoor_display_q2" + pricing_option_id: "cpm_guaranteed" + pricing_model: "cpm" + currency: "USD" + fixed_price: 12.0 + - product_id: "outdoor_video_q2" + pricing_option_id: "cpm_standard" + pricing_model: "cpm" + currency: "USD" + fixed_price: 12.0 phases: - id: capability_discovery diff --git a/static/compliance/source/specialisms/sales-broadcast-tv/index.yaml b/static/compliance/source/specialisms/sales-broadcast-tv/index.yaml index 9cdf8073b7..deb907b99d 100644 --- a/static/compliance/source/specialisms/sales-broadcast-tv/index.yaml +++ b/static/compliance/source/specialisms/sales-broadcast-tv/index.yaml @@ -64,6 +64,31 @@ prerequisites: kit provides the Nova Motors Volta EV launch campaign — an automotive brand with national broadcast reach goals and budget appropriate for primetime linear TV. test_kit: "test-kits/nova-motors.yaml" + controller_seeding: true + +fixtures: + products: + - product_id: "primetime_30s_mf" + delivery_type: "guaranteed" + channels: ["video"] + format_ids: + - id: "broadcast_spot_30s" + - product_id: "late_fringe_15s_mf" + delivery_type: "guaranteed" + channels: ["video"] + format_ids: + - id: "broadcast_spot_15s" + pricing_options: + - product_id: "primetime_30s_mf" + pricing_option_id: "unit_primetime_30" + pricing_model: "flat_rate" + currency: "USD" + fixed_price: 4500.0 + - product_id: "late_fringe_15s_mf" + pricing_option_id: "unit_fringe_15" + pricing_model: "flat_rate" + currency: "USD" + fixed_price: 1200.0 phases: - id: capability_discovery diff --git a/static/compliance/source/specialisms/sales-guaranteed/index.yaml b/static/compliance/source/specialisms/sales-guaranteed/index.yaml index 7d1d397db2..81bad5d0ed 100644 --- a/static/compliance/source/specialisms/sales-guaranteed/index.yaml +++ b/static/compliance/source/specialisms/sales-guaranteed/index.yaml @@ -61,6 +61,31 @@ prerequisites: The test kit provides a sample brand (Acme Outdoor) with campaign parameters suitable for testing the guaranteed approval flow. test_kit: "test-kits/acme-outdoor.yaml" + controller_seeding: true + +fixtures: + products: + - product_id: "sports_preroll_q2_guaranteed" + delivery_type: "guaranteed" + channels: ["video"] + format_ids: + - id: "video_30s" + - product_id: "outdoor_ctv_q2_guaranteed" + delivery_type: "guaranteed" + channels: ["ctv"] + format_ids: + - id: "video_30s" + pricing_options: + - product_id: "sports_preroll_q2_guaranteed" + pricing_option_id: "cpm_guaranteed_fixed" + pricing_model: "cpm" + currency: "USD" + fixed_price: 35.0 + - product_id: "outdoor_ctv_q2_guaranteed" + pricing_option_id: "cpm_guaranteed_fixed" + pricing_model: "cpm" + currency: "USD" + fixed_price: 45.0 phases: - id: capability_discovery