Skip to content

feat(decisioning): CampaignGovernancePlatform Protocol (breadth sprint Batch 3)#334

Merged
bokelley merged 1 commit intomainfrom
bokelley/decisioning-governance-protocols
May 1, 2026
Merged

feat(decisioning): CampaignGovernancePlatform Protocol (breadth sprint Batch 3)#334
bokelley merged 1 commit intomainfrom
bokelley/decisioning-governance-protocols

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented May 1, 2026

Summary

Breadth sprint Batch 3 — ports the governance-agent Protocol from JS reference at `src/lib/server/decisioning/specialisms/campaign-governance.ts`.

New:

  • `CampaignGovernancePlatform` — covers `governance-spend-authority` (spend gating) and `governance-delivery-monitor` (delivery monitoring). Both are governance-AGENT roles sharing the same Protocol surface (per JS guidance + spec issue `adcp#3329` consolidating both to a single `campaign-governance` slug eventually). Required methods: `check_governance`, `sync_plans`, `report_plan_outcome`, `get_plan_audit_logs`. All sync at the wire level.
  • REQUIRED_METHODS entries for the two governance-AGENT slugs.
  • Public exports in `adcp.decisioning.all`.

Architectural distinction (load-bearing): the spec's third governance slug `governance-aware-seller` names a SELLER claim (sales-* archetype that composes with a governance agent via `sync_governance` + `check_governance`). It does NOT implement CampaignGovernancePlatform — it integrates WITH a platform that does. Stays UNENFORCED in `REQUIRED_METHODS_PER_SPECIALISM` until sync_governance handler shim wiring lands for sales adopters. All three governance-* slugs remain in `GOVERNANCE_SPECIALISMS` for the foundation's governance-aware security gate.

SECURITY GATE PRESERVED. The foundation's `validate_platform` already fails-fast when any `governance-*` slug is claimed without `capabilities.governance_aware=True`. Required-method enforcement (this PR) and governance-aware enforcement (foundation) are INDEPENDENT gates; both fire. New regression test `test_governance_security_gate_independent_of_required_methods` pins this — a platform with all four governance methods present but `governance_aware=False` STILL fails server boot.

Test plan

  • 6 new tests in `tests/test_decisioning_specialisms.py` (30 total in file): runtime_checkable conformance, required-method enforcement, happy path, security regression guard, shared-method-set pin, architectural distinction pin
  • 2 existing tests updated in `test_decisioning_dispatch.py` (switched canonical "governance-aware test slug" from `governance-spend-authority` (now method-enforced) to `governance-aware-seller` (still unenforced) — keeps the tests isolated to the security gate)
  • `pytest tests/` — 2239 passed (up from 2233)
  • `mypy src/adcp/decisioning/` clean
  • Pre-commit gates pass

Remaining breadth-sprint queue

  • `BrandRightsPlatform`
  • `ContentStandardsPlatform`
  • `PropertyListsPlatform`
  • `CollectionListsPlatform`
  • (`governance-aware-seller` sync_governance handler shim wiring)

Release plan

Accumulates into the held release-please PR #328 alongside foundation (#316), codemod ergonomics (#329), parity rename (#330), F12 (#331), Signals/Audience (#332), and Creative Protocols (#333). Seven PRs ship together in 4.4.0 once salesagent validates.

🤖 Generated with Claude Code

…t Batch 3)

Third batch of the breadth-sprint per the parity audit. Ports the
governance-agent Protocol from JS reference at
``src/lib/server/decisioning/specialisms/campaign-governance.ts``.

New Protocol:

* ``CampaignGovernancePlatform``
  (src/adcp/decisioning/specialisms/governance.py) — covers
  ``governance-spend-authority`` (gates spending decisions) AND
  ``governance-delivery-monitor`` (monitors delivery actuals). Both
  are governance-AGENT roles sharing the same Protocol surface.
  When ``adcontextprotocol/adcp#3329`` lands and the spec
  consolidates to a single ``campaign-governance`` slug, the
  underlying type stays unchanged — only the slug map updates.

  Required: ``check_governance``, ``sync_plans``,
  ``report_plan_outcome``, ``get_plan_audit_logs``. All sync at
  the wire level (no Submitted arms in the response schemas);
  slow approval pipelines return current state and emit
  ``ctx.publish_status_change(resource_type='plan', ...)`` when
  the operator decision lands.

Architectural distinction (load-bearing): the spec's third
governance slug, ``governance-aware-seller``, names a SELLER claim
— a sales-* archetype that composes with a governance agent
(accepts ``sync_governance``, calls ``check_governance`` before
confirming spend). It does NOT implement
CampaignGovernancePlatform; it integrates WITH a platform that
does. So ``governance-aware-seller`` stays UNENFORCED in
``REQUIRED_METHODS_PER_SPECIALISM`` — no method-coverage rule —
until sync_governance handler shim wiring lands for sales adopters.
All three governance-* slugs remain in ``GOVERNANCE_SPECIALISMS``
for the foundation's governance-aware security gate.

SECURITY GATE PRESERVED. The foundation's
``validate_platform`` already fails-fast when any
``governance-*`` slug is claimed without
``capabilities.governance_aware=True``. Required-method enforcement
(this PR) and governance-aware enforcement (foundation) are
INDEPENDENT gates; both fire. The security regression test
``test_governance_security_gate_independent_of_required_methods``
pins this — a platform with all four governance methods present
but ``governance_aware=False`` STILL fails server boot. Without
this invariant, a method-coverage-satisfying adopter could silently
skip the governance security gate.

