Skip to content

fix(storyboards): rename divergent plan id + seed missing products#2899

Merged
bokelley merged 7 commits into
mainfrom
bokelley/storyboard-seed-alignment
Apr 23, 2026
Merged

fix(storyboards): rename divergent plan id + seed missing products#2899
bokelley merged 7 commits into
mainfrom
bokelley/storyboard-seed-alignment

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

Two more seed-fixture alignment fixes, following the pattern of #2894.

Changes

  • governance-spend-authority/index.yaml — rename governance plan from gov_acme_q2_2027 to gov_acme_spend_authority_q2_2027. protocols/governance/index.yaml already seeded a completely different plan under the same id ($100K vs $50K budget, different flight, different policies). The SDK's seed store refused the second replay with:

    INVALID_PARAMS: Fixture for seed_plan:gov_acme_q2_2027 diverges from the previously seeded fixture

  • governance-delivery-monitor/index.yaml — add products: + pricing_options: for outdoor_display_q2 and outdoor_video_q2. Both are referenced by the storyboard's create_media_buy packages but weren't seeded. Values match the canonical seed in protocols/governance/index.yaml.

Storyboard lift

Run locally against the overlaid compliance cache:

mode clean (before → after) passing steps (before → after)
legacy 44 → 46 362 → 373
framework 38 → 39 362 → 372

Test plan

  • Local dual-mode storyboard run against overlaid cache
  • Storyboards CI (legacy + framework) with raised baselines

🤖 Generated with Claude Code

Two more seed-fixture alignment fixes post-adcp-client#794:

- governance-spend-authority: rename plan_id gov_acme_q2_2027 to
  gov_acme_spend_authority_q2_2027. protocols/governance/index.yaml
  already seeded a semantically different plan under the same id
  (different budget / flight / policies). Unique ids per plan.
- governance-delivery-monitor: add products + pricing_options for
  outdoor_display_q2 and outdoor_video_q2 — referenced by the
  storyboard's create_media_buy packages but previously absent.

Storyboard lift (against overlaid compliance cache): legacy
44 → 46 clean, framework 38 → 39 clean.
… modes

Close five more storyboard failures shared across legacy + framework:

- comply_test_controller: allow creative approved→rejected transition.
  force_creative_rejected tests post-approval brand-safety rejection;
  the prior transition map only allowed pending_review→rejected.
- list_creatives: always emit `name` + `format_id.agent_url`. Falls
  back to creative_id for name and own agent URL for agent_url when a
  caller's sync_creatives payload omits them (SDK request builders
  occasionally drop agent_url; buyer may omit name). Keeps the
  response-schema assertion valid regardless of what was synced.
- calibrate_content: sandbox heuristic that scans the artifact text
  for must-rule keywords (violent, gambling, alcohol, stock photo,
  missing alt text) and returns verdict: fail when a match hits.
  Previously always returned pass, so both calibrate_must_violation
  and calibrate_after_policy_change asserted fail vs. got pass.
- log_event / provide_performance_feedback: cross-session fallback
  lookup. Framework-path tools strip `account` against the SDK's
  auto-generated input schema, so log_event / provide_feedback land
  on the open:default session while sync_event_sources /
  create_media_buy wrote under open:<brand.domain>. Scan all
  persisted sessions as a fallback so the synced entity is still
  reachable.

Storyboard tightening on the spec side:

- brand_baseline/get_capabilities: drop `array_contains` validation
  (SDK doesn't implement the check) and use field_present on
  supported_protocols instead; response_schema already validates the
  enum membership.
- brand_baseline/get_brand_identity_unknown: swap `is_error`
  (unimplemented) for `error_code` with allowed_values covering
  brand_not_found / BRAND_NOT_FOUND / NOT_FOUND.
- brand_rights/get_rights: capture the first pricing_options entry as
  $context.pricing_option_id and reference it in acquire_rights
  instead of hard-coding `standard_monthly` (which no agent offering
  exposes — every pricing_option lives under the returned rights row).

Lift (overlay against compliance cache): legacy 44 → 50 clean,
framework 38 → 44 clean. Residual 9 failures are split between two
SDK invariants (create_media_buy_retry / _relaxed_terms run-wide
denial-blocks-mutation) and framework-only handler gaps
(check_governance conditions, report_plan_outcome outcome_id,
acquire_rights_denied error code, create_media_buy replayed field,
log_event/log_events session lookup).
The CREATIVE_TRANSITIONS map now allows approved→rejected (post-approval
brand-safety flagging is a real lifecycle edge). Update the test that
previously asserted INVALID_TRANSITION: the call now surfaces
INVALID_PARAMS because a rejection without rejection_reason is the
actual failure mode. Add a companion test for the success path with
a reason supplied.
…cp/client 5.13

- Bump @adcp/client to ^5.13.0 (brings the governance.denial_blocks_mutation
  recovery-path fix from adcp-client#813; closes media_buy_seller
  /governance_denied_recovery and /measurement_terms_rejected).
- Storyboard CI overlay step: resolve the cache dir dynamically
  (5.13 switched from `latest` to the AdCP version string).
- state.ts: add findSessionMatching + per-entity wrappers
  (findMediaBuyAcrossSessions, findGovernancePlanAcrossSessions) so
  handlers whose tool schemas strip `account` can still reach state
  written by earlier steps that kept account context.
- governance-handlers.ts: fall back to a cross-session scan in
  handleCheckGovernance and handleReportPlanOutcome when the primary
  session key misses the plan.
- brand-handlers.ts: handleAcquireRights falls back the same way so
  brand_rights/governance_denied propagates GOVERNANCE_DENIED even when
  sync_plans wrote under a different session key.
- catalog-event-handlers.ts: handleLogEvent auto-registers unknown
  event_source_ids for sandbox permissiveness (sales_social doesn't
  call sync_event_sources; the buyer assumes out-of-band setup).
- framework-server.ts: wrap successful handler responses with
  wrapEnvelope({ replayed: false, context }) so idempotency and
  context echo fields land on the AdCP envelope per spec.

Storyboard lift against overlaid compliance cache:
legacy 44 → 52 clean, framework 38 → 51 clean.
@bokelley bokelley merged commit 9ff373e into main Apr 23, 2026
14 checks passed
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