Conversation
… (breadth sprint Batch 2)
Second batch of the breadth-sprint per the parity audit. Ports two
creative-archetype Protocols from JS reference at
``src/lib/server/decisioning/specialisms/{creative,creative-ad-server}.ts``
(commits ``841616d7`` F13 / ``bca20dfb`` F16-F17).
New Protocols:
* ``CreativeBuilderPlatform``
(src/adcp/decisioning/specialisms/creative.py) — covers
``creative-template`` (stateless transform — Bannerflow, Celtra)
AND ``creative-generative`` (brief-to-creative AI — Pencil,
Omneky, AdCreative.ai). Per JS commit ``841616d7`` (F13), the v6
preview's separation of CreativeTemplatePlatform and
CreativeGenerativePlatform had no meaningful interface distinction,
so they're unified here.
Required: ``build_creative``. Optional (present-or-absent, framework
surfaces ``UNSUPPORTED_FEATURE`` to buyers when missing):
``preview_creative``, ``refine_creative``, ``sync_creatives``.
``build_creative`` returns a discriminated arm per
``BuildCreativeReturn``:
``CreativeManifest | Sequence[CreativeManifest] | BuildCreativeSuccessResponse``.
Adopters route on ``req.target_format_ids`` (multi) vs
``req.target_format_id`` (single). Returning the wrong arm shape
surfaces as schema-validation failure on the wire response.
``RefinementMessage`` is exported as a TypedDict so adopters
annotate ``refine_creative(refinement: RefinementMessage)``.
* ``CreativeAdServerPlatform``
(src/adcp/decisioning/specialisms/creative_ad_server.py) — covers
``creative-ad-server``. Stateful library + per-creative pricing +
tag generation (Innovid, Flashtalking, GAM-creative, CMP-style).
Required: ``build_creative``, ``preview_creative``,
``list_creatives``, ``get_creative_delivery``. Optional:
``sync_creatives`` (hybrid sync/handoff for brand-suitability /
S&P review).
Distinct from CreativeBuilderPlatform — adopters that ALSO want
library + tag generation + delivery reporting (a full ad server on
top of the builder) declare ``creative-ad-server`` instead.
Multi-archetype omni agents are rare; the recommended pattern is
to front each archetype as a separate tenant via TenantRegistry.
Required-method coverage in ``REQUIRED_METHODS_PER_SPECIALISM``:
* ``creative-template``, ``creative-generative`` — both gate on
``{build_creative}`` (shared CreativeBuilderPlatform).
* ``creative-ad-server`` — gates on
``{build_creative, preview_creative, list_creatives,
get_creative_delivery}``.
Public re-exports added at ``adcp.decisioning.__all__``:
``CreativeBuilderPlatform``, ``CreativeAdServerPlatform``,
``RefinementMessage``.
Test coverage in ``tests/test_decisioning_specialisms.py`` (11 new
tests, 24 total in the file):
* ``runtime_checkable`` minimal-vs-full conformance per Protocol.
* ``validate_platform`` required-method enforcement per slug.
* Public-export drift guard for the new Protocols.
* Contract pin for ``creative-template`` / ``creative-generative``
shared method set (drift tracker).
* Architectural distinction test: ad-server's required set is a
strict superset of builder's.
* ``RefinementMessage`` TypedDict smoke test.
One existing test updated: the canonical "spec-recognized but
unenforced" example switched from ``creative-ad-server`` (now
enforced) to ``brand-rights`` (still pending until Batch 3+ ships
the brand/governance/lists Protocols).
Remaining specialism Protocols (governance-aware-seller,
governance-spend-authority, governance-delivery-monitor, brand-rights,
content-standards, property-lists, collection-lists) are queued for
subsequent breadth-sprint PRs.
2232 tests pass (up from 2221).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…efine_creative + tighten typing Three review findings on Batch 2 Creative Protocols: P0 (wire-spec) — ``refine_creative`` was a hallucinated wire surface. There is no ``refine-creative-*.json`` schema in ``schemas/cache/`` and no ``refine_creative`` wire tool. Per ``schemas/cache/media-buy/build-creative-request.json``, refinement is invoked via ``build_creative`` itself with ``creative_id`` referencing the prior build (the request schema's "For refinement…" description). Both the JS reference (``creative.ts``) and the initial Python port preserved a ``refine_creative`` Protocol method mirroring an earlier preview design. Dropped here: * Removed ``refine_creative`` method from ``CreativeBuilderPlatform`` * Removed ``RefinementMessage`` TypedDict (was its parameter type) * Removed both from ``adcp.decisioning`` re-exports + ``__all__`` * Removed corresponding tests * Added regression test (``test_creative_builder_protocol_has_no_refine_creative``) so a future port doesn't re-add it without checking the spec To file against the JS reference as a follow-up. P1 (typing) — ``sync_creatives`` declared ``req: Any`` on both creative Protocols. The shared ``SyncCreativesRequest`` exists in ``adcp.types`` (the sales-* archetypes use it). Typing as ``Any`` defeated the typed-input contract the rest of the SDK exposes. Tightened to ``req: SyncCreativesRequest``; the per-archetype narrowing comment kept (the shim narrows discriminated payload fields, not the envelope). P1 (regression test for adcp#3392) — added ``test_build_creative_response_has_no_submitted_arm`` that walks the ``BuildCreativeResponse`` Pydantic union and asserts no arm carries ``task_id``. When the spec inconsistency at adcp#3392 lands and the ``oneOf`` adds a Submitted variant, this test breaks and forces a coordinated SDK update to the Protocol return type. P2 (test rename) — ``test_creative_builder_runtime_checkable_minimal`` renamed to ``test_creative_builder_runtime_checkable_is_strict_structural_match``. The "minimal" framing implied the test was checking adopter-shape adequacy; it's actually checking that ``runtime_checkable`` strict structural-AND semantics are documented. Same assertion, honest name. Punt list (filed as follow-up): * ``BuildCreativeResponse2`` is mislabeled in ``src/adcp/types/aliases.py`` — currently aliased as ``BuildCreativeErrorResponse`` but the class actually carries ``creative_manifests`` (multi-success arm). The real error arm is ``BuildCreativeResponse3``. Real type-system bug affecting ``guards.py``, ``test_type_aliases.py``, ``public_api_snapshot.json``. Out of scope here; needs its own PR with public-API surface changes. * Python's ``REQUIRED_METHODS_PER_SPECIALISM`` is stricter than JS's ``SPECIALISM_REQUIREMENTS``. Deliberate Python-side hardening across all specialism Protocols (foundation + Batches 1-2); not unique to Creative. * Multi-archetype omni guidance (single tenant claiming both ``creative-template`` and ``creative-ad-server``) is unenforceable in code today. 2233 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley
added a commit
that referenced
this pull request
May 1, 2026
…ionLists Protocols (breadth sprint Batch 4 — FINAL) (#335) Final batch of the breadth-sprint per the parity audit. Ports the remaining four specialism Protocols from JS reference. With this PR, every spec specialism slug except ``governance-aware-seller`` has a Protocol class + REQUIRED_METHODS coverage. New Protocols: * ``BrandRightsPlatform`` — covers ``brand-rights``. Identity discovery + licensing. Required (3, sync): ``get_brand_identity``, ``get_rights``, ``acquire_rights``. ``acquire_rights`` returns a 3-arm discriminated success union (acquired / pending / rejected) — rejection-as-data for spec-defined GRANT rejection, AdcpError only for buyer-fixable REQUEST rejection. Async outcomes for the ``pending`` arm flow via ``push_notification_config`` webhook (NOT a polling tool). * ``ContentStandardsPlatform`` — covers ``content-standards``. Brand safety policies, content adjacency rules, per-creative compliance verification. Required (6): list/get/create/update, ``calibrate_content``, ``validate_content_delivery``. Optional (2, analyzer reads): ``get_media_buy_artifacts``, ``get_creative_features``. * ``PropertyListsPlatform`` + ``CollectionListsPlatform`` (specialisms/lists.py) — covers ``property-lists`` and ``collection-lists``. Parallel CRUD shapes (5 methods each, all required) with token-issuance semantics: ``create_*`` returns a per-seller-scoped ``fetch_token``, ``delete_*`` revokes it. Compromise-driven revocation MUST trigger the delete path. Required-method coverage in ``REQUIRED_METHODS_PER_SPECIALISM``: ``brand-rights`` (3), ``content-standards`` (6), ``property-lists`` (5), ``collection-lists`` (5). Public re-exports added at ``adcp.decisioning.__all__``: ``BrandRightsPlatform``, ``ContentStandardsPlatform``, ``PropertyListsPlatform``, ``CollectionListsPlatform``. Test coverage in ``tests/test_decisioning_specialisms.py`` (13 new tests, 43 total in the file): * ``runtime_checkable`` conformance per Protocol. * ``validate_platform`` enforcement per slug — including a security-relevant test that ``property-lists`` REQUIRES ``delete_property_list`` (revocation path) so adopters can't ship list-publishing without revocation primitives. * Contract pins per slug. * **Breadth-sprint completeness pin**: ``test_every_spec_slug_except_governance_aware_seller_is_enforced`` asserts that ``SPEC_SPECIALISM_ENUM - REQUIRED_METHODS.keys()`` yields exactly ``{governance-aware-seller, signed-requests}`` — the two slugs unenforced by design (composition claim and deprecated-moved-to-universal respectively). One existing dispatch test updated: ``test_validate_platform_warns_on_unenforced_spec_specialism`` swapped its canonical "spec-recognized but unenforced" example from ``brand-rights`` (now enforced) to ``governance-aware-seller`` (the only remaining unenforced spec slug — by design). **Breadth sprint COMPLETE.** All 8 missing specialism Protocols from the parity audit are now ported. 9 PRs total accumulating in the held release PR #328: * #316 foundation * #329 codemod ergonomics * #330 parity rename + Tier 1 docs * #331 F12 auto-emit * #332 Signals + Audience (Batch 1) * #333 Creative Builder + AdServer (Batch 2) * #334 Campaign Governance (Batch 3) * #335 Brand + Content + Lists (Batch 4 — this PR) Ready for salesagent validation against editable install before tagging 4.4.0. 2252 tests pass (up from 2239). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Breadth sprint Batch 2 — ports two creative-archetype Protocols from JS reference (commits `841616d7` F13 + `bca20dfb` F16-F17).
New:
Tests (11 new, 24 total in file):
One existing test updated: canonical "spec-recognized but unenforced" example switched from `creative-ad-server` (now enforced) to `brand-rights` (still pending until subsequent batches).
Wire-spec note: `build_creative` is sync at the wire level — the per-tool `build-creative-response.json` `oneOf` doesn't include a Submitted arm (spec inconsistency tracked as `adcontextprotocol/adcp#3392`). Until that lands, slow generation pipelines await in-request; status changes flow via `publish_status_change`. Same posture as JS reference.
Test plan
Remaining breadth-sprint queue
Release plan
Accumulates into the held release-please PR #328 alongside foundation (#316), codemod ergonomics (#329), parity rename (#330), F12 (#331), and Signals/Audience (#332). Six PRs ship together in 4.4.0 once salesagent validates.
🤖 Generated with Claude Code