Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/reserved-word-enum-replacements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"adcontextprotocol": minor
---

Schema: add reserved-word-safe replacements for six enum positions that collide with SDK target languages, and deprecate the originals (#8791). Each enum now accepts both spellings through 3.x; the original is deprecated in 3.3 and removed in 4.0.

- `pass` → `passed` in `enums/binary-verdict.json`, `get_media_buy_artifacts` `local_verdict`, and the registry feed's compliance `tracks` status. `pass` is a Python keyword.
- `global` → `agent` in the `RATE_LIMITED` details `scope`. `global` is a Python keyword.
- `name` → `full_name` in the signal definition `onboarder.match_keys`, on both `core/signal-definition.json` and `core/signal-definition-enrichment.json`. `name` collides with the enum member protocol in Python and Java.

Each deprecated value is listed in `x-deprecated-enum-values` and carries `deprecated: true`, `x-deprecated-in: "3.3.0"`, `x-removed-in: "4.0.0"`, and `x-superseded-by` in a per-value `enumMetadata` entry. The 4.0 compatibility registry lists every site. A 3.2 validator rejects the new values, so senders keep the original until the counterparty supports 3.3.
2 changes: 1 addition & 1 deletion docs/building/operating/transport-errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ The `details` field is an open object. To prevent interoperability divergence, s
| `limit` | number | Maximum requests allowed in the window |
| `remaining` | number | Requests remaining in the current window |
| `window_seconds` | number | Duration of the rate-limit window |
| `scope` | string | What the limit applies to: `account`, `tool`, or `global` |
| `scope` | string | What the limit applies to: `account`, `tool`, or `agent` (the whole agent). `global` is the deprecated spelling of `agent`: deprecated in 3.3 and removed in 4.0 ([#8791](https://github.com/adcontextprotocol/adcp/issues/8791)). Receivers accept both through 3.x; a 3.2 receiver rejects `agent`. |

### `BUDGET_TOO_LOW`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ An artifact represents content context where ad placements occur - identified by

| Field | Required | Description |
|-------|----------|-------------|
| `verdict` | Yes | Overall `pass` or `fail` decision |
| `verdict` | Yes | Overall `passed` or `fail` decision. `pass` is the deprecated spelling of `passed`: deprecated in 3.3 and removed in 4.0 ([#8791](https://github.com/adcontextprotocol/adcp/issues/8791)). Receivers accept both through 3.x; a 3.2 receiver rejects `passed`. |
| `explanation` | No | Detailed natural language explanation of the decision |
| `features` | No | Per-feature breakdown with explanations |
| `confidence` | No | Model confidence in the verdict (0-1), when available |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Uses higher limits than standard pagination because artifact result sets can be
| `artifacts[].country` | ISO 3166-1 alpha-2 country code where delivery occurred |
| `artifacts[].channel` | Channel type (display, olv, ctv, podcast, social, etc.) |
| `artifacts[].brand_context` | Brand/SKU information for policy evaluation (schema TBD) |
| `artifacts[].local_verdict` | Seller's local model verdict (pass/fail/unevaluated) |
| `artifacts[].local_verdict` | Seller's local model verdict: `passed`, `fail`, or `unevaluated`. `pass` is the deprecated spelling of `passed` (deprecated in 3.3, removed in 4.0, [#8791](https://github.com/adcontextprotocol/adcp/issues/8791)); treat the two as the same verdict. |
| `collection_info` | Artifact collection statistics — what the seller collected per the buy agreement |
| `pagination` | Cursor for fetching more results |

Expand Down Expand Up @@ -156,9 +156,11 @@ validation = verification_agent.validate_content_delivery(
)

# Check for drift between local and verified verdicts
# "pass" is the deprecated spelling of "passed"; compare them as one verdict.
normalize = lambda verdict: "passed" if verdict == "pass" else verdict
for i, result in enumerate(validation["results"]):
local = artifacts_response["artifacts"][i]["local_verdict"]
verified = result["verdict"]
local = normalize(artifacts_response["artifacts"][i]["local_verdict"])
verified = normalize(result["verdict"])
if local != verified:
print(f"Drift detected: {result['record_id']} - local={local}, verified={verified}")
```
Expand All @@ -181,7 +183,7 @@ validation = verification_agent.validate_content_delivery(
)

# Check false positive rate
false_positives = sum(1 for r in validation["results"] if r["verdict"] == "pass")
false_positives = sum(1 for r in validation["results"] if r["verdict"] in ("passed", "pass"))
print(f"False positive rate: {false_positives / len(failures['artifacts']):.1%}")
```

Expand All @@ -194,7 +196,7 @@ Governance agents receiving validation results where every `local_verdict` is `"
| `local_verdict` | `failures_only` returns? | Drift comparison possible? |
|-----------------|--------------------------|---------------------------|
| `fail` | Yes | Yes |
| `pass` | No | N/A (not in result set) |
| `passed` (or the deprecated `pass`) | No | N/A (not in result set) |
| `unevaluated` | No | No — omit `failures_only` to retrieve all collected artifacts |

## Non-Web Artifact Examples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ This keeps responsibilities clear: sellers provide content samples via `get_medi
}
```

Each result's `verdict` is `passed` or `fail`. `pass` is the deprecated spelling of `passed`: deprecated in 3.3 and removed in 4.0 ([#8791](https://github.com/adcontextprotocol/adcp/issues/8791)). Receivers accept both through 3.x; a 3.2 receiver rejects `passed`.

## Use Cases

### Post-Campaign Audit
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/migration/v4-compatibility.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ A check is added once its 4.0 change is decided. These changes are still proposa

The schemas also mark 48 deprecated fields with `x-removed-in: "4.0.0"`. The registry lists each one, either under the check that covers it or in `schema_removals_not_checked` with the reason no check covers it yet. Most uncovered fields are sent by buyers, so a seller run can't observe them. A few are seller-emitted and checkable but not graded yet: flat `valid_actions`, response-wide delivery `currency` and `aggregated_totals`, `inline_creative_management`, boolean `demographics` in product support, and the format-level build and pricing surface that `list_transformers` replaces.

Deprecated enum values carry the same marker on a per-value `enumMetadata` entry. 4.0 removes the values that collide with SDK reserved words or the enum member protocol ([#8791](https://github.com/adcontextprotocol/adcp/issues/8791)), each replaced in 3.3: `pass` by `passed`, `global` by `agent`, and the signal `match_keys` value `name` by `full_name`. Send the replacement once your counterparty supports 3.3 or later.

The full list of planned 4.0 work is the [4.0 milestone](https://github.com/adcontextprotocol/adcp/milestone/5).

## Adding a check
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"verify:schema-discovery": "node scripts/verify-schema-discovery.mjs",
"typecheck": "tsc --project server/tsconfig.json --noEmit && npm run typecheck:fixed-trace-rollout-tests",
"typecheck:fixed-trace-rollout-tests": "node scripts/typecheck-fixed-trace-rollout-tests.mjs",
"test:schemas": "node tests/schema-validation.test.cjs && node --test tests/account-ref.test.cjs tests/canonical-account-ref.test.cjs tests/image-bleed.test.cjs tests/sync-plans-reserved-names.test.cjs tests/seller-offers-contract.test.cjs tests/service-commitments.test.cjs tests/sync-platform-id.test.cjs tests/assignment-landing-page.test.cjs tests/assignment-trackers.test.cjs tests/assignment-replace.test.cjs tests/outcome-target.test.cjs tests/trusted-match-offer-creative-data.test.cjs tests/accessibility-violation-details.test.cjs tests/portfolio-routing-scope.test.cjs tests/catalog-item-availability-updates.test.cjs tests/catalog-ingestion-capabilities.test.cjs tests/sdk-implementation-metadata.test.cjs tests/seller-optimized-package-controls.test.cjs tests/compact-product-lifecycle-storyboards.test.cjs tests/timezone-resolution-storyboards.test.cjs tests/terminal-package-retention-storyboard.test.cjs tests/total-budget-redistribution-currency.test.cjs tests/dooh-allocation.test.cjs tests/x-added-in-3-3-sweep.test.cjs tests/url-pattern-loosening.test.cjs tests/performance-standard-metric-id.test.cjs tests/identity-absence-coherence.test.cjs tests/match-keys.test.cjs tests/execution-requirements.test.cjs tests/execution-readiness.test.cjs tests/schema-deprecation-metadata.test.cjs tests/products-only-brief-compatibility.test.cjs tests/async-identity-convergence.test.cjs tests/creative-rotation.test.cjs tests/creative-start-policy.test.cjs tests/canonical-forecast-point-parity.test.cjs tests/creative-revisions.test.cjs tests/creative-live-updates.test.cjs tests/creative-delivery-contracts.test.cjs tests/tracker-execution-contracts.test.cjs tests/tracker-execution-package-integration.test.cjs tests/metric-identity-coherence.test.cjs tests/print-metrics.test.cjs tests/installment-lifecycle-reporting.test.cjs tests/rights-channel-restrictions.test.cjs tests/daypart-time-of-day.test.cjs tests/audience-size-range.test.cjs tests/media-buy-lineage.test.cjs tests/delivery-projection.test.cjs tests/viewable-rate-optimization-goal.test.cjs tests/sort-contract-delivery-reporting.test.cjs tests/time-based-views-contract.test.cjs tests/metric-qualifier-parity.test.cjs tests/collection-mechanism.test.cjs tests/requested-metrics-contract.test.cjs tests/auto-breakdown-negotiation-contract.test.cjs tests/format-delivery-reporting-contract.test.cjs tests/inventory-delivery-reporting-contract.test.cjs tests/property-delivery-conformance.test.cjs tests/lint-schema-enum-drift.test.cjs tests/lint-schema-required-declared.test.cjs tests/format-asset-type-parity.test.cjs tests/canonical-manifest-constructibility.test.cjs tests/synthetic-depiction.test.cjs tests/creative-rendering-authority.test.cjs tests/buyer-reason.test.cjs tests/mutation-outcome.test.cjs tests/error-recovery-vectors.test.cjs tests/reporting-status-contract.test.cjs tests/reporting-reconciliation-fixture.test.cjs tests/reporting-core-fixture.test.cjs tests/reporting-native-version-ref-bounds.test.cjs tests/trust-json-v1.test.cjs tests/refine-proposals-expected-confirmation-at.test.cjs tests/hold-policy.test.cjs tests/hold-policy-vectors.test.cjs tests/canonical-installments.test.cjs tests/withdrawn-to-4-0.test.cjs tests/get-products-deprecated-withdrawals.test.cjs tests/deprecated-task-withdrawals.test.cjs tests/collection-catalog.test.cjs tests/collection-copies-vectors.test.cjs tests/account-change-record.test.cjs tests/notification-config-payload-view.test.cjs tests/account-requests.test.cjs tests/reporting-subscriptions.test.cjs tests/reporting-subscription-probe.test.cjs tests/reporting-subscription-coverage-vectors.test.cjs tests/reporting-subscription-coverage-properties.test.cjs tests/product-roster-coverage-vectors.test.cjs && npm run test:premium-display-formats && npm run test:geo-region-targeting",
"test:schemas": "node tests/schema-validation.test.cjs && node --test tests/account-ref.test.cjs tests/canonical-account-ref.test.cjs tests/image-bleed.test.cjs tests/sync-plans-reserved-names.test.cjs tests/seller-offers-contract.test.cjs tests/service-commitments.test.cjs tests/sync-platform-id.test.cjs tests/assignment-landing-page.test.cjs tests/assignment-trackers.test.cjs tests/assignment-replace.test.cjs tests/outcome-target.test.cjs tests/trusted-match-offer-creative-data.test.cjs tests/accessibility-violation-details.test.cjs tests/portfolio-routing-scope.test.cjs tests/catalog-item-availability-updates.test.cjs tests/catalog-ingestion-capabilities.test.cjs tests/sdk-implementation-metadata.test.cjs tests/seller-optimized-package-controls.test.cjs tests/compact-product-lifecycle-storyboards.test.cjs tests/timezone-resolution-storyboards.test.cjs tests/terminal-package-retention-storyboard.test.cjs tests/total-budget-redistribution-currency.test.cjs tests/dooh-allocation.test.cjs tests/x-added-in-3-3-sweep.test.cjs tests/url-pattern-loosening.test.cjs tests/performance-standard-metric-id.test.cjs tests/identity-absence-coherence.test.cjs tests/match-keys.test.cjs tests/execution-requirements.test.cjs tests/execution-readiness.test.cjs tests/schema-deprecation-metadata.test.cjs tests/reserved-word-enum-replacements.test.cjs tests/products-only-brief-compatibility.test.cjs tests/async-identity-convergence.test.cjs tests/creative-rotation.test.cjs tests/creative-start-policy.test.cjs tests/canonical-forecast-point-parity.test.cjs tests/creative-revisions.test.cjs tests/creative-live-updates.test.cjs tests/creative-delivery-contracts.test.cjs tests/tracker-execution-contracts.test.cjs tests/tracker-execution-package-integration.test.cjs tests/metric-identity-coherence.test.cjs tests/print-metrics.test.cjs tests/installment-lifecycle-reporting.test.cjs tests/rights-channel-restrictions.test.cjs tests/daypart-time-of-day.test.cjs tests/audience-size-range.test.cjs tests/media-buy-lineage.test.cjs tests/delivery-projection.test.cjs tests/viewable-rate-optimization-goal.test.cjs tests/sort-contract-delivery-reporting.test.cjs tests/time-based-views-contract.test.cjs tests/metric-qualifier-parity.test.cjs tests/collection-mechanism.test.cjs tests/requested-metrics-contract.test.cjs tests/auto-breakdown-negotiation-contract.test.cjs tests/format-delivery-reporting-contract.test.cjs tests/inventory-delivery-reporting-contract.test.cjs tests/property-delivery-conformance.test.cjs tests/lint-schema-enum-drift.test.cjs tests/lint-schema-required-declared.test.cjs tests/format-asset-type-parity.test.cjs tests/canonical-manifest-constructibility.test.cjs tests/synthetic-depiction.test.cjs tests/creative-rendering-authority.test.cjs tests/buyer-reason.test.cjs tests/mutation-outcome.test.cjs tests/error-recovery-vectors.test.cjs tests/reporting-status-contract.test.cjs tests/reporting-reconciliation-fixture.test.cjs tests/reporting-core-fixture.test.cjs tests/reporting-native-version-ref-bounds.test.cjs tests/trust-json-v1.test.cjs tests/refine-proposals-expected-confirmation-at.test.cjs tests/hold-policy.test.cjs tests/hold-policy-vectors.test.cjs tests/canonical-installments.test.cjs tests/withdrawn-to-4-0.test.cjs tests/get-products-deprecated-withdrawals.test.cjs tests/deprecated-task-withdrawals.test.cjs tests/collection-catalog.test.cjs tests/collection-copies-vectors.test.cjs tests/account-change-record.test.cjs tests/notification-config-payload-view.test.cjs tests/account-requests.test.cjs tests/reporting-subscriptions.test.cjs tests/reporting-subscription-probe.test.cjs tests/reporting-subscription-coverage-vectors.test.cjs tests/reporting-subscription-coverage-properties.test.cjs tests/product-roster-coverage-vectors.test.cjs && npm run test:premium-display-formats && npm run test:geo-region-targeting",
"test:performance-feedback": "node --test --test-force-exit --test-timeout=30000 tests/performance-feedback-contract.test.cjs",
"test:dist-schema-version-ids": "node --test --test-force-exit --test-timeout=30000 tests/dist-schema-version-ids.test.cjs",
"test:examples": "node tests/example-validation-simple.test.cjs && npm run test:tmp-context-merge",
Expand Down
15 changes: 15 additions & 0 deletions static/compliance/source/universal/v4-compatibility.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -502,3 +502,18 @@ schema_removals_not_checked:
sites:
- "core/targeting-overlay-support.json#/properties/demographics/anyOf/0"
- "core/targeting-overlay-requirements.json#/properties/demographics/anyOf/0"

- change: "Enum values that collide with SDK reserved words, replaced in 3.3"
issue: 8791
reason: >-
3.3 adds a replacement beside each value (pass to passed, global to
agent, name to full_name), so both are accepted through 3.x. Senders
keep the old value for 3.2 counterparties, so a 3.x run cannot grade its
use.
sites:
- "content-standards/get-media-buy-artifacts-response.json#/oneOf/0/properties/artifacts/items/properties/local_verdict/enumMetadata/pass"
- "core/registry-event.json#/$defs/compliancePayload/properties/tracks/additionalProperties/enumMetadata/pass"
- "core/signal-definition-enrichment.json#/properties/onboarder/properties/match_keys/items/enumMetadata/name"
- "core/signal-definition.json#/properties/onboarder/properties/match_keys/items/enumMetadata/name"
- "enums/binary-verdict.json#/enumMetadata/pass"
- "error-details/rate-limited.json#/properties/scope/enumMetadata/global"
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,23 @@
},
"local_verdict": {
"type": "string",
"x-deprecated-enum-values": ["pass"],
"x-deprecated-enum-values-doc": "Deprecated in 3.3 and removed in 4.0 (#8791): `pass` is a Python keyword, so generated SDKs must rename it. Use `passed`. Receivers accept both values through 3.x. Send the replacement only to a counterparty on AdCP 3.3 or later, because a 3.2 validator rejects it.",
"enum": [
"pass",
"fail",
"unevaluated"
"unevaluated",
"passed"
],
"description": "Seller's local model verdict for this artifact"
"description": "Seller's local model verdict for this artifact. `passed` replaces `pass`, which is deprecated in 3.3 and removed in 4.0; buyers treat the two as the same verdict.",
"enumMetadata": {
"pass": {
"deprecated": true,
"x-deprecated-in": "3.3.0",
"x-removed-in": "4.0.0",
"x-superseded-by": "passed"
}
}
}
},
"required": [
Expand Down
14 changes: 12 additions & 2 deletions static/schemas/source/core/registry-event.json
Original file line number Diff line number Diff line change
Expand Up @@ -758,10 +758,20 @@
"headline": { "type": ["string", "null"] },
"tracks": {
"type": "object",
"description": "Map of compliance track id to track status.",
"description": "Map of compliance track id to track status. `passed` replaces `pass`, which is deprecated in 3.3 and removed in 4.0; consumers treat the two as the same status.",
"additionalProperties": {
"type": "string",
"enum": ["pass", "fail", "partial", "skip", "silent", "warning", "unknown", "skipped"]
"x-deprecated-enum-values": ["pass"],
"x-deprecated-enum-values-doc": "Deprecated in 3.3 and removed in 4.0 (#8791): `pass` is a Python keyword, so generated SDKs must rename it. Use `passed`. Receivers accept both values through 3.x. Send the replacement only to a counterparty on AdCP 3.3 or later, because a 3.2 validator rejects it.",
"enum": ["pass", "fail", "partial", "skip", "silent", "warning", "unknown", "skipped", "passed"],
"enumMetadata": {
"pass": {
"deprecated": true,
"x-deprecated-in": "3.3.0",
"x-removed-in": "4.0.0",
"x-superseded-by": "passed"
}
}
}
},
"storyboards_passing": { "type": "integer", "minimum": 0 },
Expand Down
13 changes: 12 additions & 1 deletion static/schemas/source/core/signal-definition-enrichment.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,20 @@
"match_keys": {
"type": "array",
"minItems": 1,
"description": "Identifiers the onboarder matched on. `full_name` replaces `name`, which is deprecated in 3.3 and removed in 4.0; receivers treat the two as the same key.",
"items": {
"type": "string",
"enum": ["name", "address", "email", "postal", "lat_long", "mobile_id", "cookie_id", "ip", "customer_id", "phone"]
"x-deprecated-enum-values": ["name"],
"x-deprecated-enum-values-doc": "Deprecated in 3.3 and removed in 4.0 (#8791): `name` collides with the enum member protocol in Python and Java (`Enum.name`). Use `full_name`. Receivers accept both values through 3.x. Send the replacement only to a counterparty on AdCP 3.3 or later, because a 3.2 validator rejects it.",
"enum": ["name", "address", "email", "postal", "lat_long", "mobile_id", "cookie_id", "ip", "customer_id", "phone", "full_name"],
"enumMetadata": {
"name": {
"deprecated": true,
"x-deprecated-in": "3.3.0",
"x-removed-in": "4.0.0",
"x-superseded-by": "full_name"
}
}
}
},
"pre_onboarding_audience_expansion": {
Expand Down
Loading
Loading