fix(compliance): correct wire-placement assertions in governance denial storyboards#4004
Conversation
…al storyboards The brand_rights/governance_denied scenario previously asserted expect_error: true + error_code: GOVERNANCE_DENIED on acquire_rights. Per the GOVERNANCE_DENIED wire-placement rule (landed in #3929), tasks with a structured rejection arm must use that arm — not errors[]. The AcquireRightsRejected arm is enforced at the schema layer via not: { required: [errors] }, so the prior test was grading a schema-violating response shape as passing. Fix the scenario to assert the correct Case-1 shape: - expected_arm: rejected (paths resolution scoped to Rejected arm) - check: response_schema (catches not: { required: [errors] } violation) - check: field_value status = rejected - check: field_present reason - check: field_absent errors - Transport at HTTP 200 / MCP isError: false (not an error response) Also document the Case-2 placement rule in the media_buy_seller/ governance_denied description: create_media_buy has no rejection arm, so GOVERNANCE_DENIED surfaces via error_code (errors[].code or adcp_error.code). Closes #3998 https://claude.ai/code/session_01QW7uzhT3g9LEVMX9y6Ew1R
|
Audit pass complete (per request before merge). Surveyed every storyboard mentioning
The two files this PR touches are the only governance-denial storyboards that needed wire-placement corrections. Adjacent finding (out of scope): the |
15c4b96 to
2c02215
Compare
|
Audit confirmed — the two files this PR touches are the only governance-denial storyboards that needed wire-placement corrections. Scope is clean. Adjacent finding noted ( Generated by Claude Code |
Closes #3998
Summary
The
brand_rights/governance_deniedstoryboard scenario was assertingexpect_error: true+check: error_code, value: GOVERNANCE_DENIEDonacquire_rights. Per the GOVERNANCE_DENIED wire-placement rule (landed in #3929), tasks that define a structured rejection arm MUST use that arm — noterrors[].AcquireRightsRejectedcarriesnot: { required: [errors] }at the schema layer, so the prior storyboard was grading a schema-violating response shape as passing for any brand agent that had run thebrand_rightsspecialism suite.What changes:
brand_rights/scenarios/governance_denied.yaml— fixes Case 1 (acquire_rights):expect_error: trueandnegative_path: payload_well_formedexpected_arm: "rejected"for correct path-resolution lint scopingcheck: error_code, value: GOVERNANCE_DENIEDwith rejection-arm assertions:check: response_schema— enforcesnot: { required: [errors] }on the Rejected armcheck: field_value path: status value: rejected— arm discriminatorcheck: field_present path: reason— governance findings propagatedcheck: field_absent path: errors— explicit dual-emission guardcheck: field_value path: context.correlation_id— context echomedia-buy/scenarios/governance_denied.yaml— documents Case 2 (create_media_buy):expected:block to document the Case-2 wire-placement rule explicitly (no rejection arm →errors[].code+adcp_error.code, transport failure markers flip)error_codedescription to reference the two-layer modelNon-breaking justification: Both changes are purely in storyboard YAML assertions. They correct incorrect test expectations to match spec-required behavior; no schema, task definition, or protocol surface is changed.
Case 3 (negative/violation test) — deferred: The issue also requested a fixture that populates both the rejection arm AND
errors[]and asserts schema validation rejects it. This cannot be implemented as a live storyboard step (the runner has no mechanism to force a seller to emit an invalid response shape). It belongs as a test vector instatic/compliance/source/test-vectors/acquire-rights-response/negative/and is tracked for a follow-up.Pre-PR review:
adcp_error absenton rejection-arm responses is normative perprotocol-envelope.json;expected_arm: "rejected"added per authoring guidefield_absentis inauthored_check_kinds;field_present: errorsdropped from media-buy scenario in favor of the existing shape-agnosticerror_codecheckSession: https://claude.ai/code/session_01QW7uzhT3g9LEVMX9y6Ew1R
Generated by Claude Code