From 7e143dcfc00bace261b3211d3a3be402bd5593e4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Apr 2026 10:50:27 +0000 Subject: [PATCH 1/6] docs(spec): prohibit dual-emission of legacy status fields alongside v3 status Closes #2987. Adds explicit MUST NOT conformance language so migrating agents know the v3 `status` field is the sole authoritative task state. https://claude.ai/code/session_01XeNaS3wfWQApdBpDsU5gC7 --- .changeset/prohibit-dual-status-emission.md | 4 ++++ docs/building/implementation/task-lifecycle.mdx | 4 ++++ docs/reference/migration/index.mdx | 1 + static/schemas/source/core/protocol-envelope.json | 3 ++- 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 .changeset/prohibit-dual-status-emission.md diff --git a/.changeset/prohibit-dual-status-emission.md b/.changeset/prohibit-dual-status-emission.md new file mode 100644 index 0000000000..cefd425825 --- /dev/null +++ b/.changeset/prohibit-dual-status-emission.md @@ -0,0 +1,4 @@ +--- +--- + +Clarify that v3 agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any alias) alongside the v3 `status` field. Adds a migration checklist row, a conformance warning in the task-lifecycle reference, and an `x-adcp-conformance` annotation on the protocol envelope schema's `status` property. Closes #2987. diff --git a/docs/building/implementation/task-lifecycle.mdx b/docs/building/implementation/task-lifecycle.mdx index 8b36be7b41..1958416b33 100644 --- a/docs/building/implementation/task-lifecycle.mdx +++ b/docs/building/implementation/task-lifecycle.mdx @@ -45,6 +45,10 @@ Every AdCP response uses a **flat structure** where task-specific fields are at } ``` +:::warning Single status field required +Agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any other alias) alongside `status`. The `status` field is the single authoritative task state. Agents emitting both are non-conformant and will fail storyboard testing. +::: + ## Status Handling ### Basic Pattern diff --git a/docs/reference/migration/index.mdx b/docs/reference/migration/index.mdx index bd50572302..880400506d 100644 --- a/docs/reference/migration/index.mdx +++ b/docs/reference/migration/index.mdx @@ -50,6 +50,7 @@ Each row is a breaking change. **Effort** indicates the typical work involved: | Products | `buying_mode` required on every `get_products` request | New requirement | [get_products reference](/docs/media-buy/task-reference/get_products) | | Media buy status | `pending_activation` → `pending_start` | Rename | [Media buys](/docs/media-buy/media-buys) | | Media buy status | `pending_creatives` added (no creatives assigned yet) | New requirement | [Media buys](/docs/media-buy/media-buys) | +| Task status | Legacy status fields (`task_status`, `response_status`, or any alias) MUST NOT be emitted alongside v3 `status` — remove all pre-v3 status fields | Rename | [Task lifecycle](/docs/building/implementation/task-lifecycle) | | Capabilities | `compliance_testing` capability block on `get_adcp_capabilities` | Additive | [Capability discovery](/docs/protocol/get_adcp_capabilities#compliance_testing) | | Idempotency | `idempotency_key` required on all mutating requests (UUID v4) | New requirement | [Security § Idempotency](/docs/building/implementation/security) | | Request signing | RFC 9421 Ed25519 signing profile (optional in 3.0, mandatory under AdCP Verified) | Additive | [Security § Request signing](/docs/building/implementation/security) | diff --git a/static/schemas/source/core/protocol-envelope.json b/static/schemas/source/core/protocol-envelope.json index b22ab14f40..e2b49398c6 100644 --- a/static/schemas/source/core/protocol-envelope.json +++ b/static/schemas/source/core/protocol-envelope.json @@ -16,7 +16,8 @@ }, "status": { "$ref": "/schemas/enums/task-status.json", - "description": "Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer." + "description": "Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer.", + "x-adcp-conformance": "Agents MUST NOT emit legacy status fields (task_status, response_status, or any alias) alongside this field. The status field is the single authoritative task state." }, "message": { "type": "string", From 8471b4b0f2f0f94bf445640bada4cfad6daa31a3 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Apr 2026 10:52:40 +0000 Subject: [PATCH 2/6] fix(docs): address pre-PR review blockers on dual-status prohibition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Correct effort classification Rename → Restructure in migration table - Remove unsupported storyboard-testing claim from conformance warning - Replace x-adcp-conformance annotation (ignored on $ref nodes in draft-07) with prose in description field https://claude.ai/code/session_01XeNaS3wfWQApdBpDsU5gC7 --- docs/building/implementation/task-lifecycle.mdx | 2 +- docs/reference/migration/index.mdx | 2 +- static/schemas/source/core/protocol-envelope.json | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/building/implementation/task-lifecycle.mdx b/docs/building/implementation/task-lifecycle.mdx index 1958416b33..0779e5aed9 100644 --- a/docs/building/implementation/task-lifecycle.mdx +++ b/docs/building/implementation/task-lifecycle.mdx @@ -46,7 +46,7 @@ Every AdCP response uses a **flat structure** where task-specific fields are at ``` :::warning Single status field required -Agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any other alias) alongside `status`. The `status` field is the single authoritative task state. Agents emitting both are non-conformant and will fail storyboard testing. +Agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any other alias) alongside `status`. The `status` field is the single authoritative task state. Agents emitting both are non-conformant. ::: ## Status Handling diff --git a/docs/reference/migration/index.mdx b/docs/reference/migration/index.mdx index 880400506d..1cf5a897eb 100644 --- a/docs/reference/migration/index.mdx +++ b/docs/reference/migration/index.mdx @@ -50,7 +50,7 @@ Each row is a breaking change. **Effort** indicates the typical work involved: | Products | `buying_mode` required on every `get_products` request | New requirement | [get_products reference](/docs/media-buy/task-reference/get_products) | | Media buy status | `pending_activation` → `pending_start` | Rename | [Media buys](/docs/media-buy/media-buys) | | Media buy status | `pending_creatives` added (no creatives assigned yet) | New requirement | [Media buys](/docs/media-buy/media-buys) | -| Task status | Legacy status fields (`task_status`, `response_status`, or any alias) MUST NOT be emitted alongside v3 `status` — remove all pre-v3 status fields | Rename | [Task lifecycle](/docs/building/implementation/task-lifecycle) | +| Task status | Legacy status fields (`task_status`, `response_status`, or any alias) MUST NOT be emitted alongside v3 `status` — remove all pre-v3 status fields | Restructure | [Task lifecycle](/docs/building/implementation/task-lifecycle) | | Capabilities | `compliance_testing` capability block on `get_adcp_capabilities` | Additive | [Capability discovery](/docs/protocol/get_adcp_capabilities#compliance_testing) | | Idempotency | `idempotency_key` required on all mutating requests (UUID v4) | New requirement | [Security § Idempotency](/docs/building/implementation/security) | | Request signing | RFC 9421 Ed25519 signing profile (optional in 3.0, mandatory under AdCP Verified) | Additive | [Security § Request signing](/docs/building/implementation/security) | diff --git a/static/schemas/source/core/protocol-envelope.json b/static/schemas/source/core/protocol-envelope.json index e2b49398c6..a7e0cb01f1 100644 --- a/static/schemas/source/core/protocol-envelope.json +++ b/static/schemas/source/core/protocol-envelope.json @@ -16,8 +16,7 @@ }, "status": { "$ref": "/schemas/enums/task-status.json", - "description": "Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer.", - "x-adcp-conformance": "Agents MUST NOT emit legacy status fields (task_status, response_status, or any alias) alongside this field. The status field is the single authoritative task state." + "description": "Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer. Agents MUST NOT emit legacy status fields (task_status, response_status, or any alias) alongside this field — the status field is the single authoritative task state." }, "message": { "type": "string", From 6e88abb6e72c777ee5e12ecdd7ff2eb0b669b7f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Apr 2026 10:54:30 +0000 Subject: [PATCH 3/6] chore(changeset): fix stale changeset description after x-adcp-conformance removal https://claude.ai/code/session_01XeNaS3wfWQApdBpDsU5gC7 --- .changeset/prohibit-dual-status-emission.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/prohibit-dual-status-emission.md b/.changeset/prohibit-dual-status-emission.md index cefd425825..56415745dc 100644 --- a/.changeset/prohibit-dual-status-emission.md +++ b/.changeset/prohibit-dual-status-emission.md @@ -1,4 +1,4 @@ --- --- -Clarify that v3 agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any alias) alongside the v3 `status` field. Adds a migration checklist row, a conformance warning in the task-lifecycle reference, and an `x-adcp-conformance` annotation on the protocol envelope schema's `status` property. Closes #2987. +Clarify that v3 agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any alias) alongside the v3 `status` field. Adds a migration checklist row, a conformance warning in the task-lifecycle reference, and extends the protocol envelope schema's `status` description with the prohibition. Closes #2987. From cf53fec2e0ae72896eb396b2d876448201f597f7 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 24 Apr 2026 10:38:36 -0400 Subject: [PATCH 4/6] chore(changeset): mark as spec patch Per @bokelley comment: PR touches static/schemas/source/core/protocol-envelope.json (a published protocol schema), so the changeset should bump the spec package, not be empty. Description-only schema change = patch per SemVer guidance in .agents/playbook.md. Co-Authored-By: Claude Opus 4.7 (1M context) --- .changeset/prohibit-dual-status-emission.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.changeset/prohibit-dual-status-emission.md b/.changeset/prohibit-dual-status-emission.md index 56415745dc..6d161cc030 100644 --- a/.changeset/prohibit-dual-status-emission.md +++ b/.changeset/prohibit-dual-status-emission.md @@ -1,4 +1,5 @@ --- +"adcontextprotocol": patch --- Clarify that v3 agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any alias) alongside the v3 `status` field. Adds a migration checklist row, a conformance warning in the task-lifecycle reference, and extends the protocol envelope schema's `status` description with the prohibition. Closes #2987. From 04a4a329823142c9c271eff62ccbf4fafed1be1b Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 24 Apr 2026 11:34:21 -0400 Subject: [PATCH 5/6] chore(changeset): escape raw `<` in triage-ship-more that broke mintlify parse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Blocks the broken-links workflow: Mintlify's MDX parser hits ./.changeset/triage-ship-more.md:4:156 with "Unexpected character \`1\` (U+0031) before name" because \`<150-line\` looks like a malformed JSX tag opener. Replace with "under-150-line" — same meaning, MDX-safe. Same fix shipped by @bokelley on bokelley/issue-3010 (ce11b327e); cherry-picking here so this PR's CI isn't gated on that unrelated PR landing first. Co-Authored-By: Claude Opus 4.7 (1M context) --- .changeset/triage-ship-more.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/triage-ship-more.md b/.changeset/triage-ship-more.md index 2b6ba3a2c3..7cddbb3ee3 100644 --- a/.changeset/triage-ship-more.md +++ b/.changeset/triage-ship-more.md @@ -1,4 +1,4 @@ --- --- -Flip the triage routine's default from "flag unless obviously a small bug" to "execute unless the change is breaking, ambiguous, or high-risk." Drops the <150-line scope cap, the classification-only-Bug-or-Doc gate, and the blanket prohibition on `static/schemas/source/**` edits. Adds a crisp non-breaking-vs-breaking definition as the primary Execute/Flag binary, adds evergreen content as a first-class always-PR-able bucket, and guards `infra/agents` bucket as always-Flag (self-modification risk). CODEOWNERS + human review still gate every merge. +Flip the triage routine's default from "flag unless obviously a small bug" to "execute unless the change is breaking, ambiguous, or high-risk." Drops the under-150-line scope cap, the classification-only-Bug-or-Doc gate, and the blanket prohibition on `static/schemas/source/**` edits. Adds a crisp non-breaking-vs-breaking definition as the primary Execute/Flag binary, adds evergreen content as a first-class always-PR-able bucket, and guards `infra/agents` bucket as always-Flag (self-modification risk). CODEOWNERS + human review still gate every merge. From 7fc433f065f34f82a2dffa4b459c5865ef69463b Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 24 Apr 2026 11:54:10 -0400 Subject: [PATCH 6/6] =?UTF-8?q?docs(spec):=20address=20nastassiafulconis?= =?UTF-8?q?=20review=20=E2=80=94=20Remove=20effort,=20concrete=20aliases?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `Remove` effort label to migration legend; apply to the Task status row. - Drop vague "or any alias" from all three surfaces (migration table, task lifecycle warning, envelope schema description) — enumerate only the concrete pre-v3 names (`task_status`, `response_status`). Broader semantic overlap is covered by the prose, not by an open-ended prohibition. - Follow-up conformance check tracked in #3041. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/building/implementation/task-lifecycle.mdx | 2 +- docs/reference/migration/index.mdx | 3 ++- static/schemas/source/core/protocol-envelope.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/building/implementation/task-lifecycle.mdx b/docs/building/implementation/task-lifecycle.mdx index 0779e5aed9..ba0395d795 100644 --- a/docs/building/implementation/task-lifecycle.mdx +++ b/docs/building/implementation/task-lifecycle.mdx @@ -46,7 +46,7 @@ Every AdCP response uses a **flat structure** where task-specific fields are at ``` :::warning Single status field required -Agents MUST NOT emit legacy status fields (`task_status`, `response_status`, or any other alias) alongside `status`. The `status` field is the single authoritative task state. Agents emitting both are non-conformant. +Agents MUST NOT emit the legacy `task_status` or `response_status` fields alongside `status`. The `status` field is the single authoritative task state. Agents emitting either alongside `status` are non-conformant. ::: ## Status Handling diff --git a/docs/reference/migration/index.mdx b/docs/reference/migration/index.mdx index 1cf5a897eb..6eec78545d 100644 --- a/docs/reference/migration/index.mdx +++ b/docs/reference/migration/index.mdx @@ -27,6 +27,7 @@ Each row is a breaking change. **Effort** indicates the typical work involved: - **Rename** — Field name changed, same semantics. Find-and-replace. - **Restructure** — Shape changed (e.g., string → object, single → array). Requires code changes. +- **Remove** — Field existed in v2, removed in v3. Find-and-delete. - **New requirement** — Didn't exist in v2. Requires new implementation. | Area | Change | Effort | Details | @@ -50,7 +51,7 @@ Each row is a breaking change. **Effort** indicates the typical work involved: | Products | `buying_mode` required on every `get_products` request | New requirement | [get_products reference](/docs/media-buy/task-reference/get_products) | | Media buy status | `pending_activation` → `pending_start` | Rename | [Media buys](/docs/media-buy/media-buys) | | Media buy status | `pending_creatives` added (no creatives assigned yet) | New requirement | [Media buys](/docs/media-buy/media-buys) | -| Task status | Legacy status fields (`task_status`, `response_status`, or any alias) MUST NOT be emitted alongside v3 `status` — remove all pre-v3 status fields | Restructure | [Task lifecycle](/docs/building/implementation/task-lifecycle) | +| Task status | Legacy `task_status` and `response_status` fields MUST NOT be emitted alongside v3 `status` — remove both | Remove | [Task lifecycle](/docs/building/implementation/task-lifecycle) | | Capabilities | `compliance_testing` capability block on `get_adcp_capabilities` | Additive | [Capability discovery](/docs/protocol/get_adcp_capabilities#compliance_testing) | | Idempotency | `idempotency_key` required on all mutating requests (UUID v4) | New requirement | [Security § Idempotency](/docs/building/implementation/security) | | Request signing | RFC 9421 Ed25519 signing profile (optional in 3.0, mandatory under AdCP Verified) | Additive | [Security § Request signing](/docs/building/implementation/security) | diff --git a/static/schemas/source/core/protocol-envelope.json b/static/schemas/source/core/protocol-envelope.json index a7e0cb01f1..3650217134 100644 --- a/static/schemas/source/core/protocol-envelope.json +++ b/static/schemas/source/core/protocol-envelope.json @@ -16,7 +16,7 @@ }, "status": { "$ref": "/schemas/enums/task-status.json", - "description": "Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer. Agents MUST NOT emit legacy status fields (task_status, response_status, or any alias) alongside this field — the status field is the single authoritative task state." + "description": "Current task execution state. Indicates whether the task is completed, in progress (working), submitted for async processing, failed, or requires user input. Managed by the protocol layer. Agents MUST NOT emit the legacy task_status or response_status fields alongside this field — the status field is the single authoritative task state." }, "message": { "type": "string",