Summary
`compliance/{version}/universal/signed-requests.yaml:34` already mandates:
the runner SHOULD emit an informational notice (not a failure) advising the agent to drop the now-redundant specialism claim and rely solely on `request_signing.supported: true`.
This is the only "SHOULD emit notice" in the universal storyboards today, but the spec doesn't define what an "informational notice" is — there's no field on `runner-output-contract.yaml`, no severity enum, no machine-readable code. The reference SDK runner (`@adcp/sdk`) has not implemented it, and other runners (AdCP Verified, third-party CI gates, dashboards) have no standard place to put one.
Why now
Two 3.0 → 4.0 transitions need an advance-warning channel:
-
`request_signing` becomes required for spend-committing operations in 4.0 (per get-adcp-capabilities-response.json: "Required for spend-committing operations in 4.0"). A 3.0 seller that legitimately skips `signed_requests` today (because they don't advertise `request_signing.supported: true` — universally legal in 3.0) will fail compliance on the 4.0 cut with no advance warning unless the runner can surface "passed now, planned-required in 4.0."
-
`webhook_signing.legacy_hmac_fallback` is removed in 4.0 (same schema, line 966). Same shape of forward-required deprecation.
Without a structured notice surface, runners have two bad options: bake the advisory into prose `skip.detail` strings (unparseable by dashboards — see `adcontextprotocol/adcp-client#1702` / PR adcp-client#1703 where the SDK does exactly this as a stopgap), or stay silent and let sellers hit a wall at the 4.0 cut.
Proposed addition to `runner-output-contract.yaml`
Add a `notices` field on the per-storyboard result (and optionally on the overall compliance result for cross-storyboard signals):
```yaml
notices:
description: |
Advisory signals attached to a storyboard result. Distinct from skip
reasons (which name why a storyboard didn't run) and validation
failures (which fail the storyboard). Notices are informational and
MUST NOT change overall_passed. Runners emit one notice per advisory
condition; consumers aggregate by `code`.
type: array
items:
type: object
required: [severity, code, message]
properties:
severity:
enum: [info, deprecation, future_required]
description: |
- `info`: behavior is fine and supported; advisory context only.
- `deprecation`: an agent-side claim or behavior is allowed
today but the spec recommends migration (e.g. legacy
specialism enum values still accepted for back-compat).
- `future_required`: a capability that is optional today will
be required in a named future spec version; agents that do
not advertise it will fail compliance after the cut.
code:
type: string
description: |
Stable machine-readable identifier. Runners MUST NOT change
the code for the same advisory across versions.
message:
type: string
effective_version:
type: string
description: When severity is `future_required`, the AdCP version that flips the requirement.
requirement:
type: string
description: When the notice is tied to a structured `requires:` name, repeat it here.
capability_path:
type: string
description: |
Dotted path into the agent's `get_adcp_capabilities` response
that motivated the notice (e.g. `request_signing.supported`).
```
Canonical first-day notices
| Code |
Severity |
Spec source |
| `signed_requests_specialism_deprecated` |
`deprecation` |
signed-requests.yaml:34 (the SHOULD that motivated this issue) |
| `request_signing_required_in_4_0` |
`future_required` |
get-adcp-capabilities-response.json:892 |
| `legacy_hmac_fallback_removed_in_4_0` |
`deprecation` |
get-adcp-capabilities-response.json:966 |
Why standardize in the spec rather than the SDK
Multiple runners exist or are planned (`@adcp/sdk`, AdCP Verified, third-party CI gates). If each invents its own advisory shape, downstream consumers (dashboards, JUnit, badge renderers, the agent reporting UI on the AdCP site) have to write per-runner adapters. A single spec field collapses that to one render path.
Refs
- adcp-client#1702 / PR adcp-client#1703 — runner currently rides 4.0 forward-readiness signal in `skip.detail` prose as a stopgap pending this surface.
- adcp-client#1704 (SDK-side issue tracking the runner-output extension)
- signed-requests.yaml:34 (existing unimplemented SHOULD)
Summary
`compliance/{version}/universal/signed-requests.yaml:34` already mandates:
This is the only "SHOULD emit notice" in the universal storyboards today, but the spec doesn't define what an "informational notice" is — there's no field on `runner-output-contract.yaml`, no severity enum, no machine-readable code. The reference SDK runner (`@adcp/sdk`) has not implemented it, and other runners (AdCP Verified, third-party CI gates, dashboards) have no standard place to put one.
Why now
Two 3.0 → 4.0 transitions need an advance-warning channel:
`request_signing` becomes required for spend-committing operations in 4.0 (per get-adcp-capabilities-response.json: "Required for spend-committing operations in 4.0"). A 3.0 seller that legitimately skips `signed_requests` today (because they don't advertise `request_signing.supported: true` — universally legal in 3.0) will fail compliance on the 4.0 cut with no advance warning unless the runner can surface "passed now, planned-required in 4.0."
`webhook_signing.legacy_hmac_fallback` is removed in 4.0 (same schema, line 966). Same shape of forward-required deprecation.
Without a structured notice surface, runners have two bad options: bake the advisory into prose `skip.detail` strings (unparseable by dashboards — see `adcontextprotocol/adcp-client#1702` / PR adcp-client#1703 where the SDK does exactly this as a stopgap), or stay silent and let sellers hit a wall at the 4.0 cut.
Proposed addition to `runner-output-contract.yaml`
Add a `notices` field on the per-storyboard result (and optionally on the overall compliance result for cross-storyboard signals):
```yaml
notices:
description: |
Advisory signals attached to a storyboard result. Distinct from skip
reasons (which name why a storyboard didn't run) and validation
failures (which fail the storyboard). Notices are informational and
MUST NOT change overall_passed. Runners emit one notice per advisory
condition; consumers aggregate by `code`.
type: array
items:
type: object
required: [severity, code, message]
properties:
severity:
enum: [info, deprecation, future_required]
description: |
- `info`: behavior is fine and supported; advisory context only.
- `deprecation`: an agent-side claim or behavior is allowed
today but the spec recommends migration (e.g. legacy
specialism enum values still accepted for back-compat).
- `future_required`: a capability that is optional today will
be required in a named future spec version; agents that do
not advertise it will fail compliance after the cut.
code:
type: string
description: |
Stable machine-readable identifier. Runners MUST NOT change
the code for the same advisory across versions.
message:
type: string
effective_version:
type: string
description: When severity is `future_required`, the AdCP version that flips the requirement.
requirement:
type: string
description: When the notice is tied to a structured `requires:` name, repeat it here.
capability_path:
type: string
description: |
Dotted path into the agent's `get_adcp_capabilities` response
that motivated the notice (e.g. `request_signing.supported`).
```
Canonical first-day notices
Why standardize in the spec rather than the SDK
Multiple runners exist or are planned (`@adcp/sdk`, AdCP Verified, third-party CI gates). If each invents its own advisory shape, downstream consumers (dashboards, JUnit, badge renderers, the agent reporting UI on the AdCP site) have to write per-runner adapters. A single spec field collapses that to one render path.
Refs