Skip to content

fix(storyboard): skip media-buy context extraction from interim create/update_media_buy envelopes - #3683

Open
Synaeve wants to merge 2 commits into
adcontextprotocol:mainfrom
Synaeve:fix/3682-skip-interim-media-buy-id
Open

Synaeve wants to merge 2 commits into
adcontextprotocol:mainfrom
Synaeve:fix/3682-skip-interim-media-buy-id

Conversation

@Synaeve

@Synaeve Synaeve commented Nov 10, 2026 •

Copy link
Copy Markdown

Summary

The storyboard runner's create_media_buy context extractor recorded context.media_buy_id (and media_buy_status) from any response body, including interim task envelopes (submitted, working, input-required). A schema-valid working envelope can carry media_buy_id (create-media-buy-async-response-working.json is open), so storyboards that use skip_if: "!context.media_buy_id" to detect synchronous completion classified an asynchronous seller as synchronous. update_media_buy shared the same extraction path and is guarded the same way.

This implements option 1 from the issue: interim envelopes contribute nothing to context. It unblocks adcontextprotocol/adcp#8894 (issue adcontextprotocol/adcp#8771), where webhook_emission otherwise false-fails a working seller that echoes media_buy_id.

Changes

  • src/lib/testing/storyboard/context.ts: create_media_buy and update_media_buy return no context when the top-level status is submitted, working or input-required (the runner's poll-eligible set). None of these is a media-buy lifecycle value in any AdCP release, so the check is version-independent. Any other response, including legacy top-level lifecycle statuses, extracts as before.
  • test/lib/context-extractors.test.js: interim envelopes for both tasks (top-level and nested media_buy), a legacy lifecycle status on create, and a response with no status.
  • Patch changeset for @adcp/sdk.

Behaviour change: a seller that answers working with data is not polled, so with this fix its later steps get no context.media_buy_id. That is the intent. An interim update leaves the media_buy_id and media_buy_status recorded by earlier steps untouched instead of overwriting them. A storyboard that needs the id from an asynchronous create can capture it with a task_completion.media_buy_id context output.

Testing

  • node --test test/lib/context-extractors.test.js: 46/46. The interim-envelope tests fail without the fix.
  • Storyboard, context, webhook and task-completion suites (run on the first commit): no failures introduced compared with a baseline run without the fix.
  • npm run typecheck, npm run lint, npm run lint:boundaries clean; commitlint passes.

Closes #3682

🤖 Generated with Claude Code

…ia_buy envelopes

The create_media_buy context extractor recorded media_buy_id and
media_buy_status from any response, including submitted, working and
input-required task envelopes. Storyboards that gate on
context.media_buy_id then treated an asynchronous create as synchronous.

Interim envelopes now contribute nothing to context. Any other response
extracts as before. Storyboards that need the id from an asynchronous
create can capture it with a task_completion.media_buy_id context output.

Closes adcontextprotocol#3682
aao-secretariat[bot]
aao-secretariat Bot previously approved these changes Nov 10, 2026

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve — clean, targeted fix for #3682 with no blocking findings.

What I checked:

  • create_media_buy no longer records provisional media-buy fields from interim task envelopes (submitted/working/input-required), so async sellers stop looking synchronous to storyboards gating on context.media_buy_id.
  • INTERIM_TASK_STATUSES matches runner.ts's POLL_ELIGIBLE_STATUSES exactly; these values are never media-buy lifecycle statuses (confirmed against media-buy-status.ts), so the guard cannot swallow a terminal result.
  • Six new tests cover interim statuses, nested media_buy, and preserved legacy/no-status paths.
  • Changeset present and patch is correctly right-sized for this behavior-preserving fix.

Medium findings:

  • src/lib/testing/storyboard/context.ts:229 — update_media_buy extractor still reads interim envelopes via the identical readMediaBuyFields path with no interim guard, so the same misclassification can land via an interim update envelope.

Single medium finding, no critical/high, not a data-loss/schema/infra category, high_risk is false, gated_paths is false, no team gate. Per decision table this falls through to row 9 — approve. The update_media_buy gap is worth a follow-up but is outside this diff and non-blocking.

Medium findings

  • src/lib/testing/storyboard/context.ts:229 — update_media_buy extractor still reads interim envelopes

@Synaeve Synaeve changed the title fix(storyboard): skip media_buy_id extraction from interim create_media_buy envelopes fix(storyboard): skip media-buy context extraction from interim create/update_media_buy envelopes Nov 10, 2026

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve.

This is a subsequent review. The prior run flagged one medium finding (src/lib/testing/storyboard/context.ts:229 — update_media_buy extractor still reads interim envelopes). That finding is resolved in this delta: both create_media_buy and update_media_buy extractors now delegate to extractTerminalMediaBuyFields, which returns {} for interim task envelopes (submitted/working/input-required), so an async seller no longer appears synchronously complete to storyboards gating on context.media_buy_id. INTERIM_TASK_STATUSES is disjoint from media-buy lifecycle values, so legacy top-level-status and no-status paths still extract — both covered by new tests across both tasks and all three interim statuses.

Changeset present and correctly scoped (patch is appropriate for a storyboard-testing bugfix with no wire-contract change). No new findings this run.

Decision table: no critical/high findings (row 1 n/a); gated_paths false (row 2 n/a); high_risk false (rows 3, 5 n/a); no medium findings (rows 4, 8 n/a); prior decision was approve, not escalate (row 6 n/a); no no-auto-approve team match (row 7 n/a). Falls through to row 9 — approve.

This branch has not been deployed

No deployments
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.

Storyboard runner: create_media_buy context extractor records media_buy_id from interim task envelopes

1 participant