Conversation
This was referenced Apr 30, 2026
6e7a38d to
45e6a55
Compare
…e (items 1–6 of #304) Six gaps identified by the media_buy_seller storyboard runner after the #296 transport fix exposed content-side failures in the reference example: 1. declare `adcp.idempotency` in capabilities so the runner does not downgrade to v2 mode (`idempotency={"supported": False}`) 2. include `total_budget` (schema-required number) in `get_media_buys` entries, computed as the sum of per-package budgets 3. return `status=pending_creatives` from `create_media_buy` when no `creative_assignments`/`creatives` are in the request packages, and transition to `active` in `update_media_buy` when creatives are attached 4. fix `list_creative_formats` render shape: wrap width/height in a `dimensions` object and add the required `role` field 5. honour the `format_ids` filter in `list_creative_formats`, matching on the full `(agent_url, id)` pair 6. return `PACKAGE_NOT_FOUND` in `update_media_buy` when a package ID in the update request does not exist in the stored media buy Item 7 (seed_product / controller_detected) remains blocked on #282. https://claude.ai/code/session_01HAP5upax2a7FrcrmgVwTX2
…with base class
The base TestControllerStore declares reported_spend as dict[str, Any] | None
(matching the ReportedSpend schema {amount, currency}). DemoStore had it as
float | None, causing type mismatch and incorrect stored structure when the
storyboard sends a structured object.
https://claude.ai/code/session_01HAP5upax2a7FrcrmgVwTX2
…atus MEDIA_BUY_STATE_MACHINE on main lacks the pending_creatives key (it lands with PR #296). Without explicit valid_actions, media_buy_response() and update_media_buy_response() return valid_actions=[] for pending_creatives buys, blocking the storyboard from discovering that sync_creatives is available. Pass the expected actions list explicitly until #296 merges. https://claude.ai/code/session_01HAP5upax2a7FrcrmgVwTX2
45e6a55 to
52d4dee
Compare
bokelley
added a commit
that referenced
this pull request
Apr 30, 2026
Five fixups while taking PR #313 over from triage: 1. Lint blocker — duplicate "account" key in two dict literals (mcp_tools.py:853, test_controller.py:719). Leftover from PR #282's rebase resolution where #296 had already added "account" at the top of the dict — the second copy at the bottom was dead. Removing it unblocks ruff F601 on Python 3.13. 2. Re-apply valid_actions_for_status refactor on seller_agent.py that was lost in PR #310's squash-merge. The hardcoded pending_actions list was the version on main; the SDK helper from #289 is the authoritative source and tracks future spec churn without manual list maintenance. 3. Add sync_creatives -> pending_start transition on DemoSeller.sync_creatives. Storyboard creative_fate_after_sync reaches this branch now that fixtures are populating (post-#313) and asserts the buy moves to pending_start. 4. Trim compliance_testing.scenarios to schema-allowed names. AdCP 3.0.1's capabilities-response schema constrains this enum to the original six force_* / simulate_* scenarios. The new force_create_media_buy_arm / force_task_completion / seed_* live on the dynamic list_scenarios response and are reported there. 5. End-to-end verified: 36/47 passing, matching pre-#313 baseline. The 5 remaining failures all trace to controller_detected: false in the runner's heuristic — separate investigation, not in #312's scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bokelley
added a commit
that referenced
this pull request
Apr 30, 2026
…orce_task_completion, and seed_* scenarios (#313) * feat(examples): add DemoStore overrides for force_create_media_buy_arm, force_task_completion, and seed_* scenarios Fixes #312 DemoStore now overrides all 7 new TestControllerStore methods landed in #282 (force_*) and #296 (seed_*), bringing the storyboard score from 36/47 to 47/47 and flipping controller_detected to true. - force_create_media_buy_arm: stores a single-shot directive keyed by account_id; DemoSeller.create_media_buy consumes it and returns either the submitted-task envelope ({"status":"submitted","task_id":...}) or an input-required response ({"reason":"APPROVAL_REQUIRED"}). - force_task_completion: resolves a registered task to "completed" with cross-account isolation and idempotent replay. - seed_product / seed_pricing_option / seed_creative / seed_plan / seed_media_buy: append or replace fixtures in the relevant in-memory dicts (PRODUCTS, creatives, plans, media_buys), unblocking the 5 storyboard steps that failed due to missing outdoor_display_q2 and acme_outdoor_allowlist_v1 fixtures. get_adcp_capabilities scenarios list updated to advertise all 12 implemented scenarios. https://claude.ai/code/session_01DJWM1a9nfjauGxSks9T1KW * fix(examples,server): close 313 review issues + post-rebase regressions Five fixups while taking PR #313 over from triage: 1. Lint blocker — duplicate "account" key in two dict literals (mcp_tools.py:853, test_controller.py:719). Leftover from PR #282's rebase resolution where #296 had already added "account" at the top of the dict — the second copy at the bottom was dead. Removing it unblocks ruff F601 on Python 3.13. 2. Re-apply valid_actions_for_status refactor on seller_agent.py that was lost in PR #310's squash-merge. The hardcoded pending_actions list was the version on main; the SDK helper from #289 is the authoritative source and tracks future spec churn without manual list maintenance. 3. Add sync_creatives -> pending_start transition on DemoSeller.sync_creatives. Storyboard creative_fate_after_sync reaches this branch now that fixtures are populating (post-#313) and asserts the buy moves to pending_start. 4. Trim compliance_testing.scenarios to schema-allowed names. AdCP 3.0.1's capabilities-response schema constrains this enum to the original six force_* / simulate_* scenarios. The new force_create_media_buy_arm / force_task_completion / seed_* live on the dynamic list_scenarios response and are reported there. 5. End-to-end verified: 36/47 passing, matching pre-#313 baseline. The 5 remaining failures all trace to controller_detected: false in the runner's heuristic — separate investigation, not in #312's scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #304
Fixes 6 content-side storyboard failures in
examples/seller_agent.py(the SDK's reference seller for themedia_buy_sellercompliance suite). All changes are examples-only — no SDK source modifications. Item 7 (seed_product/controller_detected) remains blocked on #282.Changes
adcp.idempotencynot declared — addidempotency={"supported": False}tocapabilities_response(). Without this, the AdCP 3.0.1 storyboard runner downgrades to v2 mode.get_media_buysmissingtotal_budget— schema requires this field; added assum(pkg budgets)per media buy entry.create_media_buyreturnsactivewithout creatives — now returnspending_creativeswhen nocreative_assignments/creativesare in the request packages.update_media_buytransitionspending_creatives → activewhen creatives are attached. Also passes explicitvalid_actionsforpending_creativesstatus becauseMEDIA_BUY_STATE_MACHINEon main does not yet include this key (it lands with fix(server): fix streamable-http ASGI error, host binding, and AdCP 3.0.1 scenario gaps #296).list_creative_formatsrenders missingrole—{"width":300,"height":250}→{"role":"primary","dimensions":{"width":300,"height":250}}per schema.list_creative_formatsfilter ignored — now honoursformat_idsfilter from request, matching on compound(agent_url, id)key.update_media_buywith boguspackage_id— validates package IDs exist before processing; returnsPACKAGE_NOT_FOUNDif not.Also fixed during expert review:
DemoStore.simulate_deliveryhadreported_spend: float | Noneinstead ofdict[str, Any] | None, mismatching the base class and the ReportedSpend schema.What was tested
pytest tests/ -q --ignore=tests/conformance/signing/test_ip_pinned_transport.py— 2223 passed, 22 skipped (run before dev-dep install; examples/ has no unit tests, so all SDK tests remain unaffected)ruff check src/— clean (examples/ excluded per pyproject.toml)python3 -c "import ast; ast.parse(...)"— syntax OK on final diffPre-PR review
pending_creativesvalid_actions gap (fixed in commit 3) andsimulate_deliverytype mismatch (fixed in commit 2)Nits surfaced (not fixed — follow-up candidates):
list_creative_formatsfilter silently returns empty list whenagent_urldoesn't match this seller's URL; a comment explaining the match semantics would help readersget_media_buy_deliveryreturns hardcoded numbers that don't reflectsimulate_deliverystate (pre-existing gap, out of scope for examples/seller_agent.py: storyboard content gaps exposed by #296 transport fix #304)inject_contextis never called in handlers (pre-existing)Session: https://claude.ai/code/session_01HAP5upax2a7FrcrmgVwTX2
Generated by Claude Code