@adcp/sdk 12.0.0 → 12.0.2
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.
- package/dist/lib/adapters/content-standards-adapter.mjs +0 -6
- package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
- package/dist/lib/adapters/derived-account-store.mjs +0 -6
- package/dist/lib/adapters/derived-account-store.mjs.map +1 -1
- package/dist/lib/adapters/governance-adapter.mjs +0 -6
- package/dist/lib/adapters/governance-adapter.mjs.map +1 -1
- package/dist/lib/adapters/implicit-account-store.mjs +0 -6
- package/dist/lib/adapters/implicit-account-store.mjs.map +1 -1
- package/dist/lib/adapters/index.mjs +0 -6
- package/dist/lib/adapters/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/get_products.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/index.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/index.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs.map +1 -1
- package/dist/lib/adapters/legacy/v2-5/types.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs +0 -6
- package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs.map +1 -1
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs +0 -6
- package/dist/lib/adapters/oauth-passthrough-resolver.mjs.map +1 -1
- package/dist/lib/adapters/property-list-adapter.mjs +0 -6
- package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
- package/dist/lib/adapters/roster-account-store.mjs +0 -6
- package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
- package/dist/lib/adapters/si-session-manager.mjs +0 -6
- package/dist/lib/adapters/si-session-manager.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/brand-fields.mjs +0 -6
- package/dist/lib/adapters/version/3.0/brand-fields.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/get-products.mjs +0 -6
- package/dist/lib/adapters/version/3.0/get-products.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/index.mjs +0 -6
- package/dist/lib/adapters/version/3.0/index.mjs.map +1 -1
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs +0 -6
- package/dist/lib/adapters/version/3.0/sync-accounts.mjs.map +1 -1
- package/dist/lib/adapters/version/index.mjs +0 -6
- package/dist/lib/adapters/version/index.mjs.map +1 -1
- package/dist/lib/adapters/version/types.mjs +0 -6
- package/dist/lib/advanced.mjs +0 -6
- package/dist/lib/advanced.mjs.map +1 -1
- package/dist/lib/agents/index.generated.mjs +0 -6
- package/dist/lib/agents/index.generated.mjs.map +1 -1
- package/dist/lib/auth/index.mjs +0 -6
- package/dist/lib/auth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +0 -6
- package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs.map +1 -1
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +0 -6
- package/dist/lib/auth/oauth/MCPOAuthProvider.mjs.map +1 -1
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +0 -6
- package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs.map +1 -1
- package/dist/lib/auth/oauth/authorization-required.mjs +0 -6
- package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnose.mjs +0 -6
- package/dist/lib/auth/oauth/diagnose.mjs.map +1 -1
- package/dist/lib/auth/oauth/diagnostics.mjs +0 -6
- package/dist/lib/auth/oauth/diagnostics.mjs.map +1 -1
- package/dist/lib/auth/oauth/discovery.mjs +0 -6
- package/dist/lib/auth/oauth/discovery.mjs.map +1 -1
- package/dist/lib/auth/oauth/file-storage.mjs +0 -6
- package/dist/lib/auth/oauth/file-storage.mjs.map +1 -1
- package/dist/lib/auth/oauth/index.mjs +0 -6
- package/dist/lib/auth/oauth/index.mjs.map +1 -1
- package/dist/lib/auth/oauth/secret-resolver.mjs +0 -6
- package/dist/lib/auth/oauth/secret-resolver.mjs.map +1 -1
- package/dist/lib/auth/oauth/storage-registry.mjs +0 -6
- package/dist/lib/auth/oauth/storage-registry.mjs.map +1 -1
- package/dist/lib/auth/oauth/types.mjs +0 -6
- package/dist/lib/auth/oauth/types.mjs.map +1 -1
- package/dist/lib/auth/oauth/web-flow.mjs +0 -6
- package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
- package/dist/lib/brand/index.mjs +0 -6
- package/dist/lib/brand/index.mjs.map +1 -1
- package/dist/lib/canonical-references/index.mjs +6 -7
- package/dist/lib/canonical-references/index.mjs.map +1 -1
- package/dist/lib/client/index.mjs +0 -6
- package/dist/lib/client/index.mjs.map +1 -1
- package/dist/lib/compliance/index.mjs +0 -6
- package/dist/lib/compliance/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/index.mjs +0 -6
- package/dist/lib/compliance-fixtures/index.mjs.map +1 -1
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs +0 -6
- package/dist/lib/compliance-fixtures/test-authorization-server.mjs.map +1 -1
- package/dist/lib/conformance/index.mjs +0 -6
- package/dist/lib/conformance/index.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformError.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs +0 -6
- package/dist/lib/conformance/invariants/uniformErrorComparator.mjs.map +1 -1
- package/dist/lib/conformance/oracle.mjs +0 -6
- package/dist/lib/conformance/oracle.mjs.map +1 -1
- package/dist/lib/conformance/runConformance.mjs +0 -6
- package/dist/lib/conformance/runConformance.mjs.map +1 -1
- package/dist/lib/conformance/runners.mjs +0 -6
- package/dist/lib/conformance/runners.mjs.map +1 -1
- package/dist/lib/conformance/schemaArbitrary.mjs +0 -6
- package/dist/lib/conformance/schemaArbitrary.mjs.map +1 -1
- package/dist/lib/conformance/schemaLoader.mjs +5 -6
- package/dist/lib/conformance/schemaLoader.mjs.map +1 -1
- package/dist/lib/conformance/seeder.mjs +0 -6
- package/dist/lib/conformance/seeder.mjs.map +1 -1
- package/dist/lib/conformance/types.mjs +0 -6
- package/dist/lib/conformance/types.mjs.map +1 -1
- package/dist/lib/conformance/webhook.mjs +0 -6
- package/dist/lib/conformance/webhook.mjs.map +1 -1
- package/dist/lib/core/ADCPMultiAgentClient.mjs +0 -6
- package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
- package/dist/lib/core/AgentClient.mjs +0 -6
- package/dist/lib/core/AgentClient.mjs.map +1 -1
- package/dist/lib/core/AsyncHandler.mjs +0 -6
- package/dist/lib/core/AsyncHandler.mjs.map +1 -1
- package/dist/lib/core/ConfigurationManager.mjs +0 -6
- package/dist/lib/core/ConfigurationManager.mjs.map +1 -1
- package/dist/lib/core/ConversationTypes.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs +0 -6
- package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
- package/dist/lib/core/GovernanceMiddleware.mjs +0 -6
- package/dist/lib/core/GovernanceMiddleware.mjs.map +1 -1
- package/dist/lib/core/GovernanceTypes.mjs +0 -6
- package/dist/lib/core/GovernanceTypes.mjs.map +1 -1
- package/dist/lib/core/ProtocolResponseParser.mjs +0 -6
- package/dist/lib/core/ProtocolResponseParser.mjs.map +1 -1
- package/dist/lib/core/ResponseValidator.mjs +0 -6
- package/dist/lib/core/ResponseValidator.mjs.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +0 -6
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskEventTypes.mjs +0 -6
- package/dist/lib/core/TaskEventTypes.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +0 -6
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/core/match.mjs +0 -6
- package/dist/lib/core/match.mjs.map +1 -1
- package/dist/lib/core/task-status.mjs +0 -6
- package/dist/lib/core/task-status.mjs.map +1 -1
- package/dist/lib/core/webhook-url.mjs +0 -6
- package/dist/lib/core/webhook-url.mjs.map +1 -1
- package/dist/lib/discovery/adagents-redirects.mjs +0 -6
- package/dist/lib/discovery/adagents-redirects.mjs.map +1 -1
- package/dist/lib/discovery/agent-directory.mjs +0 -6
- package/dist/lib/discovery/agent-directory.mjs.map +1 -1
- package/dist/lib/discovery/inline-publisher-properties.mjs +0 -6
- package/dist/lib/discovery/inline-publisher-properties.mjs.map +1 -1
- package/dist/lib/discovery/network-consistency-checker.mjs +0 -6
- package/dist/lib/discovery/network-consistency-checker.mjs.map +1 -1
- package/dist/lib/discovery/property-crawler.mjs +0 -6
- package/dist/lib/discovery/property-crawler.mjs.map +1 -1
- package/dist/lib/discovery/property-index.mjs +0 -6
- package/dist/lib/discovery/property-index.mjs.map +1 -1
- package/dist/lib/discovery/publisher-property-selector.mjs +0 -6
- package/dist/lib/discovery/publisher-property-selector.mjs.map +1 -1
- package/dist/lib/discovery/resolve-agent-properties.mjs +0 -6
- package/dist/lib/discovery/resolve-agent-properties.mjs.map +1 -1
- package/dist/lib/discovery/types.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs +0 -6
- package/dist/lib/discovery/validate-adagents.mjs.map +1 -1
- package/dist/lib/enums.mjs +0 -6
- package/dist/lib/enums.mjs.map +1 -1
- package/dist/lib/errors/index.mjs +0 -6
- package/dist/lib/errors/index.mjs.map +1 -1
- package/dist/lib/express-mcp/index.mjs +0 -6
- package/dist/lib/express-mcp/index.mjs.map +1 -1
- package/dist/lib/governance/index.mjs +0 -6
- package/dist/lib/governance/index.mjs.map +1 -1
- package/dist/lib/handlers/types.mjs +0 -6
- package/dist/lib/handlers/types.mjs.map +1 -1
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +0 -6
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/media-buy/available-actions.mjs +0 -6
- package/dist/lib/media-buy/available-actions.mjs.map +1 -1
- package/dist/lib/media-buy/index.mjs +0 -6
- package/dist/lib/media-buy/index.mjs.map +1 -1
- package/dist/lib/media-buy/preflight.mjs +0 -6
- package/dist/lib/media-buy/preflight.mjs.map +1 -1
- package/dist/lib/media-buy/property-policy.mjs +0 -6
- package/dist/lib/media-buy/property-policy.mjs.map +1 -1
- package/dist/lib/media-buy/types.mjs +0 -6
- package/dist/lib/media-buy/types.mjs.map +1 -1
- package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
- package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
- package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
- package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/creative-template/server.mjs +0 -6
- package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
- package/dist/lib/mock-server/index.mjs +0 -6
- package/dist/lib/mock-server/index.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
- package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sales-social/server.mjs +0 -6
- package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
- package/dist/lib/mock-server/scenario.mjs +0 -6
- package/dist/lib/mock-server/scenario.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
- package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
- package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
- package/dist/lib/net/address-guards.mjs +0 -6
- package/dist/lib/net/address-guards.mjs.map +1 -1
- package/dist/lib/net/index.mjs +0 -6
- package/dist/lib/net/index.mjs.map +1 -1
- package/dist/lib/net/ssrf-fetch.mjs +0 -6
- package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
- package/dist/lib/observability/index.mjs +0 -6
- package/dist/lib/observability/index.mjs.map +1 -1
- package/dist/lib/observability/tracing.mjs +6 -7
- package/dist/lib/observability/tracing.mjs.map +1 -1
- package/dist/lib/protocols/a2a.mjs +0 -6
- package/dist/lib/protocols/a2a.mjs.map +1 -1
- package/dist/lib/protocols/abort.mjs +0 -6
- package/dist/lib/protocols/abort.mjs.map +1 -1
- package/dist/lib/protocols/index.mjs +0 -6
- package/dist/lib/protocols/index.mjs.map +1 -1
- package/dist/lib/protocols/mcp-modern.mjs +0 -6
- package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
- package/dist/lib/protocols/mcp-tasks.mjs +0 -6
- package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
- package/dist/lib/protocols/mcp.mjs +0 -6
- package/dist/lib/protocols/mcp.mjs.map +1 -1
- package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
- package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
- package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
- package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
- package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
- package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
- package/dist/lib/registry/cursor-store.mjs +0 -6
- package/dist/lib/registry/cursor-store.mjs.map +1 -1
- package/dist/lib/registry/feed-stream.mjs +0 -6
- package/dist/lib/registry/feed-stream.mjs.map +1 -1
- package/dist/lib/registry/index.mjs +0 -6
- package/dist/lib/registry/index.mjs.map +1 -1
- package/dist/lib/registry/property-registry.mjs +0 -6
- package/dist/lib/registry/property-registry.mjs.map +1 -1
- package/dist/lib/registry/sync.mjs +0 -6
- package/dist/lib/registry/sync.mjs.map +1 -1
- package/dist/lib/registry/types.generated.mjs +0 -6
- package/dist/lib/registry/types.mjs +0 -6
- package/dist/lib/schemas/index.mjs +0 -6
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/a2a-adapter.mjs +0 -6
- package/dist/lib/server/a2a-adapter.mjs.map +1 -1
- package/dist/lib/server/account-mode.mjs +0 -6
- package/dist/lib/server/account-mode.mjs.map +1 -1
- package/dist/lib/server/adcp-server.mjs +0 -6
- package/dist/lib/server/adcp-server.mjs.map +1 -1
- package/dist/lib/server/auth-introspection.mjs +0 -6
- package/dist/lib/server/auth-introspection.mjs.map +1 -1
- package/dist/lib/server/auth-signature.mjs +0 -6
- package/dist/lib/server/auth-signature.mjs.map +1 -1
- package/dist/lib/server/auth.mjs +0 -6
- package/dist/lib/server/auth.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts +13 -0
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +3 -2
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +3 -8
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/credential-policy.mjs +0 -6
- package/dist/lib/server/credential-policy.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
- package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/index.mjs +0 -6
- package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/store.mjs +0 -6
- package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
- package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
- package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
- package/dist/lib/server/decisioning/account.mjs +0 -6
- package/dist/lib/server/decisioning/account.mjs.map +1 -1
- package/dist/lib/server/decisioning/admin-router.mjs +0 -6
- package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
- package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
- package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
- package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
- package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
- package/dist/lib/server/decisioning/capabilities.mjs +0 -6
- package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
- package/dist/lib/server/decisioning/compose.mjs +0 -6
- package/dist/lib/server/decisioning/compose.mjs.map +1 -1
- package/dist/lib/server/decisioning/context.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
- package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
- package/dist/lib/server/decisioning/helpers.mjs +0 -6
- package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +0 -6
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/pagination.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
- package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
- package/dist/lib/server/decisioning/platform.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
- package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
- package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs +0 -6
- package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-changes.mjs +0 -6
- package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
- package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
- package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
- package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
- package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
- package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
- package/dist/lib/server/dynamic-registry.mjs +0 -6
- package/dist/lib/server/dynamic-registry.mjs.map +1 -1
- package/dist/lib/server/envelope-allowlist.mjs +0 -6
- package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
- package/dist/lib/server/error-arm-tools.mjs +5 -6
- package/dist/lib/server/error-arm-tools.mjs.map +1 -1
- package/dist/lib/server/errors.mjs +0 -6
- package/dist/lib/server/errors.mjs.map +1 -1
- package/dist/lib/server/example-tld-guard.mjs +0 -6
- package/dist/lib/server/example-tld-guard.mjs.map +1 -1
- package/dist/lib/server/express-adapter.mjs +0 -6
- package/dist/lib/server/express-adapter.mjs.map +1 -1
- package/dist/lib/server/governance.mjs +0 -6
- package/dist/lib/server/governance.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
- package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
- package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
- package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
- package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
- package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
- package/dist/lib/server/idempotency/index.mjs +0 -6
- package/dist/lib/server/idempotency/index.mjs.map +1 -1
- package/dist/lib/server/idempotency/store.mjs +0 -6
- package/dist/lib/server/idempotency/store.mjs.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs +0 -6
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/server/legacy/v5/index.d.mts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts +1 -1
- package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
- package/dist/lib/server/legacy/v5/index.js.map +1 -1
- package/dist/lib/server/legacy/v5/index.mjs +0 -6
- package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
- package/dist/lib/server/mcp-modern-server.mjs +0 -6
- package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
- package/dist/lib/server/media-buy-actions.mjs +0 -6
- package/dist/lib/server/media-buy-actions.mjs.map +1 -1
- package/dist/lib/server/media-buy-helpers.mjs +0 -6
- package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
- package/dist/lib/server/media-buy-store.mjs +0 -6
- package/dist/lib/server/media-buy-store.mjs.map +1 -1
- package/dist/lib/server/normalize-errors.mjs +0 -6
- package/dist/lib/server/normalize-errors.mjs.map +1 -1
- package/dist/lib/server/operational-platform.mjs +0 -6
- package/dist/lib/server/operational-platform.mjs.map +1 -1
- package/dist/lib/server/pick-safe-details.mjs +0 -6
- package/dist/lib/server/pick-safe-details.mjs.map +1 -1
- package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
- package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
- package/dist/lib/server/postgres-state-store.mjs +0 -6
- package/dist/lib/server/postgres-state-store.mjs.map +1 -1
- package/dist/lib/server/postgres-task-store.mjs +0 -6
- package/dist/lib/server/postgres-task-store.mjs.map +1 -1
- package/dist/lib/server/product-defaults.mjs +0 -6
- package/dist/lib/server/product-defaults.mjs.map +1 -1
- package/dist/lib/server/redact.mjs +0 -6
- package/dist/lib/server/redact.mjs.map +1 -1
- package/dist/lib/server/responses.mjs +0 -6
- package/dist/lib/server/responses.mjs.map +1 -1
- package/dist/lib/server/serve.mjs +0 -6
- package/dist/lib/server/serve.mjs.map +1 -1
- package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
- package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
- package/dist/lib/server/socket-mode/index.mjs +0 -6
- package/dist/lib/server/socket-mode/index.mjs.map +1 -1
- package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
- package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
- package/dist/lib/server/state-machine.mjs +0 -6
- package/dist/lib/server/state-machine.mjs.map +1 -1
- package/dist/lib/server/state-store.mjs +0 -6
- package/dist/lib/server/state-store.mjs.map +1 -1
- package/dist/lib/server/structured-serialize.mjs +0 -6
- package/dist/lib/server/structured-serialize.mjs.map +1 -1
- package/dist/lib/server/targeting-helpers.mjs +0 -6
- package/dist/lib/server/targeting-helpers.mjs.map +1 -1
- package/dist/lib/server/tasks.mjs +0 -6
- package/dist/lib/server/tasks.mjs.map +1 -1
- package/dist/lib/server/test-controller-bridge.mjs +0 -6
- package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
- package/dist/lib/server/test-controller.mjs +0 -6
- package/dist/lib/server/test-controller.mjs.map +1 -1
- package/dist/lib/server/upstream-helpers.mjs +0 -6
- package/dist/lib/server/upstream-helpers.mjs.map +1 -1
- package/dist/lib/server/webhook-emitter.mjs +0 -6
- package/dist/lib/server/webhook-emitter.mjs.map +1 -1
- package/dist/lib/server/wire-safe.mjs +0 -6
- package/dist/lib/server/wire-safe.mjs.map +1 -1
- package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
- package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
- package/dist/lib/server/wrap-envelope.mjs +0 -6
- package/dist/lib/server/wrap-envelope.mjs.map +1 -1
- package/dist/lib/signing/agent-context.mjs +0 -6
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +0 -6
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
- package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
- package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
- package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
- package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/index.mjs +0 -6
- package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
- package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
- package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
- package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
- package/dist/lib/signing/brand-jwks.mjs +0 -6
- package/dist/lib/signing/brand-jwks.mjs.map +1 -1
- package/dist/lib/signing/canonicalize.mjs +0 -6
- package/dist/lib/signing/canonicalize.mjs.map +1 -1
- package/dist/lib/signing/capability-cache.mjs +0 -6
- package/dist/lib/signing/capability-cache.mjs.map +1 -1
- package/dist/lib/signing/capability-priming.mjs +0 -6
- package/dist/lib/signing/capability-priming.mjs.map +1 -1
- package/dist/lib/signing/client.mjs +0 -6
- package/dist/lib/signing/client.mjs.map +1 -1
- package/dist/lib/signing/content-digest.mjs +0 -6
- package/dist/lib/signing/content-digest.mjs.map +1 -1
- package/dist/lib/signing/crypto.mjs +0 -6
- package/dist/lib/signing/crypto.mjs.map +1 -1
- package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
- package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
- package/dist/lib/signing/errors.mjs +0 -6
- package/dist/lib/signing/errors.mjs.map +1 -1
- package/dist/lib/signing/fetch-async.mjs +0 -6
- package/dist/lib/signing/fetch-async.mjs.map +1 -1
- package/dist/lib/signing/fetch.mjs +0 -6
- package/dist/lib/signing/fetch.mjs.map +1 -1
- package/dist/lib/signing/index.mjs +0 -6
- package/dist/lib/signing/index.mjs.map +1 -1
- package/dist/lib/signing/jwks-helpers.mjs +0 -6
- package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
- package/dist/lib/signing/jwks-https.mjs +0 -6
- package/dist/lib/signing/jwks-https.mjs.map +1 -1
- package/dist/lib/signing/jwks.mjs +0 -6
- package/dist/lib/signing/jwks.mjs.map +1 -1
- package/dist/lib/signing/middleware.mjs +0 -6
- package/dist/lib/signing/middleware.mjs.map +1 -1
- package/dist/lib/signing/parser.mjs +0 -6
- package/dist/lib/signing/parser.mjs.map +1 -1
- package/dist/lib/signing/postgres-replay-store.mjs +0 -6
- package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
- package/dist/lib/signing/protocol-response.mjs +0 -6
- package/dist/lib/signing/protocol-response.mjs.map +1 -1
- package/dist/lib/signing/provider.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs +0 -6
- package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
- package/dist/lib/signing/replay.mjs +0 -6
- package/dist/lib/signing/replay.mjs.map +1 -1
- package/dist/lib/signing/request-context.mjs +0 -6
- package/dist/lib/signing/request-context.mjs.map +1 -1
- package/dist/lib/signing/revocation-https.mjs +0 -6
- package/dist/lib/signing/revocation-https.mjs.map +1 -1
- package/dist/lib/signing/revocation.mjs +0 -6
- package/dist/lib/signing/revocation.mjs.map +1 -1
- package/dist/lib/signing/server.mjs +0 -6
- package/dist/lib/signing/server.mjs.map +1 -1
- package/dist/lib/signing/signer-async.mjs +0 -6
- package/dist/lib/signing/signer-async.mjs.map +1 -1
- package/dist/lib/signing/signer.mjs +0 -6
- package/dist/lib/signing/signer.mjs.map +1 -1
- package/dist/lib/signing/testing.mjs +0 -6
- package/dist/lib/signing/testing.mjs.map +1 -1
- package/dist/lib/signing/types.mjs +0 -6
- package/dist/lib/signing/types.mjs.map +1 -1
- package/dist/lib/signing/verifier.mjs +0 -6
- package/dist/lib/signing/verifier.mjs.map +1 -1
- package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
- package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
- package/dist/lib/signing/webhook-verifier.mjs +0 -6
- package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
- package/dist/lib/storage/MemoryStorage.mjs +0 -6
- package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
- package/dist/lib/storage/interfaces.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
- package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
- package/dist/lib/substitution/encoder/index.mjs +0 -6
- package/dist/lib/substitution/encoder/index.mjs.map +1 -1
- package/dist/lib/substitution/index.mjs +0 -6
- package/dist/lib/substitution/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
- package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
- package/dist/lib/substitution/observer/alignment.mjs +0 -6
- package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
- package/dist/lib/substitution/observer/assertions.mjs +0 -6
- package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
- package/dist/lib/substitution/observer/html-parser.mjs +0 -6
- package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
- package/dist/lib/substitution/observer/index.mjs +0 -6
- package/dist/lib/substitution/observer/index.mjs.map +1 -1
- package/dist/lib/substitution/observer/ssrf.mjs +0 -6
- package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
- package/dist/lib/substitution/rfc3986.mjs +0 -6
- package/dist/lib/substitution/rfc3986.mjs.map +1 -1
- package/dist/lib/substitution/translate.mjs +0 -6
- package/dist/lib/substitution/translate.mjs.map +1 -1
- package/dist/lib/substitution/types.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs +0 -6
- package/dist/lib/substitution/vectors.mjs.map +1 -1
- package/dist/lib/testing/agent-tester.mjs +0 -6
- package/dist/lib/testing/agent-tester.mjs.map +1 -1
- package/dist/lib/testing/client.mjs +0 -6
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/briefs.mjs +0 -6
- package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +0 -6
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +0 -6
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
- package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
- package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
- package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
- package/dist/lib/testing/compliance/summary.mjs +0 -6
- package/dist/lib/testing/compliance/summary.mjs.map +1 -1
- package/dist/lib/testing/compliance/types.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs +0 -6
- package/dist/lib/testing/comply-controller.mjs.map +1 -1
- package/dist/lib/testing/controller-assertions.mjs +0 -6
- package/dist/lib/testing/controller-assertions.mjs.map +1 -1
- package/dist/lib/testing/formatter.mjs +0 -6
- package/dist/lib/testing/formatter.mjs.map +1 -1
- package/dist/lib/testing/index.mjs +0 -6
- package/dist/lib/testing/index.mjs.map +1 -1
- package/dist/lib/testing/local-agent-runner.mjs +0 -6
- package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
- package/dist/lib/testing/orchestrator.mjs +0 -6
- package/dist/lib/testing/orchestrator.mjs.map +1 -1
- package/dist/lib/testing/personas/index.mjs +0 -6
- package/dist/lib/testing/personas/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
- package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
- package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
- package/dist/lib/testing/scenarios/creative.mjs +0 -6
- package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
- package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
- package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
- package/dist/lib/testing/scenarios/discovery.mjs +0 -6
- package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
- package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
- package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
- package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/governance.mjs +0 -6
- package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/health.mjs +0 -6
- package/dist/lib/testing/scenarios/health.mjs.map +1 -1
- package/dist/lib/testing/scenarios/index.mjs +0 -6
- package/dist/lib/testing/scenarios/index.mjs.map +1 -1
- package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
- package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
- package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
- package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
- package/dist/lib/testing/scenarios/signals.mjs +0 -6
- package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
- package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
- package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
- package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
- package/dist/lib/testing/seed-merge.mjs +0 -6
- package/dist/lib/testing/seed-merge.mjs.map +1 -1
- package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
- package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
- package/dist/lib/testing/storyboard/assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
- package/dist/lib/testing/storyboard/compliance.mjs +5 -6
- package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
- package/dist/lib/testing/storyboard/context.mjs +0 -6
- package/dist/lib/testing/storyboard/context.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs +0 -6
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/junit.mjs +0 -6
- package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +0 -6
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/path.mjs +0 -6
- package/dist/lib/testing/storyboard/path.mjs.map +1 -1
- package/dist/lib/testing/storyboard/probes.mjs +0 -6
- package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
- package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
- package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +0 -6
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
- package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
- package/dist/lib/testing/storyboard/seeding.mjs +0 -6
- package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
- package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
- package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +0 -6
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
- package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs +0 -6
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.mjs +0 -6
- package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
- package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
- package/dist/lib/testing/stubs/index.mjs +0 -6
- package/dist/lib/testing/stubs/index.mjs.map +1 -1
- package/dist/lib/testing/test-controller.mjs +0 -6
- package/dist/lib/testing/test-controller.mjs.map +1 -1
- package/dist/lib/testing/test-helpers.mjs +0 -6
- package/dist/lib/testing/test-helpers.mjs.map +1 -1
- package/dist/lib/testing/types.mjs +0 -6
- package/dist/lib/types/adcp.mjs +0 -6
- package/dist/lib/types/adcp.mjs.map +1 -1
- package/dist/lib/types/asset-instances.mjs +0 -6
- package/dist/lib/types/compat.mjs +0 -6
- package/dist/lib/types/compat.mjs.map +1 -1
- package/dist/lib/types/core.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs +0 -6
- package/dist/lib/types/enums.generated.mjs.map +1 -1
- package/dist/lib/types/error-codes.mjs +0 -6
- package/dist/lib/types/error-codes.mjs.map +1 -1
- package/dist/lib/types/error-details.aliases.mjs +0 -6
- package/dist/lib/types/error-details.aliases.mjs.map +1 -1
- package/dist/lib/types/format-asset-slots.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
- package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
- package/dist/lib/types/index.mjs +0 -6
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/inline-enums.aliases.mjs +0 -6
- package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
- package/dist/lib/types/inline-enums.generated.mjs +0 -6
- package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
- package/dist/lib/types/manifest.generated.mjs +0 -6
- package/dist/lib/types/manifest.generated.mjs.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +0 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.mjs +0 -6
- package/dist/lib/types/server-payload.mjs +0 -6
- package/dist/lib/types/sync-rows.mjs +0 -6
- package/dist/lib/types/tools.generated.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs +0 -6
- package/dist/lib/types/v2-5/index.mjs.map +1 -1
- package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs +0 -6
- package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
- package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
- package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
- package/dist/lib/upstream-recorder/constants.mjs +0 -6
- package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
- package/dist/lib/upstream-recorder/index.mjs +0 -6
- package/dist/lib/upstream-recorder/index.mjs.map +1 -1
- package/dist/lib/upstream-recorder/recorder.mjs +0 -6
- package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
- package/dist/lib/upstream-recorder/types.mjs +0 -6
- package/dist/lib/upstream-recorder/types.mjs.map +1 -1
- package/dist/lib/utils/a2a-artifacts.mjs +0 -6
- package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
- package/dist/lib/utils/a2a-discovery.mjs +0 -6
- package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
- package/dist/lib/utils/activation-key-builders.mjs +0 -6
- package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +0 -6
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/asset-builders.mjs +0 -6
- package/dist/lib/utils/asset-builders.mjs.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
- package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
- package/dist/lib/utils/capabilities.mjs +0 -6
- package/dist/lib/utils/capabilities.mjs.map +1 -1
- package/dist/lib/utils/capability-rollups.mjs +0 -6
- package/dist/lib/utils/capability-rollups.mjs.map +1 -1
- package/dist/lib/utils/creative-adapter.mjs +0 -6
- package/dist/lib/utils/creative-adapter.mjs.map +1 -1
- package/dist/lib/utils/creative-delivery.mjs +0 -6
- package/dist/lib/utils/creative-delivery.mjs.map +1 -1
- package/dist/lib/utils/deprecation.mjs +0 -6
- package/dist/lib/utils/deprecation.mjs.map +1 -1
- package/dist/lib/utils/envelope-status-compat.mjs +0 -6
- package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
- package/dist/lib/utils/error-extraction.mjs +0 -6
- package/dist/lib/utils/error-extraction.mjs.map +1 -1
- package/dist/lib/utils/extract-result.mjs +0 -6
- package/dist/lib/utils/extract-result.mjs.map +1 -1
- package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
- package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
- package/dist/lib/utils/format-assets.mjs +0 -6
- package/dist/lib/utils/format-assets.mjs.map +1 -1
- package/dist/lib/utils/format-render-builders.mjs +0 -6
- package/dist/lib/utils/format-render-builders.mjs.map +1 -1
- package/dist/lib/utils/format-renders.mjs +0 -6
- package/dist/lib/utils/format-renders.mjs.map +1 -1
- package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
- package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
- package/dist/lib/utils/glob.mjs +0 -6
- package/dist/lib/utils/glob.mjs.map +1 -1
- package/dist/lib/utils/global-async-local-storage.mjs +0 -6
- package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
- package/dist/lib/utils/idempotency.mjs +0 -6
- package/dist/lib/utils/idempotency.mjs.map +1 -1
- package/dist/lib/utils/index.mjs +0 -6
- package/dist/lib/utils/index.mjs.map +1 -1
- package/dist/lib/utils/jcs.mjs +0 -6
- package/dist/lib/utils/jcs.mjs.map +1 -1
- package/dist/lib/utils/json-depth.mjs +0 -6
- package/dist/lib/utils/json-depth.mjs.map +1 -1
- package/dist/lib/utils/logger.mjs +0 -6
- package/dist/lib/utils/logger.mjs.map +1 -1
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
- package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
- package/dist/lib/utils/media-buy-status.mjs +0 -6
- package/dist/lib/utils/media-buy-status.mjs.map +1 -1
- package/dist/lib/utils/pagination.mjs +0 -6
- package/dist/lib/utils/pagination.mjs.map +1 -1
- package/dist/lib/utils/preview-creative-builders.mjs +0 -6
- package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
- package/dist/lib/utils/preview-normalizer.mjs +0 -6
- package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
- package/dist/lib/utils/preview-utils.mjs +0 -6
- package/dist/lib/utils/preview-utils.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +0 -6
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/utils/probe-policy.mjs +0 -6
- package/dist/lib/utils/probe-policy.mjs.map +1 -1
- package/dist/lib/utils/protocol-detection.mjs +0 -6
- package/dist/lib/utils/protocol-detection.mjs.map +1 -1
- package/dist/lib/utils/redact-secrets.mjs +0 -6
- package/dist/lib/utils/redact-secrets.mjs.map +1 -1
- package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
- package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
- package/dist/lib/utils/render-builders.mjs +0 -6
- package/dist/lib/utils/render-builders.mjs.map +1 -1
- package/dist/lib/utils/request-normalizer.mjs +0 -6
- package/dist/lib/utils/request-normalizer.mjs.map +1 -1
- package/dist/lib/utils/response-schemas.mjs +0 -6
- package/dist/lib/utils/response-schemas.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +0 -6
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/utils/retry.mjs +0 -6
- package/dist/lib/utils/retry.mjs.map +1 -1
- package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
- package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
- package/dist/lib/utils/signal-id-builders.mjs +0 -6
- package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
- package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
- package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
- package/dist/lib/utils/task-state.mjs +0 -6
- package/dist/lib/utils/task-state.mjs.map +1 -1
- package/dist/lib/utils/tool-request-schemas.mjs +0 -6
- package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
- package/dist/lib/utils/typeGuards.mjs +0 -6
- package/dist/lib/utils/typeGuards.mjs.map +1 -1
- package/dist/lib/utils/union-errors.mjs +0 -6
- package/dist/lib/utils/union-errors.mjs.map +1 -1
- package/dist/lib/utils/validate-user-agent.mjs +0 -6
- package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
- package/dist/lib/v2/format-schema/fetch.mjs +0 -6
- package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
- package/dist/lib/v2/format-schema/index.mjs +0 -6
- package/dist/lib/v2/format-schema/index.mjs.map +1 -1
- package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
- package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +7 -8
- package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
- package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
- package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
- package/dist/lib/v2/projection/augment-response.mjs +0 -6
- package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
- package/dist/lib/v2/projection/builders.mjs +0 -6
- package/dist/lib/v2/projection/builders.mjs.map +1 -1
- package/dist/lib/v2/projection/cache-versions.mjs +0 -6
- package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
- package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
- package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
- package/dist/lib/v2/projection/catalog.mjs +5 -6
- package/dist/lib/v2/projection/catalog.mjs.map +1 -1
- package/dist/lib/v2/projection/constants.mjs +0 -6
- package/dist/lib/v2/projection/constants.mjs.map +1 -1
- package/dist/lib/v2/projection/index.mjs +0 -6
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/registry.mjs +5 -6
- package/dist/lib/v2/projection/registry.mjs.map +1 -1
- package/dist/lib/v2/projection/types.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
- package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
- package/dist/lib/v2/projection/write-side.mjs +0 -6
- package/dist/lib/v2/projection/write-side.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
- package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
- package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
- package/dist/lib/validation/client-hooks.mjs +0 -6
- package/dist/lib/validation/client-hooks.mjs.map +1 -1
- package/dist/lib/validation/hints.mjs +0 -6
- package/dist/lib/validation/hints.mjs.map +1 -1
- package/dist/lib/validation/index.mjs +0 -6
- package/dist/lib/validation/index.mjs.map +1 -1
- package/dist/lib/validation/schema-errors.mjs +0 -6
- package/dist/lib/validation/schema-errors.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +5 -6
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/validation/schema-validator.mjs +0 -6
- package/dist/lib/validation/schema-validator.mjs.map +1 -1
- package/dist/lib/validation/sync-creatives.mjs +0 -6
- package/dist/lib/validation/sync-creatives.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -9
- package/dist/lib/version.mjs.map +1 -1
- package/dist/lib/webhooks/index.mjs +0 -6
- package/dist/lib/webhooks/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
- package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
- package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import {
|
|
8
2
|
comply,
|
|
9
3
|
collectObservations,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/compliance/index.ts"],"sourcesContent":["/**\n * AdCP Compliance Assessment\n *\n * comply → \"Your agent works\" (deterministic, per-track)\n */\n\nexport {\n comply,\n collectObservations,\n computeOverallStatus,\n formatComplianceResults,\n formatComplianceResultsJSON,\n} from './comply';\nexport type { ComplyOptions } from './comply';\n\nexport {\n buildComplianceSummary,\n buildCrashSummary,\n formatComplianceSummaryText,\n formatComplianceSummaryMarkdown,\n} from './summary';\nexport type {\n ComplianceSummaryArtifact,\n ComplianceSummaryFailure,\n ComplianceSummaryFailureKind,\n BuildSummaryOptions,\n BuildCrashSummaryOptions,\n} from './summary';\n\nexport { SAMPLE_BRIEFS, getBriefById, getBriefsByVertical } from './briefs';\n\nexport type {\n ComplianceTrack,\n TrackResult,\n TrackStatus,\n OverallStatus,\n ComplianceFailure,\n ComplianceResult,\n ComplianceSummary,\n AdvisoryObservation,\n ObservationCategory,\n ObservationSeverity,\n ObservationSource,\n SampleBrief,\n} from './types';\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/compliance/index.ts"],"sourcesContent":["/**\n * AdCP Compliance Assessment\n *\n * comply → \"Your agent works\" (deterministic, per-track)\n */\n\nexport {\n comply,\n collectObservations,\n computeOverallStatus,\n formatComplianceResults,\n formatComplianceResultsJSON,\n} from './comply';\nexport type { ComplyOptions } from './comply';\n\nexport {\n buildComplianceSummary,\n buildCrashSummary,\n formatComplianceSummaryText,\n formatComplianceSummaryMarkdown,\n} from './summary';\nexport type {\n ComplianceSummaryArtifact,\n ComplianceSummaryFailure,\n ComplianceSummaryFailureKind,\n BuildSummaryOptions,\n BuildCrashSummaryOptions,\n} from './summary';\n\nexport { SAMPLE_BRIEFS, getBriefById, getBriefsByVertical } from './briefs';\n\nexport type {\n ComplianceTrack,\n TrackResult,\n TrackStatus,\n OverallStatus,\n ComplianceFailure,\n ComplianceResult,\n ComplianceSummary,\n AdvisoryObservation,\n ObservationCategory,\n ObservationSeverity,\n ObservationSource,\n SampleBrief,\n} from './types';\n"],"mappings":"AAMA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AASP,SAAS,eAAe,cAAc,2BAA2B;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = "__spec_conformance__/account_discovery";
|
|
8
2
|
function isAccountBearingSpecialism(specialism) {
|
|
9
3
|
if (specialism.startsWith("sales-")) return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"sourcesContent":["/**\n * Cross-storyboard spec conformance gates.\n *\n * Some AdCP rules are universal (apply to any seller agent regardless of\n * which specialism they're testing) rather than per-storyboard. Encoding\n * them as per-storyboard `required_tools` predicates would mean tagging\n * every relevant scenario, and the rule would still drift for adopters\n * authoring third-party storyboards.\n *\n * This module emits synthetic `StoryboardResult`s for those rules — the\n * comply orchestrator pushes them into the storyboard-results array\n * before track grouping. Pipeline downstream (failure extraction, track\n * mapping, summary, skip-cause aggregator) treats them as any other\n * storyboard result.\n *\n * Currently wires one gate:\n *\n * - **Account discovery (adcp-client#1624 / adcp#4302).** Every seller\n * agent (any specialism in `sales-*` / `audience-sync` / `governance-*`)\n * MUST advertise at least one of `list_accounts` or `sync_accounts`.\n * Spec normative as of AdCP 3.0.9; the requirement existed before the\n * explicit MUST landed. The runner honors AdCP 3.1\n * `required_any_of_tools` tags when present, but this fallback remains\n * until upstream storyboards carry the tag consistently.\n */\n\nimport type { AgentProfile } from '../types';\nimport type { StoryboardResult } from '../storyboard/types';\n\n/**\n * Synthetic storyboard ID emitted when the account-discovery gate fails.\n * Stable across releases — dashboards / badges can grep for it. Distinct\n * from any real storyboard ID; the gate runs cross-storyboard.\n */\nexport const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = '__spec_conformance__/account_discovery';\n\n/**\n * Specialisms that operate on accounts and therefore require the agent\n * to expose `list_accounts` OR `sync_accounts`. Per AdCP 3.0.9\n * `accounts/overview.mdx`. Adopters claiming any of these specialisms\n * without an account-discovery tool are non-conformant.\n *\n * Match rules:\n * - `sales-*` prefix — every selling specialism operates on accounts.\n * - exact `audience-sync` — audiences belong to accounts.\n * - `governance-*` prefix — governance applies per-account.\n * - exact `creative-generative` — dual-role specialism. A generative\n * seller (selling inventory + generating creatives) is an account-\n * bearing adopter even if they only claim `creative-generative`,\n * not a `sales-*` specialism. The upstream storyboard at\n * `compliance/cache/<v>/specialisms/creative-generative/generative-seller.yaml`\n * exercises `sync_accounts` directly, confirming this scope.\n *\n * Other creative specialisms (`creative-ad-server`, `creative-template`)\n * are stand-alone — those agents don't sell inventory and don't need\n * account discovery. Same for `signal-*`, `brand-rights`,\n * `signed-requests`.\n */\nfunction isAccountBearingSpecialism(specialism: string): boolean {\n if (specialism.startsWith('sales-')) return true;\n if (specialism === 'audience-sync') return true;\n if (specialism.startsWith('governance-')) return true;\n if (specialism === 'creative-generative') return true;\n return false;\n}\n\n/**\n * Run the account-discovery conformance gate. Returns `null` when the\n * gate doesn't apply (agent declared no account-bearing specialism,\n * couldn't enumerate specialisms, or already advertises a discovery\n * tool). Returns a synthetic failing `StoryboardResult` when the agent\n * is non-conformant.\n *\n * The returned result has:\n * - `overall_passed: false` so it counts toward `failed` in summaries\n * - one synthetic phase + step that surfaces the specific specialism(s)\n * triggering the gate so operators can act\n * - `track` is left unset on the synthetic id; `extractFailures` falls\n * back to `'core'` for any storyboard not in the applicable-storyboards\n * lookup, which is correct — account discovery is a core protocol\n * invariant, not a specialism-specific concern\n *\n * Note: when the agent doesn't expose `get_adcp_capabilities` (so\n * `profile.specialisms` is undefined), the gate is a no-op. The runner\n * separately surfaces an observation about the missing capability call;\n * we don't double-report.\n *\n * TODO(adcp-client#1642): delete this synthesis path when upstream\n * storyboards in `compliance/cache/` carry `required_any_of_tools`\n * consistently for every account-bearing scenario.\n */\nexport function checkAccountDiscoveryGate(profile: AgentProfile, agentUrl: string): StoryboardResult | null {\n const accountBearing = (profile.specialisms ?? []).filter(isAccountBearingSpecialism);\n if (accountBearing.length === 0) return null;\n\n if (profile.tools.includes('list_accounts') || profile.tools.includes('sync_accounts')) {\n return null;\n }\n\n const now = new Date().toISOString();\n const detail =\n `Agent declared account-bearing specialism(s) [${accountBearing.join(', ')}] but advertises ` +\n `neither list_accounts nor sync_accounts. AdCP 3.0.9 §accounts/overview requires every seller ` +\n `agent to expose at least one of these tools. Agent tools: [${profile.tools.join(', ')}].`;\n\n return {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n storyboard_title: 'Spec conformance: account discovery',\n agent_url: agentUrl,\n overall_passed: false,\n phases: [\n {\n phase_id: 'account_discovery_gate',\n phase_title: 'Account discovery',\n passed: false,\n duration_ms: 0,\n steps: [\n {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n step_id: 'list_or_sync_accounts',\n phase_id: 'account_discovery_gate',\n title: 'Seller agent must advertise list_accounts or sync_accounts',\n task: '',\n passed: false,\n duration_ms: 0,\n validations: [],\n context: {},\n error: detail,\n extraction: { path: 'none' },\n },\n ],\n },\n ],\n context: {},\n total_duration_ms: 0,\n passed_count: 0,\n failed_count: 1,\n skipped_count: 0,\n tested_at: now,\n notices: [],\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"sourcesContent":["/**\n * Cross-storyboard spec conformance gates.\n *\n * Some AdCP rules are universal (apply to any seller agent regardless of\n * which specialism they're testing) rather than per-storyboard. Encoding\n * them as per-storyboard `required_tools` predicates would mean tagging\n * every relevant scenario, and the rule would still drift for adopters\n * authoring third-party storyboards.\n *\n * This module emits synthetic `StoryboardResult`s for those rules — the\n * comply orchestrator pushes them into the storyboard-results array\n * before track grouping. Pipeline downstream (failure extraction, track\n * mapping, summary, skip-cause aggregator) treats them as any other\n * storyboard result.\n *\n * Currently wires one gate:\n *\n * - **Account discovery (adcp-client#1624 / adcp#4302).** Every seller\n * agent (any specialism in `sales-*` / `audience-sync` / `governance-*`)\n * MUST advertise at least one of `list_accounts` or `sync_accounts`.\n * Spec normative as of AdCP 3.0.9; the requirement existed before the\n * explicit MUST landed. The runner honors AdCP 3.1\n * `required_any_of_tools` tags when present, but this fallback remains\n * until upstream storyboards carry the tag consistently.\n */\n\nimport type { AgentProfile } from '../types';\nimport type { StoryboardResult } from '../storyboard/types';\n\n/**\n * Synthetic storyboard ID emitted when the account-discovery gate fails.\n * Stable across releases — dashboards / badges can grep for it. Distinct\n * from any real storyboard ID; the gate runs cross-storyboard.\n */\nexport const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = '__spec_conformance__/account_discovery';\n\n/**\n * Specialisms that operate on accounts and therefore require the agent\n * to expose `list_accounts` OR `sync_accounts`. Per AdCP 3.0.9\n * `accounts/overview.mdx`. Adopters claiming any of these specialisms\n * without an account-discovery tool are non-conformant.\n *\n * Match rules:\n * - `sales-*` prefix — every selling specialism operates on accounts.\n * - exact `audience-sync` — audiences belong to accounts.\n * - `governance-*` prefix — governance applies per-account.\n * - exact `creative-generative` — dual-role specialism. A generative\n * seller (selling inventory + generating creatives) is an account-\n * bearing adopter even if they only claim `creative-generative`,\n * not a `sales-*` specialism. The upstream storyboard at\n * `compliance/cache/<v>/specialisms/creative-generative/generative-seller.yaml`\n * exercises `sync_accounts` directly, confirming this scope.\n *\n * Other creative specialisms (`creative-ad-server`, `creative-template`)\n * are stand-alone — those agents don't sell inventory and don't need\n * account discovery. Same for `signal-*`, `brand-rights`,\n * `signed-requests`.\n */\nfunction isAccountBearingSpecialism(specialism: string): boolean {\n if (specialism.startsWith('sales-')) return true;\n if (specialism === 'audience-sync') return true;\n if (specialism.startsWith('governance-')) return true;\n if (specialism === 'creative-generative') return true;\n return false;\n}\n\n/**\n * Run the account-discovery conformance gate. Returns `null` when the\n * gate doesn't apply (agent declared no account-bearing specialism,\n * couldn't enumerate specialisms, or already advertises a discovery\n * tool). Returns a synthetic failing `StoryboardResult` when the agent\n * is non-conformant.\n *\n * The returned result has:\n * - `overall_passed: false` so it counts toward `failed` in summaries\n * - one synthetic phase + step that surfaces the specific specialism(s)\n * triggering the gate so operators can act\n * - `track` is left unset on the synthetic id; `extractFailures` falls\n * back to `'core'` for any storyboard not in the applicable-storyboards\n * lookup, which is correct — account discovery is a core protocol\n * invariant, not a specialism-specific concern\n *\n * Note: when the agent doesn't expose `get_adcp_capabilities` (so\n * `profile.specialisms` is undefined), the gate is a no-op. The runner\n * separately surfaces an observation about the missing capability call;\n * we don't double-report.\n *\n * TODO(adcp-client#1642): delete this synthesis path when upstream\n * storyboards in `compliance/cache/` carry `required_any_of_tools`\n * consistently for every account-bearing scenario.\n */\nexport function checkAccountDiscoveryGate(profile: AgentProfile, agentUrl: string): StoryboardResult | null {\n const accountBearing = (profile.specialisms ?? []).filter(isAccountBearingSpecialism);\n if (accountBearing.length === 0) return null;\n\n if (profile.tools.includes('list_accounts') || profile.tools.includes('sync_accounts')) {\n return null;\n }\n\n const now = new Date().toISOString();\n const detail =\n `Agent declared account-bearing specialism(s) [${accountBearing.join(', ')}] but advertises ` +\n `neither list_accounts nor sync_accounts. AdCP 3.0.9 §accounts/overview requires every seller ` +\n `agent to expose at least one of these tools. Agent tools: [${profile.tools.join(', ')}].`;\n\n return {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n storyboard_title: 'Spec conformance: account discovery',\n agent_url: agentUrl,\n overall_passed: false,\n phases: [\n {\n phase_id: 'account_discovery_gate',\n phase_title: 'Account discovery',\n passed: false,\n duration_ms: 0,\n steps: [\n {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n step_id: 'list_or_sync_accounts',\n phase_id: 'account_discovery_gate',\n title: 'Seller agent must advertise list_accounts or sync_accounts',\n task: '',\n passed: false,\n duration_ms: 0,\n validations: [],\n context: {},\n error: detail,\n extraction: { path: 'none' },\n },\n ],\n },\n ],\n context: {},\n total_duration_ms: 0,\n passed_count: 0,\n failed_count: 1,\n skipped_count: 0,\n tested_at: now,\n notices: [],\n };\n}\n"],"mappings":"AAkCO,MAAM,uCAAuC;AAwBpD,SAAS,2BAA2B,YAA6B;AAC/D,MAAI,WAAW,WAAW,QAAQ,EAAG,QAAO;AAC5C,MAAI,eAAe,gBAAiB,QAAO;AAC3C,MAAI,WAAW,WAAW,aAAa,EAAG,QAAO;AACjD,MAAI,eAAe,sBAAuB,QAAO;AACjD,SAAO;AACT;AA2BO,SAAS,0BAA0B,SAAuB,UAA2C;AAC1G,QAAM,kBAAkB,QAAQ,eAAe,CAAC,GAAG,OAAO,0BAA0B;AACpF,MAAI,eAAe,WAAW,EAAG,QAAO;AAExC,MAAI,QAAQ,MAAM,SAAS,eAAe,KAAK,QAAQ,MAAM,SAAS,eAAe,GAAG;AACtF,WAAO;AAAA,EACT;AAEA,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,SACJ,iDAAiD,eAAe,KAAK,IAAI,CAAC,+KAEZ,QAAQ,MAAM,KAAK,IAAI,CAAC;AAExF,SAAO;AAAA,IACL,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,QAAQ;AAAA,MACN;AAAA,QACE,UAAU;AAAA,QACV,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,OAAO;AAAA,UACL;AAAA,YACE,eAAe;AAAA,YACf,SAAS;AAAA,YACT,UAAU;AAAA,YACV,OAAO;AAAA,YACP,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,aAAa,CAAC;AAAA,YACd,SAAS,CAAC;AAAA,YACV,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,OAAO;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA,IACV,mBAAmB;AAAA,IACnB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,SAAS,CAAC;AAAA,EACZ;AACF;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
const TRACK_LABELS = {
|
|
8
2
|
core: "Core Protocol",
|
|
9
3
|
products: "Product Discovery",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/compliance/storyboard-tracks.ts"],"sourcesContent":["/**\n * Bridges storyboard execution to the comply() track system.\n *\n * Maps StoryboardResult objects to TrackResult objects so that\n * comply() can use storyboards as its testing engine while\n * maintaining the existing ComplianceResult interface.\n */\n\nimport type { TestResult, TestStepResult, AgentProfile } from '../types';\nimport type { ComplianceTrack, TrackResult, TrackStatus, AdvisoryObservation } from './types';\nimport type { StoryboardResult, StoryboardStepResult } from '../storyboard/types';\n\n/** Labels for each compliance track. */\nexport const TRACK_LABELS: Record<ComplianceTrack, string> = {\n core: 'Core Protocol',\n products: 'Product Discovery',\n media_buy: 'Media Buy Lifecycle',\n creative: 'Creative Management',\n reporting: 'Reporting & Delivery',\n governance: 'Governance',\n campaign_governance: 'Campaign Governance',\n signals: 'Signals',\n si: 'Sponsored Intelligence',\n audiences: 'Audience Management',\n error_handling: 'Error Handling',\n brand: 'Brand Rights',\n};\n\n/**\n * Convert storyboard results to a TrackResult for backwards-compatible ComplianceResult.\n */\nexport function mapStoryboardResultsToTrackResult(\n track: ComplianceTrack,\n storyboardResults: StoryboardResult[],\n _profile: AgentProfile\n): TrackResult {\n const label = TRACK_LABELS[track] || track;\n\n // No storyboards ran for this track\n if (storyboardResults.length === 0) {\n return {\n track,\n status: 'skip',\n label,\n scenarios: [],\n skipped_scenarios: [],\n observations: [],\n duration_ms: 0,\n };\n }\n\n // Convert each storyboard result into pseudo-TestResults (one per phase)\n const scenarios: TestResult[] = [];\n const observations: AdvisoryObservation[] = [];\n let totalDuration = 0;\n\n for (const sbResult of storyboardResults) {\n totalDuration += sbResult.total_duration_ms;\n\n for (const phase of sbResult.phases) {\n const steps: TestStepResult[] = phase.steps.map(stepResult => mapStepToTestStep(stepResult));\n\n const testResult: TestResult = {\n agent_url: sbResult.agent_url,\n scenario: `${sbResult.storyboard_id}/${phase.phase_id}` as any,\n overall_passed: phase.passed,\n steps,\n summary: phase.passed\n ? `${phase.phase_title}: all steps passed`\n : `${phase.phase_title}: ${steps.filter(s => !s.passed).length} step(s) failed`,\n total_duration_ms: phase.duration_ms,\n tested_at: sbResult.tested_at,\n };\n\n scenarios.push(testResult);\n }\n }\n\n // Determine track status\n const status = computeTrackStatus(storyboardResults);\n\n // Detect deterministic mode\n const hasDeterministic = storyboardResults.some(r =>\n r.phases.some(p => p.steps.some(s => s.task === 'comply_test_controller'))\n );\n\n return {\n track,\n status,\n label,\n scenarios,\n skipped_scenarios: [],\n observations,\n duration_ms: totalDuration,\n mode: hasDeterministic ? 'deterministic' : 'observational',\n };\n}\n\n/**\n * Map a StoryboardStepResult to a TestStepResult.\n */\nfunction mapStepToTestStep(stepResult: StoryboardStepResult): TestStepResult {\n // v.warning carries actionable hints (shape-drift recipes, strict deltas,\n // variant-fallback notices). Append alongside v.error so JSON consumers —\n // CI dashboards, LLM self-correction loops, JUnit formatters — see the\n // recipe without having to know to read the full ValidationResult shape.\n const validationDetails = stepResult.validations\n .map(v => {\n const status = v.passed ? '✓' : '✗';\n const error = v.error ? `: ${v.error}` : '';\n const warning = v.warning ? ` [⚠ ${v.warning}]` : '';\n return `${status} ${v.description}${error}${warning}`;\n })\n .join('; ');\n\n return {\n step: stepResult.title,\n task: stepResult.task,\n passed: stepResult.passed,\n duration_ms: stepResult.duration_ms,\n error: stepResult.error,\n details: validationDetails || undefined,\n observation_data: stepResult.response as Record<string, unknown> | undefined,\n warnings: stepResult.skipped\n ? [stepResult.skip?.detail ?? skipReasonLabel(stepResult.skip_reason) ?? 'Step skipped']\n : undefined,\n ...(stepResult.skipped && { skipped: true as const }),\n ...(stepResult.skip_reason && { skip_reason: stepResult.skip_reason }),\n ...(stepResult.selection_result?.reason && { selection_reason: stepResult.selection_result.reason }),\n ...(stepResult.skip?.requirement && { requirement: stepResult.skip.requirement }),\n };\n}\n\nfunction skipReasonLabel(reason: string | undefined): string | undefined {\n if (!reason) return undefined;\n const labels: Record<string, string> = {\n // `not_applicable` is the spec reason for both\n // \"agent did not declare this protocol/specialism\" AND\n // \"storyboard was introduced in a later AdCP version\".\n not_applicable:\n 'Not applicable: agent did not declare this protocol/specialism, or storyboard was introduced in a later AdCP version',\n no_phases: 'Skipped: storyboard has no executable phases',\n prerequisite_failed: 'Skipped: a prerequisite did not pass',\n missing_tool: 'Skipped: agent did not advertise the required tool',\n missing_test_controller: 'Not testable: requires comply_test_controller',\n unsatisfied_contract: 'Skipped: test-kit contract is out of scope',\n peer_branch_taken: 'Skipped: a peer branch in the same any_of branch set already contributed the aggregation flag',\n };\n return labels[reason];\n}\n\n/**\n * Compute the track status from storyboard results.\n *\n * `silent` lands when every observation-based invariant on the track\n * ran with zero observations *and* nothing failed — the agent is wired\n * but its lifecycle protections were not exercised this run, so the\n * track has nothing to attest. See `TrackStatus` doc and\n * adcontextprotocol/adcp#2834.\n */\nfunction computeTrackStatus(results: StoryboardResult[]): TrackStatus {\n const totalPassed = results.reduce((sum, r) => sum + r.passed_count, 0);\n const totalFailed = results.reduce((sum, r) => sum + r.failed_count, 0);\n const totalSkipped = results.reduce((sum, r) => sum + r.skipped_count, 0);\n const totalSteps = totalPassed + totalFailed + totalSkipped;\n\n if (totalSteps === 0) return 'skip';\n if (totalSteps === totalSkipped) return 'skip';\n if (totalFailed > 0) return totalPassed === 0 ? 'fail' : 'partial';\n\n // No failures. Demote to `silent` when every observation-bearing\n // invariant record reports zero observations. Step-level passes alone\n // (response_schema, field_present, …) are not enough to lift a track\n // out of silent — only an invariant that actually observed a\n // lifecycle resource counts as real protection. Tracks whose\n // invariants don't carry `observation_count` (no observation-based\n // assertion ran) stay `pass` as before.\n const observationRecords = results\n .flatMap(r => r.assertions ?? [])\n .filter(a => typeof a.observation_count === 'number');\n if (observationRecords.length > 0 && observationRecords.every(a => a.observation_count === 0)) {\n return 'silent';\n }\n return 'pass';\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/compliance/storyboard-tracks.ts"],"sourcesContent":["/**\n * Bridges storyboard execution to the comply() track system.\n *\n * Maps StoryboardResult objects to TrackResult objects so that\n * comply() can use storyboards as its testing engine while\n * maintaining the existing ComplianceResult interface.\n */\n\nimport type { TestResult, TestStepResult, AgentProfile } from '../types';\nimport type { ComplianceTrack, TrackResult, TrackStatus, AdvisoryObservation } from './types';\nimport type { StoryboardResult, StoryboardStepResult } from '../storyboard/types';\n\n/** Labels for each compliance track. */\nexport const TRACK_LABELS: Record<ComplianceTrack, string> = {\n core: 'Core Protocol',\n products: 'Product Discovery',\n media_buy: 'Media Buy Lifecycle',\n creative: 'Creative Management',\n reporting: 'Reporting & Delivery',\n governance: 'Governance',\n campaign_governance: 'Campaign Governance',\n signals: 'Signals',\n si: 'Sponsored Intelligence',\n audiences: 'Audience Management',\n error_handling: 'Error Handling',\n brand: 'Brand Rights',\n};\n\n/**\n * Convert storyboard results to a TrackResult for backwards-compatible ComplianceResult.\n */\nexport function mapStoryboardResultsToTrackResult(\n track: ComplianceTrack,\n storyboardResults: StoryboardResult[],\n _profile: AgentProfile\n): TrackResult {\n const label = TRACK_LABELS[track] || track;\n\n // No storyboards ran for this track\n if (storyboardResults.length === 0) {\n return {\n track,\n status: 'skip',\n label,\n scenarios: [],\n skipped_scenarios: [],\n observations: [],\n duration_ms: 0,\n };\n }\n\n // Convert each storyboard result into pseudo-TestResults (one per phase)\n const scenarios: TestResult[] = [];\n const observations: AdvisoryObservation[] = [];\n let totalDuration = 0;\n\n for (const sbResult of storyboardResults) {\n totalDuration += sbResult.total_duration_ms;\n\n for (const phase of sbResult.phases) {\n const steps: TestStepResult[] = phase.steps.map(stepResult => mapStepToTestStep(stepResult));\n\n const testResult: TestResult = {\n agent_url: sbResult.agent_url,\n scenario: `${sbResult.storyboard_id}/${phase.phase_id}` as any,\n overall_passed: phase.passed,\n steps,\n summary: phase.passed\n ? `${phase.phase_title}: all steps passed`\n : `${phase.phase_title}: ${steps.filter(s => !s.passed).length} step(s) failed`,\n total_duration_ms: phase.duration_ms,\n tested_at: sbResult.tested_at,\n };\n\n scenarios.push(testResult);\n }\n }\n\n // Determine track status\n const status = computeTrackStatus(storyboardResults);\n\n // Detect deterministic mode\n const hasDeterministic = storyboardResults.some(r =>\n r.phases.some(p => p.steps.some(s => s.task === 'comply_test_controller'))\n );\n\n return {\n track,\n status,\n label,\n scenarios,\n skipped_scenarios: [],\n observations,\n duration_ms: totalDuration,\n mode: hasDeterministic ? 'deterministic' : 'observational',\n };\n}\n\n/**\n * Map a StoryboardStepResult to a TestStepResult.\n */\nfunction mapStepToTestStep(stepResult: StoryboardStepResult): TestStepResult {\n // v.warning carries actionable hints (shape-drift recipes, strict deltas,\n // variant-fallback notices). Append alongside v.error so JSON consumers —\n // CI dashboards, LLM self-correction loops, JUnit formatters — see the\n // recipe without having to know to read the full ValidationResult shape.\n const validationDetails = stepResult.validations\n .map(v => {\n const status = v.passed ? '✓' : '✗';\n const error = v.error ? `: ${v.error}` : '';\n const warning = v.warning ? ` [⚠ ${v.warning}]` : '';\n return `${status} ${v.description}${error}${warning}`;\n })\n .join('; ');\n\n return {\n step: stepResult.title,\n task: stepResult.task,\n passed: stepResult.passed,\n duration_ms: stepResult.duration_ms,\n error: stepResult.error,\n details: validationDetails || undefined,\n observation_data: stepResult.response as Record<string, unknown> | undefined,\n warnings: stepResult.skipped\n ? [stepResult.skip?.detail ?? skipReasonLabel(stepResult.skip_reason) ?? 'Step skipped']\n : undefined,\n ...(stepResult.skipped && { skipped: true as const }),\n ...(stepResult.skip_reason && { skip_reason: stepResult.skip_reason }),\n ...(stepResult.selection_result?.reason && { selection_reason: stepResult.selection_result.reason }),\n ...(stepResult.skip?.requirement && { requirement: stepResult.skip.requirement }),\n };\n}\n\nfunction skipReasonLabel(reason: string | undefined): string | undefined {\n if (!reason) return undefined;\n const labels: Record<string, string> = {\n // `not_applicable` is the spec reason for both\n // \"agent did not declare this protocol/specialism\" AND\n // \"storyboard was introduced in a later AdCP version\".\n not_applicable:\n 'Not applicable: agent did not declare this protocol/specialism, or storyboard was introduced in a later AdCP version',\n no_phases: 'Skipped: storyboard has no executable phases',\n prerequisite_failed: 'Skipped: a prerequisite did not pass',\n missing_tool: 'Skipped: agent did not advertise the required tool',\n missing_test_controller: 'Not testable: requires comply_test_controller',\n unsatisfied_contract: 'Skipped: test-kit contract is out of scope',\n peer_branch_taken: 'Skipped: a peer branch in the same any_of branch set already contributed the aggregation flag',\n };\n return labels[reason];\n}\n\n/**\n * Compute the track status from storyboard results.\n *\n * `silent` lands when every observation-based invariant on the track\n * ran with zero observations *and* nothing failed — the agent is wired\n * but its lifecycle protections were not exercised this run, so the\n * track has nothing to attest. See `TrackStatus` doc and\n * adcontextprotocol/adcp#2834.\n */\nfunction computeTrackStatus(results: StoryboardResult[]): TrackStatus {\n const totalPassed = results.reduce((sum, r) => sum + r.passed_count, 0);\n const totalFailed = results.reduce((sum, r) => sum + r.failed_count, 0);\n const totalSkipped = results.reduce((sum, r) => sum + r.skipped_count, 0);\n const totalSteps = totalPassed + totalFailed + totalSkipped;\n\n if (totalSteps === 0) return 'skip';\n if (totalSteps === totalSkipped) return 'skip';\n if (totalFailed > 0) return totalPassed === 0 ? 'fail' : 'partial';\n\n // No failures. Demote to `silent` when every observation-bearing\n // invariant record reports zero observations. Step-level passes alone\n // (response_schema, field_present, …) are not enough to lift a track\n // out of silent — only an invariant that actually observed a\n // lifecycle resource counts as real protection. Tracks whose\n // invariants don't carry `observation_count` (no observation-based\n // assertion ran) stay `pass` as before.\n const observationRecords = results\n .flatMap(r => r.assertions ?? [])\n .filter(a => typeof a.observation_count === 'number');\n if (observationRecords.length > 0 && observationRecords.every(a => a.observation_count === 0)) {\n return 'silent';\n }\n return 'pass';\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import { DETAILED_SKIP_TO_CANONICAL } from "../storyboard/types.mjs";
|
|
8
2
|
const SUMMARY_SCHEMA_VERSION = 2;
|
|
9
3
|
function buildComplianceSummary(result, opts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/compliance/summary.ts"],"sourcesContent":["/**\n * Narrow, schema-stable summary artifact for compliance runs.\n *\n * `formatComplianceResultsJSON` serializes the full ComplianceResult — that\n * shape evolves with the protocol. Downstream tooling (badges, Slack bots,\n * dashboards) wants a thin contract: pass/fail counts and a flat list of\n * failures with stable IDs. That's what this module provides.\n *\n * Three renderers:\n * - `buildComplianceSummary` → ComplianceSummaryArtifact (the JSON contract)\n * - `formatComplianceSummaryText` → stderr block with greppable `STORYBOARD-FAIL` prefix\n * - `formatComplianceSummaryMarkdown` → table for $GITHUB_STEP_SUMMARY\n *\n * The v2 summary separates selected-but-skipped steps from not-selected\n * exclusions. Treat unknown fields as ignorable per schema_version semantics.\n * Crash-path summaries built by `buildCrashSummary` omit `skip_causes`\n * because the runner never reached the storyboard execution phase.\n */\n\nimport type {\n ComplianceFailure,\n ComplianceNotSelectedRecord,\n ComplianceResult,\n ComplianceTrack,\n OverallStatus,\n} from './types';\nimport type { RunnerSelectionReason, RunnerSkipReason } from '../storyboard/types';\nimport { DETAILED_SKIP_TO_CANONICAL, type RunnerDetailedSkipReason } from '../storyboard/types';\n\nconst SUMMARY_SCHEMA_VERSION = 2;\n\n/**\n * A grouped skip-cause entry for the always-on summary block.\n * Only actionable causes are included — internal runner routing skips\n * (peer_branch_taken, not_applicable, etc.) are filtered out.\n */\nexport interface ComplianceSummarySkipCause {\n cause: string;\n count: number;\n detail: string;\n /** Scenario IDs affected (capped at SKIP_CAUSE_AFFECTED_LIMIT; remainder noted in text output). */\n affected: string[];\n}\n\n/**\n * Stable, schema-versioned summary. Adopters depending on this shape should\n * gate on `schema_version` and treat unknown fields as ignorable.\n */\nexport interface ComplianceSummaryArtifact {\n schema_version: number;\n agent_url: string;\n sdk_version: string;\n adcp_version: string;\n overall_status: OverallStatus;\n passed: number;\n failed: number;\n skipped: number;\n /**\n * Validation results graded `not_applicable`. Present only when non-zero so\n * CI/badge consumers can distinguish clean passes from downgraded coverage.\n */\n validations_not_applicable?: number;\n not_selected_count: number;\n not_selected_by_reason: Partial<Record<RunnerSelectionReason, number>>;\n skipped_by_reason: Partial<Record<RunnerSkipReason | string, number>>;\n not_selected?: ComplianceNotSelectedRecord[];\n total_duration_ms: number;\n tested_at: string;\n storyboards_executed: string[];\n failures: ComplianceSummaryFailure[];\n /** Actionable skip causes grouped by reason. Present only when skipped > 0. */\n skip_causes?: ComplianceSummarySkipCause[];\n}\n\n/**\n * Discriminator for `reason`. Lets a Slack bot color-code or filter without\n * regexing the reason string. Pinned at v1; new kinds are additive.\n */\nexport type ComplianceSummaryFailureKind =\n | 'error' /** The step itself raised — network, transport, runtime exception. */\n | 'validation' /** A storyboard validation check failed (schema, field_present, etc.). */\n | 'expected_mismatch' /** No structured validation; reason derived from the step's `expected:` text. */\n | 'unspecified'; /** Failure with no extractable reason — should be rare. */\n\nexport interface ComplianceSummaryFailure {\n track: ComplianceTrack;\n storyboard_id: string;\n step_id: string;\n reason: string;\n reason_kind: ComplianceSummaryFailureKind;\n}\n\nexport interface BuildSummaryOptions {\n sdkVersion: string;\n adcpVersion: string;\n}\n\nexport function buildComplianceSummary(result: ComplianceResult, opts: BuildSummaryOptions): ComplianceSummaryArtifact {\n const skipCauses = buildSkipCauses(result);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: result.agent_url,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: result.overall_status,\n passed: result.summary.steps_passed ?? 0,\n failed: result.summary.steps_failed ?? 0,\n skipped: result.summary.steps_skipped ?? 0,\n ...(result.summary.validations_not_applicable\n ? { validations_not_applicable: result.summary.validations_not_applicable }\n : {}),\n not_selected_count: result.summary.steps_not_selected ?? 0,\n not_selected_by_reason: result.summary.not_selected_by_reason ?? {},\n skipped_by_reason: result.summary.skipped_by_reason ?? {},\n ...(result.summary.not_selected?.length ? { not_selected: result.summary.not_selected } : {}),\n total_duration_ms: result.total_duration_ms,\n tested_at: result.tested_at,\n storyboards_executed: result.storyboards_executed ?? [],\n failures: (result.failures ?? []).map(toSummaryFailure),\n ...(skipCauses.length > 0 ? { skip_causes: skipCauses } : {}),\n };\n}\n\nfunction toSummaryFailure(f: ComplianceFailure): ComplianceSummaryFailure {\n const { reason, reason_kind } = deriveReason(f);\n return {\n track: f.track,\n storyboard_id: f.storyboard_id,\n step_id: f.step_id,\n reason,\n reason_kind,\n };\n}\n\nconst REASON_MAX_CHARS = 500;\n\nfunction deriveReason(f: ComplianceFailure): { reason: string; reason_kind: ComplianceSummaryFailureKind } {\n if (f.error) return { reason: truncate(f.error, REASON_MAX_CHARS), reason_kind: 'error' };\n if (f.validation?.description) {\n const desc = f.validation.description;\n const ptr = f.validation.json_pointer ? ` at ${f.validation.json_pointer}` : '';\n return { reason: truncate(`${desc}${ptr}`, REASON_MAX_CHARS), reason_kind: 'validation' };\n }\n if (f.expected) {\n return { reason: truncate(f.expected.split('\\n')[0]!, REASON_MAX_CHARS), reason_kind: 'expected_mismatch' };\n }\n return { reason: 'failed', reason_kind: 'unspecified' };\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// Skip-cause aggregation\n// ────────────────────────────────────────────────────────────────────────────\n\nconst SKIP_CAUSE_AFFECTED_LIMIT = 5;\n\n// Actionable canonical reasons — gaps the adopter can close. Internal\n// runner-routing reasons (peer_branch_taken, not_applicable, …) are excluded\n// because they are expected behavior, not agent deficiencies. Detailed\n// skip reasons (e.g. `controller_seeding_failed`, `capability_unsupported`,\n// `requirement_unmet` per adcp-client#1626) are normalized via\n// `DETAILED_SKIP_TO_CANONICAL` before this lookup; the runner writes\n// detailed forms to `step.skip_reason` directly per types.ts so consumers\n// of `step.skip_reason` see the more specific value.\nconst ACTIONABLE_CANONICAL_REASONS = new Set<string>([\n 'missing_tool',\n 'missing_test_controller',\n 'prerequisite_failed',\n 'unsatisfied_contract',\n 'no_phases',\n 'requirement_unmet',\n]);\n\n/**\n * True when the skip reason is something the adopter can act on.\n * Accepts both canonical `RunnerSkipReason` and detailed\n * `RunnerDetailedSkipReason` strings — detailed forms are mapped to their\n * canonical equivalent before the actionability check, so e.g.\n * `controller_seeding_failed` (detailed) → `prerequisite_failed`\n * (canonical, actionable) is correctly surfaced rather than silently\n * dropped.\n */\nfunction isActionableSkipReason(reason: string): boolean {\n if (ACTIONABLE_CANONICAL_REASONS.has(reason)) return true;\n const canonical = DETAILED_SKIP_TO_CANONICAL[reason as RunnerDetailedSkipReason];\n return canonical !== undefined && ACTIONABLE_CANONICAL_REASONS.has(canonical);\n}\n\nfunction extractMissingToolNames(warning: string): string[] {\n // Step-level: `Agent did not advertise tool \"sync_accounts\"; agent tools: [...]`\n const stepMatch = warning.match(/Agent did not advertise tool \"([^\"]+)\"/i);\n if (stepMatch) return [stepMatch[1]!];\n // Storyboard-level: `agent does not advertise any of [sync_accounts, list_accounts]`\n // Each tool is a separate gap — emit one cause per tool so dashboards see\n // the full list, not a single comma-joined \"tool name\".\n const sbMatch = warning.match(/agent does not advertise any of \\[([^\\]]+)\\]/i);\n if (sbMatch) {\n return sbMatch[1]!\n .split(/,\\s*/)\n .map(t => t.trim())\n .filter(Boolean);\n }\n return [];\n}\n\nfunction skipCauseDetail(reason: string): string {\n switch (reason) {\n case 'missing_test_controller':\n return \"agent doesn't expose comply_test_controller\";\n case 'missing_tool':\n return \"agent doesn't advertise tool\";\n case 'prerequisite_failed':\n return 'prerequisite step did not pass';\n case 'unsatisfied_contract':\n return 'test-kit contract out of scope';\n case 'no_phases':\n return 'storyboard has no executable phases';\n case 'requirement_unmet':\n return 'storyboard requires a runtime that is not available on this run';\n case 'controller_seeding_failed':\n return 'pre-flight controller seeding failed';\n case 'capability_unsupported':\n return 'agent self-declared capability unsupported';\n default:\n return reason;\n }\n}\n\nfunction buildSkipCauses(result: ComplianceResult): ComplianceSummarySkipCause[] {\n const causeMap = new Map<string, { count: number; detail: string; affectedSet: Set<string> }>();\n\n const recordCause = (causeKey: string, baseReason: string, scenarioId: string) => {\n if (!causeMap.has(causeKey)) {\n causeMap.set(causeKey, {\n count: 0,\n detail: skipCauseDetail(baseReason),\n affectedSet: new Set(),\n });\n }\n const entry = causeMap.get(causeKey)!;\n entry.count++;\n entry.affectedSet.add(scenarioId);\n };\n\n for (const track of result.tracks) {\n for (const scenario of track.scenarios) {\n const scenarioId = String(scenario.scenario);\n for (const step of scenario.steps ?? []) {\n if (!step.skipped || !step.skip_reason) continue;\n if (step.selection_reason) continue;\n if (!isActionableSkipReason(step.skip_reason)) continue;\n\n // missing_tool: sub-group by tool name. Storyboard-level matches\n // can carry multiple tools (one cause per tool); step-level matches\n // are always single-tool. extractMissingToolNames returns [] when\n // the warning text doesn't match either pattern, in which case we\n // fall through to the un-grouped reason.\n if (step.skip_reason === 'missing_tool' && step.warnings?.[0]) {\n const toolNames = extractMissingToolNames(step.warnings[0]);\n if (toolNames.length > 0) {\n for (const toolName of toolNames) {\n recordCause(`missing_tool: ${toolName}`, 'missing_tool', scenarioId);\n }\n continue;\n }\n }\n\n // requirement_unmet: sub-group by the unmet requirement name\n // (adcp-client#1626). The runner emits `step.skip.requirement`\n // which `toComplianceStep` propagates as `step.requirement` on\n // the flattened `TestStepResult`, so per-requirement aggregation\n // works without parsing the warning text.\n if (step.skip_reason === 'requirement_unmet' && step.requirement) {\n recordCause(`requirement_unmet: ${step.requirement}`, 'requirement_unmet', scenarioId);\n continue;\n }\n if (step.skip_reason === 'requirement_unmet' && step.warnings?.[0]) {\n const requiredFamily = parseMissingRequiredToolFamilyCause(step.warnings[0]);\n if (requiredFamily) {\n recordCause(requiredFamily, 'requirement_unmet', scenarioId);\n continue;\n }\n }\n\n recordCause(step.skip_reason, step.skip_reason, scenarioId);\n }\n }\n }\n\n return Array.from(causeMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([cause, { count, detail, affectedSet }]) => ({\n cause,\n count,\n detail,\n // Cap at aggregator level so JSON consumers see the same bound the\n // text/markdown renderers honor — keeps the JSON contract truthful\n // about the cap documented on `ComplianceSummarySkipCause.affected`.\n affected: Array.from(affectedSet).slice(0, SKIP_CAUSE_AFFECTED_LIMIT),\n }));\n}\n\nfunction parseMissingRequiredToolFamilyCause(warning: string): string | null {\n const match = warning.match(/^missing_required_tool_family: needs\\s+([\\s\\S]*)$/);\n if (!match) return null;\n const family = match[1]!.replace(/\\s*[;(][\\s\\S]*$/, '').trim();\n return family ? `missing_required_tool_family: needs ${family}` : null;\n}\n\n/**\n * Hard-failure statuses — runs that should never look green to CI. `partial`\n * is intentionally not in this set: it means some tracks ran silent (wired\n * but unexercised), which is a reportable observation, not a CI block.\n */\nconst HARD_FAIL_STATUSES = new Set<OverallStatus>(['failing', 'unreachable', 'auth_required']);\n\nfunction isHardFail(s: ComplianceSummaryArtifact): boolean {\n return HARD_FAIL_STATUSES.has(s.overall_status) || s.failures.length > 0;\n}\n\nfunction formatReasonCounts(counts: Partial<Record<string, number>> | undefined): string | undefined {\n if (!counts) return undefined;\n const entries = Object.entries(counts).filter(\n (entry): entry is [string, number] => typeof entry[1] === 'number' && entry[1] > 0\n );\n if (entries.length === 0) return undefined;\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([reason, count]) => `${reason}=${count}`)\n .join(', ');\n}\n\n/**\n * stderr-style summary block. Always starts with `STORYBOARD-FAIL` (kebab,\n * no spaces) on any hard-failing run, so CI scripts can `grep -q STORYBOARD-FAIL`\n * regardless of how the workflow handles the exit code. `partial` runs render\n * `STORYBOARD-PARTIAL` — distinct from both green and red so dashboards can\n * surface \"wired but unexercised\" without false-alarming CI.\n */\nexport function formatComplianceSummaryText(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n lines.push('');\n lines.push(`──── Storyboard Summary ────`);\n lines.push(`Agent: ${s.agent_url}`);\n lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);\n lines.push(`Status: ${s.overall_status}`);\n lines.push(\n `Steps: ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`Skipped: ${skippedReasons}`);\n if (s.skip_causes?.length) {\n const countWidth = String(Math.max(...s.skip_causes.map(c => c.count))).length;\n // \" [\" + countWidth chars + \"] \" — derived so Affected: aligns under the cause text\n const affectedIndent = ' '.repeat(4 + 1 + countWidth + 1 + 1);\n lines.push(` Skip causes:`);\n for (const cause of s.skip_causes) {\n const count = String(cause.count).padStart(countWidth);\n lines.push(` [${count}] ${cause.cause} — ${cause.detail}`);\n // Overflow is the difference between the total count for this cause\n // and how many distinct scenario IDs we kept after the aggregator's\n // SKIP_CAUSE_AFFECTED_LIMIT cap. The slice here is defensive — the\n // aggregator already caps, but if a future caller hands us an\n // uncapped artifact (e.g. JSON re-input from an older runner), we\n // still bound the visible list.\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText = overflow > 0 ? `${visible.join(', ')}, … ${overflow} more` : visible.join(', ');\n lines.push(`${affectedIndent}Affected: ${affectedText}`);\n }\n }\n lines.push(`Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (!isHardFail(s)) {\n if (s.overall_status === 'passing') {\n lines.push(`STORYBOARD-OK ${s.passed}/${s.passed + s.failed + s.skipped} selected steps passed`);\n } else {\n // `partial` and `silent` — some tracks were wired but not exercised.\n // Distinct marker so dashboards can surface this without lighting CI red.\n lines.push(`STORYBOARD-PARTIAL ${s.passed} steps passed, run ended ${s.overall_status}`);\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n if (s.failures.length === 0) {\n lines.push(`STORYBOARD-FAIL run ended ${s.overall_status} with no graded steps`);\n } else {\n lines.push(`STORYBOARD-FAIL ${s.failures.length} step(s):`);\n for (const f of s.failures) {\n lines.push(` - ${f.storyboard_id}/${f.step_id} [${f.track}]: ${f.reason}`);\n }\n }\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Markdown for `$GITHUB_STEP_SUMMARY`. Renders in the PR UI summary panel,\n * so reviewers see failures without opening the run log.\n */\nexport function formatComplianceSummaryMarkdown(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n const heading = !isHardFail(s)\n ? s.overall_status === 'passing'\n ? '✅ Storyboard run passed'\n : `⚠️ Storyboard run ended ${s.overall_status} (wired but partly unexercised)`\n : s.failures.length === 0\n ? `❌ Storyboard run: ended ${s.overall_status} with no graded steps`\n : `❌ Storyboard run: ${s.failures.length} failure(s)`;\n lines.push(`## ${heading}`);\n lines.push('');\n lines.push(`- **Agent:** \\`${s.agent_url}\\``);\n lines.push(`- **SDK:** \\`@adcp/sdk ${s.sdk_version}\\` (AdCP \\`${s.adcp_version}\\`)`);\n lines.push(`- **Status:** \\`${s.overall_status}\\``);\n lines.push(\n `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`- **Skipped:** ${skippedReasons}`);\n lines.push(`- **Duration:** ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (s.failures.length > 0) {\n lines.push('| Track | Storyboard | Step | Reason |');\n lines.push('| --- | --- | --- | --- |');\n for (const f of s.failures) {\n lines.push(`| \\`${f.track}\\` | \\`${f.storyboard_id}\\` | \\`${f.step_id}\\` | ${escapeTableCell(f.reason)} |`);\n }\n lines.push('');\n }\n\n if (s.skip_causes?.length) {\n const total = s.skip_causes.reduce((n, c) => n + c.count, 0);\n lines.push(`<details>`);\n lines.push(\n `<summary>Skip causes (${s.skip_causes.length} cause${s.skip_causes.length === 1 ? '' : 's'}, ${total} skipped step${total === 1 ? '' : 's'})</summary>`\n );\n lines.push('');\n lines.push('| Count | Cause | Detail | Affected |');\n lines.push('| --- | --- | --- | --- |');\n for (const cause of s.skip_causes) {\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText =\n overflow > 0\n ? `${visible.map(escapeTableCell).join(', ')}, … ${overflow} more`\n : visible.map(escapeTableCell).join(', ');\n lines.push(\n `| ${cause.count} | \\`${escapeTableCell(cause.cause)}\\` | ${escapeTableCell(cause.detail)} | ${affectedText} |`\n );\n }\n lines.push('');\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction escapeTableCell(s: string): string {\n // Escape backslashes first so a `\\|` in the input doesn't combine with\n // the pipe-escape below and produce `\\\\|` (literal backslash + raw pipe,\n // which breaks the table). Order matters: `\\` → `\\\\` then `|` → `\\|`.\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n\n/**\n * Synthesize a summary artifact when the runner itself crashed before\n * `comply()` produced a result (network down, capabilities parse error,\n * auth handshake exception). Schema-stable on the same summary artifact\n * contract so a Slack bot built against the artifact sees a valid payload\n * — rather than nothing — precisely when the agent is broken hardest.\n */\nexport interface BuildCrashSummaryOptions extends BuildSummaryOptions {\n agentUrl: string;\n error: Error | string;\n startedAt: string;\n durationMs: number;\n}\n\nexport function buildCrashSummary(opts: BuildCrashSummaryOptions): ComplianceSummaryArtifact {\n const message = opts.error instanceof Error ? opts.error.message : String(opts.error);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: opts.agentUrl,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: 'unreachable',\n passed: 0,\n failed: 1,\n skipped: 0,\n not_selected_count: 0,\n not_selected_by_reason: {},\n skipped_by_reason: {},\n total_duration_ms: opts.durationMs,\n tested_at: opts.startedAt,\n storyboards_executed: [],\n failures: [\n {\n track: 'core',\n storyboard_id: 'pre-flight',\n step_id: 'comply',\n reason: message.length > 500 ? `${message.slice(0, 499)}…` : message,\n reason_kind: 'error',\n },\n ],\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/compliance/summary.ts"],"sourcesContent":["/**\n * Narrow, schema-stable summary artifact for compliance runs.\n *\n * `formatComplianceResultsJSON` serializes the full ComplianceResult — that\n * shape evolves with the protocol. Downstream tooling (badges, Slack bots,\n * dashboards) wants a thin contract: pass/fail counts and a flat list of\n * failures with stable IDs. That's what this module provides.\n *\n * Three renderers:\n * - `buildComplianceSummary` → ComplianceSummaryArtifact (the JSON contract)\n * - `formatComplianceSummaryText` → stderr block with greppable `STORYBOARD-FAIL` prefix\n * - `formatComplianceSummaryMarkdown` → table for $GITHUB_STEP_SUMMARY\n *\n * The v2 summary separates selected-but-skipped steps from not-selected\n * exclusions. Treat unknown fields as ignorable per schema_version semantics.\n * Crash-path summaries built by `buildCrashSummary` omit `skip_causes`\n * because the runner never reached the storyboard execution phase.\n */\n\nimport type {\n ComplianceFailure,\n ComplianceNotSelectedRecord,\n ComplianceResult,\n ComplianceTrack,\n OverallStatus,\n} from './types';\nimport type { RunnerSelectionReason, RunnerSkipReason } from '../storyboard/types';\nimport { DETAILED_SKIP_TO_CANONICAL, type RunnerDetailedSkipReason } from '../storyboard/types';\n\nconst SUMMARY_SCHEMA_VERSION = 2;\n\n/**\n * A grouped skip-cause entry for the always-on summary block.\n * Only actionable causes are included — internal runner routing skips\n * (peer_branch_taken, not_applicable, etc.) are filtered out.\n */\nexport interface ComplianceSummarySkipCause {\n cause: string;\n count: number;\n detail: string;\n /** Scenario IDs affected (capped at SKIP_CAUSE_AFFECTED_LIMIT; remainder noted in text output). */\n affected: string[];\n}\n\n/**\n * Stable, schema-versioned summary. Adopters depending on this shape should\n * gate on `schema_version` and treat unknown fields as ignorable.\n */\nexport interface ComplianceSummaryArtifact {\n schema_version: number;\n agent_url: string;\n sdk_version: string;\n adcp_version: string;\n overall_status: OverallStatus;\n passed: number;\n failed: number;\n skipped: number;\n /**\n * Validation results graded `not_applicable`. Present only when non-zero so\n * CI/badge consumers can distinguish clean passes from downgraded coverage.\n */\n validations_not_applicable?: number;\n not_selected_count: number;\n not_selected_by_reason: Partial<Record<RunnerSelectionReason, number>>;\n skipped_by_reason: Partial<Record<RunnerSkipReason | string, number>>;\n not_selected?: ComplianceNotSelectedRecord[];\n total_duration_ms: number;\n tested_at: string;\n storyboards_executed: string[];\n failures: ComplianceSummaryFailure[];\n /** Actionable skip causes grouped by reason. Present only when skipped > 0. */\n skip_causes?: ComplianceSummarySkipCause[];\n}\n\n/**\n * Discriminator for `reason`. Lets a Slack bot color-code or filter without\n * regexing the reason string. Pinned at v1; new kinds are additive.\n */\nexport type ComplianceSummaryFailureKind =\n | 'error' /** The step itself raised — network, transport, runtime exception. */\n | 'validation' /** A storyboard validation check failed (schema, field_present, etc.). */\n | 'expected_mismatch' /** No structured validation; reason derived from the step's `expected:` text. */\n | 'unspecified'; /** Failure with no extractable reason — should be rare. */\n\nexport interface ComplianceSummaryFailure {\n track: ComplianceTrack;\n storyboard_id: string;\n step_id: string;\n reason: string;\n reason_kind: ComplianceSummaryFailureKind;\n}\n\nexport interface BuildSummaryOptions {\n sdkVersion: string;\n adcpVersion: string;\n}\n\nexport function buildComplianceSummary(result: ComplianceResult, opts: BuildSummaryOptions): ComplianceSummaryArtifact {\n const skipCauses = buildSkipCauses(result);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: result.agent_url,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: result.overall_status,\n passed: result.summary.steps_passed ?? 0,\n failed: result.summary.steps_failed ?? 0,\n skipped: result.summary.steps_skipped ?? 0,\n ...(result.summary.validations_not_applicable\n ? { validations_not_applicable: result.summary.validations_not_applicable }\n : {}),\n not_selected_count: result.summary.steps_not_selected ?? 0,\n not_selected_by_reason: result.summary.not_selected_by_reason ?? {},\n skipped_by_reason: result.summary.skipped_by_reason ?? {},\n ...(result.summary.not_selected?.length ? { not_selected: result.summary.not_selected } : {}),\n total_duration_ms: result.total_duration_ms,\n tested_at: result.tested_at,\n storyboards_executed: result.storyboards_executed ?? [],\n failures: (result.failures ?? []).map(toSummaryFailure),\n ...(skipCauses.length > 0 ? { skip_causes: skipCauses } : {}),\n };\n}\n\nfunction toSummaryFailure(f: ComplianceFailure): ComplianceSummaryFailure {\n const { reason, reason_kind } = deriveReason(f);\n return {\n track: f.track,\n storyboard_id: f.storyboard_id,\n step_id: f.step_id,\n reason,\n reason_kind,\n };\n}\n\nconst REASON_MAX_CHARS = 500;\n\nfunction deriveReason(f: ComplianceFailure): { reason: string; reason_kind: ComplianceSummaryFailureKind } {\n if (f.error) return { reason: truncate(f.error, REASON_MAX_CHARS), reason_kind: 'error' };\n if (f.validation?.description) {\n const desc = f.validation.description;\n const ptr = f.validation.json_pointer ? ` at ${f.validation.json_pointer}` : '';\n return { reason: truncate(`${desc}${ptr}`, REASON_MAX_CHARS), reason_kind: 'validation' };\n }\n if (f.expected) {\n return { reason: truncate(f.expected.split('\\n')[0]!, REASON_MAX_CHARS), reason_kind: 'expected_mismatch' };\n }\n return { reason: 'failed', reason_kind: 'unspecified' };\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// Skip-cause aggregation\n// ────────────────────────────────────────────────────────────────────────────\n\nconst SKIP_CAUSE_AFFECTED_LIMIT = 5;\n\n// Actionable canonical reasons — gaps the adopter can close. Internal\n// runner-routing reasons (peer_branch_taken, not_applicable, …) are excluded\n// because they are expected behavior, not agent deficiencies. Detailed\n// skip reasons (e.g. `controller_seeding_failed`, `capability_unsupported`,\n// `requirement_unmet` per adcp-client#1626) are normalized via\n// `DETAILED_SKIP_TO_CANONICAL` before this lookup; the runner writes\n// detailed forms to `step.skip_reason` directly per types.ts so consumers\n// of `step.skip_reason` see the more specific value.\nconst ACTIONABLE_CANONICAL_REASONS = new Set<string>([\n 'missing_tool',\n 'missing_test_controller',\n 'prerequisite_failed',\n 'unsatisfied_contract',\n 'no_phases',\n 'requirement_unmet',\n]);\n\n/**\n * True when the skip reason is something the adopter can act on.\n * Accepts both canonical `RunnerSkipReason` and detailed\n * `RunnerDetailedSkipReason` strings — detailed forms are mapped to their\n * canonical equivalent before the actionability check, so e.g.\n * `controller_seeding_failed` (detailed) → `prerequisite_failed`\n * (canonical, actionable) is correctly surfaced rather than silently\n * dropped.\n */\nfunction isActionableSkipReason(reason: string): boolean {\n if (ACTIONABLE_CANONICAL_REASONS.has(reason)) return true;\n const canonical = DETAILED_SKIP_TO_CANONICAL[reason as RunnerDetailedSkipReason];\n return canonical !== undefined && ACTIONABLE_CANONICAL_REASONS.has(canonical);\n}\n\nfunction extractMissingToolNames(warning: string): string[] {\n // Step-level: `Agent did not advertise tool \"sync_accounts\"; agent tools: [...]`\n const stepMatch = warning.match(/Agent did not advertise tool \"([^\"]+)\"/i);\n if (stepMatch) return [stepMatch[1]!];\n // Storyboard-level: `agent does not advertise any of [sync_accounts, list_accounts]`\n // Each tool is a separate gap — emit one cause per tool so dashboards see\n // the full list, not a single comma-joined \"tool name\".\n const sbMatch = warning.match(/agent does not advertise any of \\[([^\\]]+)\\]/i);\n if (sbMatch) {\n return sbMatch[1]!\n .split(/,\\s*/)\n .map(t => t.trim())\n .filter(Boolean);\n }\n return [];\n}\n\nfunction skipCauseDetail(reason: string): string {\n switch (reason) {\n case 'missing_test_controller':\n return \"agent doesn't expose comply_test_controller\";\n case 'missing_tool':\n return \"agent doesn't advertise tool\";\n case 'prerequisite_failed':\n return 'prerequisite step did not pass';\n case 'unsatisfied_contract':\n return 'test-kit contract out of scope';\n case 'no_phases':\n return 'storyboard has no executable phases';\n case 'requirement_unmet':\n return 'storyboard requires a runtime that is not available on this run';\n case 'controller_seeding_failed':\n return 'pre-flight controller seeding failed';\n case 'capability_unsupported':\n return 'agent self-declared capability unsupported';\n default:\n return reason;\n }\n}\n\nfunction buildSkipCauses(result: ComplianceResult): ComplianceSummarySkipCause[] {\n const causeMap = new Map<string, { count: number; detail: string; affectedSet: Set<string> }>();\n\n const recordCause = (causeKey: string, baseReason: string, scenarioId: string) => {\n if (!causeMap.has(causeKey)) {\n causeMap.set(causeKey, {\n count: 0,\n detail: skipCauseDetail(baseReason),\n affectedSet: new Set(),\n });\n }\n const entry = causeMap.get(causeKey)!;\n entry.count++;\n entry.affectedSet.add(scenarioId);\n };\n\n for (const track of result.tracks) {\n for (const scenario of track.scenarios) {\n const scenarioId = String(scenario.scenario);\n for (const step of scenario.steps ?? []) {\n if (!step.skipped || !step.skip_reason) continue;\n if (step.selection_reason) continue;\n if (!isActionableSkipReason(step.skip_reason)) continue;\n\n // missing_tool: sub-group by tool name. Storyboard-level matches\n // can carry multiple tools (one cause per tool); step-level matches\n // are always single-tool. extractMissingToolNames returns [] when\n // the warning text doesn't match either pattern, in which case we\n // fall through to the un-grouped reason.\n if (step.skip_reason === 'missing_tool' && step.warnings?.[0]) {\n const toolNames = extractMissingToolNames(step.warnings[0]);\n if (toolNames.length > 0) {\n for (const toolName of toolNames) {\n recordCause(`missing_tool: ${toolName}`, 'missing_tool', scenarioId);\n }\n continue;\n }\n }\n\n // requirement_unmet: sub-group by the unmet requirement name\n // (adcp-client#1626). The runner emits `step.skip.requirement`\n // which `toComplianceStep` propagates as `step.requirement` on\n // the flattened `TestStepResult`, so per-requirement aggregation\n // works without parsing the warning text.\n if (step.skip_reason === 'requirement_unmet' && step.requirement) {\n recordCause(`requirement_unmet: ${step.requirement}`, 'requirement_unmet', scenarioId);\n continue;\n }\n if (step.skip_reason === 'requirement_unmet' && step.warnings?.[0]) {\n const requiredFamily = parseMissingRequiredToolFamilyCause(step.warnings[0]);\n if (requiredFamily) {\n recordCause(requiredFamily, 'requirement_unmet', scenarioId);\n continue;\n }\n }\n\n recordCause(step.skip_reason, step.skip_reason, scenarioId);\n }\n }\n }\n\n return Array.from(causeMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([cause, { count, detail, affectedSet }]) => ({\n cause,\n count,\n detail,\n // Cap at aggregator level so JSON consumers see the same bound the\n // text/markdown renderers honor — keeps the JSON contract truthful\n // about the cap documented on `ComplianceSummarySkipCause.affected`.\n affected: Array.from(affectedSet).slice(0, SKIP_CAUSE_AFFECTED_LIMIT),\n }));\n}\n\nfunction parseMissingRequiredToolFamilyCause(warning: string): string | null {\n const match = warning.match(/^missing_required_tool_family: needs\\s+([\\s\\S]*)$/);\n if (!match) return null;\n const family = match[1]!.replace(/\\s*[;(][\\s\\S]*$/, '').trim();\n return family ? `missing_required_tool_family: needs ${family}` : null;\n}\n\n/**\n * Hard-failure statuses — runs that should never look green to CI. `partial`\n * is intentionally not in this set: it means some tracks ran silent (wired\n * but unexercised), which is a reportable observation, not a CI block.\n */\nconst HARD_FAIL_STATUSES = new Set<OverallStatus>(['failing', 'unreachable', 'auth_required']);\n\nfunction isHardFail(s: ComplianceSummaryArtifact): boolean {\n return HARD_FAIL_STATUSES.has(s.overall_status) || s.failures.length > 0;\n}\n\nfunction formatReasonCounts(counts: Partial<Record<string, number>> | undefined): string | undefined {\n if (!counts) return undefined;\n const entries = Object.entries(counts).filter(\n (entry): entry is [string, number] => typeof entry[1] === 'number' && entry[1] > 0\n );\n if (entries.length === 0) return undefined;\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([reason, count]) => `${reason}=${count}`)\n .join(', ');\n}\n\n/**\n * stderr-style summary block. Always starts with `STORYBOARD-FAIL` (kebab,\n * no spaces) on any hard-failing run, so CI scripts can `grep -q STORYBOARD-FAIL`\n * regardless of how the workflow handles the exit code. `partial` runs render\n * `STORYBOARD-PARTIAL` — distinct from both green and red so dashboards can\n * surface \"wired but unexercised\" without false-alarming CI.\n */\nexport function formatComplianceSummaryText(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n lines.push('');\n lines.push(`──── Storyboard Summary ────`);\n lines.push(`Agent: ${s.agent_url}`);\n lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);\n lines.push(`Status: ${s.overall_status}`);\n lines.push(\n `Steps: ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`Skipped: ${skippedReasons}`);\n if (s.skip_causes?.length) {\n const countWidth = String(Math.max(...s.skip_causes.map(c => c.count))).length;\n // \" [\" + countWidth chars + \"] \" — derived so Affected: aligns under the cause text\n const affectedIndent = ' '.repeat(4 + 1 + countWidth + 1 + 1);\n lines.push(` Skip causes:`);\n for (const cause of s.skip_causes) {\n const count = String(cause.count).padStart(countWidth);\n lines.push(` [${count}] ${cause.cause} — ${cause.detail}`);\n // Overflow is the difference between the total count for this cause\n // and how many distinct scenario IDs we kept after the aggregator's\n // SKIP_CAUSE_AFFECTED_LIMIT cap. The slice here is defensive — the\n // aggregator already caps, but if a future caller hands us an\n // uncapped artifact (e.g. JSON re-input from an older runner), we\n // still bound the visible list.\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText = overflow > 0 ? `${visible.join(', ')}, … ${overflow} more` : visible.join(', ');\n lines.push(`${affectedIndent}Affected: ${affectedText}`);\n }\n }\n lines.push(`Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (!isHardFail(s)) {\n if (s.overall_status === 'passing') {\n lines.push(`STORYBOARD-OK ${s.passed}/${s.passed + s.failed + s.skipped} selected steps passed`);\n } else {\n // `partial` and `silent` — some tracks were wired but not exercised.\n // Distinct marker so dashboards can surface this without lighting CI red.\n lines.push(`STORYBOARD-PARTIAL ${s.passed} steps passed, run ended ${s.overall_status}`);\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n if (s.failures.length === 0) {\n lines.push(`STORYBOARD-FAIL run ended ${s.overall_status} with no graded steps`);\n } else {\n lines.push(`STORYBOARD-FAIL ${s.failures.length} step(s):`);\n for (const f of s.failures) {\n lines.push(` - ${f.storyboard_id}/${f.step_id} [${f.track}]: ${f.reason}`);\n }\n }\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Markdown for `$GITHUB_STEP_SUMMARY`. Renders in the PR UI summary panel,\n * so reviewers see failures without opening the run log.\n */\nexport function formatComplianceSummaryMarkdown(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n const heading = !isHardFail(s)\n ? s.overall_status === 'passing'\n ? '✅ Storyboard run passed'\n : `⚠️ Storyboard run ended ${s.overall_status} (wired but partly unexercised)`\n : s.failures.length === 0\n ? `❌ Storyboard run: ended ${s.overall_status} with no graded steps`\n : `❌ Storyboard run: ${s.failures.length} failure(s)`;\n lines.push(`## ${heading}`);\n lines.push('');\n lines.push(`- **Agent:** \\`${s.agent_url}\\``);\n lines.push(`- **SDK:** \\`@adcp/sdk ${s.sdk_version}\\` (AdCP \\`${s.adcp_version}\\`)`);\n lines.push(`- **Status:** \\`${s.overall_status}\\``);\n lines.push(\n `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`- **Skipped:** ${skippedReasons}`);\n lines.push(`- **Duration:** ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (s.failures.length > 0) {\n lines.push('| Track | Storyboard | Step | Reason |');\n lines.push('| --- | --- | --- | --- |');\n for (const f of s.failures) {\n lines.push(`| \\`${f.track}\\` | \\`${f.storyboard_id}\\` | \\`${f.step_id}\\` | ${escapeTableCell(f.reason)} |`);\n }\n lines.push('');\n }\n\n if (s.skip_causes?.length) {\n const total = s.skip_causes.reduce((n, c) => n + c.count, 0);\n lines.push(`<details>`);\n lines.push(\n `<summary>Skip causes (${s.skip_causes.length} cause${s.skip_causes.length === 1 ? '' : 's'}, ${total} skipped step${total === 1 ? '' : 's'})</summary>`\n );\n lines.push('');\n lines.push('| Count | Cause | Detail | Affected |');\n lines.push('| --- | --- | --- | --- |');\n for (const cause of s.skip_causes) {\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText =\n overflow > 0\n ? `${visible.map(escapeTableCell).join(', ')}, … ${overflow} more`\n : visible.map(escapeTableCell).join(', ');\n lines.push(\n `| ${cause.count} | \\`${escapeTableCell(cause.cause)}\\` | ${escapeTableCell(cause.detail)} | ${affectedText} |`\n );\n }\n lines.push('');\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction escapeTableCell(s: string): string {\n // Escape backslashes first so a `\\|` in the input doesn't combine with\n // the pipe-escape below and produce `\\\\|` (literal backslash + raw pipe,\n // which breaks the table). Order matters: `\\` → `\\\\` then `|` → `\\|`.\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n\n/**\n * Synthesize a summary artifact when the runner itself crashed before\n * `comply()` produced a result (network down, capabilities parse error,\n * auth handshake exception). Schema-stable on the same summary artifact\n * contract so a Slack bot built against the artifact sees a valid payload\n * — rather than nothing — precisely when the agent is broken hardest.\n */\nexport interface BuildCrashSummaryOptions extends BuildSummaryOptions {\n agentUrl: string;\n error: Error | string;\n startedAt: string;\n durationMs: number;\n}\n\nexport function buildCrashSummary(opts: BuildCrashSummaryOptions): ComplianceSummaryArtifact {\n const message = opts.error instanceof Error ? opts.error.message : String(opts.error);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: opts.agentUrl,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: 'unreachable',\n passed: 0,\n failed: 1,\n skipped: 0,\n not_selected_count: 0,\n not_selected_by_reason: {},\n skipped_by_reason: {},\n total_duration_ms: opts.durationMs,\n tested_at: opts.startedAt,\n storyboards_executed: [],\n failures: [\n {\n track: 'core',\n storyboard_id: 'pre-flight',\n step_id: 'comply',\n reason: message.length > 500 ? `${message.slice(0, 499)}…` : message,\n reason_kind: 'error',\n },\n ],\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
//# sourceMappingURL=types.mjs.map
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
import {
|
|
8
2
|
CONTROLLER_SCENARIOS,
|
|
9
3
|
DISCOVERY_ARM_SCENARIOS,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/testing/comply-controller.ts"],"sourcesContent":["/**\n * Seller-side scaffold for the `comply_test_controller` tool.\n *\n * `createComplyController` turns a set of domain-grouped adapters into the\n * pieces needed to register the tool on an MCP server: a tool definition, a\n * raw handler, an MCP-envelope handler, and a one-call `register(server)`.\n *\n * The helper owns:\n * - Dispatching `scenario` to the correct adapter\n * - Param validation + typed error envelopes (`UNKNOWN_SCENARIO`,\n * `INVALID_PARAMS`, `NOT_FOUND`, `INVALID_TRANSITION`, `FORBIDDEN`)\n * - Seed re-seed idempotency (same id + equivalent fixture =\n * `SeedSuccess` with `message: \"Fixture re-seeded (equivalent)\"`;\n * divergent fixture = `INVALID_PARAMS`)\n * - Optional sandbox gating at both `tools/list` and per-request level\n *\n * The helper does NOT own the state machine. Transition enforcement lives\n * inside your adapters so production and compliance testing share one source\n * of truth — throw `TestControllerError('INVALID_TRANSITION', …)` from the\n * adapter when a transition is disallowed.\n *\n * For custom MCP wrappers that need AsyncLocalStorage, sandbox gating at the\n * transport layer, or a session-backed store factory, compose\n * `handleTestControllerRequest`, `toMcpResponse`, and `TOOL_INPUT_SHAPE` from\n * `@adcp/sdk/server` directly — the flat-store surface documented there.\n *\n * @example\n * ```ts\n * import { createComplyController } from '@adcp/sdk/testing';\n *\n * const controller = createComplyController({\n * sandboxGate: input => input.auth?.sandbox === true,\n * seed: {\n * product: (params) => productRepo.upsert(params.product_id, params.fixture),\n * creative: (params) => creativeRepo.upsert(params.creative_id, params.fixture),\n * },\n * force: {\n * creative_status: (params) => creativeRepo.transition(params.creative_id, params.status),\n * },\n * });\n *\n * controller.register(server);\n * ```\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ZodTypeAny } from 'zod';\nimport {\n CONTROLLER_SCENARIOS,\n DISCOVERY_ARM_SCENARIOS,\n TOOL_INPUT_SHAPE,\n createSeedFixtureCache,\n handleTestControllerRequest,\n toMcpResponse,\n type ControllerScenario,\n type SeedFixtureCache,\n type TestControllerStore,\n type UpstreamTrafficSuccessResponse,\n} from '../server/test-controller';\nimport { getSdkServer, type AdcpServer } from '../server/adcp-server';\nimport type {\n ComplyTestControllerResponse,\n ControllerError,\n ForcedDirectiveSuccess,\n ProvenanceAuditObservationsSuccess,\n SimulationSuccess,\n StateTransitionSuccess,\n} from '../types/tools.generated';\nimport type {\n AccountStatus,\n AudienceStatus,\n CatalogItemStatus,\n CreativeStatus,\n MediaBuyStatus,\n} from '../types/core.generated';\nimport type { BuyerAgent, BuyerAgentBillingMode, BuyerAgentStatus } from '../server/decisioning/buyer-agent';\nimport type { McpToolResponse } from '../server/responses';\n\n// ────────────────────────────────────────────────────────────\n// Adapter param shapes\n// ────────────────────────────────────────────────────────────\n\n/** Common second argument every adapter receives: the raw tool input so\n * adapters can read `context.session_id`, `ext`, or vendor-specific fields. */\nexport interface ComplyControllerContext {\n /** The tool input as received over the wire, pre-validation. */\n input: Record<string, unknown>;\n}\n\n/** Params for `seed_product`. `fixture` mirrors the persisted product shape\n * (delivery_type, channels, pricing_options, …). Kept permissive — the spec\n * lets storyboards declare only the fields each test needs. */\nexport interface SeedProductParams {\n product_id: string;\n fixture: Record<string, unknown>;\n}\n\n/** Params for `seed_account`. `fixture` mirrors the persisted account shape\n * (name, status, billing/rate-card metadata, authorization, …). Kept\n * permissive because storyboards declare only the account fields they need. */\nexport interface SeedAccountParams {\n account_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedPricingOptionParams {\n product_id: string;\n pricing_option_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedCreativeParams {\n creative_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedPlanParams {\n plan_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedMediaBuyParams {\n media_buy_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedCreativeFormatParams {\n format_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedMeasurementCatalogParams {\n vendor: unknown;\n metrics: unknown;\n fixture: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SeedBuyerAgentParams {\n agent_url: string;\n display_name?: string;\n status?: BuyerAgentStatus;\n billing_capabilities?: BuyerAgentBillingMode[];\n default_account_terms?: BuyerAgent['default_account_terms'];\n allowed_brands?: string[];\n aliases?: string[];\n sandbox_only?: boolean;\n [key: string]: unknown;\n}\n\nexport interface ForceCreativeStatusParams {\n creative_id: string;\n status: CreativeStatus;\n rejection_reason?: string;\n}\n\nexport interface ForceAccountStatusParams {\n account_id: string;\n status: AccountStatus;\n}\n\nexport interface ForceMediaBuyStatusParams {\n media_buy_id: string;\n status: MediaBuyStatus;\n rejection_reason?: string;\n}\n\nexport interface ForceSessionStatusParams {\n session_id: string;\n status: 'complete' | 'terminated';\n termination_reason?: string;\n}\n\nexport interface ForceCreateMediaBuyArmParams {\n arm: 'submitted' | 'input-required';\n task_id?: string;\n message?: string;\n}\n\nexport interface ForceGetProductsArmParams {\n arm: 'submitted';\n task_id: string;\n message?: string;\n}\n\nexport interface ForceGetSignalsArmParams {\n arm: 'submitted';\n task_id: string;\n message?: string;\n}\n\nexport interface ForceTaskCompletionParams {\n task_id: string;\n result: Record<string, unknown>;\n}\n\nexport interface ForceCreativePurgeParams {\n creative_id: string;\n purge_kind?: 'soft' | 'hard';\n reason_code?: string;\n reason_detail?: string;\n [key: string]: unknown;\n}\n\nexport interface ForceUpstreamUnavailableParams {\n tool: string;\n upstream_name?: string;\n}\n\n/**\n * Params for `force_audience_status` (extension scenario; issue #1819).\n * `status` is typed against the spec-shipped `AudienceStatus`; offline\n * values (e.g. `suspended` for adcp#2860's impairment storyboard) flow\n * through automatically once the spec ships them and codegen reruns.\n */\nexport interface ForceAudienceStatusParams {\n audience_id: string;\n status: AudienceStatus;\n reason?: string;\n}\n\n/** Params for `force_catalog_item_status` (extension scenario; issue #1819). */\nexport interface ForceCatalogItemStatusParams {\n catalog_item_id: string;\n status: CatalogItemStatus;\n reason?: string;\n}\n\nexport interface SimulateDeliveryParams {\n media_buy_id: string;\n impressions?: number;\n clicks?: number;\n conversions?: number;\n reported_spend?: { amount: number; currency: string };\n [key: string]: unknown;\n}\n\nexport interface SimulateBudgetSpendParams {\n account_id?: string;\n media_buy_id?: string;\n spend_percentage: number;\n [key: string]: unknown;\n}\n\n// ────────────────────────────────────────────────────────────\n// Adapter function shapes\n// ────────────────────────────────────────────────────────────\n\n/** Seed adapters persist the fixture to the seller's data layer. Return\n * value is ignored — the helper builds the `SeedSuccess` envelope (the\n * 3.0.1+ message-only seed arm) from its own idempotency cache. Throw\n * {@link TestControllerError} for typed errors (`INVALID_PARAMS`,\n * `FORBIDDEN`). */\nexport type SeedAdapter<P> = (params: P, ctx: ComplyControllerContext) => Promise<void> | void;\n\n/** Force adapters return a {@link StateTransitionSuccess}. Throw\n * `TestControllerError('INVALID_TRANSITION', msg, currentState)` when the\n * state machine disallows the transition. */\nexport type ForceAdapter<P> = (\n params: P,\n ctx: ComplyControllerContext\n) => Promise<StateTransitionSuccess> | StateTransitionSuccess;\n\n/** Directive adapters return a {@link ForcedDirectiveSuccess} (pre-registration\n * of a pending directive, not a state-machine transition). Used for\n * `create_media_buy_arm` which acknowledges the registered arm rather than\n * recording a `previous_state` / `current_state` transition. */\nexport type DirectiveAdapter<P> = (\n params: P,\n ctx: ComplyControllerContext\n) => Promise<ForcedDirectiveSuccess> | ForcedDirectiveSuccess;\n\n/** Simulate adapters return a {@link SimulationSuccess}. */\nexport type SimulateAdapter<P> = (\n params: P,\n ctx: ComplyControllerContext\n) => Promise<SimulationSuccess> | SimulationSuccess;\n\n/** Params for the `query_upstream_traffic` extension scenario (spec PR\n * adcontextprotocol/adcp#3816). All fields optional; the recorder\n * filters by these. */\nexport interface QueryUpstreamTrafficParams {\n since_timestamp?: string;\n endpoint_pattern?: string;\n limit?: number;\n attestation_mode?: 'raw' | 'digest';\n identifier_value_digests?: string[];\n}\n\n/** Adapter for the `query_upstream_traffic` extension scenario. Returns\n * the recorded upstream HTTP calls produced during the current\n * storyboard step — the runner consults this for `check: upstream_traffic`\n * validations. Adopters typically delegate to the reference recorder\n * middleware shipped at `@adcp/sdk/upstream-recorder`:\n *\n * ```ts\n * complyTest: {\n * queryUpstreamTraffic: (params, _ctx) => {\n * const result = recorder.query({\n * principal: RECORDER_PRINCIPAL,\n * ...(params.since_timestamp !== undefined && { sinceTimestamp: params.since_timestamp }),\n * ...(params.endpoint_pattern !== undefined && { endpointPattern: params.endpoint_pattern }),\n * ...(params.limit !== undefined && { limit: params.limit }),\n * ...(params.attestation_mode !== undefined && { attestationMode: params.attestation_mode }),\n * ...(params.identifier_value_digests !== undefined && {\n * identifierValueDigests: params.identifier_value_digests,\n * }),\n * });\n * return toQueryUpstreamTrafficResponse(result);\n * },\n * }\n * ```\n *\n * The principal MUST match between record-time (`runWithPrincipal`) and\n * query-time, or the recorder returns zero rows per cross-tenant\n * isolation. */\nexport type QueryUpstreamTrafficAdapter = (\n params: QueryUpstreamTrafficParams,\n ctx: ComplyControllerContext\n) => Promise<UpstreamTrafficSuccessResponse> | UpstreamTrafficSuccessResponse;\n\nexport interface QueryProvenanceAuditObservationsParams {\n creative_id: string;\n [key: string]: unknown;\n}\n\n/** Adapter for `query_provenance_audit_observations`. Returns sandbox-only\n * audit observations recorded for the creative under test. */\nexport type QueryProvenanceAuditObservationsAdapter = (\n params: QueryProvenanceAuditObservationsParams,\n ctx: ComplyControllerContext\n) => Promise<ProvenanceAuditObservationsSuccess> | ProvenanceAuditObservationsSuccess;\n\n// ────────────────────────────────────────────────────────────\n// Controller config\n// ────────────────────────────────────────────────────────────\n\nexport interface ComplyControllerConfig {\n /** Per-request gate. Return `false` to reject with `FORBIDDEN` — suitable\n * for tenants flagged as production, accounts not marked sandbox, or\n * missing sandbox headers. When omitted, every request is allowed.\n *\n * MCP tools/list visibility is controlled by *whether you call*\n * {@link ComplyController.register}. Wrap registration with your own\n * environment check if you need to hide the tool outside sandbox:\n *\n * ```ts\n * if (process.env.ADCP_SANDBOX === '1') controller.register(server);\n * ```\n *\n * Called for every request; the helper does NOT invoke adapters when the\n * gate returns false. Errors thrown from the gate are treated as denials\n * so a broken gate fails closed.\n */\n sandboxGate?: (input: Record<string, unknown>) => boolean | Promise<boolean>;\n\n /** Seed adapters. Each registered method advertises its scenario as\n * implemented; omitted methods return `UNKNOWN_SCENARIO` when called. */\n seed?: {\n account?: SeedAdapter<SeedAccountParams>;\n product?: SeedAdapter<SeedProductParams>;\n pricing_option?: SeedAdapter<SeedPricingOptionParams>;\n creative?: SeedAdapter<SeedCreativeParams>;\n plan?: SeedAdapter<SeedPlanParams>;\n media_buy?: SeedAdapter<SeedMediaBuyParams>;\n creative_format?: SeedAdapter<SeedCreativeFormatParams>;\n measurement_catalog?: SeedAdapter<SeedMeasurementCatalogParams>;\n buyer_agent?: SeedAdapter<SeedBuyerAgentParams>;\n };\n\n /** Force adapters (state transitions and directives). */\n force?: {\n creative_status?: ForceAdapter<ForceCreativeStatusParams>;\n account_status?: ForceAdapter<ForceAccountStatusParams>;\n media_buy_status?: ForceAdapter<ForceMediaBuyStatusParams>;\n session_status?: ForceAdapter<ForceSessionStatusParams>;\n /** Register a directive shaping the next `create_media_buy` arm. Consumed\n * on the next call. `arm: 'submitted'` requires `task_id`. */\n create_media_buy_arm?: DirectiveAdapter<ForceCreateMediaBuyArmParams>;\n /** Register a directive shaping the next `get_products` async arm. Extension\n * scenario for async discovery storyboards (adcp#5342). */\n get_products_arm?: DirectiveAdapter<ForceGetProductsArmParams>;\n /** Register a directive shaping the next `get_signals` submitted arm. Extension\n * scenario for async discovery storyboards (adcp#5342). */\n get_signals_arm?: DirectiveAdapter<ForceGetSignalsArmParams>;\n /** Transition an in-flight task to `completed` with the given result\n * payload. The seller delivers `result` to the buyer's push-notification\n * URL per the AdCP 3.0 async completion path. */\n task_completion?: ForceAdapter<ForceTaskCompletionParams>;\n /** Destroy or tombstone a sandbox creative so lifecycle webhooks can be tested. */\n creative_purge?: ForceAdapter<ForceCreativePurgeParams>;\n /** Mark a named upstream dependency unreachable for stale-cache testing. */\n upstream_unavailable?: ForceAdapter<ForceUpstreamUnavailableParams>;\n /** Transition a synced audience to a matching status. Backs the\n * `impairment.coherence` audience inverse-rule traversal (issue #1819).\n * Advertised as `force_audience_status`. */\n audience_status?: ForceAdapter<ForceAudienceStatusParams>;\n /** Transition a single catalog item to a review status. Backs the\n * catalog-side `impairment.coherence` traversal (issue #1819).\n * Advertised as `force_catalog_item_status`. */\n catalog_item_status?: ForceAdapter<ForceCatalogItemStatusParams>;\n };\n\n /** Simulation adapters (synthetic delivery/budget data). */\n simulate?: {\n delivery?: SimulateAdapter<SimulateDeliveryParams>;\n budget_spend?: SimulateAdapter<SimulateBudgetSpendParams>;\n };\n\n /**\n * `query_upstream_traffic` adapter (spec PR adcontextprotocol/adcp#3816).\n * Returns the recorded upstream HTTP calls produced during the current\n * storyboard step so the runner can grade `check: upstream_traffic`\n * validations. Adopters typically wire the reference recorder from\n * `@adcp/sdk/upstream-recorder`. When omitted, the scenario reports as\n * `not_applicable` per the runner's normal capability discovery.\n */\n queryUpstreamTraffic?: QueryUpstreamTrafficAdapter;\n\n /**\n * `query_provenance_audit_observations` adapter. When omitted, provenance\n * audit-observation storyboards grade as not applicable after scenario\n * discovery.\n */\n queryProvenanceAuditObservations?: QueryProvenanceAuditObservationsAdapter;\n\n /** Override the seed idempotency cache (e.g., to scope by tenant or\n * persist across restarts). Defaults to an unbounded in-memory cache. */\n seedCache?: SeedFixtureCache;\n\n /**\n * Extra Zod fields to merge into the canonical `comply_test_controller`\n * input schema. Use this when a custom wrapper routes sandbox gating\n * or tenant scoping through a top-level field (e.g., `account`) that\n * the spec-canonical {@link TOOL_INPUT_SHAPE} doesn't include.\n * Keys override canonical fields if there's a name collision; the\n * resulting shape is what the framework passes to\n * `mcp.registerTool(..., { inputSchema })` at registration.\n *\n * Mirrors the documented `{ ...TOOL_INPUT_SHAPE, account: ... }`\n * pattern from `test-controller.ts` so adopters routed through\n * `createAdcpServerFromPlatform({ complyTest })` get the same\n * extension seam as adopters wiring `registerTestController` directly.\n *\n * Storyboard fixtures that send a top-level `account` or `brand`\n * (rather than `context.account` / `context.brand`) are the canonical\n * cases for this option — both are stripped by the spec-canonical\n * shape.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n *\n * complyTest: {\n * inputSchema: {\n * account: z.object({ account_id: z.string() }).passthrough().optional(),\n * brand: z.object({ domain: z.string() }).passthrough().optional(),\n * },\n * force: { ... },\n * }\n * ```\n */\n inputSchema?: Record<string, ZodTypeAny>;\n}\n\n// ────────────────────────────────────────────────────────────\n// Controller result\n// ────────────────────────────────────────────────────────────\n\nexport interface ComplyControllerToolDefinition {\n name: 'comply_test_controller';\n description: string;\n /**\n * The merged Zod input shape — canonical {@link TOOL_INPUT_SHAPE}\n * fields plus any adopter-supplied {@link ComplyControllerConfig.inputSchema}\n * extensions. Adopter keys win on collision. Pass directly to\n * `server.registerTool(name, { inputSchema }, handler)` when wiring\n * the controller manually.\n */\n inputSchema: typeof TOOL_INPUT_SHAPE & Record<string, ZodTypeAny>;\n}\n\nexport interface ComplyController {\n /** MCP tool definition — pass to `server.registerTool(name, { description, inputSchema }, handle)`\n * manually, or use {@link ComplyController.register} to do it for you. */\n readonly toolDefinition: ComplyControllerToolDefinition;\n\n /** Protocol-level handler. Returns a {@link ComplyTestControllerResponse}\n * without the MCP envelope — useful for A2A adaptation or custom transports. */\n handleRaw(input: Record<string, unknown>): Promise<ComplyTestControllerResponse>;\n\n /** MCP-envelope handler. Wraps {@link ComplyController.handleRaw} with\n * `content` + `structuredContent` + `isError`. */\n handle(input: Record<string, unknown>): Promise<McpToolResponse & { isError?: true }>;\n\n /** Register the tool on an `AdcpServer` or raw `McpServer`. Equivalent to\n * calling `server.registerTool(name, { description, inputSchema }, handle)`. */\n register(server: AdcpServer | McpServer): void;\n}\n\n// ────────────────────────────────────────────────────────────\n// Implementation\n// ────────────────────────────────────────────────────────────\n\nfunction controllerError(code: ControllerError['error'], detail: string): ComplyTestControllerResponse {\n // AdCP 3.1.0-beta.2+: envelope `status` is REQUIRED on every response,\n // including the error arms of a discriminated controller response.\n return { status: 'failed', success: false, error: code, error_detail: detail } as ComplyTestControllerResponse;\n}\n\n/** Build a {@link TestControllerStore} that delegates to the domain-grouped\n * adapters. Only methods for registered adapters are set, so\n * `handleTestControllerRequest` returns `UNKNOWN_SCENARIO` for the rest. */\nfunction buildStore(config: ComplyControllerConfig, ctx: ComplyControllerContext): TestControllerStore {\n const store: TestControllerStore = {};\n const { seed, force, simulate, queryUpstreamTraffic, queryProvenanceAuditObservations } = config;\n\n if (seed?.account) {\n store.seedAccount = async (accountId, fixture) => {\n await seed.account!({ account_id: accountId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.product) {\n store.seedProduct = async (productId, fixture) => {\n await seed.product!({ product_id: productId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.pricing_option) {\n store.seedPricingOption = async (productId, pricingOptionId, fixture) => {\n await seed.pricing_option!(\n { product_id: productId, pricing_option_id: pricingOptionId, fixture: fixture ?? {} },\n ctx\n );\n };\n }\n if (seed?.creative) {\n store.seedCreative = async (creativeId, fixture) => {\n await seed.creative!({ creative_id: creativeId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.plan) {\n store.seedPlan = async (planId, fixture) => {\n await seed.plan!({ plan_id: planId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.media_buy) {\n store.seedMediaBuy = async (mediaBuyId, fixture) => {\n await seed.media_buy!({ media_buy_id: mediaBuyId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.creative_format) {\n store.seedCreativeFormat = async (formatId, fixture) => {\n await seed.creative_format!({ format_id: formatId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.measurement_catalog) {\n store.seedMeasurementCatalog = async params => {\n await seed.measurement_catalog!(\n {\n ...params,\n vendor: params.vendor,\n metrics: params.metrics,\n fixture: params.fixture ?? {},\n },\n ctx\n );\n };\n }\n if (seed?.buyer_agent) {\n store.seedBuyerAgent = async (agentUrl, fixture) => {\n const { agent_url: _ignored, ...safeFixture } = fixture ?? {};\n void _ignored;\n await seed.buyer_agent!({ ...safeFixture, agent_url: agentUrl }, ctx);\n };\n }\n\n if (force?.creative_status) {\n store.forceCreativeStatus = (creativeId, status, rejection_reason) =>\n Promise.resolve(force.creative_status!({ creative_id: creativeId, status, rejection_reason }, ctx));\n }\n if (force?.account_status) {\n store.forceAccountStatus = (accountId, status) =>\n Promise.resolve(force.account_status!({ account_id: accountId, status }, ctx));\n }\n if (force?.media_buy_status) {\n store.forceMediaBuyStatus = (mediaBuyId, status, rejection_reason) =>\n Promise.resolve(force.media_buy_status!({ media_buy_id: mediaBuyId, status, rejection_reason }, ctx));\n }\n if (force?.session_status) {\n store.forceSessionStatus = (sessionId, status, termination_reason) =>\n Promise.resolve(force.session_status!({ session_id: sessionId, status, termination_reason }, ctx));\n }\n if (force?.create_media_buy_arm) {\n store.forceCreateMediaBuyArm = params => Promise.resolve(force.create_media_buy_arm!(params, ctx));\n }\n if (force?.get_products_arm) {\n store.forceGetProductsArm = params => Promise.resolve(force.get_products_arm!(params, ctx));\n }\n if (force?.get_signals_arm) {\n store.forceGetSignalsArm = params => Promise.resolve(force.get_signals_arm!(params, ctx));\n }\n if (force?.task_completion) {\n store.forceTaskCompletion = (taskId, result) =>\n Promise.resolve(force.task_completion!({ task_id: taskId, result }, ctx));\n }\n if (force?.creative_purge) {\n store.forceCreativePurge = (creativeId, params) =>\n Promise.resolve(force.creative_purge!({ creative_id: creativeId, ...params }, ctx));\n }\n if (force?.upstream_unavailable) {\n store.forceUpstreamUnavailable = params => Promise.resolve(force.upstream_unavailable!(params, ctx));\n }\n if (force?.audience_status) {\n store.forceAudienceStatus = (audienceId, status, reason) =>\n Promise.resolve(force.audience_status!({ audience_id: audienceId, status, reason }, ctx));\n }\n if (force?.catalog_item_status) {\n store.forceCatalogItemStatus = (itemId, status, reason) =>\n Promise.resolve(force.catalog_item_status!({ catalog_item_id: itemId, status, reason }, ctx));\n }\n\n if (simulate?.delivery) {\n store.simulateDelivery = (mediaBuyId, params) =>\n Promise.resolve(simulate.delivery!({ media_buy_id: mediaBuyId, ...params }, ctx));\n }\n if (simulate?.budget_spend) {\n store.simulateBudgetSpend = params => Promise.resolve(simulate.budget_spend!(params, ctx));\n }\n\n if (queryUpstreamTraffic) {\n store.queryUpstreamTraffic = params => Promise.resolve(queryUpstreamTraffic(params, ctx));\n }\n if (queryProvenanceAuditObservations) {\n store.queryProvenanceAuditObservations = params => Promise.resolve(queryProvenanceAuditObservations(params, ctx));\n }\n\n return store;\n}\n\n/** The set of canonical scenarios a config advertises via `list_scenarios`.\n * `list_scenarios` itself is implicit and excluded. */\nfunction advertisedScenarios(config: ComplyControllerConfig): ControllerScenario[] {\n const out: ControllerScenario[] = [];\n if (config.force?.creative_status) out.push(CONTROLLER_SCENARIOS.FORCE_CREATIVE_STATUS);\n if (config.force?.account_status) out.push(CONTROLLER_SCENARIOS.FORCE_ACCOUNT_STATUS);\n if (config.force?.media_buy_status) out.push(CONTROLLER_SCENARIOS.FORCE_MEDIA_BUY_STATUS);\n if (config.force?.session_status) out.push(CONTROLLER_SCENARIOS.FORCE_SESSION_STATUS);\n if (config.force?.create_media_buy_arm) out.push(CONTROLLER_SCENARIOS.FORCE_CREATE_MEDIA_BUY_ARM);\n if (config.force?.get_products_arm) out.push(DISCOVERY_ARM_SCENARIOS.FORCE_GET_PRODUCTS_ARM as ControllerScenario);\n if (config.force?.get_signals_arm) out.push(DISCOVERY_ARM_SCENARIOS.FORCE_GET_SIGNALS_ARM as ControllerScenario);\n if (config.force?.task_completion) out.push(CONTROLLER_SCENARIOS.FORCE_TASK_COMPLETION);\n if (config.force?.creative_purge) out.push(CONTROLLER_SCENARIOS.FORCE_CREATIVE_PURGE);\n if (config.simulate?.delivery) out.push(CONTROLLER_SCENARIOS.SIMULATE_DELIVERY);\n if (config.simulate?.budget_spend) out.push(CONTROLLER_SCENARIOS.SIMULATE_BUDGET_SPEND);\n if (config.seed?.account) out.push('seed_account' as unknown as ControllerScenario);\n if (config.seed?.product) out.push('seed_product');\n if (config.seed?.pricing_option) out.push('seed_pricing_option');\n if (config.seed?.creative) out.push('seed_creative');\n if (config.seed?.plan) out.push('seed_plan');\n if (config.seed?.media_buy) out.push('seed_media_buy');\n if (config.seed?.creative_format) out.push('seed_creative_format');\n if (config.seed?.measurement_catalog) out.push('seed_measurement_catalog');\n // Extension scenarios not yet in the schema cache's `ControllerScenario`\n // enum are still accepted by the dispatcher under the open-extension\n // `TOOL_INPUT_SHAPE.scenario: z.string()` pattern.\n if (config.seed?.buyer_agent) out.push('seed_buyer_agent' as unknown as ControllerScenario);\n if (config.force?.audience_status) out.push('force_audience_status' as unknown as ControllerScenario);\n if (config.force?.catalog_item_status) out.push('force_catalog_item_status' as unknown as ControllerScenario);\n if (config.queryUpstreamTraffic) out.push(CONTROLLER_SCENARIOS.QUERY_UPSTREAM_TRAFFIC);\n if (config.queryProvenanceAuditObservations) {\n out.push(CONTROLLER_SCENARIOS.QUERY_PROVENANCE_AUDIT_OBSERVATIONS);\n }\n if (config.force?.upstream_unavailable) out.push(CONTROLLER_SCENARIOS.FORCE_UPSTREAM_UNAVAILABLE);\n return out;\n}\n\n/** Create a comply_test_controller scaffold from domain-grouped adapters. */\nexport function createComplyController(config: ComplyControllerConfig): ComplyController {\n const seedCache = config.seedCache ?? createSeedFixtureCache();\n const scenarios = advertisedScenarios(config);\n // Stable reference so factory answers list_scenarios without invoking\n // createStore — handleTestControllerRequest inspects the `scenarios` field.\n const factoryScenarios = Object.freeze([...scenarios]) as readonly ControllerScenario[];\n\n async function handleRaw(input: Record<string, unknown>): Promise<ComplyTestControllerResponse> {\n const inputCtx = input.context;\n // Echoes input.context on FORBIDDEN early-returns (sandboxGate denial/throw)\n // that bypass handleTestControllerRequest. The delegated call at the end of\n // this function already echoes context internally — addCtx is a no-op there.\n const addCtx = (r: ComplyTestControllerResponse): ComplyTestControllerResponse =>\n inputCtx !== undefined && typeof inputCtx === 'object' && inputCtx !== null && r.context === undefined\n ? ({ ...r, context: inputCtx } as ComplyTestControllerResponse)\n : r;\n\n // `list_scenarios` is a capability probe — answer it without consulting\n // the gate so buyer tooling can distinguish \"controller exists but\n // locked\" from \"controller missing entirely\". State-mutating scenarios\n // still go through the gate below.\n const isListScenariosProbe = input.scenario === 'list_scenarios';\n\n if (config.sandboxGate && !isListScenariosProbe) {\n let allowed: unknown;\n try {\n allowed = await config.sandboxGate(input);\n } catch (err) {\n // Don't leak gate-internal errors. Treat as denial — matches how a\n // sandbox would fail closed if its auth layer threw.\n void err;\n return addCtx(controllerError('FORBIDDEN', 'Sandbox gate check failed'));\n }\n // Strict equality: anything that is not literally `true` is a denial.\n // Guards against gates that accidentally return a reason string, a\n // number, or a truthy object.\n if (allowed !== true) {\n return addCtx(\n controllerError(\n 'FORBIDDEN',\n 'comply_test_controller is disabled in this environment (non-sandbox or gate denied)'\n )\n );\n }\n }\n\n const ctx: ComplyControllerContext = { input };\n const store = buildStore(config, ctx);\n\n return handleTestControllerRequest({ scenarios: factoryScenarios, createStore: () => store }, input, { seedCache });\n }\n\n async function handle(input: Record<string, unknown>) {\n return toMcpResponse(await handleRaw(input));\n }\n\n // Shallow-copy the canonical shape and overlay any adopter-supplied\n // extension fields. Spread order is canonical-then-extensions so a\n // collision (e.g., adopter redefines `params`) lets the adopter win.\n // Zod schema values are themselves immutable, so a one-level copy is\n // enough to keep callers from poisoning subsequent registrations.\n const toolDefinition: ComplyControllerToolDefinition = Object.freeze({\n name: 'comply_test_controller',\n description: 'Triggers seller-side state transitions for compliance testing. Sandbox only.',\n inputSchema: { ...TOOL_INPUT_SHAPE, ...(config.inputSchema ?? {}) },\n });\n\n // Per-controller latch so the \"ungated controller\" warning fires once even\n // when serve() invokes the factory (and therefore register) per request.\n let hasWarnedOnRegister = false;\n\n function register(server: AdcpServer | McpServer): void {\n // Loud warning when the tool is about to be exposed without any explicit\n // gate. Sellers who intentionally gate at the transport layer can silence\n // this by setting ADCP_SANDBOX=1 (or ADCP_COMPLY_CONTROLLER_UNGATED=1 to\n // opt out entirely). Prevents silent fail-open misuse without breaking\n // the API's \"gate is optional\" shape.\n if (\n !hasWarnedOnRegister &&\n !config.sandboxGate &&\n process.env.ADCP_SANDBOX !== '1' &&\n process.env.ADCP_COMPLY_CONTROLLER_UNGATED !== '1'\n ) {\n hasWarnedOnRegister = true;\n // eslint-disable-next-line no-console\n console.warn(\n '[comply_test_controller] Registered with no sandboxGate and no ' +\n 'ADCP_SANDBOX / ADCP_COMPLY_CONTROLLER_UNGATED env flag. The tool ' +\n 'will accept every request — only correct if your transport layer ' +\n 'enforces sandbox isolation. See createComplyController docs.'\n );\n }\n const mcp = getSdkServer(server as AdcpServer) ?? (server as McpServer);\n mcp.registerTool(\n toolDefinition.name,\n {\n description: toolDefinition.description,\n inputSchema: toolDefinition.inputSchema,\n },\n (async (input: Record<string, unknown>) => handle(input)) as Parameters<typeof mcp.registerTool>[2]\n );\n }\n\n return { toolDefinition, handleRaw, handle, register };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/testing/comply-controller.ts"],"sourcesContent":["/**\n * Seller-side scaffold for the `comply_test_controller` tool.\n *\n * `createComplyController` turns a set of domain-grouped adapters into the\n * pieces needed to register the tool on an MCP server: a tool definition, a\n * raw handler, an MCP-envelope handler, and a one-call `register(server)`.\n *\n * The helper owns:\n * - Dispatching `scenario` to the correct adapter\n * - Param validation + typed error envelopes (`UNKNOWN_SCENARIO`,\n * `INVALID_PARAMS`, `NOT_FOUND`, `INVALID_TRANSITION`, `FORBIDDEN`)\n * - Seed re-seed idempotency (same id + equivalent fixture =\n * `SeedSuccess` with `message: \"Fixture re-seeded (equivalent)\"`;\n * divergent fixture = `INVALID_PARAMS`)\n * - Optional sandbox gating at both `tools/list` and per-request level\n *\n * The helper does NOT own the state machine. Transition enforcement lives\n * inside your adapters so production and compliance testing share one source\n * of truth — throw `TestControllerError('INVALID_TRANSITION', …)` from the\n * adapter when a transition is disallowed.\n *\n * For custom MCP wrappers that need AsyncLocalStorage, sandbox gating at the\n * transport layer, or a session-backed store factory, compose\n * `handleTestControllerRequest`, `toMcpResponse`, and `TOOL_INPUT_SHAPE` from\n * `@adcp/sdk/server` directly — the flat-store surface documented there.\n *\n * @example\n * ```ts\n * import { createComplyController } from '@adcp/sdk/testing';\n *\n * const controller = createComplyController({\n * sandboxGate: input => input.auth?.sandbox === true,\n * seed: {\n * product: (params) => productRepo.upsert(params.product_id, params.fixture),\n * creative: (params) => creativeRepo.upsert(params.creative_id, params.fixture),\n * },\n * force: {\n * creative_status: (params) => creativeRepo.transition(params.creative_id, params.status),\n * },\n * });\n *\n * controller.register(server);\n * ```\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ZodTypeAny } from 'zod';\nimport {\n CONTROLLER_SCENARIOS,\n DISCOVERY_ARM_SCENARIOS,\n TOOL_INPUT_SHAPE,\n createSeedFixtureCache,\n handleTestControllerRequest,\n toMcpResponse,\n type ControllerScenario,\n type SeedFixtureCache,\n type TestControllerStore,\n type UpstreamTrafficSuccessResponse,\n} from '../server/test-controller';\nimport { getSdkServer, type AdcpServer } from '../server/adcp-server';\nimport type {\n ComplyTestControllerResponse,\n ControllerError,\n ForcedDirectiveSuccess,\n ProvenanceAuditObservationsSuccess,\n SimulationSuccess,\n StateTransitionSuccess,\n} from '../types/tools.generated';\nimport type {\n AccountStatus,\n AudienceStatus,\n CatalogItemStatus,\n CreativeStatus,\n MediaBuyStatus,\n} from '../types/core.generated';\nimport type { BuyerAgent, BuyerAgentBillingMode, BuyerAgentStatus } from '../server/decisioning/buyer-agent';\nimport type { McpToolResponse } from '../server/responses';\n\n// ────────────────────────────────────────────────────────────\n// Adapter param shapes\n// ────────────────────────────────────────────────────────────\n\n/** Common second argument every adapter receives: the raw tool input so\n * adapters can read `context.session_id`, `ext`, or vendor-specific fields. */\nexport interface ComplyControllerContext {\n /** The tool input as received over the wire, pre-validation. */\n input: Record<string, unknown>;\n}\n\n/** Params for `seed_product`. `fixture` mirrors the persisted product shape\n * (delivery_type, channels, pricing_options, …). Kept permissive — the spec\n * lets storyboards declare only the fields each test needs. */\nexport interface SeedProductParams {\n product_id: string;\n fixture: Record<string, unknown>;\n}\n\n/** Params for `seed_account`. `fixture` mirrors the persisted account shape\n * (name, status, billing/rate-card metadata, authorization, …). Kept\n * permissive because storyboards declare only the account fields they need. */\nexport interface SeedAccountParams {\n account_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedPricingOptionParams {\n product_id: string;\n pricing_option_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedCreativeParams {\n creative_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedPlanParams {\n plan_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedMediaBuyParams {\n media_buy_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedCreativeFormatParams {\n format_id: string;\n fixture: Record<string, unknown>;\n}\n\nexport interface SeedMeasurementCatalogParams {\n vendor: unknown;\n metrics: unknown;\n fixture: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SeedBuyerAgentParams {\n agent_url: string;\n display_name?: string;\n status?: BuyerAgentStatus;\n billing_capabilities?: BuyerAgentBillingMode[];\n default_account_terms?: BuyerAgent['default_account_terms'];\n allowed_brands?: string[];\n aliases?: string[];\n sandbox_only?: boolean;\n [key: string]: unknown;\n}\n\nexport interface ForceCreativeStatusParams {\n creative_id: string;\n status: CreativeStatus;\n rejection_reason?: string;\n}\n\nexport interface ForceAccountStatusParams {\n account_id: string;\n status: AccountStatus;\n}\n\nexport interface ForceMediaBuyStatusParams {\n media_buy_id: string;\n status: MediaBuyStatus;\n rejection_reason?: string;\n}\n\nexport interface ForceSessionStatusParams {\n session_id: string;\n status: 'complete' | 'terminated';\n termination_reason?: string;\n}\n\nexport interface ForceCreateMediaBuyArmParams {\n arm: 'submitted' | 'input-required';\n task_id?: string;\n message?: string;\n}\n\nexport interface ForceGetProductsArmParams {\n arm: 'submitted';\n task_id: string;\n message?: string;\n}\n\nexport interface ForceGetSignalsArmParams {\n arm: 'submitted';\n task_id: string;\n message?: string;\n}\n\nexport interface ForceTaskCompletionParams {\n task_id: string;\n result: Record<string, unknown>;\n}\n\nexport interface ForceCreativePurgeParams {\n creative_id: string;\n purge_kind?: 'soft' | 'hard';\n reason_code?: string;\n reason_detail?: string;\n [key: string]: unknown;\n}\n\nexport interface ForceUpstreamUnavailableParams {\n tool: string;\n upstream_name?: string;\n}\n\n/**\n * Params for `force_audience_status` (extension scenario; issue #1819).\n * `status` is typed against the spec-shipped `AudienceStatus`; offline\n * values (e.g. `suspended` for adcp#2860's impairment storyboard) flow\n * through automatically once the spec ships them and codegen reruns.\n */\nexport interface ForceAudienceStatusParams {\n audience_id: string;\n status: AudienceStatus;\n reason?: string;\n}\n\n/** Params for `force_catalog_item_status` (extension scenario; issue #1819). */\nexport interface ForceCatalogItemStatusParams {\n catalog_item_id: string;\n status: CatalogItemStatus;\n reason?: string;\n}\n\nexport interface SimulateDeliveryParams {\n media_buy_id: string;\n impressions?: number;\n clicks?: number;\n conversions?: number;\n reported_spend?: { amount: number; currency: string };\n [key: string]: unknown;\n}\n\nexport interface SimulateBudgetSpendParams {\n account_id?: string;\n media_buy_id?: string;\n spend_percentage: number;\n [key: string]: unknown;\n}\n\n// ────────────────────────────────────────────────────────────\n// Adapter function shapes\n// ────────────────────────────────────────────────────────────\n\n/** Seed adapters persist the fixture to the seller's data layer. Return\n * value is ignored — the helper builds the `SeedSuccess` envelope (the\n * 3.0.1+ message-only seed arm) from its own idempotency cache. Throw\n * {@link TestControllerError} for typed errors (`INVALID_PARAMS`,\n * `FORBIDDEN`). */\nexport type SeedAdapter<P> = (params: P, ctx: ComplyControllerContext) => Promise<void> | void;\n\n/** Force adapters return a {@link StateTransitionSuccess}. Throw\n * `TestControllerError('INVALID_TRANSITION', msg, currentState)` when the\n * state machine disallows the transition. */\nexport type ForceAdapter<P> = (\n params: P,\n ctx: ComplyControllerContext\n) => Promise<StateTransitionSuccess> | StateTransitionSuccess;\n\n/** Directive adapters return a {@link ForcedDirectiveSuccess} (pre-registration\n * of a pending directive, not a state-machine transition). Used for\n * `create_media_buy_arm` which acknowledges the registered arm rather than\n * recording a `previous_state` / `current_state` transition. */\nexport type DirectiveAdapter<P> = (\n params: P,\n ctx: ComplyControllerContext\n) => Promise<ForcedDirectiveSuccess> | ForcedDirectiveSuccess;\n\n/** Simulate adapters return a {@link SimulationSuccess}. */\nexport type SimulateAdapter<P> = (\n params: P,\n ctx: ComplyControllerContext\n) => Promise<SimulationSuccess> | SimulationSuccess;\n\n/** Params for the `query_upstream_traffic` extension scenario (spec PR\n * adcontextprotocol/adcp#3816). All fields optional; the recorder\n * filters by these. */\nexport interface QueryUpstreamTrafficParams {\n since_timestamp?: string;\n endpoint_pattern?: string;\n limit?: number;\n attestation_mode?: 'raw' | 'digest';\n identifier_value_digests?: string[];\n}\n\n/** Adapter for the `query_upstream_traffic` extension scenario. Returns\n * the recorded upstream HTTP calls produced during the current\n * storyboard step — the runner consults this for `check: upstream_traffic`\n * validations. Adopters typically delegate to the reference recorder\n * middleware shipped at `@adcp/sdk/upstream-recorder`:\n *\n * ```ts\n * complyTest: {\n * queryUpstreamTraffic: (params, _ctx) => {\n * const result = recorder.query({\n * principal: RECORDER_PRINCIPAL,\n * ...(params.since_timestamp !== undefined && { sinceTimestamp: params.since_timestamp }),\n * ...(params.endpoint_pattern !== undefined && { endpointPattern: params.endpoint_pattern }),\n * ...(params.limit !== undefined && { limit: params.limit }),\n * ...(params.attestation_mode !== undefined && { attestationMode: params.attestation_mode }),\n * ...(params.identifier_value_digests !== undefined && {\n * identifierValueDigests: params.identifier_value_digests,\n * }),\n * });\n * return toQueryUpstreamTrafficResponse(result);\n * },\n * }\n * ```\n *\n * The principal MUST match between record-time (`runWithPrincipal`) and\n * query-time, or the recorder returns zero rows per cross-tenant\n * isolation. */\nexport type QueryUpstreamTrafficAdapter = (\n params: QueryUpstreamTrafficParams,\n ctx: ComplyControllerContext\n) => Promise<UpstreamTrafficSuccessResponse> | UpstreamTrafficSuccessResponse;\n\nexport interface QueryProvenanceAuditObservationsParams {\n creative_id: string;\n [key: string]: unknown;\n}\n\n/** Adapter for `query_provenance_audit_observations`. Returns sandbox-only\n * audit observations recorded for the creative under test. */\nexport type QueryProvenanceAuditObservationsAdapter = (\n params: QueryProvenanceAuditObservationsParams,\n ctx: ComplyControllerContext\n) => Promise<ProvenanceAuditObservationsSuccess> | ProvenanceAuditObservationsSuccess;\n\n// ────────────────────────────────────────────────────────────\n// Controller config\n// ────────────────────────────────────────────────────────────\n\nexport interface ComplyControllerConfig {\n /** Per-request gate. Return `false` to reject with `FORBIDDEN` — suitable\n * for tenants flagged as production, accounts not marked sandbox, or\n * missing sandbox headers. When omitted, every request is allowed.\n *\n * MCP tools/list visibility is controlled by *whether you call*\n * {@link ComplyController.register}. Wrap registration with your own\n * environment check if you need to hide the tool outside sandbox:\n *\n * ```ts\n * if (process.env.ADCP_SANDBOX === '1') controller.register(server);\n * ```\n *\n * Called for every request; the helper does NOT invoke adapters when the\n * gate returns false. Errors thrown from the gate are treated as denials\n * so a broken gate fails closed.\n */\n sandboxGate?: (input: Record<string, unknown>) => boolean | Promise<boolean>;\n\n /** Seed adapters. Each registered method advertises its scenario as\n * implemented; omitted methods return `UNKNOWN_SCENARIO` when called. */\n seed?: {\n account?: SeedAdapter<SeedAccountParams>;\n product?: SeedAdapter<SeedProductParams>;\n pricing_option?: SeedAdapter<SeedPricingOptionParams>;\n creative?: SeedAdapter<SeedCreativeParams>;\n plan?: SeedAdapter<SeedPlanParams>;\n media_buy?: SeedAdapter<SeedMediaBuyParams>;\n creative_format?: SeedAdapter<SeedCreativeFormatParams>;\n measurement_catalog?: SeedAdapter<SeedMeasurementCatalogParams>;\n buyer_agent?: SeedAdapter<SeedBuyerAgentParams>;\n };\n\n /** Force adapters (state transitions and directives). */\n force?: {\n creative_status?: ForceAdapter<ForceCreativeStatusParams>;\n account_status?: ForceAdapter<ForceAccountStatusParams>;\n media_buy_status?: ForceAdapter<ForceMediaBuyStatusParams>;\n session_status?: ForceAdapter<ForceSessionStatusParams>;\n /** Register a directive shaping the next `create_media_buy` arm. Consumed\n * on the next call. `arm: 'submitted'` requires `task_id`. */\n create_media_buy_arm?: DirectiveAdapter<ForceCreateMediaBuyArmParams>;\n /** Register a directive shaping the next `get_products` async arm. Extension\n * scenario for async discovery storyboards (adcp#5342). */\n get_products_arm?: DirectiveAdapter<ForceGetProductsArmParams>;\n /** Register a directive shaping the next `get_signals` submitted arm. Extension\n * scenario for async discovery storyboards (adcp#5342). */\n get_signals_arm?: DirectiveAdapter<ForceGetSignalsArmParams>;\n /** Transition an in-flight task to `completed` with the given result\n * payload. The seller delivers `result` to the buyer's push-notification\n * URL per the AdCP 3.0 async completion path. */\n task_completion?: ForceAdapter<ForceTaskCompletionParams>;\n /** Destroy or tombstone a sandbox creative so lifecycle webhooks can be tested. */\n creative_purge?: ForceAdapter<ForceCreativePurgeParams>;\n /** Mark a named upstream dependency unreachable for stale-cache testing. */\n upstream_unavailable?: ForceAdapter<ForceUpstreamUnavailableParams>;\n /** Transition a synced audience to a matching status. Backs the\n * `impairment.coherence` audience inverse-rule traversal (issue #1819).\n * Advertised as `force_audience_status`. */\n audience_status?: ForceAdapter<ForceAudienceStatusParams>;\n /** Transition a single catalog item to a review status. Backs the\n * catalog-side `impairment.coherence` traversal (issue #1819).\n * Advertised as `force_catalog_item_status`. */\n catalog_item_status?: ForceAdapter<ForceCatalogItemStatusParams>;\n };\n\n /** Simulation adapters (synthetic delivery/budget data). */\n simulate?: {\n delivery?: SimulateAdapter<SimulateDeliveryParams>;\n budget_spend?: SimulateAdapter<SimulateBudgetSpendParams>;\n };\n\n /**\n * `query_upstream_traffic` adapter (spec PR adcontextprotocol/adcp#3816).\n * Returns the recorded upstream HTTP calls produced during the current\n * storyboard step so the runner can grade `check: upstream_traffic`\n * validations. Adopters typically wire the reference recorder from\n * `@adcp/sdk/upstream-recorder`. When omitted, the scenario reports as\n * `not_applicable` per the runner's normal capability discovery.\n */\n queryUpstreamTraffic?: QueryUpstreamTrafficAdapter;\n\n /**\n * `query_provenance_audit_observations` adapter. When omitted, provenance\n * audit-observation storyboards grade as not applicable after scenario\n * discovery.\n */\n queryProvenanceAuditObservations?: QueryProvenanceAuditObservationsAdapter;\n\n /** Override the seed idempotency cache (e.g., to scope by tenant or\n * persist across restarts). Defaults to an unbounded in-memory cache. */\n seedCache?: SeedFixtureCache;\n\n /**\n * Extra Zod fields to merge into the canonical `comply_test_controller`\n * input schema. Use this when a custom wrapper routes sandbox gating\n * or tenant scoping through a top-level field (e.g., `account`) that\n * the spec-canonical {@link TOOL_INPUT_SHAPE} doesn't include.\n * Keys override canonical fields if there's a name collision; the\n * resulting shape is what the framework passes to\n * `mcp.registerTool(..., { inputSchema })` at registration.\n *\n * Mirrors the documented `{ ...TOOL_INPUT_SHAPE, account: ... }`\n * pattern from `test-controller.ts` so adopters routed through\n * `createAdcpServerFromPlatform({ complyTest })` get the same\n * extension seam as adopters wiring `registerTestController` directly.\n *\n * Storyboard fixtures that send a top-level `account` or `brand`\n * (rather than `context.account` / `context.brand`) are the canonical\n * cases for this option — both are stripped by the spec-canonical\n * shape.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n *\n * complyTest: {\n * inputSchema: {\n * account: z.object({ account_id: z.string() }).passthrough().optional(),\n * brand: z.object({ domain: z.string() }).passthrough().optional(),\n * },\n * force: { ... },\n * }\n * ```\n */\n inputSchema?: Record<string, ZodTypeAny>;\n}\n\n// ────────────────────────────────────────────────────────────\n// Controller result\n// ────────────────────────────────────────────────────────────\n\nexport interface ComplyControllerToolDefinition {\n name: 'comply_test_controller';\n description: string;\n /**\n * The merged Zod input shape — canonical {@link TOOL_INPUT_SHAPE}\n * fields plus any adopter-supplied {@link ComplyControllerConfig.inputSchema}\n * extensions. Adopter keys win on collision. Pass directly to\n * `server.registerTool(name, { inputSchema }, handler)` when wiring\n * the controller manually.\n */\n inputSchema: typeof TOOL_INPUT_SHAPE & Record<string, ZodTypeAny>;\n}\n\nexport interface ComplyController {\n /** MCP tool definition — pass to `server.registerTool(name, { description, inputSchema }, handle)`\n * manually, or use {@link ComplyController.register} to do it for you. */\n readonly toolDefinition: ComplyControllerToolDefinition;\n\n /** Protocol-level handler. Returns a {@link ComplyTestControllerResponse}\n * without the MCP envelope — useful for A2A adaptation or custom transports. */\n handleRaw(input: Record<string, unknown>): Promise<ComplyTestControllerResponse>;\n\n /** MCP-envelope handler. Wraps {@link ComplyController.handleRaw} with\n * `content` + `structuredContent` + `isError`. */\n handle(input: Record<string, unknown>): Promise<McpToolResponse & { isError?: true }>;\n\n /** Register the tool on an `AdcpServer` or raw `McpServer`. Equivalent to\n * calling `server.registerTool(name, { description, inputSchema }, handle)`. */\n register(server: AdcpServer | McpServer): void;\n}\n\n// ────────────────────────────────────────────────────────────\n// Implementation\n// ────────────────────────────────────────────────────────────\n\nfunction controllerError(code: ControllerError['error'], detail: string): ComplyTestControllerResponse {\n // AdCP 3.1.0-beta.2+: envelope `status` is REQUIRED on every response,\n // including the error arms of a discriminated controller response.\n return { status: 'failed', success: false, error: code, error_detail: detail } as ComplyTestControllerResponse;\n}\n\n/** Build a {@link TestControllerStore} that delegates to the domain-grouped\n * adapters. Only methods for registered adapters are set, so\n * `handleTestControllerRequest` returns `UNKNOWN_SCENARIO` for the rest. */\nfunction buildStore(config: ComplyControllerConfig, ctx: ComplyControllerContext): TestControllerStore {\n const store: TestControllerStore = {};\n const { seed, force, simulate, queryUpstreamTraffic, queryProvenanceAuditObservations } = config;\n\n if (seed?.account) {\n store.seedAccount = async (accountId, fixture) => {\n await seed.account!({ account_id: accountId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.product) {\n store.seedProduct = async (productId, fixture) => {\n await seed.product!({ product_id: productId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.pricing_option) {\n store.seedPricingOption = async (productId, pricingOptionId, fixture) => {\n await seed.pricing_option!(\n { product_id: productId, pricing_option_id: pricingOptionId, fixture: fixture ?? {} },\n ctx\n );\n };\n }\n if (seed?.creative) {\n store.seedCreative = async (creativeId, fixture) => {\n await seed.creative!({ creative_id: creativeId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.plan) {\n store.seedPlan = async (planId, fixture) => {\n await seed.plan!({ plan_id: planId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.media_buy) {\n store.seedMediaBuy = async (mediaBuyId, fixture) => {\n await seed.media_buy!({ media_buy_id: mediaBuyId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.creative_format) {\n store.seedCreativeFormat = async (formatId, fixture) => {\n await seed.creative_format!({ format_id: formatId, fixture: fixture ?? {} }, ctx);\n };\n }\n if (seed?.measurement_catalog) {\n store.seedMeasurementCatalog = async params => {\n await seed.measurement_catalog!(\n {\n ...params,\n vendor: params.vendor,\n metrics: params.metrics,\n fixture: params.fixture ?? {},\n },\n ctx\n );\n };\n }\n if (seed?.buyer_agent) {\n store.seedBuyerAgent = async (agentUrl, fixture) => {\n const { agent_url: _ignored, ...safeFixture } = fixture ?? {};\n void _ignored;\n await seed.buyer_agent!({ ...safeFixture, agent_url: agentUrl }, ctx);\n };\n }\n\n if (force?.creative_status) {\n store.forceCreativeStatus = (creativeId, status, rejection_reason) =>\n Promise.resolve(force.creative_status!({ creative_id: creativeId, status, rejection_reason }, ctx));\n }\n if (force?.account_status) {\n store.forceAccountStatus = (accountId, status) =>\n Promise.resolve(force.account_status!({ account_id: accountId, status }, ctx));\n }\n if (force?.media_buy_status) {\n store.forceMediaBuyStatus = (mediaBuyId, status, rejection_reason) =>\n Promise.resolve(force.media_buy_status!({ media_buy_id: mediaBuyId, status, rejection_reason }, ctx));\n }\n if (force?.session_status) {\n store.forceSessionStatus = (sessionId, status, termination_reason) =>\n Promise.resolve(force.session_status!({ session_id: sessionId, status, termination_reason }, ctx));\n }\n if (force?.create_media_buy_arm) {\n store.forceCreateMediaBuyArm = params => Promise.resolve(force.create_media_buy_arm!(params, ctx));\n }\n if (force?.get_products_arm) {\n store.forceGetProductsArm = params => Promise.resolve(force.get_products_arm!(params, ctx));\n }\n if (force?.get_signals_arm) {\n store.forceGetSignalsArm = params => Promise.resolve(force.get_signals_arm!(params, ctx));\n }\n if (force?.task_completion) {\n store.forceTaskCompletion = (taskId, result) =>\n Promise.resolve(force.task_completion!({ task_id: taskId, result }, ctx));\n }\n if (force?.creative_purge) {\n store.forceCreativePurge = (creativeId, params) =>\n Promise.resolve(force.creative_purge!({ creative_id: creativeId, ...params }, ctx));\n }\n if (force?.upstream_unavailable) {\n store.forceUpstreamUnavailable = params => Promise.resolve(force.upstream_unavailable!(params, ctx));\n }\n if (force?.audience_status) {\n store.forceAudienceStatus = (audienceId, status, reason) =>\n Promise.resolve(force.audience_status!({ audience_id: audienceId, status, reason }, ctx));\n }\n if (force?.catalog_item_status) {\n store.forceCatalogItemStatus = (itemId, status, reason) =>\n Promise.resolve(force.catalog_item_status!({ catalog_item_id: itemId, status, reason }, ctx));\n }\n\n if (simulate?.delivery) {\n store.simulateDelivery = (mediaBuyId, params) =>\n Promise.resolve(simulate.delivery!({ media_buy_id: mediaBuyId, ...params }, ctx));\n }\n if (simulate?.budget_spend) {\n store.simulateBudgetSpend = params => Promise.resolve(simulate.budget_spend!(params, ctx));\n }\n\n if (queryUpstreamTraffic) {\n store.queryUpstreamTraffic = params => Promise.resolve(queryUpstreamTraffic(params, ctx));\n }\n if (queryProvenanceAuditObservations) {\n store.queryProvenanceAuditObservations = params => Promise.resolve(queryProvenanceAuditObservations(params, ctx));\n }\n\n return store;\n}\n\n/** The set of canonical scenarios a config advertises via `list_scenarios`.\n * `list_scenarios` itself is implicit and excluded. */\nfunction advertisedScenarios(config: ComplyControllerConfig): ControllerScenario[] {\n const out: ControllerScenario[] = [];\n if (config.force?.creative_status) out.push(CONTROLLER_SCENARIOS.FORCE_CREATIVE_STATUS);\n if (config.force?.account_status) out.push(CONTROLLER_SCENARIOS.FORCE_ACCOUNT_STATUS);\n if (config.force?.media_buy_status) out.push(CONTROLLER_SCENARIOS.FORCE_MEDIA_BUY_STATUS);\n if (config.force?.session_status) out.push(CONTROLLER_SCENARIOS.FORCE_SESSION_STATUS);\n if (config.force?.create_media_buy_arm) out.push(CONTROLLER_SCENARIOS.FORCE_CREATE_MEDIA_BUY_ARM);\n if (config.force?.get_products_arm) out.push(DISCOVERY_ARM_SCENARIOS.FORCE_GET_PRODUCTS_ARM as ControllerScenario);\n if (config.force?.get_signals_arm) out.push(DISCOVERY_ARM_SCENARIOS.FORCE_GET_SIGNALS_ARM as ControllerScenario);\n if (config.force?.task_completion) out.push(CONTROLLER_SCENARIOS.FORCE_TASK_COMPLETION);\n if (config.force?.creative_purge) out.push(CONTROLLER_SCENARIOS.FORCE_CREATIVE_PURGE);\n if (config.simulate?.delivery) out.push(CONTROLLER_SCENARIOS.SIMULATE_DELIVERY);\n if (config.simulate?.budget_spend) out.push(CONTROLLER_SCENARIOS.SIMULATE_BUDGET_SPEND);\n if (config.seed?.account) out.push('seed_account' as unknown as ControllerScenario);\n if (config.seed?.product) out.push('seed_product');\n if (config.seed?.pricing_option) out.push('seed_pricing_option');\n if (config.seed?.creative) out.push('seed_creative');\n if (config.seed?.plan) out.push('seed_plan');\n if (config.seed?.media_buy) out.push('seed_media_buy');\n if (config.seed?.creative_format) out.push('seed_creative_format');\n if (config.seed?.measurement_catalog) out.push('seed_measurement_catalog');\n // Extension scenarios not yet in the schema cache's `ControllerScenario`\n // enum are still accepted by the dispatcher under the open-extension\n // `TOOL_INPUT_SHAPE.scenario: z.string()` pattern.\n if (config.seed?.buyer_agent) out.push('seed_buyer_agent' as unknown as ControllerScenario);\n if (config.force?.audience_status) out.push('force_audience_status' as unknown as ControllerScenario);\n if (config.force?.catalog_item_status) out.push('force_catalog_item_status' as unknown as ControllerScenario);\n if (config.queryUpstreamTraffic) out.push(CONTROLLER_SCENARIOS.QUERY_UPSTREAM_TRAFFIC);\n if (config.queryProvenanceAuditObservations) {\n out.push(CONTROLLER_SCENARIOS.QUERY_PROVENANCE_AUDIT_OBSERVATIONS);\n }\n if (config.force?.upstream_unavailable) out.push(CONTROLLER_SCENARIOS.FORCE_UPSTREAM_UNAVAILABLE);\n return out;\n}\n\n/** Create a comply_test_controller scaffold from domain-grouped adapters. */\nexport function createComplyController(config: ComplyControllerConfig): ComplyController {\n const seedCache = config.seedCache ?? createSeedFixtureCache();\n const scenarios = advertisedScenarios(config);\n // Stable reference so factory answers list_scenarios without invoking\n // createStore — handleTestControllerRequest inspects the `scenarios` field.\n const factoryScenarios = Object.freeze([...scenarios]) as readonly ControllerScenario[];\n\n async function handleRaw(input: Record<string, unknown>): Promise<ComplyTestControllerResponse> {\n const inputCtx = input.context;\n // Echoes input.context on FORBIDDEN early-returns (sandboxGate denial/throw)\n // that bypass handleTestControllerRequest. The delegated call at the end of\n // this function already echoes context internally — addCtx is a no-op there.\n const addCtx = (r: ComplyTestControllerResponse): ComplyTestControllerResponse =>\n inputCtx !== undefined && typeof inputCtx === 'object' && inputCtx !== null && r.context === undefined\n ? ({ ...r, context: inputCtx } as ComplyTestControllerResponse)\n : r;\n\n // `list_scenarios` is a capability probe — answer it without consulting\n // the gate so buyer tooling can distinguish \"controller exists but\n // locked\" from \"controller missing entirely\". State-mutating scenarios\n // still go through the gate below.\n const isListScenariosProbe = input.scenario === 'list_scenarios';\n\n if (config.sandboxGate && !isListScenariosProbe) {\n let allowed: unknown;\n try {\n allowed = await config.sandboxGate(input);\n } catch (err) {\n // Don't leak gate-internal errors. Treat as denial — matches how a\n // sandbox would fail closed if its auth layer threw.\n void err;\n return addCtx(controllerError('FORBIDDEN', 'Sandbox gate check failed'));\n }\n // Strict equality: anything that is not literally `true` is a denial.\n // Guards against gates that accidentally return a reason string, a\n // number, or a truthy object.\n if (allowed !== true) {\n return addCtx(\n controllerError(\n 'FORBIDDEN',\n 'comply_test_controller is disabled in this environment (non-sandbox or gate denied)'\n )\n );\n }\n }\n\n const ctx: ComplyControllerContext = { input };\n const store = buildStore(config, ctx);\n\n return handleTestControllerRequest({ scenarios: factoryScenarios, createStore: () => store }, input, { seedCache });\n }\n\n async function handle(input: Record<string, unknown>) {\n return toMcpResponse(await handleRaw(input));\n }\n\n // Shallow-copy the canonical shape and overlay any adopter-supplied\n // extension fields. Spread order is canonical-then-extensions so a\n // collision (e.g., adopter redefines `params`) lets the adopter win.\n // Zod schema values are themselves immutable, so a one-level copy is\n // enough to keep callers from poisoning subsequent registrations.\n const toolDefinition: ComplyControllerToolDefinition = Object.freeze({\n name: 'comply_test_controller',\n description: 'Triggers seller-side state transitions for compliance testing. Sandbox only.',\n inputSchema: { ...TOOL_INPUT_SHAPE, ...(config.inputSchema ?? {}) },\n });\n\n // Per-controller latch so the \"ungated controller\" warning fires once even\n // when serve() invokes the factory (and therefore register) per request.\n let hasWarnedOnRegister = false;\n\n function register(server: AdcpServer | McpServer): void {\n // Loud warning when the tool is about to be exposed without any explicit\n // gate. Sellers who intentionally gate at the transport layer can silence\n // this by setting ADCP_SANDBOX=1 (or ADCP_COMPLY_CONTROLLER_UNGATED=1 to\n // opt out entirely). Prevents silent fail-open misuse without breaking\n // the API's \"gate is optional\" shape.\n if (\n !hasWarnedOnRegister &&\n !config.sandboxGate &&\n process.env.ADCP_SANDBOX !== '1' &&\n process.env.ADCP_COMPLY_CONTROLLER_UNGATED !== '1'\n ) {\n hasWarnedOnRegister = true;\n // eslint-disable-next-line no-console\n console.warn(\n '[comply_test_controller] Registered with no sandboxGate and no ' +\n 'ADCP_SANDBOX / ADCP_COMPLY_CONTROLLER_UNGATED env flag. The tool ' +\n 'will accept every request — only correct if your transport layer ' +\n 'enforces sandbox isolation. See createComplyController docs.'\n );\n }\n const mcp = getSdkServer(server as AdcpServer) ?? (server as McpServer);\n mcp.registerTool(\n toolDefinition.name,\n {\n description: toolDefinition.description,\n inputSchema: toolDefinition.inputSchema,\n },\n (async (input: Record<string, unknown>) => handle(input)) as Parameters<typeof mcp.registerTool>[2]\n );\n }\n\n return { toolDefinition, handleRaw, handle, register };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
function expectControllerError(result, code) {
|
|
8
2
|
if (result.success !== false) {
|
|
9
3
|
throw new Error(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/testing/controller-assertions.ts"],"sourcesContent":["/**\n * Assertion helpers for unit tests that exercise\n * {@link handleTestControllerRequest} directly.\n */\n\nimport type {\n ComplyTestControllerResponse,\n ControllerError,\n ListScenariosSuccess,\n StateTransitionSuccess,\n SimulationSuccess,\n ForcedDirectiveSuccess,\n SeedSuccess,\n} from '../types/tools.generated';\n\ntype AnyControllerSuccess =\n | ListScenariosSuccess\n | StateTransitionSuccess\n | SimulationSuccess\n | ForcedDirectiveSuccess\n | SeedSuccess;\n\n/**\n * `ControllerError` with `error_detail` guaranteed to be present. The SDK's\n * internal `controllerError` constructor always populates it, so in practice\n * every error returned by the dispatcher satisfies this narrower type —\n * returning it lets callers assert on detail without `!` or `?.`.\n */\nexport type ControllerErrorWithDetail = ControllerError & { error_detail: string };\n\n/**\n * Narrow a `ComplyTestControllerResponse` to the `ControllerError` arm and\n * assert its `error` code. Throws an `Error` with a descriptive message when\n * the response is success-shaped or when the code does not match.\n *\n * Returns the narrowed error so callers can make further assertions on\n * `error_detail` / `current_state` without re-casting.\n *\n * ```ts\n * const result = await handleTestControllerRequest(store, {\n * scenario: 'force_account_status',\n * params: {},\n * });\n * const err = expectControllerError(result, 'INVALID_PARAMS');\n * assert.match(err.error_detail, /account_id/);\n * ```\n */\nexport function expectControllerError(\n result: ComplyTestControllerResponse,\n code: ControllerError['error']\n): ControllerErrorWithDetail {\n if (result.success !== false) {\n throw new Error(\n `expectControllerError(${code}): expected a ControllerError response but got success-shaped result: ${JSON.stringify(\n result\n )}`\n );\n }\n if (result.error !== code) {\n throw new Error(\n `expectControllerError(${code}): expected error code \"${code}\" but got \"${result.error}\" (detail: ${\n result.error_detail ?? 'n/a'\n })`\n );\n }\n // error_detail is always populated by the SDK's controllerError() constructor.\n return result as ControllerErrorWithDetail;\n}\n\n/**\n * Narrow a `ComplyTestControllerResponse` to its success arm and optionally\n * assert which success shape it is (`'list'`, `'transition'`, or `'simulation'`).\n * Throws when the response is an error or when the arm doesn't match.\n *\n * Returns the narrowed success value so callers skip the `if (result.success)`\n * boilerplate and access arm-specific fields directly.\n *\n * ```ts\n * const result = await handleTestControllerRequest(store, {\n * scenario: 'force_account_status',\n * params: { account_id: 'acct-1', status: 'suspended' },\n * });\n * const ok = expectControllerSuccess(result, 'transition');\n * assert.strictEqual(ok.current_state, 'suspended');\n * ```\n */\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind?: 'list'): ListScenariosSuccess;\nexport function expectControllerSuccess(\n result: ComplyTestControllerResponse,\n kind: 'transition'\n): StateTransitionSuccess;\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind: 'simulation'): SimulationSuccess;\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind: 'forced'): ForcedDirectiveSuccess;\n/**\n * Narrow to the `SeedSuccess` arm (3.0.1+ message-only seed acknowledgement).\n *\n * Every `seed_*` scenario returns `SeedSuccess` (`{ success: true, message? }`)\n * — both responses produced by the SDK's own `dispatchSeed` and responses\n * from third-party sellers. Force_* scenarios continue to return\n * `StateTransitionSuccess` (`previous_state` / `current_state`) under\n * `kind: 'transition'`.\n */\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind: 'seed'): SeedSuccess;\nexport function expectControllerSuccess(result: ComplyTestControllerResponse): AnyControllerSuccess;\nexport function expectControllerSuccess(\n result: ComplyTestControllerResponse,\n kind?: 'list' | 'transition' | 'simulation' | 'forced' | 'seed'\n): AnyControllerSuccess {\n if (result.success !== true) {\n throw new Error(\n `expectControllerSuccess: expected a success response but got ControllerError ${result.error}${\n result.error_detail ? ` (${result.error_detail})` : ''\n }`\n );\n }\n\n if (kind === undefined) {\n return result;\n }\n\n // Discriminate by required field — every success arm has exactly one\n // distinguishing key. `seed` is the message-only fallback when no other\n // arm's required field is present.\n const actual: 'list' | 'transition' | 'simulation' | 'forced' | 'seed' =\n 'scenarios' in result\n ? 'list'\n : 'previous_state' in result\n ? 'transition'\n : 'simulated' in result\n ? 'simulation'\n : 'forced' in result\n ? 'forced'\n : 'seed';\n if (actual !== kind) {\n throw new Error(`expectControllerSuccess(${kind}): expected \"${kind}\" arm but got \"${actual}\"`);\n }\n return result;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/testing/controller-assertions.ts"],"sourcesContent":["/**\n * Assertion helpers for unit tests that exercise\n * {@link handleTestControllerRequest} directly.\n */\n\nimport type {\n ComplyTestControllerResponse,\n ControllerError,\n ListScenariosSuccess,\n StateTransitionSuccess,\n SimulationSuccess,\n ForcedDirectiveSuccess,\n SeedSuccess,\n} from '../types/tools.generated';\n\ntype AnyControllerSuccess =\n | ListScenariosSuccess\n | StateTransitionSuccess\n | SimulationSuccess\n | ForcedDirectiveSuccess\n | SeedSuccess;\n\n/**\n * `ControllerError` with `error_detail` guaranteed to be present. The SDK's\n * internal `controllerError` constructor always populates it, so in practice\n * every error returned by the dispatcher satisfies this narrower type —\n * returning it lets callers assert on detail without `!` or `?.`.\n */\nexport type ControllerErrorWithDetail = ControllerError & { error_detail: string };\n\n/**\n * Narrow a `ComplyTestControllerResponse` to the `ControllerError` arm and\n * assert its `error` code. Throws an `Error` with a descriptive message when\n * the response is success-shaped or when the code does not match.\n *\n * Returns the narrowed error so callers can make further assertions on\n * `error_detail` / `current_state` without re-casting.\n *\n * ```ts\n * const result = await handleTestControllerRequest(store, {\n * scenario: 'force_account_status',\n * params: {},\n * });\n * const err = expectControllerError(result, 'INVALID_PARAMS');\n * assert.match(err.error_detail, /account_id/);\n * ```\n */\nexport function expectControllerError(\n result: ComplyTestControllerResponse,\n code: ControllerError['error']\n): ControllerErrorWithDetail {\n if (result.success !== false) {\n throw new Error(\n `expectControllerError(${code}): expected a ControllerError response but got success-shaped result: ${JSON.stringify(\n result\n )}`\n );\n }\n if (result.error !== code) {\n throw new Error(\n `expectControllerError(${code}): expected error code \"${code}\" but got \"${result.error}\" (detail: ${\n result.error_detail ?? 'n/a'\n })`\n );\n }\n // error_detail is always populated by the SDK's controllerError() constructor.\n return result as ControllerErrorWithDetail;\n}\n\n/**\n * Narrow a `ComplyTestControllerResponse` to its success arm and optionally\n * assert which success shape it is (`'list'`, `'transition'`, or `'simulation'`).\n * Throws when the response is an error or when the arm doesn't match.\n *\n * Returns the narrowed success value so callers skip the `if (result.success)`\n * boilerplate and access arm-specific fields directly.\n *\n * ```ts\n * const result = await handleTestControllerRequest(store, {\n * scenario: 'force_account_status',\n * params: { account_id: 'acct-1', status: 'suspended' },\n * });\n * const ok = expectControllerSuccess(result, 'transition');\n * assert.strictEqual(ok.current_state, 'suspended');\n * ```\n */\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind?: 'list'): ListScenariosSuccess;\nexport function expectControllerSuccess(\n result: ComplyTestControllerResponse,\n kind: 'transition'\n): StateTransitionSuccess;\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind: 'simulation'): SimulationSuccess;\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind: 'forced'): ForcedDirectiveSuccess;\n/**\n * Narrow to the `SeedSuccess` arm (3.0.1+ message-only seed acknowledgement).\n *\n * Every `seed_*` scenario returns `SeedSuccess` (`{ success: true, message? }`)\n * — both responses produced by the SDK's own `dispatchSeed` and responses\n * from third-party sellers. Force_* scenarios continue to return\n * `StateTransitionSuccess` (`previous_state` / `current_state`) under\n * `kind: 'transition'`.\n */\nexport function expectControllerSuccess(result: ComplyTestControllerResponse, kind: 'seed'): SeedSuccess;\nexport function expectControllerSuccess(result: ComplyTestControllerResponse): AnyControllerSuccess;\nexport function expectControllerSuccess(\n result: ComplyTestControllerResponse,\n kind?: 'list' | 'transition' | 'simulation' | 'forced' | 'seed'\n): AnyControllerSuccess {\n if (result.success !== true) {\n throw new Error(\n `expectControllerSuccess: expected a success response but got ControllerError ${result.error}${\n result.error_detail ? ` (${result.error_detail})` : ''\n }`\n );\n }\n\n if (kind === undefined) {\n return result;\n }\n\n // Discriminate by required field — every success arm has exactly one\n // distinguishing key. `seed` is the message-only fallback when no other\n // arm's required field is present.\n const actual: 'list' | 'transition' | 'simulation' | 'forced' | 'seed' =\n 'scenarios' in result\n ? 'list'\n : 'previous_state' in result\n ? 'transition'\n : 'simulated' in result\n ? 'simulation'\n : 'forced' in result\n ? 'forced'\n : 'seed';\n if (actual !== kind) {\n throw new Error(`expectControllerSuccess(${kind}): expected \"${kind}\" arm but got \"${actual}\"`);\n }\n return result;\n}\n"],"mappings":"AA+CO,SAAS,sBACd,QACA,MAC2B;AAC3B,MAAI,OAAO,YAAY,OAAO;AAC5B,UAAM,IAAI;AAAA,MACR,yBAAyB,IAAI,yEAAyE,KAAK;AAAA,QACzG;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,OAAO,UAAU,MAAM;AACzB,UAAM,IAAI;AAAA,MACR,yBAAyB,IAAI,2BAA2B,IAAI,cAAc,OAAO,KAAK,cACpF,OAAO,gBAAgB,KACzB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAqCO,SAAS,wBACd,QACA,MACsB;AACtB,MAAI,OAAO,YAAY,MAAM;AAC3B,UAAM,IAAI;AAAA,MACR,gFAAgF,OAAO,KAAK,GAC1F,OAAO,eAAe,KAAK,OAAO,YAAY,MAAM,EACtD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,QAAW;AACtB,WAAO;AAAA,EACT;AAKA,QAAM,SACJ,eAAe,SACX,SACA,oBAAoB,SAClB,eACA,eAAe,SACb,eACA,YAAY,SACV,WACA;AACZ,MAAI,WAAW,MAAM;AACnB,UAAM,IAAI,MAAM,2BAA2B,IAAI,gBAAgB,IAAI,kBAAkB,MAAM,GAAG;AAAA,EAChG;AACA,SAAO;AACT;","names":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
|
|
2
|
-
import { dirname as __adcpDirname } from 'node:path';
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from 'node:module';
|
|
4
|
-
const __filename = __adcpFileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = __adcpDirname(__filename);
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
7
1
|
function formatTestResults(result) {
|
|
8
2
|
const statusEmoji = result.overall_passed ? "\u2705" : "\u274C";
|
|
9
3
|
let output = `## ${statusEmoji} Agent Test Results
|