Skip to content

spec(creative): transformer refinement-retention + fan-out multiplicity discriminators#5229

Merged
bokelley merged 1 commit into
account-specific-user-configfrom
creative-transformers-caps
May 31, 2026
Merged

spec(creative): transformer refinement-retention + fan-out multiplicity discriminators#5229
bokelley merged 1 commit into
account-specific-user-configfrom
creative-transformers-caps

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Follow-on #3 (the keystone) from the persona/scenario review of #5219. Stacked on account-specific-user-config (#5219); retarget to main once that merges.

Gives buyer agents pre-call discriminators so they know what a creative agent supports before sending max_creatives/max_variants/refine_from, instead of probing and handling failures. Fully additive/optional — every field defaults to "unsupported / unbounded" — and it's the surface the spend-control (F1) and conformance (F4) follow-ons build on.

Changes

  • get_adcp_capabilitiescreative.refinable_retention_seconds — the guaranteed-minimum window a produced build_variant_id stays refinable. Replaces the prose-only "agent-defined window" with a machine-readable floor; omit to keep it agent-defined.
  • get_adcp_capabilitiescreative.multiplicitysupports_catalog_fanout + max_creatives_limit, supports_variants + max_variants_limit, variant_dimensions[]. Over-limit fan-out is clamped to the ceilings (shortfall via items_returned < items_total), not rejected — consistent with item_limit's "use the lesser" rule. Absent = no fan-out.
  • transformer.json → optional multiplicity that narrows the agent-level object per transformer (ceilings ≤ agent, variant_dimensions ⊆ agent).
  • build_creative docs note the clamp behavior on the fan-out rows.

Validation

build:schemas, schema suite, json-schema, composed, oneof-discriminators, x-entity lint, docs-nav — all green. minor changeset included.

Design decisions (open to WG)

  • refinable_retention_seconds is a floor (guaranteed minimum), not a ceiling.
  • Over-limit → clamp, not reject (matches item_limit).
  • Discriminators on the agent with optional per-transformer narrowing.

🤖 Generated with Claude Code

…ty discriminators

Follow-on #3 (keystone) from the persona/scenario review: give buyers pre-call
discriminators so they know what an agent supports before sending, rather than
probing and handling failures. Additive/optional; the surface the spend-control
and conformance follow-ons read.

- get_adcp_capabilities creative.refinable_retention_seconds (guaranteed-minimum
  refinable window — machine-readable floor for the prior prose-only "agent-defined
  window").
- get_adcp_capabilities creative.multiplicity {supports_catalog_fanout +
  max_creatives_limit, supports_variants + max_variants_limit, variant_dimensions[]}.
  Over-limit fan-out is clamped (items_returned < items_total), not rejected.
- transformer.multiplicity narrows the agent-level object per transformer
  (ceilings <= agent, dimensions subset of agent).
- build_creative docs note the clamp behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@aao-release-bot aao-release-bot Bot left a comment

Choose a reason for hiding this comment

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

Approved. Additive, fully optional, every new field defaults to "unsupported / unbounded" — the right shape for a pre-call discriminator and the only shape that lets a buyer agent learn what's supported without probing for failures.

Things I checked

  • variant_dimensions enum (voice|theme|best_of_n|transformer_config|custom) at get-adcp-capabilities-response.json:1138-1141 matches variant_axis.dimension on build-creative-request.json:93 exactly. No drift.
  • Both new multiplicity blocks are additionalProperties: true — consistent with the surrounding creative capability object and the rest of the capabilities surface.
  • No oneOf introduced; the discriminator baseline at scripts/oneof-discriminators.baseline.json is untouched.
  • items_returned/items_total referenced by the clamp prose exist on BuildCreativeVariantSuccess (build-creative-response.json:383-391).
  • Transformer-level multiplicity mirrors the agent-level shape — same property names, same types, same enum, same additionalProperties posture.
  • Changeset is minor. Correct: fully additive, no field renames, no enum removals, no required flips.
  • Docs row at get_adcp_capabilities.mdx:388-389 mirrors the schema descriptions; build_creative.mdx carries the clamp note on max_creatives/max_variants.

Follow-ups (non-blocking — file as issues)

  • Silent-clamp observability gap. items_total on build-creative-response.json:386 is "total catalog items eligible for the build (before max_creatives sampling)" — i.e. catalog input size, not the requested ceiling. So items_returned < items_total fires for normal under-sampling (max_creatives: 5 of 150) AND for a ceiling clamp (max_creatives: 50 against max_creatives_limit: 20). A buyer cannot tell "I got the sample I asked for" from "I was silently clamped below what I asked for." The spend-control (F1) follow-on this PR is the keystone for needs that distinction — add an explicit clamped: true / applied_limit: N signal on the success envelope (or an advisory error) before F1 lands.
  • max_variants clamp signal is undefined. build_creative.mdx:36 says "clamped" but items_returned/items_total are catalog-fan-out fields — they don't carry per-creative best-of-N shortfall. Either give max_variants its own observable signal or state explicitly that the clamp is silent and the response simply contains fewer variants.
  • "Use the lesser" parallel is mis-cited. item_limit's rule on build-creative-request.json:135 is "lesser of item_limit vs the format's max_items" — request-vs-format reconciliation within a single creative. Not request-vs-capability-ceiling across a fan-out. The clamp behavior is defensible on its own; the changeset and multiplicity description just shouldn't lean on this precedent. Drop the analogy or cite a different one.
  • Omitted-limit semantics. max_creatives_limit and max_variants_limit say "Omitted means no advertised ceiling," but the parent multiplicity description says over-limit requests are clamped to these ceilings. If the ceiling is omitted, what does the clamp clamp to? Either explicitly say "absent limit → no clamp" or require the limit when supports_catalog_fanout/supports_variants is true. Same caveat on transformer.json:51,53.
  • Cross-field invariant on refinable_retention_seconds. Schema doesn't enforce that this field is only meaningful when supports_refinement: true. Draft-07 if/then would catch the misconfiguration, but no precedent exists elsewhere in this file. Conformance-suite check is fine.
  • Transformer-narrows-agent is prose-only. "Ceilings ≤ agent, variant_dimensions ⊆ agent" is a cross-document constraint JSON Schema can't express. Accepted repo pattern, but it needs to land in the conformance suite, not just the description.

Minor nits (non-blocking)

  1. Typo. transformer.json:47 — "this transformer's authoritative" reads as a missing word. One-word fix to "this transformer's [object is] authoritative."
  2. multiplicity has no default. Description says "Absent means no fan-out" — if you want that machine-readable, default: {} plus the per-field default: false carries it. Cosmetic; prose is clear.

Approving on the strength of the discriminator design plus the clean enum cross-reference. The clamp-observability gap is the one I'd want closed before F1 ships, not before this one.

@bokelley
Copy link
Copy Markdown
Contributor Author

Folding the transformer follow-ons into #5219 instead of stacking. The F3 capability-discriminator commit (66dcdac) is now on #5219; closing this stacked PR.

@bokelley bokelley merged commit 66dcdac into account-specific-user-config May 31, 2026
5 checks passed
@bokelley bokelley deleted the creative-transformers-caps branch May 31, 2026 18:12
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