Skip to content

feat(compat): v2.5 create_media_buy + update_media_buy adapters (stage 5c)#669

Merged
bokelley merged 5 commits into
mainfrom
claude/versioned-schemas-stage-5c
May 11, 2026
Merged

feat(compat): v2.5 create_media_buy + update_media_buy adapters (stage 5c)#669
bokelley merged 5 commits into
mainfrom
claude/versioned-schemas-stage-5c

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Stage 5c. Closes out the v2.5 → v3 adapter catalog. Stacked on #668 (Stage 5b get_products).

Summary

Two more adapters + shared helpers module. Both tools translate package shape (creative_idscreative_assignments); create_media_buy additionally translates brand_manifestbrand.

Lossy paths (silent — per user direction)

  • Response weight and placement_ids dropped when v3 creative_assignments collapse to v2.5 creative_ids. v2.5 buyers have no field to surface them on; raising on every response that uses weights would reject the typical case unfairly.
  • Null-array coercion — some servers emit explicit null for optional arrays; convert to absent fields.

Full v2.5 catalog now adapted

Remaining versioned-validation work

  • Stage 4b: bundle real v2.5 schemas (pinned GitHub SHA fetch) — required for pre-adapter request validation; today the dispatcher only validates the adapter output against v3.

Test plan

  • pytest — 4515 passed
  • 23 new tests for create_media_buy/update_media_buy
  • Updated test_v2_5_tool_without_adapter_raises_invalid_request to use check_governance (a v3-added tool with no v2.5 adapter)
  • ruff check + mypy

🤖 Generated with Claude Code

bokelley and others added 5 commits May 11, 2026 07:10
Port of pricing-adapter.ts (inverted from JS direction) plus
brand/catalog/channel translation. JS is v3→v2 (client side); our
server-side use case is v2→v3, so request and response swap roles.

* brand_manifest (v2.5 URL) ↔ brand.domain (v3 BrandReference)
* promoted_offerings (v2.5 nested) ↔ catalog (v3 discriminated union)
* Channels — lossy both directions:
  - video → olv+ctv, audio → streaming_audio, native → display, retail → retail_media
  - response collapses back, deduped
* Pricing options:
  - rate + is_fixed ↔ fixed_price
  - price_guidance.floor ↔ top-level floor_price
  - Percentile fields stay in price_guidance

20 new tests cover both directions, idempotency on v3-already-shape,
and unknown-channel pass-through.

Updated test_v2_5_tool_without_adapter_raises_invalid_request to use
create_media_buy (still unported in Stage 5c).

Stage 5c will port create_media_buy + update_media_buy (creative-adapter.ts).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review feedback on PR #668 flagged that the v2/v3 precedence in
``_normalize_pricing_option`` is correct but undocumented. Add a test
that pins ``rate`` (v2) over ``fixed_price`` (v3) when both are
present — matches the JS reference implementation's behaviour and
documents intent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e 5c)

Closes out the v2.5 → v3 adapter catalog. Shared helpers in
``_media_buy_helpers`` (creative_ids ↔ creative_assignments, brand
manifest, null-array coercion).

Translations:
* Package shape: v2.5 creative_ids ↔ v3 creative_assignments. The
  response-direction collapse drops v3-only weight + placement_ids
  silently — v2.5 buyers can't surface them, so the alternative
  (raise on every response with weights) rejects the typical case.
* create_media_buy: brand_manifest URL → brand.domain.
* Null-array coercion (creative_assignments / creative_ids / products
  set to null become absent fields).

update_media_buy does NOT translate brand_manifest — updates don't
carry brand in v3, and v2.5 buyers sending the field on an update are
passing through metadata the handler can ignore. Tested explicitly.

Updated test_v2_5_tool_without_adapter_raises_invalid_request to use
check_governance (v3-added tool with no v2.5 adapter) since
create_media_buy is now covered.

Full v2.5 catalog now adapted: sync_creatives,
list_creative_formats, preview_creative, get_products,
create_media_buy, update_media_buy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review feedback on PR #669. The helper was defined byte-for-byte
in both ``_media_buy_helpers.py`` and ``get_products.py``; future
edits would drift. Move to ``adcp.compat.legacy.v2_5._url`` so both
import the same canonical implementation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit 4e3473a into main May 11, 2026
16 checks passed
@bokelley bokelley deleted the claude/versioned-schemas-stage-5c branch May 11, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant