Context
adcontextprotocol/adcp#4058 adds a new normative cascade_rules section to runner-output-contract.yaml (bumping it 2.0.0 → 2.1.0). The TS SDK already conforms (adcp-client#1146, #1545). This Python SDK runner needs to catch up.
What changed in the contract
A new MUST: when a phase contains a sole stateful step that grades not_applicable, missing_tool, or missing_test_controller, and no same-phase peer declares provides_state_for, downstream phases MUST evaluate independently (i.e., the cascade is suppressed).
default_cascade enumerates the trigger set (passed:false, prerequisite_failed, unsatisfied_contract, peer_branch_taken) and the non-trigger set (peer_substituted, plus the new exemption).
Why it matters
Until this Python runner implements the exemption, the same storyboard graded against the same adopter via TS vs Python produces different cascade outcomes for sole-stateful-step skips. Vendors running comply through both runners will see grade divergence on this edge case.
Acceptance criteria
References
Context
adcontextprotocol/adcp#4058 adds a new normative
cascade_rulessection torunner-output-contract.yaml(bumping it 2.0.0 → 2.1.0). The TS SDK already conforms (adcp-client#1146, #1545). This Python SDK runner needs to catch up.What changed in the contract
A new MUST: when a phase contains a sole stateful step that grades
not_applicable,missing_tool, ormissing_test_controller, and no same-phase peer declaresprovides_state_for, downstream phases MUST evaluate independently (i.e., the cascade is suppressed).default_cascadeenumerates the trigger set (passed:false,prerequisite_failed,unsatisfied_contract,peer_branch_taken) and the non-trigger set (peer_substituted, plus the new exemption).Why it matters
Until this Python runner implements the exemption, the same storyboard graded against the same adopter via TS vs Python produces different cascade outcomes for sole-stateful-step skips. Vendors running comply through both runners will see grade divergence on this edge case.
Acceptance criteria
cascade_rulesfrom the contract YAMLpassed:false,prerequisite_failed,unsatisfied_contract,peer_branch_taken(no regression)peer_substitutedcontinues to not cascade (no regression)provides_state_forpeer → cascade still firesversion: 2.1.0accepted by parserReferences