Skip to content

spec(3.1): SHOULD-publish capability_id on every format_options[] entry#4861

Merged
bokelley merged 1 commit into
mainfrom
bokelley/issue-4856
May 20, 2026
Merged

spec(3.1): SHOULD-publish capability_id on every format_options[] entry#4861
bokelley merged 1 commit into
mainfrom
bokelley/issue-4856

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

Closes #4856.

#4845 added PackageRequest.capability_ids[] so V2-mental-model buyers can author create_media_buy without translating back through v1_format_ref[]. That path needs sellers to publish capability_id on the format_options[] entries the buyer targets — but the field is currently REQUIRED only when entries share a format_kind. For single-entry products (the 90% case), it's optional, and V2 authoring is silently unreachable.

Adds a SHOULD on product-format-declaration.json: sellers SHOULD set capability_id on every format_options[] entry, not just when forced by a collision. Co-located with the buyer-side change in the same minor (3.1) so release-notes readers see the buyer capability and the seller obligation together — splitting them across minors would create a release where buyers ship V2 code against sellers who weren't told to update.

Change

Description-text only. The field stays optional at the schema level — no structural change, no break to anyone shipping today. Sellers that don't comply remain 3.1-conformant; their products just aren't V2-authorable until they assign capability_id values.

Aligned docs/creative/canonical-formats.mdx definitions (table rows for ProductFormatDeclaration and capability_id) to reflect the SHOULD framing — previously described as purely-optional.

Files

  • static/schemas/source/core/product-format-declaration.json — extended capability_id description
  • docs/creative/canonical-formats.mdx — 2 table rows updated to match
  • .changeset/should-publish-capability-id-on-every-format-option.mdpatch

4.0 cutover

The 4.0 cutover (SHOULD → MUST, schema-level enforcement) is tracked in #4857 with a dependency checklist: 3.1 SHOULD (this PR), conformance signal in Verified, adoption telemetry, migration guidance.

Test plan

  • CI green
  • Mintlify renders the updated table rows cleanly

🤖 Generated with Claude Code

#4845 added `PackageRequest.capability_ids[]` so V2-mental-model buyers
can author `create_media_buy` without translating back through
`v1_format_ref[]`. That path needs sellers to publish `capability_id`
on the `format_options[]` entries the buyer targets — but the field is
currently REQUIRED only when entries share a `format_kind`. For
single-entry products (the 90% case), it's optional, and V2 authoring
is silently unreachable.

Add a SHOULD: sellers SHOULD set `capability_id` on every entry, not
just when forced by a collision. Co-located with the buyer-side change
in the same minor so 3.1 release-notes readers see the buyer capability
and the seller obligation together.

Description-text only — no structural change. The 4.0 cutover will
tighten SHOULD → MUST (tracked in #4857).

Closes #4856.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@aao-release-bot aao-release-bot 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.

LGTM. Description-only tightening with no wire change, cross-referenced cleanly to the buyer-side rule already shipped in #4845. The right shape: co-locate the seller obligation with the buyer capability in the same minor so 3.1 release-notes readers see both.

Things I checked

  • static/schemas/source/core/product-format-declaration.json:12 — new SHOULD framing on capability_id is internally consistent with the existing structural rule (REQUIRED only on format_kind collisions). Field stays optional at the schema level; happy path is unchanged for sellers shipping today.
  • Reciprocal contract verified: static/schemas/source/media-buy/package-request.json:28 already carries the failure-mode the new description cites — UNSUPPORTED_FEATURE with error.details.reason: capability_ids_not_published when a product's format_options[] entries don't publish capability_id. The two sides reference each other coherently.
  • docs/creative/canonical-formats.mdx rows 29 and 33 updated in lockstep with the schema. No further drift in docs/media-buy/task-reference/create_media_buy.mdx:189,922 — the V2-path docs already describe capability_ids_not_published as the fall-back signal.
  • Changeset present (patch), correct package, references the upstream PR and the 4.0 cutover issue.
  • No structural change → no oneOf discriminator regression risk. No required-flag flips. No enum changes.

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

  • Root description at static/schemas/source/core/product-format-declaration.json:5 still calls capability_id "Optional" and frames it as routing-only-on-collision. That's the pre-3.1 framing. The property-level description (L12) was tightened to SHOULD but the root paragraph one block above still reads as the old story. Worth a one-line fix to keep the schema internally consistent — readers who only skim the top blurb get the old contract.
  • Manifest-side cross-reference. creative-manifest.json:18 (and creative-asset.json:27) describe their capability_id as cleanly "optional in the single-entry case" with no pointer to the new seller-side SHOULD. Not a contradiction — manifest-validation truly is optional there — but a one-sentence "sellers SHOULD publish per product-format-declaration.json; manifests still MAY omit when format_kind routes unambiguously" would prevent readers from concluding the optionality is symmetric.
  • canonical-formats.mdx:828-830 describes manifest-side capability_id as OPTIONAL when format_kinds are distinct. Technically a different surface (buyer-side manifest vs. seller-side declaration) so not contradictory, but adjacent prose that reads "recommended habit" undersells the SHOULD that now sits on the product side. A clarifying line about which surface is which would help.

Minor nits (non-blocking)

  1. Changeset severity. patch is defensible — no wire shape change, no codegen delta, existing sellers stay conformant. A stricter read of "new normative SHOULD" argues minor. Worth checking what bucket #4845's changeset landed in — release-notes symmetry between the buyer capability and the seller obligation is the whole point of co-locating them, and a mismatch reads odd. Not blocking.

Test plan in the PR body shows CI-green and Mintlify-render checks unticked; both are passive CI gates rather than manual smokes, and the relevant CI checks are green at review time. The unchecked Mintlify item is the only user-facing surface this PR changes — worth eyeballing the rendered table rows once before merge, but not a hold.

Approving.

@bokelley bokelley merged commit 210b8a7 into main May 20, 2026
19 checks passed
@bokelley bokelley deleted the bokelley/issue-4856 branch May 20, 2026 18:46
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.

spec(3.1): SHOULD-publish capability_id on every format_options[] entry

1 participant