Skip to content

fix(compliance): apply the capability rollup to AdCP 3.1.24+ bundles - #3699

Open
Synaeve wants to merge 1 commit into
adcontextprotocol:mainfrom
Synaeve:fix/8534-capability-rollup-3-1-24
Open

Synaeve wants to merge 1 commit into
adcontextprotocol:mainfrom
Synaeve:fix/8534-capability-rollup-3-1-24

Conversation

@Synaeve

@Synaeve Synaeve commented Nov 12, 2026 •

Copy link
Copy Markdown

Refs adcontextprotocol/adcp#8534

Problem

buildComplianceBundleResults grades a storyboard whose only result is the runner's root capability_unsupported row as not_applicable. This is the rule from #2960: an optional scenario the agent never claimed does not cap its bundle. The rule applies only when the storyboard's loader-stamped adcp_version is 3.2 or later (CAPABILITY_ROLLUP_MIN_ADCP_VERSION = '3.2'). #2960 deferred 3.1 for two reasons. The 3.1 governance scenarios lacked a capability predicate, and every 3.1 release lacked the "Applicability order" rule that makes this grade normative.

adcontextprotocol/adcp#7625 (closing adcp#7584) fixed both on the 3.1 line. It backported the rule, and it gated the governance scenarios on media_buy.governance_aware. adcp#7584 asked for this explicitly "so adcp-client#2960's rule can apply to 3.1 bundles as well". Every stable 3.1 bundle from 3.1.24 carries the same text as 3.2: an unsatisfied root capability predicate "keeps optional capability storyboards out of the coverage totals of agents that never claimed the capability". Other 3.1 scenarios already declared root predicates before 3.1.24; what they lacked was the rule. #3520 already lets these gated storyboards reach the runner, so only the rollup cutoff was left.

Today a 3.1 seller that declines optional capabilities keeps partial bundles. For the non-guaranteed media-buy seller in adcp#8534, graded on 3.1.29, 31 declined scenarios keep the media-buy protocol bundle partial. The universal wholesale_feed_* bundles stay partial too. Strict Spec grading on agenticadvertising.org reads these bundle verdicts.

Changes

src/lib/testing/compliance/comply.ts

  • isCapabilityUnsupportedSkip now asks carriesApplicabilityOrderRule(adcp_version). That is true from 3.2, as before, or for a stable 3.1.N release with N >= 24.
  • compareAdcpVersionStrings orders by major.minor and ignores the patch, so the 3.1 line is matched on its exact patch (STABLE_3_1_RELEASE_PATTERN). 3.1, v3.1.24 and 3.1 prereleases still fail closed.
  • Every other condition is unchanged: the declared predicate, the compliance_testing.* refusal, the result/phase/step allowlists, the counts and the empty skip.requirement.
  • 3.0 and 3.1.0–3.1.23 bundles keep capping.

src/lib/testing/storyboard/runner.ts

Comment only: the applicability order is noted as backported to 3.1.24.

test/lib/storyboard-capability-rollup.test.js

  • The version table now pins 3.1.23, 3.1, a 3.1 prerelease and v3.1.24 as partial, and 3.1.24 and 3.1.31 as passing.
  • The real-cache test now checks every capability-gated scenario of the 3.1.31 bundle (not compliance_testing.*). Each one is neutralized as loaded, and stays partial when re-stamped 3.1.23.
  • The header and legacy-fixture comments now describe the backport. LEGACY_CACHE is renamed CACHE_3_1.

test/lib/compliance-required-tools-applicability.test.js

The #3520 test that pinned 3.1.29 as partial now checks both sides of the boundary. On 3.1.23 every bundle stays partial. On 3.1.29 the unclaimed protocol's bundles are not_applicable, while the claimed protocol keeps its controller gap.

.changeset/capability-rollup-3-1-24.md

Patch changeset for @adcp/sdk.

What this unblocks for 3.1 sellers

Once hosted grading pins a release with this change:

  • The declined, non-compliance_testing scenarios of the media-buy protocol bundle stop counting: audience, clicks and reach flows, frequency caps, inventory lists, proposals, refine, vendor-metric optimization, creative-library and governance scenarios.
  • The universal wholesale_feed_* bundles stop counting for a seller that does not offer wholesale feeds.

The media-buy bundle can still stay partial through scenarios whose gate also involves compliance_testing.*. #2960 refuses any predicate set that contains a compliance_testing path, even when the failed predicate is the product one.

  • On 3.1.29 that is create_media_buy_async, gated on compliance_testing.scenarios containing force_create_media_buy_arm.
  • From 3.1.31 it also includes canonical_formats, canonical_custom_formats, canonical_experimental_formats, measurement_accountability, vendor_metric_accountability and universal stale-response-advisory. These AND a product predicate (for example media_buy.buying_modes contains wholesale) with compliance_testing.scenarios.

Claimants still need the tools, the controller and passing assertions.

Tests

  • storyboard-capability-rollup.test.js: 46/46 pass with no skips (3.0.25, 3.1.31, 3.2.8 and 3.3.0-beta.5 caches present).
    • The two changed tests fail on the original source.
    • They also fail with a mutation that applies the rule to every 3.1 patch.
  • compliance-required-tools-applicability.test.js: the re-pinned test passes, and fails on the original source.
  • Seven related files (rollup, required-tools applicability, bundle results, phase capability cascade, universal metadata, OAuth metadata graph, request-signing vector transport): 131/132, no skips. The one local failure also fails locally on the original source, and passes on main CI.
  • tsc --noEmit, eslint (no new findings) and prettier --check pass.

Out of scope / follow-ups

🤖 Generated with Claude Code

compliance
- grade a declined root capability gate not_applicable on 3.1.24+ bundles,
  which carry the backported applicability-order rule (adcp#7625)
- keep 3.0 and 3.1.0-3.1.23 bundles capping

tests
- pin 3.1.23 partial and 3.1.24+ neutralized in the rollup and
  required-tools applicability suites

@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.

Backports the AdCP 3.2 "Applicability order" capability-rollup rule to 3.1.24+. The reviewer verified carriesApplicabilityOrderRule is correctly shaped: compareAdcpVersionStrings parses major.minor only (comply.ts:1474-1483) so 3.1.x < 3.2, and the exact-patch regex ^3\.1\.(\d+)$ bounded at patch ≥ 24 is the sole 3.1-line path. Fails closed on absent/invalid/v-prefixed/prerelease versions, each pinned by test. Guard stays narrow (compliance_testing.* gates, unmet requirements, execution evidence still cap). Tests add positive+negative boundary coverage (3.1.23 partial / 3.1.24+ passing); runner.ts change is comment-only and accurate. Changeset present and patch is appropriate for a grading alignment with no wire/export impact — satisfies DR-0033 minor-release pathway and changeset-vs-wire-impact rules.

No blocking or Medium findings. No gated paths, no high-risk flag, no team gate. Falls through to row 9.

This branch has not been deployed

No deployments
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