Public re-exports added at ``adcp.decisioning.__all__``:
``CampaignGovernancePlatform``.

Test coverage in ``tests/test_decisioning_specialisms.py`` (6 new
tests, 30 total in the file):

* ``runtime_checkable`` conformance.
* Required-method enforcement against partial impls.
* Happy path: complete governance platform with
  ``governance_aware=True`` passes both gates.
* SECURITY REGRESSION GUARD: complete impl with
  ``governance_aware=False`` STILL fails (independent gates).
* Contract pin for shared method set across the two governance-AGENT
  slugs.
* Architectural distinction pin: ``governance-aware-seller`` is in
  ``GOVERNANCE_SPECIALISMS`` (governance-aware gate) but NOT in
  ``REQUIRED_METHODS_PER_SPECIALISM`` (no method coverage).

Two existing tests in ``test_decisioning_dispatch.py`` updated:
their canonical "governance-aware test slug" switched from
``governance-spend-authority`` (now method-enforced) to
``governance-aware-seller`` (still unenforced — keeps the tests
isolated to the governance-aware security gate).

Remaining specialism Protocols (brand-rights, content-standards,
property-lists, collection-lists) are queued for subsequent
breadth-sprint PRs.

2239 tests pass (up from 2233).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit 2ca828a into main May 1, 2026
12 checks passed
bokelley added a commit that referenced this pull request May 1, 2026
…ionLists Protocols (breadth sprint Batch 4 — FINAL) (#335)

Final batch of the breadth-sprint per the parity audit. Ports the
remaining four specialism Protocols from JS reference. With this
PR, every spec specialism slug except ``governance-aware-seller``
has a Protocol class + REQUIRED_METHODS coverage.

New Protocols:

* ``BrandRightsPlatform`` — covers ``brand-rights``. Identity
  discovery + licensing. Required (3, sync): ``get_brand_identity``,
  ``get_rights``, ``acquire_rights``. ``acquire_rights`` returns a
  3-arm discriminated success union (acquired / pending / rejected)
  — rejection-as-data for spec-defined GRANT rejection, AdcpError
  only for buyer-fixable REQUEST rejection. Async outcomes for the
  ``pending`` arm flow via ``push_notification_config`` webhook
  (NOT a polling tool).

* ``ContentStandardsPlatform`` — covers ``content-standards``.
  Brand safety policies, content adjacency rules, per-creative
  compliance verification. Required (6): list/get/create/update,
  ``calibrate_content``, ``validate_content_delivery``. Optional
  (2, analyzer reads): ``get_media_buy_artifacts``,
  ``get_creative_features``.

* ``PropertyListsPlatform`` + ``CollectionListsPlatform``
  (specialisms/lists.py) — covers ``property-lists`` and
  ``collection-lists``. Parallel CRUD shapes (5 methods each, all
  required) with token-issuance semantics: ``create_*`` returns a
  per-seller-scoped ``fetch_token``, ``delete_*`` revokes it.
  Compromise-driven revocation MUST trigger the delete path.

Required-method coverage in ``REQUIRED_METHODS_PER_SPECIALISM``:
``brand-rights`` (3), ``content-standards`` (6),
``property-lists`` (5), ``collection-lists`` (5).

Public re-exports added at ``adcp.decisioning.__all__``:
``BrandRightsPlatform``, ``ContentStandardsPlatform``,
``PropertyListsPlatform``, ``CollectionListsPlatform``.

Test coverage in ``tests/test_decisioning_specialisms.py`` (13 new
tests, 43 total in the file):

* ``runtime_checkable`` conformance per Protocol.
* ``validate_platform`` enforcement per slug — including a
  security-relevant test that ``property-lists`` REQUIRES
  ``delete_property_list`` (revocation path) so adopters can't ship
  list-publishing without revocation primitives.
* Contract pins per slug.
* **Breadth-sprint completeness pin**:
  ``test_every_spec_slug_except_governance_aware_seller_is_enforced``
  asserts that ``SPEC_SPECIALISM_ENUM - REQUIRED_METHODS.keys()``
  yields exactly ``{governance-aware-seller, signed-requests}`` —
  the two slugs unenforced by design (composition claim and
  deprecated-moved-to-universal respectively).

One existing dispatch test updated:
``test_validate_platform_warns_on_unenforced_spec_specialism``
swapped its canonical "spec-recognized but unenforced" example
from ``brand-rights`` (now enforced) to ``governance-aware-seller``
(the only remaining unenforced spec slug — by design).

**Breadth sprint COMPLETE.** All 8 missing specialism Protocols
from the parity audit are now ported. 9 PRs total accumulating in
the held release PR #328:

* #316 foundation
* #329 codemod ergonomics
* #330 parity rename + Tier 1 docs
* #331 F12 auto-emit
* #332 Signals + Audience (Batch 1)
* #333 Creative Builder + AdServer (Batch 2)
* #334 Campaign Governance (Batch 3)
* #335 Brand + Content + Lists (Batch 4 — this PR)

Ready for salesagent validation against editable install before
tagging 4.4.0.

2252 tests pass (up from 2239).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant