spec: fold protocol-envelope into per-task response schemas (closes #4878)#4896
spec: fold protocol-envelope into per-task response schemas (closes #4878)#4896bokelley wants to merge 1 commit into
Conversation
…4878) Companion to #4876 (envelope status REQUIRED). That PR locked the contract on protocol-envelope.json; this PR cascades the requirement to every per-task response schema so per-task response_schema validators catch envelope omissions directly, without relying on the separate envelope_field_present storyboard check. 64 task response schemas now $ref protocol-envelope.json alongside version-envelope.json. Two schemas (brand/search-brands, creative/ validate-input) had allOf added for consistency. Carve-outs: - core/pagination-response.json, core/catalog-events-response.json: nested helpers, not task responses. - governance/check-governance-response.json, governance/report-plan-outcome-response.json: body-level status enum collides with envelope status on MCP flat serialization. Tracked as a separate spec issue (body-status rename to verdict/decision before 3.1 GA). Cleanup applied alongside the fold: - 25 examples in response schemas updated to carry status: "completed" - 62 JSON blocks across 27 docs .mdx files updated likewise - Test fixtures in tests/composed-schema-validation.test.cjs, tests/example-validation-simple.test.cjs, and tests/schema-validation.test.cjs updated - Storyboard sample_response for signal-marketplace/governance_denied updated to include status: "failed" Validation: - npm run test:schemas (8/8) - npm run test:examples (36/36) - npm run test:json-schema (270/270 doc snippets) - npm run test:composed (43/43) - npm run test:storyboard-response-schema (passes) SDK companion (#4877) is the going-forward fix in @adcp/client. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
LGTM. The fold is the right cascade from #4876 — per-task validators now catch envelope omissions directly instead of leaning on the envelope_field_present storyboard check.
Things I checked
- Carve-out completeness:
grep -L protocol-envelope.json static/schemas/source/**/*-response.jsonreturns exactly the four documented files (core/pagination-response.json,core/catalog-events-response.json,governance/check-governance-response.json,governance/report-plan-outcome-response.json). 64 schemas folded + 4 carved = full inventory. No drift. tasks-get-response.jsonandtasks-list-response.jsonare correctly folded (they are real task responses, not core helpers).- The two schemas without an existing
allOf(brand/search-brands-response.json,creative/validate-input-response.json) hadallOfadded with both envelope refs — the right shape. - Carve-out rationale on the governance pair: body
status$refsenums/governance-decision.json(approved/denied/conditions); envelopestatus$refsenums/task-status.json. On MCP flat serialization both occupy the same root-levelstatuskey. The carve-out is load-bearing — folding without renaming the body field would produce schemas that reject every conformantcheck_governanceresponse. - Universal
envelope_field_presentstoryboard check is unchanged and still enforces top-levelstatusat the runner layer for the two carve-outs. The gap is annotated, not silent. minorchangeset severity matches #4876's precedent for the symmetric envelope-level change. Required-field promotion on responses is buyer-tolerant / seller-emit-tightening, which is the AdCP convention forminorduring a beta train.ad-tech-protocol-expert: sound-with-caveats — the fold is correct, severity is right, carve-out is sound but leaves a known false-pass oncheck_governance(astatus: "approved"body field passes per-task but fails envelope task-status enum). The body-rename follow-up is the close.code-reviewer: sound — no functional defects. Flags the em-dash →—Unicode escape churn and a fixture comment opportunity.audit-oneof.mjswalker walks top-leveloneOffor variant discrimination and does not traverseallOfsiblings — composing envelope refs alongside existing top-leveloneOf(e.g.,account/get-account-financials-response.json,brand/search-brands-response.json) does not change variant fingerprints. No regression expected; confirm on CI.
Follow-ups (non-blocking — file as issues)
- Body-status rename on the governance carve-outs.
check_governanceandreport_plan_outcomebodystatus→verdict/decisionis the close on the carve-out. Should be a hard 3.1-GA blocker with a milestone label, not a fire-and-forget. Until it lands, a conformantcheck_governanceresponse is non-conformant against the envelope — the exact class of split-validation seam this PR is removing elsewhere. - SDK companion release coupling. PR description notes #4877 must ship with this for
@adcp/client's auto-registeredget_adcp_capabilitieshandler. Coordinate the beta.3 cut so the spec and the SDK land together; otherwise current adopters become non-conformant against the per-task validator instantly. - Carve-out
$commentbreadcrumbs. Add an inline$commenton the four carve-out schemas explaining why the envelope ref is absent. Right now the rationale lives only in the PR body and changeset; once merged, a maintainer runninggrep -L protocol-envelopehas no on-schema explanation. - Test fixture annotation.
tests/composed-schema-validation.test.cjs:519usesstatus: 'accepted'on thereport_plan_outcomefixture — the body-status enum value. Add a comment pointing at the body-rename follow-up so a future reader doesn't "fix" this by flipping it tocompletedand lose the body-status assertion.
Minor nits (non-blocking)
- Em-dash →
—Unicode escape churn acrossstatic/schemas/source/**/*-response.json. Serializer artifact (likelyjson.dumps(..., ensure_ascii=True)or equivalent), affects ~200 lines of unrelated description text. No-op for JSON parsers, but bloats the diff and breaks byte-level fingerprints for downstream consumers (content-addressed schema stores, codegen output diffs). Re-run the serializer withensure_ascii=Falseif you re-roll for any reason — not worth a force-push on its own.
Approving on the strength of the carve-out completeness check and the precedent set by #4876.
|
Holding this PR pending #4877 (SDK companion) landing in The failing CI check ( The training agent ( Sequencing:
The fold itself is sound (all schema-relevant test suites pass: test:schemas 8/8, test:examples 36/36, test:json-schema 270/270, test:composed 43/43, test:storyboard-response-schema). Only the SDK-rendered-response check fails — which is exactly the contract we just locked, and exactly what #4877 is in flight to deliver. Cross-linking #4877 so the publish event is visible from here. |
…report_plan_outcome (#4897) (#4902) Frees the top-level `status` key for envelope task-status (TaskStatus) under MCP flat-on-the-wire serialization. The body-level governance field and the envelope share a root key but carry different enums; whichever wins on the wire, the other is silently destroyed and no validator catches it. WG-recommended Option A per the issue triage (both ad-tech-protocol-expert and adtech-product-expert): - check-governance-response.json: status → verdict (enum unchanged: approved | denied | conditions). Updates the three if/then discriminator blocks, the required[], and prose threads on findings/conditions/expires_at. - report-plan-outcome-response.json: status → outcome_state (enum unchanged: accepted | findings). Updates required[] and the findings prose thread. - get-plan-audit-logs-response.json: entries[].status → entries[].verdict (cascade for vocabulary consistency with check-governance-response). Other status fields on the same response (plans[].status, governed_actions[].status) are lifecycle states, not verdicts — left unchanged. Docs swept (~25 example bodies + table descriptions + prose): - docs/governance/overview.mdx - docs/governance/campaign/tasks/{check_governance,report_plan_outcome,get_plan_audit_logs}.mdx - docs/governance/campaign/{audit-trail,specification}.mdx - docs/reference/whats-new-in-3-1.mdx (migration note in Final-spec clarifications batch) Storyboards swept — the triage scoped this as "no yaml renames needed" but during implementation found four storyboards with field_present / field_value assertions keyed on path: "status" against check-governance-response. Updated to path: "verdict": - specialisms/governance-spend-authority/{index,denied}.yaml - specialisms/governance-delivery-monitor/index.yaml - protocols/governance/index.yaml (plus a stale expected block referencing status: recorded — not in the enum — corrected to outcome_state: accepted) Test fixture: composed-schema-validation report_plan_outcome case updated to use outcome_state. Adopter impact: wire-shape change on three experimental governance schemas (x-status: experimental). Buyers and sellers rename one property name per emitter / consumer; enum values unchanged. SDK regen required. Related: - #4876 — envelope status REQUIRED (beta.2) - #4895 — companion media-buy collision (separate PR) - #4896 — per-task envelope fold; carve-outs for these two schemas can be removed once this lands Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes #4878. Companion to #4876 (envelope `status` REQUIRED) — that PR locked the contract on the envelope schema; this PR cascades it to every per-task response schema so per-task `response_schema` validators catch envelope omissions directly, without relying on the separate `envelope_field_present` storyboard check.
What changed
64 task response schemas now extend `protocol-envelope.json` in their `allOf` chain alongside the existing `version-envelope.json` ref. Two schemas without an existing `allOf` (`brand/search-brands-response.json`, `creative/validate-input-response.json`) had `allOf` added with both envelope refs for consistency.
Carve-outs (4 schemas excluded from fold)
Nested helpers, not task responses:
Body-level `status` enum collisions with envelope status:
On MCP flat serialization both occupy the same root-level `status` key. Tracked as a separate spec issue (body-status rename to `verdict` / `decision` before 3.1 GA — filing follow-up).
What this catches
Pre-3.1-GA, any response shape lacking top-level envelope `status` now fails its own per-task `response_schema` validator, not just the universal `envelope_field_present` storyboard step. Validators integrated against the per-task schema (typed-SDK codegen, request-replay tooling, schema-aware test fixtures) gain envelope coverage for free.
Cleanup also applied (same PR)
The fold surfaced 87+ places where `status` was missing on examples / test fixtures / doc snippets:
Validation
The one pre-existing failure in `test:storyboard-sample-request-schema` is from #4810's `native_in_feed.yaml` (`impression_tracker oneOf`) and is unrelated to this PR — verified by stashing my changes and re-running.
Adopter impact
statuson auto-registered get_adcp_capabilities handler #4877; until that lands, adopter conformance against the per-task schema validators will fail. Both PRs should ship together in beta.3.Diff size
98 files / +971 / -306. Per [[feedback_diff_stat_sanity_check]] I verified the diff matches the expected breakdown:
Related
statuson every task response envelope (closes #4832) #4876 — envelope status REQUIRED (merged in beta.2)statuson auto-registered get_adcp_capabilities handler #4877 — adcp-client SDK companion (sibling repo, in flight)