Skip to content

feat(media-buy): add targeting-aware product discovery - #6203

Open
bokelley wants to merge 6 commits into
mainfrom
verify-get-products-filters
Open

feat(media-buy): add targeting-aware product discovery#6203
bokelley wants to merge 6 commits into
mainfrom
verify-get-products-filters

Conversation

@bokelley

@bokelley bokelley commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

This proposes the AdCP 3.2 targeting-aware product-discovery contract:

  • filters are offer filters and work consistently in brief, wholesale, and refine modes
  • targeting_overlay carries exact targeting known during discovery, so availability, price, and forecast reflect it
  • required_overlay_support asks for targeting dimensions that must remain selectable on packages later
  • products return overlay_support and sparse targeting_resolution.modifications only when applied targeting differs
  • response-level targeting_resolution.brief_targeting can confirm hard targeting inferred from prose once per result set
  • request-specific configurations use opaque, expiring product IDs that remain stable within their discovery/refinement context
  • placement, property, and collection selection follow the same targeting lifecycle, incorporating update_media_buy: add first-class purchased-placement selection to PackageUpdate #6132
  • typed device_platform_exclude uses the canonical platform enum, exclusion-wins semantics, reject-rather-than-drop enforcement, and independently declared product support

The implementation includes schemas, normative design, migration guidance, task/reference docs, buyer education, the media-buy skill, Addie curriculum guidance, compliance storyboards, test vectors, and regression tests.

Important semantics

  • Structured fields are preferred over equivalent brief prose because they are deterministic, token-efficient, and lossless. Explicit hard prose remains binding.
  • An unchanged structured overlay is not echoed. A changed overlay is disclosed sparsely and selecting the configured product accepts the proposal.
  • Product-discovery, booked-package, and response-level brief resolutions use separate schemas so lifecycle-invalid combinations cannot be generated by SDKs.
  • Fixed placement sets may satisfy an exact named request inherently, but are not independently selectable. Placement updates and creative-routing replacements are validated atomically.
  • Inclusion and exclusion are separate product capabilities. Support for device_platform does not imply device_platform_exclude.
  • External buyers do not receive a generic ad-server control plane. Arbitrary buyer-supplied custom, key_value_pairs, and equivalent raw targeting maps are explicitly out of scope; sellers compile typed fields and signals into backend controls internally.
  • Expired configured products return PRODUCT_EXPIRED; unknown IDs return PRODUCT_NOT_FOUND.

Training rollout

Live training-agent behavior is intentionally deferred until the 3.2 beta schemas have generated SDK support. Tracking issue: #6199.

Until then, the curriculum separates the current live buying workflow from 3.2 schema-fixture validation so ignored preview fields cannot look like success.

Expert review

The final diff received explicit merge-ready approval from three independent review passes focused on:

  • ad-tech protocol interoperability
  • media-product and buying-workflow semantics
  • education, training, and agent behavior

Their findings drove the separate request/support shapes, configured-product expiry rules, fixed/selectable placement model, atomic creative-routing behavior, lifecycle-specific resolutions, deterministic refinement semantics, and training-runtime deferral.

Community feedback requested

  1. Is one response-level brief_targeting confirmation the right scope for a curated result set?
  2. Is product selection sufficient acceptance of sparse modifications, or should a later version carry an explicit digest acknowledgment?
  3. Does required_overlay_support correctly promise independent selection, and should future versions express cross-dimension combinations or numeric minima?
  4. Is the fixed-versus-selectable placement model operationally sufficient?
  5. Is is_custom the right marker for all request-bound configured offers?
  6. Is independent platform-exclusion support the right model for other future typed include/exclude dimensions?

Validation

  • npm test — passed, including 358 server test files and 5,153 tests (30 skipped)
  • focused targeting-aware and demographic suites — passed after rebase onto current main
  • all 670 schemas and $ref links — passed before rebase; post-rebase schema build, bundled schemas, MCP projection, and generated skill schemas passed on the 3.1.10 baseline
  • oneOf discriminator audit — passed
  • compliance build and storyboard path lints — passed
  • current compliance storyboard matrix — all six tenants passed before rebase
  • focused product_filter_behavior live run — 9/9 graded checks passed across brief, wholesale, and refine modes
  • current compliance storyboard matrix after this addition — all six tenants passed (/sales: 91 clean storyboards, 500 passing steps)
  • focused targeting-aware scenario confirms the 3.2 configured-product path remains gated on training runtime Implement targeting-aware discovery in the training agent after 3.2 beta #6199; no preview fields are treated as success
  • released 3.0 compatibility storyboard matrix — all six tenants passed
  • OpenAPI generation parity and TypeScript typecheck — passed
  • docs navigation and temporary snapshot redirects — passed

The pre-commit hook's duplicate server-unit invocation hit its 240-second wrapper timeout after the complete suite had already passed; the commit bypassed that redundant hook. No test failed.

Related work

Closes #6132. The design document records the intentional changes from the issue proposal: placement selection is unified under targeting_overlay, authorized by update_targeting, and governed by complete-overlay replacement semantics.

