Skip to content

fix(compat): infer display_tag and every 3.2 asset type from the asset key - #1628

Merged
bokelley merged 1 commit into
mainfrom
claude/issue-1624-display-tag-asset-type
Oct 26, 2026
Merged

bokelley merged 1 commit into
mainfrom
claude/issue-1624-display-tag-asset-type

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Fixes #1624 (part 1: display_tag inference; part 2, normalize_url whitespace, is a separate PR)

Problem

coerce_legacy_assets / infer_asset_type let an exact type-name key win over field presence. The type names came from a hand-kept list of 14 that predates AdCP 3.2, so an untyped asset under display_tag was inferred as text, url or image from its other keys:

coerce_legacy_assets({"display_tag": {"content": "<script ...>"}})
# before: {'display_tag': {..., 'asset_type': 'text'}}
# after:  {'display_tag': {..., 'asset_type': 'display_tag'}}

Fix

The vocabulary is now derived from the generated AssetVariant union (adcp.types.domains.core.assets.asset_union), the canonical creative-asset union. This follows #1501's derived format vocabulary. It is read lazily on first call and cached, so importing the legacy helpers still doesn't build the asset graph. A schema bump that adds an asset type extends key inference in the same regeneration.

Checking the full 3.2 vocabulary found 7 types missing from the hand list, not just display_tag. All are now inferred from an exact key: display_tag, zip, card, published_post, pixel_tracker, vast_tracker, daast_tracker.

Judgement call: this applies only when asset_type is absent and the key is exactly a type name. That is the precedence infer_asset_type already documents; the list had just gone stale. An untyped asset keyed exactly card or zip that used to be inferred as text/url is now inferred as its named type. That is the spec-correct reading, and the same change the issue asks for on display_tag.

Tests

  • The issue's display_tag example, with both content and url assets.
  • Every asset type in the format slot union's own derived vocabulary (_KNOWN_BASE_INDIVIDUAL_ASSET_TYPES) is inferred from its key, so the two generated vocabularies can't drift apart.

make lint, make typecheck-all and make test were run locally. One unrelated A2A integration test (test_a2a_context_id) flakes under local -n 8. It fails the same way on the #1619 branch and passed in #1626's CI.

🤖 Generated with Claude Code

…t key

coerce_legacy_assets() / infer_asset_type() let an exact type-name key win
over field presence, but the type names came from a hand-kept list of 14 that
predated AdCP 3.2. An untyped asset under `display_tag` was inferred as
text, url or image from its other keys.

Derive the vocabulary from the generated AssetVariant union instead, so the
key list is the 21 asset types the pinned schema declares (adds display_tag,
zip, card, published_post, pixel_tracker, vast_tracker, daast_tracker) and a
schema bump extends it in the same regeneration. Imported lazily on first use.

Fixes #1624

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

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ladon verdict: Approve

Approve — clean fix with no blocking findings.

Checked: replaces the stale 14-entry hand-kept _KNOWN_ASSET_TYPES in src/adcp/types/_legacy_assets.py with a vocabulary derived lazily and cached from the generated AssetVariant union (21 arms), so a schema bump extends key inference during regeneration. This directly addresses the repo's "hand-written vocabulary beside a generated union" concern — the derivation now tracks the generated source rather than drifting. Derivation handles both AdCPBaseModel arms and the RootModel multi-shape arms (display_tag, vast, daast, published_post); all 14 prior entries are retained with no existing-key regression. The fix(compat) semver signal is correct: the behavior change (untyped card/zip keys now infer their named type) is a documented spec-correct bug fix, not a published-contract break — no public export removed/renamed, no required↔optional flip, no enum member removal. The new cross-check test ties the legacy-derived vocabulary to format's emitted _KNOWN_BASE_INDIVIDUAL_ASSET_TYPES, preventing drift between the two generated lists.

No Critical/High/Medium findings. high_risk is false, gated_paths is false, no author team gate. Decision table rows 1–8 do not fire; falls through to row 9 (approve). Note: review_decision is REVIEW_REQUIRED, but since gated_paths is false, row 2 does not apply.

@bokelley
bokelley merged commit 88cf04a into main Oct 26, 2026
47 checks passed
@bokelley
bokelley deleted the claude/issue-1624-display-tag-asset-type branch October 26, 2026 01:47
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.

coerce_legacy_assets doesn't know display_tag, and normalize_url keeps surrounding whitespace

1 participant