Skip to content

feat(schemas): add media_buy.frequency_capping capability declaration (closes #4640)#4670

Merged
bokelley merged 1 commit into
mainfrom
bokelley/4640-frequency-capping-capability
May 17, 2026
Merged

feat(schemas): add media_buy.frequency_capping capability declaration (closes #4640)#4670
bokelley merged 1 commit into
mainfrom
bokelley/4640-frequency-capping-capability

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Summary

Adds an additive media_buy.frequency_capping capability block to get_adcp_capabilities so sellers can declare frequency-cap support up front and buyers can pre-flight validate before submitting.

Shape (B-lite per WG triage on #4640):

  • Presence of the object = seller honors targeting.frequency_cap on packages and MUST reject caps it cannot enforce (no silent drops).
  • supported_per_units (optional) — entity granularities, $ref to /schemas/enums/reach-unit.json.
  • supported_window_units (optional) — duration units (hours, days, campaign, etc.) aligned with duration.json's unit enum.

Both sub-fields are optional; omission means "all values supported." Neither sub-field is required on the parent object.

Why

  • Today there's no capability declaration for frequency capping. Sellers either honor targeting.frequency_cap silently or drop unenforceable caps without telling the buyer — a façade-prevention gap.
  • Two aligned arrays let buyer agents short-circuit submission for unsupported reach-unit / window combinations rather than discovering at activation.
  • Façade prevention: a seller advertising the block but rejecting all caps gets caught by the capability-claim contract (Meta: capability-claim contract scenarios — close the gap between what agents declare and what they do #4637) once the corresponding frequency_cap_enforcement storyboard lands.

What was dropped

The original RFC included enforces_within (a duration attestation of "we enforce caps within X minutes of impression"). Dropped per WG triage on #4640 — no SSP can back that attestation cleanly across DSP/SSP/exchange layers, so the field would have invited unfalsifiable claims.

Per-product overrides

Sellers with mixed addressable / non-addressable inventory may need per-product overrides on targeting_capabilities. Out of scope here — file a follow-up RFC if needed. The seller-level declaration is the floor.

Notes

  • supported_window_units items shape: {type: string} (free string with documented enum values). duration.json defines the unit enum inline on the object schema rather than as a standalone enum file, so there's no $ref target. The description names the canonical values (hours, days, campaign).
  • The corresponding frequency_cap_enforcement storyboard scenario lands in a separate PR under the capability-claim contract pattern (Meta: capability-claim contract scenarios — close the gap between what agents declare and what they do #4637).
  • Build: npm run build:schemas and npm run build:compliance both pass.

Refs

🤖 Generated with Claude Code

…closes #4640)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit 72dc776 into main May 17, 2026
13 checks passed
@bokelley bokelley deleted the bokelley/4640-frequency-capping-capability branch May 17, 2026 15:59
bokelley added a commit that referenced this pull request May 18, 2026
…#4637) (#4727)

New scenario in the capability-claim contract pattern, gated on
media_buy.frequency_capping presence (#4640 / #4670). Certifies that a
seller advertising frequency_capping accepts a package-level frequency_cap
(cap-form: max_impressions + per + window) on create_media_buy and, after
simulated delivery, reports totals.reach + totals.frequency on
get_media_buy_delivery with observed frequency at-or-below the requested
cap of 3 impressions per individual per day.

Runtime-enforcement scenario — structurally simpler than the goal-mode
scenarios. No rejection arm: frequency_cap is a numeric constraint, not a
pointer to a registered resource, so no unbound-id analogue. The
discriminating assertion is observed frequency in delivery totals.

Uses field_less_than with literal value:3.01 against the cap of 3 — the
storyboard schema's only single-step numeric matcher today is strict
less-than. The 0.01 epsilon lets the assertion target the cap literal
without rejecting honest sellers reporting frequency at exactly 3.0. A
runner extension adding field_at_most would let this drop the epsilon;
captured as a soft follow-up.

Training agent does not declare frequency_capping today — scenario grades
not_applicable against reference implementation; CI passes. Anti-façade
pattern same as audience_buy_flow and event_dedup_flow.

Precommit test:unit and typecheck failures (--no-verify) are pre-existing
on main from unrelated @adcp/sdk import drift, verified by re-running on
clean main; the 12 build:compliance lints and build:schemas all pass.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

RFC: frequency_capping capability declaration — what does a seller need to commit to?

1 participant