@adcp/sdk 14.0.0-rc.41 → 14.0.0-rc.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/bin/adcp-grade.js +4 -3
  2. package/bin/adcp-storyboard-summary.js +1 -1
  3. package/bin/adcp.js +4 -6
  4. package/dist/lib/conformance/index.d.mts +2 -0
  5. package/dist/lib/conformance/index.d.ts +2 -0
  6. package/dist/lib/conformance/index.js +7 -0
  7. package/dist/lib/conformance/index.mjs +8 -0
  8. package/dist/lib/conformance/targeting.d.mts +72 -0
  9. package/dist/lib/conformance/targeting.d.ts +72 -0
  10. package/dist/lib/conformance/targeting.js +163 -0
  11. package/dist/lib/conformance/targeting.mjs +137 -0
  12. package/dist/lib/core/AgentClient.d.mts +27 -1
  13. package/dist/lib/core/AgentClient.d.ts +27 -1
  14. package/dist/lib/core/AgentClient.js +41 -2
  15. package/dist/lib/core/AgentClient.mjs +39 -1
  16. package/dist/lib/errors/index.d.mts +4 -1
  17. package/dist/lib/errors/index.d.ts +4 -1
  18. package/dist/lib/errors/index.js +6 -1
  19. package/dist/lib/errors/index.mjs +6 -1
  20. package/dist/lib/index.d.mts +1 -1
  21. package/dist/lib/index.d.ts +1 -1
  22. package/dist/lib/index.js +2 -0
  23. package/dist/lib/index.mjs +3 -1
  24. package/dist/lib/media-buy/action-assessment.js +7 -0
  25. package/dist/lib/media-buy/action-assessment.mjs +7 -0
  26. package/dist/lib/media-buy/available-actions.d.mts +8 -1
  27. package/dist/lib/media-buy/available-actions.d.ts +8 -1
  28. package/dist/lib/media-buy/available-actions.js +18 -3
  29. package/dist/lib/media-buy/available-actions.mjs +15 -2
  30. package/dist/lib/media-buy/index.d.mts +1 -0
  31. package/dist/lib/media-buy/index.d.ts +1 -0
  32. package/dist/lib/media-buy/preflight.js +23 -12
  33. package/dist/lib/media-buy/preflight.mjs +25 -13
  34. package/dist/lib/protocols/transportDiagnostics.d.mts +2 -0
  35. package/dist/lib/protocols/transportDiagnostics.d.ts +2 -0
  36. package/dist/lib/protocols/transportDiagnostics.js +60 -20
  37. package/dist/lib/protocols/transportDiagnostics.mjs +61 -21
  38. package/dist/lib/reporting/ledger/handler.js +67 -11
  39. package/dist/lib/reporting/ledger/handler.mjs +69 -12
  40. package/dist/lib/reporting/ledger/producer.js +4 -9
  41. package/dist/lib/reporting/ledger/producer.mjs +4 -9
  42. package/dist/lib/reporting/ledger/status-ingest.js +1 -1
  43. package/dist/lib/reporting/ledger/status-ingest.mjs +1 -1
  44. package/dist/lib/reporting/reconciliation.d.mts +4 -9
  45. package/dist/lib/reporting/reconciliation.d.ts +4 -9
  46. package/dist/lib/reporting/reconciliation.js +5 -5
  47. package/dist/lib/reporting/reconciliation.mjs +5 -5
  48. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  49. package/dist/lib/server/decisioning/runtime/from-platform.js +16 -3
  50. package/dist/lib/server/decisioning/runtime/from-platform.mjs +16 -3
  51. package/dist/lib/server/index.d.mts +1 -0
  52. package/dist/lib/server/index.d.ts +1 -0
  53. package/dist/lib/server/media-buy-actions.js +3 -1
  54. package/dist/lib/server/media-buy-actions.mjs +3 -1
  55. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.mts +118 -0
  56. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.ts +118 -0
  57. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.js +180 -0
  58. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.mjs +144 -0
  59. package/dist/lib/testing/storyboard/request-signing/builder.d.mts +21 -1
  60. package/dist/lib/testing/storyboard/request-signing/builder.d.ts +21 -1
  61. package/dist/lib/testing/storyboard/request-signing/builder.js +22 -0
  62. package/dist/lib/testing/storyboard/request-signing/builder.mjs +22 -0
  63. package/dist/lib/testing/storyboard/request-signing/grader.d.mts +5 -6
  64. package/dist/lib/testing/storyboard/request-signing/grader.d.ts +5 -6
  65. package/dist/lib/testing/storyboard/request-signing/grader.js +79 -8
  66. package/dist/lib/testing/storyboard/request-signing/grader.mjs +79 -8
  67. package/dist/lib/testing/storyboard/request-signing/index.d.mts +1 -0
  68. package/dist/lib/testing/storyboard/request-signing/index.d.ts +1 -0
  69. package/dist/lib/testing/storyboard/request-signing/index.js +7 -0
  70. package/dist/lib/testing/storyboard/request-signing/index.mjs +8 -0
  71. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.mts +10 -29
  72. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts +10 -29
  73. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js +49 -5
  74. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +39 -5
  75. package/dist/lib/testing/storyboard/runner.js +28 -2
  76. package/dist/lib/testing/storyboard/runner.mjs +18 -2
  77. package/dist/lib/testing/storyboard/types.d.mts +8 -19
  78. package/dist/lib/testing/storyboard/types.d.ts +8 -19
  79. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  80. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  81. package/dist/lib/types/index.d.mts +11 -2
  82. package/dist/lib/types/index.d.ts +11 -2
  83. package/dist/lib/types/schemas.generated.js +17 -0
  84. package/dist/lib/types/schemas.generated.mjs +17 -0
  85. package/dist/lib/utils/reporting-status-response.js +2 -2
  86. package/dist/lib/utils/reporting-status-response.mjs +2 -2
  87. package/dist/lib/validation/schema-loader.js +13 -6
  88. package/dist/lib/validation/schema-loader.mjs +13 -6
  89. package/dist/lib/version.d.mts +3 -3
  90. package/dist/lib/version.d.ts +3 -3
  91. package/dist/lib/version.js +3 -3
  92. package/dist/lib/version.mjs +3 -3
  93. package/docs/TYPE-SUMMARY.md +9 -1
  94. package/docs/guides/EXISTING-PLATFORM.md +61 -33
  95. package/docs/guides/MEDIA-BUY-3.2-COMPATIBILITY.md +27 -1
  96. package/docs/guides/REPORTING-LEDGER.md +3 -1
  97. package/docs/guides/REPORTING-RECONCILIATION.md +1 -1
  98. package/docs/guides/VALIDATE-YOUR-AGENT.md +4 -4
  99. package/docs/llms.txt +2 -2
  100. package/docs/migration-14.x-rc-worksheet.md +4 -4
  101. package/examples/existing-platform-thin.ts +29 -1
  102. package/examples/targeting-input-existing-platform.ts +2 -8
  103. package/package.json +1 -1
  104. package/skills/build-seller-agent/specialisms/signed-requests.md +1 -1