Behavioral filter conformance (#2902)

This PR now absorbs the deterministic get_products.filters portion of #2902. The normative contract requires every returned product to satisfy every supplied filter predicate in brief, wholesale, and refine modes. A new independent storyboard seeds one matching product plus separate channel-only and delivery-only negative controls, so full and partial filter no-ops fail by membership and field assertions rather than by assuming two responses must differ.

#2902 intentionally remains open for get_media_buy_delivery, get_media_buys, and list_creatives behavioral coverage. Natural-language brief relevance remains outside its mechanical filter track. The targeting-aware storyboard separately books and reads back concrete platform exclusion, placement, property, and collection targeting.

Grounded lifecycle readback (#4291 / #6173)

This PR also absorbs the configured-product lifecycle slice of #6173: after creating and updating a buy, the targeting readback now uses field_equals_context to prove both media_buy_id and package_id match the identities captured during creation. This prevents an unrelated but correctly shaped buy from satisfying the targeting assertions.

The remainder of #6173 stays independent: delivery identity, creative-delivery membership, and generic list_* round trips. The async lifecycle (#6174), rights lifecycle (#6175), and HTTP creative-approval harness (#6176) are unrelated to targeting-aware discovery and remain separate.

@bokelley bokelley changed the title Add targeting-aware product discovery feat(media-buy): add targeting-aware product discovery Aug 5, 2026
@bokelley
bokelley marked this pull request as ready for review August 5, 2026 05:49
@aao-secretariat aao-secretariat Bot added the ladon/needs-human-review Ladon has escalated this PR for human review. label Aug 5, 2026

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Escalate to human review

Escalate — gated-path change requires human/CODEOWNERS review.

This PR modifies/adds ~15 files under static/schemas/source/**, which are under a hard, deterministic approval gate (gated_paths: true). The current review_decision is REVIEW_REQUIRED, not APPROVED, so decision-table row 2 fires and the outcome cannot be approve or plain comment.

Independent of the gate, this is a Breaking-class-eligible protocol change (new AdCP 3.2 targeting-aware product-discovery contract) touching published wire surface. Under the repo's "Breaking-class changes are never auto-approved" hard gate, ratification is a human act.

The reviewer found no Critical/High/Medium findings: schema↔docs coherence verified (product.json overlay_support / targeting_resolution / is_custom / expires_at match get_products.mdx and targeting.mdx), the demographic_targeting_resolution→targeting_resolution.demographics rename is on an unreleased 3.2-beta field (absent from dist/**) so the minor changeset is correct, both new oneOf schemas carry discriminators (mode/operation), and released dist artifacts are untouched. Clean diff, but the deterministic gate stands until a human/CODEOWNERS approval lands.

Escalation reasons

  • Modifies/adds ~22 files under static/schemas/source/** (gated path) with review_decision: REVIEW_REQUIRED — human/CODEOWNERS approval required before merge.
  • New published protocol contract (AdCP 3.2 targeting-aware discovery) requires human ratification per the Breaking-class hard gate.

No blocking code findings; escalation is procedural (approval gate), not a defect.

Why human review

  • Modifies/adds ~22 files under static/schemas/source/** (gated path) while review_decision is REVIEW_REQUIRED — human/CODEOWNERS approval required (row 2).
  • New AdCP 3.2 published protocol contract requires human ratification per the repo's Breaking-class hard gate.
  • This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/creative-assignment.json (modified) matches static/schemas/source/**; static/schemas/source/core/package-targeting-resolution.json (added) matches static/schemas/source/**; static/schemas/source/core/package.json (modified) matches static/schemas/source/**; static/schemas/source/core/placement-selection.json (added) matches static/schemas/source/**; static/schemas/source/core/placement.json (modified) matches static/schemas/source/**; static/schemas/source/core/product-filters.json (modified) matches static/schemas/source/**; static/schemas/source/core/product-targeting-resolution.json (added) matches static/schemas/source/**; static/schemas/source/core/product.json (modified) matches static/schemas/source/**; static/schemas/source/core/targeting-modification.json (added) matches static/schemas/source/**; static/schemas/source/core/targeting-overlay-requirements.json (added) matches static/schemas/source/**; static/schemas/source/core/targeting-overlay-support.json (added) matches static/schemas/source/**; static/schemas/source/core/targeting.json (modified) matches static/schemas/source/**; static/schemas/source/core/x-entity-types.json (modified) matches static/schemas/source/**; static/schemas/source/enums/error-code.json (modified) matches static/schemas/source/**; static/schemas/source/index.json (modified) matches static/schemas/source/**; static/schemas/source/media-buy/get-media-buys-response.json (modified) matches static/schemas/source/**; static/schemas/source/media-buy/get-products-request.json (modified) matches static/schemas/source/**; static/schemas/source/media-buy/get-products-response.json (modified) matches static/schemas/source/**; static/schemas/source/media-buy/get-products-targeting-resolution.json (added) matches static/schemas/source/**; static/schemas/source/media-buy/package-request.json (modified) matches `static

…(truncated)…

@aao-secretariat

Copy link
Copy Markdown
Contributor

Ladon cannot review this PR until merge conflicts are resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ladon/needs-human-review Ladon has escalated this PR for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

update_media_buy: add first-class purchased-placement selection to PackageUpdate

1 participant