feat(creative)!: make canonical models primary in v7 - #994
Conversation
b0e8dbe to
8741518
Compare
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
There was a problem hiding this comment.
Request changes: breaking diff shipped under a minor-bump conventional-commit signal. The architecture is right — canonical-first with an explicit Legacy* boundary is the correct shape, and the credential and layering invariants hold — but the semver signal has to match the diff before this can merge.
MUST FIX (blocking)
1. Breaking public-API change under feat: without ! or a BREAKING CHANGE: footer. pyproject.toml:7 bumps 6.6.0 → 7.0.0rc1 (major), but the lead commit is feat(creative): make canonical models primary in v7 — no !, and every commit body is empty, so no BREAKING CHANGE: footer either. The diff is unambiguously breaking on the wire:
FormatIdremoved from theadcp.*surface (src/adcp/__init__.py__all__+_LAZY_MODULES; confirmed gone intests/fixtures/public_api_snapshot.json).BuildCreativeRequest/BuildCreativeResponse/PreviewCreativeRequest/PreviewCreativeResponse(+*Interactive*/*Static*/ numbered variants) renamed toLegacy*insrc/adcp/__init__.py.ADCPClient.build_creative/preview_creativerenamed to*_legacyinsrc/adcp/client.py, andbuild_creative/list_creative_formatsnow hard-rejected byexecute_task'slegacy_only_tasksgate.
This repo runs release-please + conventional commits: feat: computes a MINOR bump. Failure mode in one sentence: release-please reads feat(creative):, cuts 6.7.0, and every v6 adopter doing pip install -U then from adcp import FormatId / BuildCreativeRequest — or calling client.build_creative(...) — breaks on what the changelog calls a non-breaking minor. Fix: retitle to feat(creative)!: and add a BREAKING CHANGE: footer enumerating the removed/renamed public API. The migration note itself is already here (MIGRATION_v6_to_v7.md), so this is purely the commit-message signal — but the signal is the contract release-please acts on, not the prose. The version string and the commit currently disagree about what kind of release this is.
Things I checked
- Security is clean.
security-reviewer: no High/Medium.dispatch.pyis capability-slug renames only —_build_request_contextand_CREDENTIAL_SHAPED_KEY_SUFFIXESuntouched, so the no-credentials-in-RequestContext.metadatacontract holds. The PR actually adds an echo-path control:Format's before-validator rejects credential-shaped keys inparams/extras (src/adcp/types/canonical_creative.py), tested intests/test_canonical_projection_scope.py. - No committed secret.
projection.py:60hmac.new(b"", …)is an empty-key content hash for RC3 byte-parity, not an auth primitive; process-boundary safety does not rely on it being secret (resolve_legacy_format_refsatprojection.py:721refuses to reverse-guess without an explicit durable resolver regardless). - Wire shape holds.
ad-tech-protocol-expert: sound-with-caveats, no cited divergence. Option-ID hashing handles the two parity traps correctly — JS integer normalization (float.is_integer()→int) andseparators=(",",":")/ensure_ascii=Falseto mirrorJSON.stringify— andLegacyFormatId.agent_urlis narrowed tostr(src/adcp/types/legacy.py:139-151) so PydanticAnyUrlcan't append a trailing slash and mutate the hashed tuple. Route precedence (exact owner+id wins, bare-id fallback only on unique bundled-AAO match), collision-poison-to-None, and unsafe-owner fail-closed (projection.py:83-104) are consistent with canonical-format semantics. - Layering not breached at the test level.
tests/test_import_layering.pyaddslegacy.pyandcanonical_creative.pyto the allowlist in lockstep with theirgenerated_pocimports, so the enforced contract passes. - Imports resolve.
Format/Productrebind tocanonical_creativein_eager.py;FormatIdis removed everywhere, not left dangling.
Follow-ups (non-blocking — file as issues)
- CLAUDE.md layering list is now stale. The "Import Architecture for Generated Types" section still names only the old allow-set;
legacy.pyandcanonical_creative.pynow import fromgenerated_pocand were added totest_import_layering.pybut not to the doc.test_claude_md_documents_the_ruleonly regex-checks loosely, so it won't catch the drift. (code-reviewer) - Golden fixture is forward-only and narrow.
tests/fixtures/canonical/typescript-13.0.0-rc.3-golden.jsonis 17 image/audio/generative cases from 3 owners with no downgrade golden, despite the PR title claiming "downgrade parity," and no video/custom/publisher-scope/non-ASCII coverage. Parity is pinned to a hand-authored fixture, not an automated TS↔Python conformance run. (ad-tech-protocol-expert) - Fail-closed product omission couples correctness to catalog freshness.
project_legacy_productreturnsproduct=Nonewhen no format maps (projection.py:610-625); a v7 buyer against a live seller emitting named IDs not in the vendoredrc3-aao-additions.json, with nolegacy_format_converter, silently drops products. Defensible, but worth a documented refresh/versioning story for the vendored catalog.
Minor nits (non-blocking)
- Unreachable diagnostic arm.
projection.py:600-608:raw.pop(\"format_ids\", None)runs just above, sonot raw.get(\"format_ids\")is always True and a non-empty-but-unprojectable list is mislabeledlegacy_format_list_empty. Base the branch onhad_legacy+ the original list length. (code-reviewer) FormatIdremoval raises a bareAttributeError. Unlike the_REMOVED_IN_V4map (__init__.py:56-86),from adcp import FormatIdnow gives no migration hint. Add it to an informative-error map pointing atLegacyFormatId.hmacframing.projection.py:60empty-key HMAC is a determinism hash, not integrity — a one-line comment stops a future reader from treatingformat_option_idas a trust boundary.
Flip to approve once the lead commit carries feat(creative)!: + a BREAKING CHANGE: footer listing the removed/renamed public API. Everything else here is a follow-up.
BREAKING CHANGE: FormatId is removed from the normal root API in favor of LegacyFormatId and explicit legacy modules. BuildCreativeRequest/Response and PreviewCreativeRequest/Response variants are renamed to Legacy*; ADCPClient build_creative/preview_creative and list_creative_formats move to *_legacy methods. Product and creative filters no longer expose format_ids, and generic primary execution rejects legacy-only creative tasks.
7c5474c to
fbd70f5
Compare
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
2 similar comments
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
Reject unsupported validator bundles, make capability routing deterministic, preserve opaque request bags, enforce safe one-to-one durable routes, and give validated publisher/community snapshots precedence over bundled AAO fallbacks. Vendor and pin the complete TypeScript 13.0.0-rc.3 transition corpus.
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
|
Final head |
Summary
Legacy*APIs and makelist_creative_formatslegacy-onlyDownstream blocker audit
context/extbagscanonical_creatives: true; explicit 3.0 removes the field; explicit legacy-only compatibility fixtures remain supportedlatest93/93 selected steps andadcp-3.059/59feat(creative)!:and the lead commit has a concreteBREAKING CHANGE:footerCompatibility behavior
Validation
pytest -q: 6,016 passed, 41 skipped, 9 deselected, 1 expected failure@adcp/sdk@latestseller storyboard: 93 selected steps passed@adcp/sdk@adcp-3.0seller storyboard: 59 steps passedorigin/mainFormat, unavailable rootFormatId, explicitLegacyFormatId, and recursively clean primary schemasCloses #972