@@ -2,7 +2,7 @@ import type { Client as MCPClient } from '@modelcontextprotocol/sdk/client/index
2
2
  import type { AgentConfig } from '../types';
3
3
  import type { MCPWebhookPayload, GetBrandIdentityRequest, GetBrandIdentityResponse, ContextMatchRequest, ContextMatchResponse, IdentityMatchRequest, IdentityMatchResponseRouterPublisher } from '../types/core.generated';
4
4
  import type { Task as A2ATask, TaskStatusUpdateEvent } from '@a2a-js/sdk';
5
- import { type CanonicalReadTaskOptions, type CreativeDeliveryTaskOptions, type SingleAgentClientConfig, type SyncCreativesTaskOptions, type VerifyAndParseWebhookOptions, type WebhookHandlerAdapter, type WebhookParseResult, type WebhookRequestContext } from './SingleAgentClient';
5
+ import { type CapabilityEvidenceScope, type CapabilityEvidenceSnapshot, type CanonicalReadTaskOptions, type CreativeDeliveryTaskOptions, type SingleAgentClientConfig, type SyncCreativesTaskOptions, type VerifyAndParseWebhookOptions, type WebhookHandlerAdapter, type WebhookParseResult, type WebhookRequestContext } from './SingleAgentClient';
6
6
  import type { InputHandler, TaskOptions, TaskResult, TaskInfo, Message, DirectPauseRecoveryRequest } from './ConversationTypes';
7
7
  import type { AdcpCapabilities } from '../utils/capabilities';
8
8
  import type { WebhookHeaderValue } from '../webhooks';
@@ -167,6 +167,22 @@ export type InProcessAgentClientConfig = Pick<SingleAgentClientConfig, 'adcpVers
167
167
  */
168
168
  agentId?: string;
169
169
  };
