Repository navigation
Conversation
media_buy.audience_targeting now promises audience_include and audience_exclude plus discovery-only sync_audiences, which a declaring seller MUST answer, but no longer promises inline member push. The sync_audiences pattern in the experimental supported_activation_methods declares push; when the field is absent, push is supported as in 3.2. supported_identifier_types and minimum_audience_size move from required to an if/then that requires them only when the seller accepts inline push, so every 3.2-valid capabilities document stays valid. A seller without push rejects add/remove member deltas, and new audiences without a source reference, with UNSUPPORTED_FEATURE. Closes #8936 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated schema paths require human/CODEOWNERS approval.
This PR loosens the media_buy.audience_targeting capability contract (#8936): get-adcp-capabilities-response.json replaces an unconditional required: [supported_identifier_types, minimum_audience_size] with an if/then conditional. The reviewer verified the schema change across all four cases, confirmed docs↔schema coherence across 7 doc files, found the minor changeset correct for a loosening (precedent #8024/#8057), and surfaced no blocking or Medium findings. The change itself looks clean.
However, this PR modifies gated files under static/schemas/source/**:
- static/schemas/source/media-buy/sync-audiences-request.json
- static/schemas/source/protocol/get-adcp-capabilities-response.json
gated_paths is true and review_decision is REVIEW_REQUIRED (not APPROVED), so the hard approval gate (decision rule row 2) is not satisfied. Per policy this cannot auto-approve — a human/CODEOWNERS review is required to clear the gate. Once review_decision is APPROVED, a clean diff like this may fall through to approve.
Escalation reasons
- Modifies gated path
static/schemas/source/protocol/get-adcp-capabilities-response.json— human/CODEOWNERS approval required (review_decision: REVIEW_REQUIRED). - Modifies gated path
static/schemas/source/media-buy/sync-audiences-request.json— human/CODEOWNERS approval required.
Why human review
- Modifies gated path static/schemas/source/protocol/get-adcp-capabilities-response.json — human/CODEOWNERS approval required (review_decision: REVIEW_REQUIRED, not APPROVED)
- Modifies gated path static/schemas/source/media-buy/sync-audiences-request.json — human/CODEOWNERS approval required
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/media-buy/sync-audiences-request.json (modified) matches
static/schemas/source/**; static/schemas/source/protocol/get-adcp-capabilities-response.json (modified) matchesstatic/schemas/source/**) and the current GitHub review decision is 'REVIEW_REQUIRED', not APPROVED. This is a hard gate enforced in code — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.
Closes #8960
What changes
image_carouselgains an optionalcta_valuesparameter that governs each card'scta. It has the same type ascta_valuesonnative_in_feedandimage, and carries"x-added-in": "3.3.0".ctaMUST be one of the listed values. A seller refuses any other value withCREATIVE_VALUE_NOT_ALLOWED, witherror.fieldpointing at that card'scta.ctatakes free text and is not refused asCREATIVE_VALUE_NOT_ALLOWED.This is additive on an open
paramsobject, so it is a minor, likecard_image_sizesin #8937. Before this change, a carousel option could carrycta_valuesonly as an undeclared extra parameter.Files
static/schemas/source/formats/canonical/image_carousel.json: the newcta_valuesproperty, using the definition proposed in the issue.static/schemas/source/core/assets/card-asset.json: thectadescription now namesimage_carousel'scta_valuesas the governing set. It also states the refusal code, theerror.fieldtarget and the free-text default.docs/creative/channels/carousels.mdx: the declaration example showscta_values, the manifest example shows per-cardcta, and a new "Card call to action" section says howcta_valuesgoverns each card'scta.docs/reference/whats-new-in-3-3.mdxand.changeset/image-carousel-cta-values.md: the release-doc entry and the changeset (minor).tests/x-added-in-3-3-sweep.test.cjs: registers the new property.Compliance step: added
New optional scenario
media_buy_seller/declared_carousel_cta_values(introduced_in: "3.3", gated oncreative.has_creative_library). It mirrorsdeclared_format_option_acceptance: the runner seeds a product whoseimage_carouseloption declarescta_values: [SHOP_NOW, LEARN_MORE], and the buyer syncs a three-card creative withformat_option_ref.reject_card_cta_not_in_enum: cards one and two carrySHOP_NOW, and card three carriesEXPLORE_MORE. The step expectsCREATIVE_VALUE_NOT_ALLOWED, witherrors[0].fieldmatchingcards\[2\]\.cta$.accept_card_cta_in_enum: the same creative, with card three'sctaset toLEARN_MORE, is accepted.The scenario is not added to
media_buy_seller'srequires_scenarios. If it were required, every seller with a creative library would need to acceptimage_carouselbefore the RC. It runs wherever the seller's declared scope selects it, the same waycreative/native_in_feedruns. Say so if you'd rather make it required.Training agent
The training agent had no per-card checks for carousels.
server/src/training-agent/task-handlers.tsnow generalises the native_in_feed declaration resolution:formatOptionDeclarationGroups(formatKind, …)resolves the declaration in this order:format_option_ref, then assigned packages, then the agent's own capability.declaredFormatOptionErrorbuilds the error.native_in_feedkeeps its behaviour, andimageCarouselValidationErrorreuses both helpers. A cardctaoutside a declaredcta_valuesreturnsCREATIVE_VALUE_NOT_ALLOWEDatcreatives[i].assets.cards[n].cta, withdetails.allowed_values. The agent declares no carousel capability params, so a carousel that no option governs stays unconstrained.server/tests/unit/training-agent-image-carousel-cta-values.test.tscovers five cases:cta;cta_values;Overlap with #8949
#8949 (open) also edits the
card-asset.jsonctadescription, and it renamesdetails.allowed_valuestoaccepted_valueson the line that now lives in the shareddeclaredFormatOptionError. Whichever PR merges second needs a small rebase. The wording here already covers what #8949 adds tocard-assetcta.Verification
VERIFICATION_PLACEHOLDER
🤖 Generated with Claude Code