chore: release package#1693
Merged
Merged
Conversation
561be0c to
d4b5d18
Compare
aa09e2f to
05e2291
Compare
5 tasks
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.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@adcp/sdk@7.0.0
Major Changes
e93306c: feat(conform)!: split
storyboards_missing_toolsfromstoryboards_not_applicableinComplianceResultBreaking change:
ComplianceResult.storyboards_not_applicable[]previously included both version-gated and missing-tool coverage gaps. It now contains only version-gated entries. Consumers that check(result.storyboards_not_applicable ?? []).length === 0to assert zero coverage gaps must also checkstoryboards_missing_tools.ComplianceResult.storyboards_not_applicable[]previously conflated two coverage-gap reasons that the AdCP spec'srunner-output-contract.yaml(L249-300) keeps distinct:not_applicable— the agent didn't declare the protocol the storyboard tests (version-gating path).missing_tool— the agent declared the protocol but a required tool was absent from the discovered toolset (introduced by PR fix(conformance): grade storyboards not_applicable when required_tools are missing #1682).Both cases are now surfaced separately:
storyboards_not_applicablekeeps its current semantics but now only contains version-gated entries.storyboards_missing_toolsis new. The combined set is[...storyboards_not_applicable, ...storyboards_missing_tools]— the total coverage gap is unchanged.Migration: Update any consumer that relied on
storyboards_not_applicablealone to detect missing-tool coverage gaps to also checkstoryboards_missing_tools. Per-storyboard tool names (i.e. which tools were missing) are available inComplianceSummaryArtifact.skip_causes;storyboards_missing_toolsis a plainstring[]of storyboard IDs for symmetry withstoryboards_not_applicable.Naming note: The spec's
RunnerSkipReasonenum uses the singularmissing_tool; this field uses the pluralstoryboards_missing_toolsto match thestoryboards_*naming convention.Closes Distinguish storyboard-level
missing_tools[]fromnot_applicable[]in ComplianceResult #1695.Minor Changes
7f21587: feat(client): add
issues[]as first-class field onAdcpErrorInfo(per core/error.json 3.0 GA)AdcpErrorInfonow carriesissues?: AdcpValidationIssue[], populated from the seller'sVALIDATION_ERRORenvelope when present. Previously theissues[]array landed in thefree-form
detailsfield, forcing consumers to readdetails.validation_errorsas aconvention rather than a typed API.
Each
AdcpValidationIssuecarriespointer(RFC 6901 JSON Pointer to the offending field),message(human-readable),keyword(JSON Schema keyword:'required','type','enum',etc. — the key field for LLM self-correction), and optional
schemaPath. Only items thatsatisfy the required-field shape are forwarded; malformed wire items are silently dropped.
ExtractedAdcpError(returned byextractAdcpErrorFromMcp/extractAdcpErrorFromTransport)also gains
issues?: AdcpValidationIssue[]for callers using the transport-level helpersdirectly.
AdcpValidationIssueis exported from the package root.Closes Add
issues[]as first-class field on AdcpErrorInfo (per core/error.json 3.0 GA) #1694.f92d9d9: fix(comply): forward structured adcp_error detail from failed storyboard steps
ComplianceResultnow surfacesadcp_error?: AdcpErrorInfoalongside the existingerror?: stringonComplianceFailureandStoryboardStepResult. Previously,the structured error envelope (code, field, validation_errors) returned by the
agent was silently dropped at the
executeStoryboardTaskboundary — only thehuman-readable string was forwarded.
Consumers (dashboards, LLM self-correction loops) can now read
failure.adcp_error.fieldand
failure.adcp_error.details.validation_errorsdirectly instead of re-running thefailing step to obtain the wire-level detail. Fixes comply() ComplianceResult drops step.error to {} — wire-level INVALID_REQUEST detail lost #1679.
8258e1c: Add
omit_accountescape hatch toStoryboardStepfor schema_validation conformance (Addomit_accountescape hatch for schema_validation storyboards #1696).Follow-up to fix(client): remove account_from_brand fabrication shim in normalizeRequestParams #1683 which removed the
account_from_brandfabrication shim: storyboard steps that deliberately test seller-side missing-account rejection could no longer reach the seller because the SDK's client-sideValidationErrorshort-circuited before the wire call.omit_account?: booleanonStoryboardStepmirrors the existingomit_idempotency_keypattern:applyBrandInvariantskips both the synthetic-account-construction branch and the natural-key-merge branch for the step.normalizeRequestParamsandvalidateRequestskip theaccount-required check (skipAccountValidationoption onTaskOptions).Without this escape hatch, conformance cannot grade "does the seller reject a missing-account
create_media_buy?" because the client-side throw hides the spec contract from the grader.8fbae3f: Add the
parallel_dispatch_runnertest-kit contract and swap the in-flight branch toIDEMPOTENCY_IN_FLIGHT(parallel_dispatch_runner: implement the storyboard runner contract for concurrent-retry tests (rule 9) #1686, @adcp/sdk middleware: return IDEMPOTENCY_IN_FLIGHT instead of SERVICE_UNAVAILABLE on the in-flight branch #1687).Storyboard runner (parallel_dispatch_runner: implement the storyboard runner contract for concurrent-retry tests (rule 9) #1686):
parallel_dispatchstep field: fans out N concurrent dispatches against the same agent (process_local mode, viaPromise.all) and grades the cross-response set. Drives the AdCP 3.1 concurrent-retry phase of the idempotency storyboard (rule 9 / first-insert-wins).cross_response_field_equal { path }— every resolved dispatch carries the same value at the named path.cross_response_count_distinct { path, allowed_values }— distinct cardinality across resolved dispatches is inallowed_values. Useallowed_values: [1]to assert "exactly one resource created" on a race.IDEMPOTENCY_IN_FLIGHTor legacySERVICE_UNAVAILABLEretry with the sameidempotency_keyafter the seller'sretry_afterhint elapses, up to the per-dispatch retry budget and the outerbarrier_timeout_ms(default 5000 ms).response_schema,field_present,error_code, …) run once per dispatch and aggregate. Cross-response checks run once with the resolved set.not_applicablewhen theparallel_dispatch_runnercontract is not inoptions.contracts, whenmode: distributedis requested (out of scope for this SDK), or on a single-dispatch step that accidentally declared across_response_*check.not_applicableper the existing runner-output-contract behavior.Server middleware (@adcp/sdk middleware: return IDEMPOTENCY_IN_FLIGHT instead of SERVICE_UNAVAILABLE on the in-flight branch #1687):
IDEMPOTENCY_IN_FLIGHT(AdCP 3.1 wire code) instead ofSERVICE_UNAVAILABLE, withrecovery: transient. Buyer SDKs that auto-retry transient +retry_afterare unchanged.retry_afteris derived from the in-flight claim's age rather than hardcoded1— short hint for fresh claims, longer for slow handlers, capped at 5 s so a long-running handler doesn't stall buyer retries past the outer barrier.IdempotencyCheckResult.kind === 'in-flight'variant now carriesretryAfterSecondsso custom store implementations can drive the same hint.Test impact:
server-idempotencytests updated to expectIDEMPOTENCY_IN_FLIGHTon parallel-retry paths. Newstoryboard-parallel-dispatchtest covers the cross-response validators, the in-flight retry loop, barrier timeout, andsame_idempotency_keyopt-out.b5774ba: Remove deprecated
account_from_brandshim innormalizeRequestParams(request-normalizer fabricates account from brand on create_media_buy — silently ships invented data as 3.0 #1676).The shim silently fabricated
account.operator = brand.domainwhen acreate_media_buycall omittedaccount. This was semantically wrong for any caller with a buying-side intermediary, and caused compliance badges to certify requests with invented data rather than caller-supplied account semantics. With AdCP 3.0 GA (April 2026) sunsetting v2 support, the back-compat rationale no longer applies.Behavior change (two cases):
create_media_buywithbrand.domainbut noaccount— previously fabricated{ brand, operator: brand.domain }(wrong for non-direct topologies); now throwsValidationError.create_media_buywith neitheraccountnorbrand— previously fell through to seller-side schema rejection; now throwsValidationErrorclient-side.create_media_buycalls that omitaccountnow throwValidationError(exported asADCPValidationError) with fieldaccount. Uselist_accountsto discover an existingaccount_id, orsync_accountsto register a natural-key account (implicit-account sellers only).17d1c9a: fix(comply): autodetect
webhook_receiverrequirement from storyboard token presencecomply()was shipping the literal mustache token{{runner.webhook_url:<step_id>}}on the wire whenever a webhook-emitting storyboard ran without a configured receiver. 3.0-strict sellers reject the resulting payload asINVALID_REQUEST: Input should be a valid URL, relative URL without a base, cascading 5 distinct first-step failures acrosswebhook_emission/*andidempotency/replay_same_payload.This PR adds
'webhook_receiver'toRequirementNameandKNOWN_REQUIREMENTS, maps it torequirement_unmetin the runner's skip-reason table, and adds a structural pre-pass (detectImplicitRequires) that scans every step'ssample_requestfor{{runner.webhook_url:…}}or{{runner.webhook_base}}tokens. When any are found andoptions.webhook_receiveris unset, the storyboard gradesnot_applicablewithskip.requirement: 'webhook_receiver'— matching the spec contract atcompliance/{version}/universal/webhook-emission.yaml(L34, L62–70, L331–332).Authoring impact: none. Storyboard authors do not need to add
requires: [webhook_receiver]— the token presence is the declaration. Existing storyboards that reference the runner's webhook URL automatically inherit the gate.Behavior change: runs that previously failed with
INVALID_REQUESTfrom a strict seller now gradenot_applicableand surfacerequirement_unmet:webhook_receiverin the structured skip block. Runs that already configurewebhook_receiverare unchanged.Fixes comply() sends relative push_notification_config.url — 3.0-strict sellers reject #1678. Part of the coordinated stance at Tracking: ship 1676–1680 as one stance — the SDK is a witness, not a translator #1685.
Patch Changes
d6eefb3: docs(AdcpErrorInfo): warn sellers that message/details are grader-visible via ComplianceResult
AdcpErrorInfo.messageandAdcpErrorInfo.detailsJSDoc now note that thesefields are forwarded into
ComplianceResult.failures[].adcp_errorand aregrader-visible beyond the request lifetime. Sellers should not embed bearer
tokens, account IDs, or internal paths in these fields. Fixes Document
adcp_error.message/detailssecret-hygiene for sellers in CTX-METADATA-SAFETY.md #1697.7130dc4: fix(creative):
CreativeBuilderPlatformno longer advertiseslist_creatives,get_creative_delivery, orsync_creativesintools/listwhen those methods are absent from the platform implementation.Previously,
buildCreativeHandlersunconditionally attached handler stubs for these three tools regardless of platform archetype, causing them to appear intools/listfor every creative agent — including stateless builder/transform agents that never had these methods. Buyer agents would call them, receiveUNSUPPORTED_FEATURE, and burn retry attempts against tools that were never callable. The fix conditionalises handler registration on method presence, matching the pattern already used bybuildAccountHandlers.1ceacb2: fix(conformance): grade storyboards not_applicable when required_tools are missing from agent toolset
comply()was attempting every capability-resolved storyboard even when the agent's discovered toolset was missing one or more tools declared in the storyboard'srequired_toolsfield. The cascading step-level skips caused the storyboard to gradepartial, which propagated to the track as a false failure — particularly visible for governance storyboards run against non-governance agents.Fix: before running each storyboard, check its
required_toolsagainst the agent's discovered tools. If any are missing, push the storyboard tonotApplicable(with reasonmissing required_tools: <list>) and skip execution. Thenot_applicablesynthetic result keeps the track row accurate and carriesoverall_passed: true, consistent with the existing version-gating behavior.Also corrects
storyboards_executed,groupByTrack, andextractFailuresto reference the filtered runnable set rather than the full expanded set.7b556bb: fix(normalizer): throw ValidationError on pre-3.0 PackageRequest shapes instead of silently passing them through
normalizePackageParamsnow throwsValidationError(code:VALIDATION_ERROR) when it encounterspackages[].product_ids(plural array, pre-3.0) orpackages[].budgetas an object (pre-3.0{ total, currency }shape). Both shapes cannot be translated to AdCP 3.0 equivalents without data loss (product_ids[]→product_id: which id wins?budget:object→number: which currency?). Previously they silently reached 3.0-strict sellers and causedINVALID_REQUESTrejections. Now callers get an early, actionable error at the client boundary.Also fixes a TypeScript-only cast in
request-builder.ts(baseSample.budget as number | undefined) that did not guard at runtime — replaced withtypeof baseSample.budget === 'number'check so storyboard fixtures with object budgets are correctly dropped in favour of discovery-derived values.v2 sunset policy: v2 unsupported as of 3.0 GA (April 2026); no translation obligation.