170
+ /** Context passed to {@link AgentClient.createWithCapabilityPreflight}. */
171
+ export interface CapabilityPreflightContext {
172
+ /** The exact client instance that will be returned by the factory. */
173
+ client: AgentClient;
174
+ /** Opaque authorization/transport scope the returned snapshot must carry. */
175
+ scope: CapabilityEvidenceScope;
176
+ }
177
+ /** Load or perform capability discovery for one newly constructed client. */
178
+ export type CapabilityPreflightLoader = (context: CapabilityPreflightContext) => CapabilityEvidenceSnapshot | Promise<CapabilityEvidenceSnapshot>;
179
+ export type CapabilityPreflightErrorCode = 'scoped_transport' | 'scope_rotated' | 'invalid_evidence';
180
+ /** Actionable factory failure without weakening the same-instance invariant. */
181
+ export declare class CapabilityPreflightError extends Error {
182
+ readonly code: CapabilityPreflightErrorCode;
183
+ readonly name = "CapabilityPreflightError";
184
+ constructor(code: CapabilityPreflightErrorCode, message: string);
185
+ }
170
186
  export declare class AgentClient {
171
187
  private agent;
172
188
  private config;
@@ -176,6 +192,16 @@ export declare class AgentClient {
176
192
  private readonly sessionTrackedDeferredContinuations;
177
193
  private readonly _isInProcess;
178
194
  constructor(agent: AgentConfig, config?: SingleAgentClientConfig);
195
+ /**
196
+ * Construct and prime one client before exposing it for task dispatch.
197
+ *
198
+ * Capability evidence is intentionally bound to a client instance. This
199
+ * factory gives application factories the instance and its opaque scope
200
+ * before the first task can be sent, then installs the callback's snapshot
201
+ * on that same instance. Evidence from an otherwise identical client is
202
+ * rejected rather than silently falling back to redundant discovery.
203
+ */
204
+ static createWithCapabilityPreflight(agent: AgentConfig, loadEvidence: CapabilityPreflightLoader, config?: SingleAgentClientConfig): Promise<AgentClient>;
179
205
  /**
180
206
  * Recover the current A2A pause generation for a direct mutation that opted
181
207
  * into `TaskOptions.durableContinuationRecovery`.
@@ -18,7 +18,8 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var AgentClient_exports = {};
20
20
  __export(AgentClient_exports, {
21
- AgentClient: () => AgentClient
21
+ AgentClient: () => AgentClient,
22
+ CapabilityPreflightError: () => CapabilityPreflightError
22
23
  });
23
24
  module.exports = __toCommonJS(AgentClient_exports);
24
25
  var import_node_crypto = require("node:crypto");
@@ -33,6 +34,14 @@ function stripRefineProposalsSdkAnnotations(data) {
33
34
  delete canonical._message;
34
35
  return canonical;
35
36
  }
37
+ class CapabilityPreflightError extends Error {
38
+ constructor(code, message) {
39
+ super(message);
40
+ this.code = code;
41
+ }
42
+ code;
43
+ name = "CapabilityPreflightError";
44
+ }
36
45
  const NON_TERMINAL_STATES = /* @__PURE__ */ new Set([
37
46
  "working",
38
47
  "input-required",
@@ -54,6 +63,35 @@ class AgentClient {
54
63
  pendingTask;
55
64
  sessionTrackedDeferredContinuations = /* @__PURE__ */ new WeakSet();
56
65
  _isInProcess;
66
+ /**
67
+ * Construct and prime one client before exposing it for task dispatch.
68
+ *
69
+ * Capability evidence is intentionally bound to a client instance. This
70
+ * factory gives application factories the instance and its opaque scope
71
+ * before the first task can be sent, then installs the callback's snapshot
72
+ * on that same instance. Evidence from an otherwise identical client is
73
+ * rejected rather than silently falling back to redundant discovery.
74
+ */
75
+ static async createWithCapabilityPreflight(agent, loadEvidence, config = {}) {
76
+ const client = new AgentClient(agent, config);
77
+ if (config.transport?.trustedFetchFn || config.transport?.fetchFn) {
78
+ throw new CapabilityPreflightError(
79
+ "scoped_transport",
80
+ "AgentClient.createWithCapabilityPreflight cannot prime a client configured with transport.trustedFetchFn. Keep the scoped transport: construct AgentClient normally so capability discovery runs inside that transport scope."
81
+ );
82
+ }
83
+ const scope = client.getCapabilityEvidenceScope();
84
+ const snapshot = await loadEvidence({ client, scope });
85
+ if (!client.primeCapabilities(snapshot)) {
86
+ const currentScope = client.getCapabilityEvidenceScope();
87
+ const scopeRotated = currentScope.scopeKey !== scope.scopeKey && snapshot?.scope?.scopeKey !== currentScope.scopeKey;
88
+ throw new CapabilityPreflightError(
89
+ scopeRotated ? "scope_rotated" : "invalid_evidence",
90
+ scopeRotated ? "AgentClient.createWithCapabilityPreflight: authorization changed while capability evidence was loading. Repeat preflight with the client's current scope, or construct normally to perform cold discovery." : "AgentClient.createWithCapabilityPreflight: evidence was stale, malformed, missing tool evidence, or scoped to another client. Return a fresh snapshot carrying the callback scope; otherwise construct normally to perform cold discovery."
91
+ );
92
+ }
93
+ return client;
94
+ }
57
95
  /**
58
96
  * Internal access to the underlying `TaskExecutor`. Used by the storyboard
59
97
  * runner's `pollTaskCompletion` race so it can poll AdCP `tasks/get` against
@@ -1306,5 +1344,6 @@ class AgentClient {
1306
1344
  }
1307
1345
  // Annotate the CommonJS export names for ESM import in node:
1308
1346
  0 && (module.exports = {
1309
- AgentClient
1347
+ AgentClient,
1348
+ CapabilityPreflightError
1310
1349
  });
@@ -12,6 +12,14 @@ function stripRefineProposalsSdkAnnotations(data) {
12
12
  delete canonical._message;
13
13
  return canonical;
14
14
  }
15
+ class CapabilityPreflightError extends Error {
16
+ constructor(code, message) {
17
+ super(message);
18
+ this.code = code;
19
+ }
20
+ code;
21
+ name = "CapabilityPreflightError";
22
+ }
15
23
  const NON_TERMINAL_STATES = /* @__PURE__ */ new Set([
16
24
  "working",
17
25
  "input-required",
@@ -33,6 +41,35 @@ class AgentClient {
33
41
  pendingTask;
34
42
  sessionTrackedDeferredContinuations = /* @__PURE__ */ new WeakSet();
35
43
  _isInProcess;
44
+ /**
45
+ * Construct and prime one client before exposing it for task dispatch.
46
+ *
47
+ * Capability evidence is intentionally bound to a client instance. This
48
+ * factory gives application factories the instance and its opaque scope
49
+ * before the first task can be sent, then installs the callback's snapshot
50
+ * on that same instance. Evidence from an otherwise identical client is
51
+ * rejected rather than silently falling back to redundant discovery.
52
+ */
53
+ static async createWithCapabilityPreflight(agent, loadEvidence, config = {}) {
54
+ const client = new AgentClient(agent, config);
55
+ if (config.transport?.trustedFetchFn || config.transport?.fetchFn) {
56
+ throw new CapabilityPreflightError(
57
+ "scoped_transport",
58
+ "AgentClient.createWithCapabilityPreflight cannot prime a client configured with transport.trustedFetchFn. Keep the scoped transport: construct AgentClient normally so capability discovery runs inside that transport scope."
59
+ );
60
+ }
61
+ const scope = client.getCapabilityEvidenceScope();
62
+ const snapshot = await loadEvidence({ client, scope });
63
+ if (!client.primeCapabilities(snapshot)) {
64
+ const currentScope = client.getCapabilityEvidenceScope();
65
+ const scopeRotated = currentScope.scopeKey !== scope.scopeKey && snapshot?.scope?.scopeKey !== currentScope.scopeKey;
66
+ throw new CapabilityPreflightError(
67
+ scopeRotated ? "scope_rotated" : "invalid_evidence",
68
+ scopeRotated ? "AgentClient.createWithCapabilityPreflight: authorization changed while capability evidence was loading. Repeat preflight with the client's current scope, or construct normally to perform cold discovery." : "AgentClient.createWithCapabilityPreflight: evidence was stale, malformed, missing tool evidence, or scoped to another client. Return a fresh snapshot carrying the callback scope; otherwise construct normally to perform cold discovery."
69
+ );
70
+ }
71
+ return client;
72
+ }
36
73
  /**
37
74
  * Internal access to the underlying `TaskExecutor`. Used by the storyboard
38
75
  * runner's `pollTaskCompletion` race so it can poll AdCP `tasks/get` against
@@ -1284,5 +1321,6 @@ class AgentClient {
1284
1321
  }
1285
1322
  }
1286
1323
  export {
1287
- AgentClient
1324
+ AgentClient,
1325
+ CapabilityPreflightError
1288
1326
  };
@@ -378,7 +378,7 @@ export type ActionNotAllowedReasonValue = 'wrong_status' | 'not_supported_on_pro
378
378
  export type ActionNotAllowedAttemptedAction = string;
379
379
  export interface ActionNotAllowedAvailableAction {
380
380
  action: ActionNotAllowedAttemptedAction;
381
- mode: 'self_serve' | 'conditional_self_serve' | 'requires_proposal' | 'requires_approval';
381
+ mode: 'self_serve' | 'conditional_self_serve' | 'seller_managed' | 'requires_proposal' | 'requires_approval';
382
382
  sla?: unknown;
383
383
  terms_ref?: string;
384
384
  }
@@ -388,6 +388,9 @@ export type ActionNotAllowedRecovery = {
388
388
  } | {
389
389
  kind: 'waitForApproval';
390
390
  message: string;
391
+ } | {
392
+ kind: 'waitForTask';
393
+ message: string;
391
394
  } | {
392
395
  kind: 'reissueAsDirect';
393
396
  message: string;
@@ -378,7 +378,7 @@ export type ActionNotAllowedReasonValue = 'wrong_status' | 'not_supported_on_pro
378
378
  export type ActionNotAllowedAttemptedAction = string;
379
379
  export interface ActionNotAllowedAvailableAction {
380
380
  action: ActionNotAllowedAttemptedAction;
381
- mode: 'self_serve' | 'conditional_self_serve' | 'requires_proposal' | 'requires_approval';
381
+ mode: 'self_serve' | 'conditional_self_serve' | 'seller_managed' | 'requires_proposal' | 'requires_approval';
382
382
  sla?: unknown;
383
383
  terms_ref?: string;
384
384
  }
@@ -388,6 +388,9 @@ export type ActionNotAllowedRecovery = {
388
388
  } | {
389
389
  kind: 'waitForApproval';
390
390
  message: string;
391
+ } | {
392
+ kind: 'waitForTask';
393
+ message: string;
391
394
  } | {
392
395
  kind: 'reissueAsDirect';
393
396
  message: string;
@@ -396,6 +396,11 @@ function buildModeMismatchRecovery(details) {
396
396
  const match = details.currently_available_actions?.find((a) => a.action === details.attempted_action);
397
397
  if (!match) return void 0;
398
398
  switch (match.mode) {
399
+ case "seller_managed":
400
+ return {
401
+ kind: "waitForTask",
402
+ message: "Use the declared task and follow its submitted/working/completed lifecycle."
403
+ };
399
404
  case "requires_proposal":
400
405
  return {
401
406
  kind: "createProposal",
@@ -508,7 +513,7 @@ function isActionNotAllowedReason(value) {
508
513
  return value === "wrong_status" || value === "not_supported_on_product" || value === "not_supported_on_buy" || value === "mode_mismatch";
509
514
  }
510
515
  function isActionMode(value) {
511
- return value === "self_serve" || value === "conditional_self_serve" || value === "requires_proposal" || value === "requires_approval";
516
+ return value === "self_serve" || value === "conditional_self_serve" || value === "seller_managed" || value === "requires_proposal" || value === "requires_approval";
512
517
  }
513
518
  function isADCPError(error) {
514
519
  return error instanceof ADCPError;
@@ -345,6 +345,11 @@ function buildModeMismatchRecovery(details) {
345
345
  const match = details.currently_available_actions?.find((a) => a.action === details.attempted_action);
346
346
  if (!match) return void 0;
347
347
  switch (match.mode) {
348
+ case "seller_managed":
349
+ return {
350
+ kind: "waitForTask",
351
+ message: "Use the declared task and follow its submitted/working/completed lifecycle."
352
+ };
348
353
  case "requires_proposal":
349
354
  return {
350
355
  kind: "createProposal",
@@ -457,7 +462,7 @@ function isActionNotAllowedReason(value) {
457
462
  return value === "wrong_status" || value === "not_supported_on_product" || value === "not_supported_on_buy" || value === "mode_mismatch";
458
463
  }
459
464
  function isActionMode(value) {
460
- return value === "self_serve" || value === "conditional_self_serve" || value === "requires_proposal" || value === "requires_approval";
465
+ return value === "self_serve" || value === "conditional_self_serve" || value === "seller_managed" || value === "requires_proposal" || value === "requires_approval";
461
466
  }
462
467
  function isADCPError(error) {
463
468
  return error instanceof ADCPError;
@@ -19,7 +19,7 @@ export { InMemoryWebhookRegistrationStore, type InMemoryWebhookRegistrationStore
19
19
  export { pgWebhookRegistrationStore, getWebhookRegistrationMigration, WEBHOOK_REGISTRATION_MIGRATION, cleanupExpiredWebhookRegistrations, type PgWebhookRegistrationStoreOptions, type CleanupExpiredWebhookRegistrationsOptions, } from './core/postgres-webhook-registration-store.mjs';
20
20
  export { redisWebhookRegistrationStore, type RedisWebhookRegistrationStoreOptions, } from './core/redis-webhook-registration-store.mjs';
21
21
  export type { DelegatedOperatorAuthorizationContext } from './signing/agent-resolver/index.mjs';
22
- export { AgentClient, type CanonicalGetProductsResponse, type CanonicalProjectionTaskOptions, type ProposalRefinementTaskOptions, type TaskResponseTypeMap, type TaskRequestTypeMap, type TaskRequestFor, type AdcpTaskName, type InProcessAgentClientConfig, } from './core/AgentClient.mjs';
22
+ export { AgentClient, CapabilityPreflightError, type CanonicalGetProductsResponse, type CanonicalProjectionTaskOptions, type ProposalRefinementTaskOptions, type TaskResponseTypeMap, type TaskRequestTypeMap, type TaskRequestFor, type AdcpTaskName, type CapabilityPreflightContext, type CapabilityPreflightErrorCode, type CapabilityPreflightLoader, type InProcessAgentClientConfig, } from './core/AgentClient.mjs';
23
23
  export { MediaBuyLifecycleCoordinator, MediaBuyLifecycleCompatibilityError, LegacyPurchaseContinuationError, negotiateMediaBuyLifecycle, type CompatibleDeclineProposalsResponse, type CompatibleDeclineProposalsWireResponse, type CompatibleDeclineResult, type CompatibleProductsResponse, type CompatibleProductsWireResponse, type CompatibleProduct, type CompatibleProposal, type CompatibleProposalResponse, type CompatibleProjectedDeclineResult, type CompatibleRefinementResult, type CompatibleRefineProposalsResponse, type CompatibleRefineProposalsWireResponse, type CompatibleRequestProposalsResponse, type CompatibleRequestProposalsWireResponse, type CompatibleAcceptProposalRequest, type CompatibilityDeferredContinuation, type CompatibilitySubmittedContinuation, type CompatibilityTaskResult, type EstablishedProductsWireResponse, type EstablishedProposalAcceptanceFallback, type EstablishedProposalTaskReconciliationInput, type MediaBuyCompatibility, type MediaBuyCompatibilityLoss, type MediaBuyCompatibilityReport, type MediaBuyLifecycle, type MediaBuyLifecycleCoordinatorOptions, type LegacyPurchaseContinuationErrorCode, } from './media-buy/compatibility.mjs';
24
24
  export { InMemoryLegacyPurchaseContinuationStore, createInMemoryLegacyPurchaseContinuationStore, LEGACY_PURCHASE_PUBLICATION_PROOF_RETENTION_MS, legacyPurchaseSettlementFingerprint, type InMemoryLegacyPurchaseContinuationStoreOptions, type LegacyPurchaseBinding, type LegacyPurchaseClaim, type LegacyPurchaseClaimRequest, type LegacyPurchaseClaimResult, type LegacyPurchaseCompleteResult, type LegacyPurchaseContinuationRecord, type LegacyPurchaseContinuationStore, type LegacyPurchaseCreateResult, type LegacyPurchaseLoss, type LegacyPurchaseOperation, type LegacyPurchasePendingSettlement, type LegacyPurchasePendingSettlementResult, type LegacyPurchasePublicationLease, type LegacyPurchaseReconciliationResult, type LegacyPurchaseSourceVersion, type LegacyPurchaseTerminalResult, type ReconcileLegacyPurchase, } from './media-buy/legacy-purchase-continuation.mjs';
25
25
  export { InMemoryEstablishedProposalStore, createInMemoryEstablishedProposalStore, ESTABLISHED_PROPOSAL_COMPLETION_TOMBSTONE_RETENTION_MS, type EstablishedProposalBinding, type EstablishedProposalCompletionWindow, type EstablishedProposalMutationClaim, type EstablishedProposalMutationBinding, type EstablishedProposalMutationIntent, type EstablishedProposalMutationDisposition, type EstablishedProposalMutationKind, type EstablishedProposalOperation, type EstablishedProposalPutResult, type EstablishedProposalRecord, type EstablishedProposalReserveRequest, type EstablishedProposalReserveResult, type EstablishedProposalScope, type EstablishedProposalSourceVersion, type EstablishedProposalStore, type EstablishedProposalSubmittedOperation, type EstablishedProposalTaskScope, type EstablishedProposalTransitionResult, type InMemoryEstablishedProposalStoreOptions, type ProposalSnapshotEntry, } from './media-buy/established-proposal-store.mjs';
@@ -19,7 +19,7 @@ export { InMemoryWebhookRegistrationStore, type InMemoryWebhookRegistrationStore
19
19
  export { pgWebhookRegistrationStore, getWebhookRegistrationMigration, WEBHOOK_REGISTRATION_MIGRATION, cleanupExpiredWebhookRegistrations, type PgWebhookRegistrationStoreOptions, type CleanupExpiredWebhookRegistrationsOptions, } from './core/postgres-webhook-registration-store';
20
20
  export { redisWebhookRegistrationStore, type RedisWebhookRegistrationStoreOptions, } from './core/redis-webhook-registration-store';
21
21
  export type { DelegatedOperatorAuthorizationContext } from './signing/agent-resolver';
22
- export { AgentClient, type CanonicalGetProductsResponse, type CanonicalProjectionTaskOptions, type ProposalRefinementTaskOptions, type TaskResponseTypeMap, type TaskRequestTypeMap, type TaskRequestFor, type AdcpTaskName, type InProcessAgentClientConfig, } from './core/AgentClient';
22
+ export { AgentClient, CapabilityPreflightError, type CanonicalGetProductsResponse, type CanonicalProjectionTaskOptions, type ProposalRefinementTaskOptions, type TaskResponseTypeMap, type TaskRequestTypeMap, type TaskRequestFor, type AdcpTaskName, type CapabilityPreflightContext, type CapabilityPreflightErrorCode, type CapabilityPreflightLoader, type InProcessAgentClientConfig, } from './core/AgentClient';
23
23
  export { MediaBuyLifecycleCoordinator, MediaBuyLifecycleCompatibilityError, LegacyPurchaseContinuationError, negotiateMediaBuyLifecycle, type CompatibleDeclineProposalsResponse, type CompatibleDeclineProposalsWireResponse, type CompatibleDeclineResult, type CompatibleProductsResponse, type CompatibleProductsWireResponse, type CompatibleProduct, type CompatibleProposal, type CompatibleProposalResponse, type CompatibleProjectedDeclineResult, type CompatibleRefinementResult, type CompatibleRefineProposalsResponse, type CompatibleRefineProposalsWireResponse, type CompatibleRequestProposalsResponse, type CompatibleRequestProposalsWireResponse, type CompatibleAcceptProposalRequest, type CompatibilityDeferredContinuation, type CompatibilitySubmittedContinuation, type CompatibilityTaskResult, type EstablishedProductsWireResponse, type EstablishedProposalAcceptanceFallback, type EstablishedProposalTaskReconciliationInput, type MediaBuyCompatibility, type MediaBuyCompatibilityLoss, type MediaBuyCompatibilityReport, type MediaBuyLifecycle, type MediaBuyLifecycleCoordinatorOptions, type LegacyPurchaseContinuationErrorCode, } from './media-buy/compatibility';
24
24
  export { InMemoryLegacyPurchaseContinuationStore, createInMemoryLegacyPurchaseContinuationStore, LEGACY_PURCHASE_PUBLICATION_PROOF_RETENTION_MS, legacyPurchaseSettlementFingerprint, type InMemoryLegacyPurchaseContinuationStoreOptions, type LegacyPurchaseBinding, type LegacyPurchaseClaim, type LegacyPurchaseClaimRequest, type LegacyPurchaseClaimResult, type LegacyPurchaseCompleteResult, type LegacyPurchaseContinuationRecord, type LegacyPurchaseContinuationStore, type LegacyPurchaseCreateResult, type LegacyPurchaseLoss, type LegacyPurchaseOperation, type LegacyPurchasePendingSettlement, type LegacyPurchasePendingSettlementResult, type LegacyPurchasePublicationLease, type LegacyPurchaseReconciliationResult, type LegacyPurchaseSourceVersion, type LegacyPurchaseTerminalResult, type ReconcileLegacyPurchase, } from './media-buy/legacy-purchase-continuation';
25
25
  export { InMemoryEstablishedProposalStore, createInMemoryEstablishedProposalStore, ESTABLISHED_PROPOSAL_COMPLETION_TOMBSTONE_RETENTION_MS, type EstablishedProposalBinding, type EstablishedProposalCompletionWindow, type EstablishedProposalMutationClaim, type EstablishedProposalMutationBinding, type EstablishedProposalMutationIntent, type EstablishedProposalMutationDisposition, type EstablishedProposalMutationKind, type EstablishedProposalOperation, type EstablishedProposalPutResult, type EstablishedProposalRecord, type EstablishedProposalReserveRequest, type EstablishedProposalReserveResult, type EstablishedProposalScope, type EstablishedProposalSourceVersion, type EstablishedProposalStore, type EstablishedProposalSubmittedOperation, type EstablishedProposalTaskScope, type EstablishedProposalTransitionResult, type InMemoryEstablishedProposalStoreOptions, type ProposalSnapshotEntry, } from './media-buy/established-proposal-store';
package/dist/lib/index.js CHANGED
@@ -57,6 +57,7 @@ __export(index_exports, {
57
57
  CREATIVE_ASSET_TRANSITIONS: () => import_server.CREATIVE_ASSET_TRANSITIONS,
58
58
  CREATIVE_TOOLS: () => import_capabilities.CREATIVE_TOOLS,
59
59
  CanonicalFormat: () => import_projection.CanonicalFormat,
60
+ CapabilityPreflightError: () => import_AgentClient.CapabilityPreflightError,
60
61
  ClientCredentialsExchangeError: () => import_oauth4.ClientCredentialsExchangeError,
61
62
  ConfigurationError: () => import_errors.ConfigurationError,
62
63
  ConfigurationManager: () => import_ConfigurationManager.ConfigurationManager,
@@ -868,6 +869,7 @@ function createAdCPClientFromEnv() {
868
869
  CREATIVE_ASSET_TRANSITIONS,
869
870
  CREATIVE_TOOLS,
870
871
  CanonicalFormat,
872
+ CapabilityPreflightError,
871
873
  ClientCredentialsExchangeError,
872
874
  ConfigurationError,
873
875
  ConfigurationManager,
@@ -88,7 +88,8 @@ import {
88
88
  redisWebhookRegistrationStore
89
89
  } from "./core/redis-webhook-registration-store.mjs";
90
90
  import {
91
- AgentClient
91
+ AgentClient,
92
+ CapabilityPreflightError
92
93
  } from "./core/AgentClient.mjs";
93
94
  import {
94
95
  MediaBuyLifecycleCoordinator,
@@ -825,6 +826,7 @@ export {
825
826
  CREATIVE_ASSET_TRANSITIONS,
826
827
  CREATIVE_TOOLS,
827
828
  CanonicalFormat,
829
+ CapabilityPreflightError,
828
830
  ClientCredentialsExchangeError,
829
831
  ConfigurationError,
830
832
  ConfigurationManager,
@@ -29,6 +29,7 @@ module.exports = __toCommonJS(action_assessment_exports);
29
29
  var import_action_contracts = require('./action-contracts.js');
30
30
  var import_action_constraints = require('./action-constraints.js');
31
31
  var import_mutations = require('./mutations.js');
32
+ var import_available_actions = require('./available-actions.js');
32
33
  function assessProductAction(product, action) {
33
34
  if (product?.allowed_actions === void 0)
34
35
  return { status: "unknown", binding: false, message: "Product action information is absent." };
@@ -163,6 +164,12 @@ function assessActionAvailability(buy, action, options = {}) {
163
164
  return deny("condition_unresolved", "The deliberately emitted term aliases disagree.", "unknown");
164
165
  if (metadataOnly && entry.change_term_id !== void 0)
165
166
  return deny("condition_unresolved", "Metadata-only actions cannot identify a commercial change term.", "unknown");
167
+ if (entry.mode === import_available_actions.LEGACY_REQUIRES_PROPOSAL_MODE)
168
+ return deny(
169
+ "mode_mismatch",
170
+ "This unpublished legacy mode requires the proposal lifecycle; do not dispatch the mutation directly.",
171
+ "blocked"
172
+ );
166
173
  if (!["self_serve", "conditional_self_serve", "seller_managed", "requires_approval"].includes(entry.mode))
167
174
  return deny("condition_unresolved", "Unknown live action mode; refresh the seller declaration.", "unknown");
168
175
  if (term && (entry.mode !== term.service_mode || !(0, import_action_contracts.slaWithin)(term.processing_sla, entry.sla)))
@@ -14,6 +14,7 @@ import {
14
14
  } from "./action-contracts.mjs";
15
15
  import { evaluateChangeTermConstraints } from "./action-constraints.mjs";
16
16
  import { decomposeUpdateMediaBuy, hasUnmappedMutation, mutationShapeIssue } from "./mutations.mjs";
17
+ import { LEGACY_REQUIRES_PROPOSAL_MODE } from "./available-actions.mjs";
17
18
  function assessProductAction(product, action) {
18
19
  if (product?.allowed_actions === void 0)
19
20
  return { status: "unknown", binding: false, message: "Product action information is absent." };
@@ -148,6 +149,12 @@ function assessActionAvailability(buy, action, options = {}) {
148
149
  return deny("condition_unresolved", "The deliberately emitted term aliases disagree.", "unknown");
149
150
  if (metadataOnly && entry.change_term_id !== void 0)
150
151
  return deny("condition_unresolved", "Metadata-only actions cannot identify a commercial change term.", "unknown");
152
+ if (entry.mode === LEGACY_REQUIRES_PROPOSAL_MODE)
153
+ return deny(
154
+ "mode_mismatch",
155
+ "This unpublished legacy mode requires the proposal lifecycle; do not dispatch the mutation directly.",
156
+ "blocked"
157
+ );
151
158
  if (!["self_serve", "conditional_self_serve", "seller_managed", "requires_approval"].includes(entry.mode))
152
159
  return deny("condition_unresolved", "Unknown live action mode; refresh the seller declaration.", "unknown");
153
160
  if (term && (entry.mode !== term.service_mode || !slaWithin(term.processing_sla, entry.sla)))
@@ -17,6 +17,13 @@ export interface AvailableActionsResult {
17
17
  */
18
18
  deprecationHint?: string;
19
19
  }
20
+ /** Unpublished pre-GA mode retained only to route persisted data to recovery. */
21
+ export declare const LEGACY_REQUIRES_PROPOSAL_MODE: "requires_proposal";
22
+ export type LegacyRequiresProposalAction = Omit<MediaBuyAvailableAction, 'mode'> & {
23
+ mode: typeof LEGACY_REQUIRES_PROPOSAL_MODE;
24
+ };
25
+ export type RuntimeCompatibleAvailableAction = MediaBuyAvailableAction | LegacyRequiresProposalAction;
26
+ export declare function isLegacyRequiresProposalAction(entry: RuntimeCompatibleAvailableAction): entry is LegacyRequiresProposalAction;
20
27
  /**
21
28
  * Hook for tests (this repo's and downstream adopters') to reset the
22
29
  * one-shot warning gate. Underscore-prefixed name signals it's not part
@@ -49,7 +56,7 @@ export declare function getAvailableActions(buy: MediaBuyActionContext, options?
49
56
  export declare function findAvailableAction(buy: MediaBuyActionContext, action: MediaBuyActionId, options?: {
50
57
  silent?: boolean;
51
58
  }): {
52
- entry: MediaBuyAvailableAction;
59
+ entry: RuntimeCompatibleAvailableAction;
53
60
  result: AvailableActionsResult;
54
61
  } | undefined;
55
62
  /**
@@ -17,6 +17,13 @@ export interface AvailableActionsResult {
17
17
  */
18
18
  deprecationHint?: string;
19
19
  }
20
+ /** Unpublished pre-GA mode retained only to route persisted data to recovery. */
21
+ export declare const LEGACY_REQUIRES_PROPOSAL_MODE: "requires_proposal";
22
+ export type LegacyRequiresProposalAction = Omit<MediaBuyAvailableAction, 'mode'> & {
23
+ mode: typeof LEGACY_REQUIRES_PROPOSAL_MODE;
24
+ };
25
+ export type RuntimeCompatibleAvailableAction = MediaBuyAvailableAction | LegacyRequiresProposalAction;
26
+ export declare function isLegacyRequiresProposalAction(entry: RuntimeCompatibleAvailableAction): entry is LegacyRequiresProposalAction;
20
27
  /**
21
28
  * Hook for tests (this repo's and downstream adopters') to reset the
22
29
  * one-shot warning gate. Underscore-prefixed name signals it's not part
@@ -49,7 +56,7 @@ export declare function getAvailableActions(buy: MediaBuyActionContext, options?
49
56
  export declare function findAvailableAction(buy: MediaBuyActionContext, action: MediaBuyActionId, options?: {
50
57
  silent?: boolean;
51
58
  }): {
52
- entry: MediaBuyAvailableAction;
59
+ entry: RuntimeCompatibleAvailableAction;
53
60
  result: AvailableActionsResult;
54
61
  } | undefined;
55
62
  /**
@@ -18,12 +18,25 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var available_actions_exports = {};
20
20
  __export(available_actions_exports, {
21
+ LEGACY_REQUIRES_PROPOSAL_MODE: () => LEGACY_REQUIRES_PROPOSAL_MODE,
21
22
  __resetValidActionsWarningForTests: () => __resetValidActionsWarningForTests,
22
23
  findAvailableAction: () => findAvailableAction,
23
24
  getAvailableActions: () => getAvailableActions,
24
- getRollupParent: () => getRollupParent
25
+ getRollupParent: () => getRollupParent,
26
+ isLegacyRequiresProposalAction: () => isLegacyRequiresProposalAction
25
27
  });
26
28
  module.exports = __toCommonJS(available_actions_exports);
29
+ const LEGACY_REQUIRES_PROPOSAL_MODE = "requires_proposal";
30
+ const RUNTIME_RECOGNIZED_MODES = /* @__PURE__ */ new Set([
31
+ "self_serve",
32
+ "conditional_self_serve",
33
+ "seller_managed",
34
+ "requires_approval",
35
+ LEGACY_REQUIRES_PROPOSAL_MODE
36
+ ]);
37
+ function isLegacyRequiresProposalAction(entry) {
38
+ return entry.mode === LEGACY_REQUIRES_PROPOSAL_MODE;
39
+ }
27
40
  const DEPRECATION_HINT = "seller emitted `valid_actions[]` only (legacy 3.0). mode and sla unknown; preflight assumes self_serve. sellers SHOULD populate `available_actions[]` during 3.x.";
28
41
  let warnedOnce = false;
29
42
  function emitDeprecationWarning() {
@@ -54,7 +67,7 @@ function getAvailableActions(buy, options = {}) {
54
67
  function findAvailableAction(buy, action, options = {}) {
55
68
  const result = getAvailableActions(buy, options);
56
69
  const direct = result.actions.find((a) => a.action === action);
57
- const knownMode = (entry) => ["self_serve", "conditional_self_serve", "seller_managed", "requires_approval"].includes(entry.mode);
70
+ const knownMode = (entry) => RUNTIME_RECOGNIZED_MODES.has(entry.mode);
58
71
  if (direct) return knownMode(direct) ? { entry: direct, result } : void 0;
59
72
  const rollupParent = ROLLUP_PARENT_OF[action];
60
73
  if (rollupParent) {
@@ -83,8 +96,10 @@ function getRollupParent(action) {
83
96
  }
84
97
  // Annotate the CommonJS export names for ESM import in node:
85
98
  0 && (module.exports = {
99
+ LEGACY_REQUIRES_PROPOSAL_MODE,
86
100
  __resetValidActionsWarningForTests,
87
101
  findAvailableAction,
88
102
  getAvailableActions,
89
- getRollupParent
103
+ getRollupParent,
104
+ isLegacyRequiresProposalAction
90
105
  });
@@ -1,3 +1,14 @@
1
+ const LEGACY_REQUIRES_PROPOSAL_MODE = "requires_proposal";
2
+ const RUNTIME_RECOGNIZED_MODES = /* @__PURE__ */ new Set([
3
+ "self_serve",
4
+ "conditional_self_serve",
5
+ "seller_managed",
6
+ "requires_approval",
7
+ LEGACY_REQUIRES_PROPOSAL_MODE
8
+ ]);
9
+ function isLegacyRequiresProposalAction(entry) {
10
+ return entry.mode === LEGACY_REQUIRES_PROPOSAL_MODE;
11
+ }
1
12
  const DEPRECATION_HINT = "seller emitted `valid_actions[]` only (legacy 3.0). mode and sla unknown; preflight assumes self_serve. sellers SHOULD populate `available_actions[]` during 3.x.";
2
13
  let warnedOnce = false;
3
14
  function emitDeprecationWarning() {
@@ -28,7 +39,7 @@ function getAvailableActions(buy, options = {}) {
28
39
  function findAvailableAction(buy, action, options = {}) {
29
40
  const result = getAvailableActions(buy, options);
30
41
  const direct = result.actions.find((a) => a.action === action);
31
- const knownMode = (entry) => ["self_serve", "conditional_self_serve", "seller_managed", "requires_approval"].includes(entry.mode);
42
+ const knownMode = (entry) => RUNTIME_RECOGNIZED_MODES.has(entry.mode);
32
43
  if (direct) return knownMode(direct) ? { entry: direct, result } : void 0;
33
44
  const rollupParent = ROLLUP_PARENT_OF[action];
34
45
  if (rollupParent) {
@@ -56,8 +67,10 @@ function getRollupParent(action) {
56
67
  return ROLLUP_PARENT_OF[action];
57
68
  }
58
69
  export {
70
+ LEGACY_REQUIRES_PROPOSAL_MODE,
59
71
  __resetValidActionsWarningForTests,
60
72
  findAvailableAction,
61
73
  getAvailableActions,
62
- getRollupParent
74
+ getRollupParent,
75
+ isLegacyRequiresProposalAction
63
76
  };
@@ -13,6 +13,7 @@ export type { MediaBuyUpdateFieldAction, StructuredOnlyMediaBuyAction, UpdateFie
13
13
  export { ACTIONS_BY_FIELD, STRUCTURED_ONLY_MEDIA_BUY_ACTIONS, UPDATE_FIELDS_BY_ACTION, } from './update-fields.generated.mjs';
14
14
  export { applyTargetingInput, hasTargetingClears, resolveTargetingInput } from './targeting-input.mjs';
15
15
  export type { ResolvedTargetingInput, TargetingInputFor } from './targeting-input.mjs';
16
+ export type { CreateTargetingInput, UpdateTargetingInput } from '../types/index.mjs';
16
17
  export * from './compatibility.mjs';
17
18
  export * from './established-proposal-store.mjs';
18
19
  export * from './legacy-purchase-continuation.mjs';
@@ -13,6 +13,7 @@ export type { MediaBuyUpdateFieldAction, StructuredOnlyMediaBuyAction, UpdateFie
13
13
  export { ACTIONS_BY_FIELD, STRUCTURED_ONLY_MEDIA_BUY_ACTIONS, UPDATE_FIELDS_BY_ACTION, } from './update-fields.generated';
14
14
  export { applyTargetingInput, hasTargetingClears, resolveTargetingInput } from './targeting-input';
15
15
  export type { ResolvedTargetingInput, TargetingInputFor } from './targeting-input';
16
+ export type { CreateTargetingInput, UpdateTargetingInput } from '../types';
16
17
  export * from './compatibility';
17
18
  export * from './established-proposal-store';
18
19
  export * from './legacy-purchase-continuation';
@@ -59,7 +59,8 @@ function tasksForLegacyMutation(action) {
59
59
  );
60
60
  }
61
61
  function isAvailable(buy, action) {
62
- return (0, import_available_actions.findAvailableAction)(buy, action, { silent: true }) !== void 0;
62
+ const match = (0, import_available_actions.findAvailableAction)(buy, action, { silent: true });
63
+ return match !== void 0 && !(0, import_available_actions.isLegacyRequiresProposalAction)(match.entry);
63
64
  }
64
65
  const canPause = (buy) => isAvailable(buy, "pause");
65
66
  const canResume = (buy) => isAvailable(buy, "resume");
@@ -123,6 +124,16 @@ function preflightUpdateMediaBuy(currentBuy, request, options = {}) {
123
124
  }
124
125
  }
125
126
  }
127
+ const lookup = (0, import_available_actions.findAvailableAction)(currentBuy, resolvedAction.action, { silent: true });
128
+ if (lookup && (0, import_available_actions.isLegacyRequiresProposalAction)(lookup.entry)) {
129
+ denials.push({
130
+ action: resolvedAction.action,
131
+ reason: "mode_mismatch",
132
+ recovery: recoveryForModeMismatch(resolvedAction.action, result.actions)
133
+ });
134
+ continue;
135
+ }
136
+ const liveEntry = lookup?.entry;
126
137
  if (strict || options.proposal !== void 0 || resolvedAction.action === "update_name") {
127
138
  const assessment = (0, import_action_assessment.assessActionAvailability)(assessmentBuy, resolvedAction.action, { ...options, request });
128
139
  if (assessment.status === "currently_unavailable") {
@@ -130,12 +141,11 @@ function preflightUpdateMediaBuy(currentBuy, request, options = {}) {
130
141
  continue;
131
142
  }
132
143
  }
133
- const lookup = (0, import_available_actions.findAvailableAction)(currentBuy, resolvedAction.action, { silent: true });
134
- if (!lookup) {
144
+ if (!liveEntry) {
135
145
  denials.push({ action: resolvedAction.action, reason: "not_supported_on_buy" });
136
146
  continue;
137
147
  }
138
- if (options.adcpVersion && !(0, import_action_contracts.liveActionFitsVersion)(lookup.entry, options.adcpVersion)) {
148
+ if (options.adcpVersion && !(0, import_action_contracts.liveActionFitsVersion)(liveEntry, options.adcpVersion)) {
139
149
  denials.push({
140
150
  action: resolvedAction.action,
141
151
  reason: "condition_unresolved",
@@ -149,14 +159,14 @@ function preflightUpdateMediaBuy(currentBuy, request, options = {}) {
149
159
  });
150
160
  continue;
151
161
  }
152
- if (!strict && lookup.entry.task !== void 0 && !tasksForLegacyMutation(resolvedAction.action).includes(lookup.entry.task)) {
162
+ if (!strict && liveEntry.task !== void 0 && !tasksForLegacyMutation(resolvedAction.action).includes(liveEntry.task)) {
153
163
  denials.push({ action: resolvedAction.action, reason: "mode_mismatch" });
154
164
  continue;
155
165
  }
156
- if (!strict && lookup.entry.applicable_package_ids !== void 0) {
166
+ if (!strict && liveEntry.applicable_package_ids !== void 0) {
157
167
  const scoped = decomposition.mutations.filter((m) => m.action === resolvedAction.action);
158
- const ids = lookup.entry.applicable_package_ids;
159
- if ((0, import_action_contracts.liveActionIssues)([lookup.entry]).length || !scoped.length) {
168
+ const ids = liveEntry.applicable_package_ids;
169
+ if ((0, import_action_contracts.liveActionIssues)([liveEntry]).length || !scoped.length) {
160
170
  denials.push({ action: resolvedAction.action, reason: "condition_unresolved" });
161
171
  continue;
162
172
  }
@@ -165,12 +175,12 @@ function preflightUpdateMediaBuy(currentBuy, request, options = {}) {
165
175
  continue;
166
176
  }
167
177
  }
168
- if (!strict && options.task !== "update_media_buy" && options.task !== (lookup.entry.task ?? "update_media_buy")) {
178
+ if (!strict && options.task !== "update_media_buy" && options.task !== (liveEntry.task ?? "update_media_buy")) {
169
179
  denials.push({ action: resolvedAction.action, reason: "mode_mismatch" });
170
180
  continue;
171
181
  }
172
- matched.push(lookup.entry);
173
- modes.push(lookup.entry.mode);
182
+ matched.push(liveEntry);
183
+ modes.push(liveEntry.mode);
174
184
  }
175
185
  if (strict && options.task !== "update_media_buy" && denials.length === 0 && new Set(matched.map((entry) => entry.task ?? "update_media_buy")).size > 1) {
176
186
  for (const action of resolved) denials.push({ action: action.action, reason: "mode_mismatch" });
@@ -195,7 +205,8 @@ function preflightUpdateMediaBuy(currentBuy, request, options = {}) {
195
205
  };
196
206
  }
197
207
  function recoveryForModeMismatch(attemptedAction, currentlyAvailable) {
198
- const entry = currentlyAvailable.find((a) => a.action === attemptedAction);
208
+ const rollup = (0, import_available_actions.getRollupParent)(attemptedAction);
209
+ const entry = currentlyAvailable.find((a) => a.action === attemptedAction) ?? (rollup === void 0 ? void 0 : currentlyAvailable.find((a) => a.action === rollup));
199
210
  if (!entry) return void 0;
200
211
  switch (entry.mode) {
201
212
  case "seller_managed":