@adcp/sdk 12.0.0 → 12.0.1
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.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.mjs +0 -6
- 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.mjs +0 -6
- package/dist/lib/server/index.mjs.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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/storyboard/agent-routing.ts"],"sourcesContent":["/**\n * Per-specialism agent routing for the storyboard runner (#1066).\n *\n * Resolves each step's `task` to one of N agents in\n * `StoryboardRunOptions.agents` so storyboards that span specialisms\n * (e.g., a `signal_marketplace/governance_denied` flow that calls\n * `sync_governance` then `activate_signal`) can hit the tenant that\n * actually owns each tool.\n *\n * Resolution order per step:\n * 1. Explicit `step.agent` (escape hatch for cross-domain tools)\n * 2. `TASK_FEATURE_MAP` → first protocol → unique claimant in the agents map\n * 3. `options.default_agent`\n * 4. Throw `RoutingError`\n *\n * Multi-claim conflicts (two agents claim the same protocol AND a step\n * relying on that protocol lacks an explicit `agent:` override) fail-fast\n * at routing-context build time, BEFORE any non-discovery network calls.\n *\n * ## Webhook receiver topology in routed mode\n *\n * When `StoryboardRunOptions.webhook_receiver` is set alongside `agents`,\n * the receiver is **shared** across all tenants — one HTTP server, one base\n * URL. The runner does not create per-tenant receivers and does not need to:\n * delivery correlation is by **step-keyed URL** (`/step/<step_id>/<op_id>`),\n * not by source agent. If both a governance tenant and a signals tenant\n * emit webhooks during the same run, the assertion harness matches each\n * delivery to its `expect_webhook*` step by URL path, regardless of which\n * tenant posted it. This means:\n *\n * - `{{runner.webhook_base}}` substitutes the same URL for every step\n * across all agents — no per-agent variable needed.\n * - `{{runner.webhook_url:<step_id>}}` is always sufficient to pin a\n * delivery to the step that requested it, even when multiple tenants\n * emit concurrently.\n * - Per-tenant receivers are not supported; if a future storyboard needs\n * delivery-source disambiguation, use distinct step IDs (they already\n * produce distinct URL paths).\n *\n * See `StoryboardRunOptions.webhook_receiver` JSDoc and `webhook-receiver.ts`\n * for implementation details.\n */\nimport type { TestClient } from '../client';\nimport { getOrCreateClient, getOrDiscoverProfile } from '../client';\nimport type { AgentProfile } from '../types';\nimport { TASK_FEATURE_MAP, type AdcpProtocol } from '../../utils/capabilities';\nimport type { AgentEntry, Storyboard, StoryboardRunOptions, StoryboardStep } from './types';\n\n// `compliance_testing` is on the wire as a top-level capability block, NOT\n// in `supported_protocols`. `parseCapabilitiesResponse`\n// (`src/lib/utils/capabilities.ts`) normalizes the block into the\n// `protocols[]` list before `getOrDiscoverProfile` writes it onto the\n// profile, so by the time routing reads `profile.supported_protocols`\n// the value is present. Any future refactor that strips that\n// normalization needs to either preserve it or drop `compliance_testing`\n// from this set.\nconst KNOWN_PROTOCOLS: ReadonlySet<AdcpProtocol> = new Set([\n 'media_buy',\n 'signals',\n 'governance',\n 'creative',\n 'sponsored_intelligence',\n 'trusted_match',\n 'compliance_testing',\n 'brand',\n]);\n\n/**\n * Redact common auth-token patterns before propagating an upstream error\n * message into runner output / CI logs / `StoryboardResult.error`. The\n * concrete leak path: a misconfigured agent that echoes its received\n * `Authorization: Bearer <token>` header in a 401 body would put the\n * caller's own bearer for that tenant into CI artifacts. The bearer is\n * already in the caller's CI environment, so this is parity with single-\n * agent mode rather than a fix for a new leak — but defense-in-depth is\n * cheap and the regex is bounded.\n *\n * Patterns covered:\n * - `Authorization: Bearer <token>` (any case, common in 401 echoes)\n * - `Bearer <token>` standalone\n * - `?token=<value>` / `&token=<value>` query-string tokens\n *\n * Best-effort. Anything unusual (custom-header schemes, base64-encoded\n * blobs in JSON bodies) is not caught — operators should still treat\n * upstream-error CI logs as sensitive.\n */\nfunction scrubAuthSecrets(text: string): string {\n // The character class `[A-Za-z0-9._~+/=-]+` looks like high-entropy\n // content to entropy-based secret scanners (GitGuardian/gitleaks). It\n // is the redaction pattern itself — no secret is encoded here.\n // ggignore\n return text\n .replace(/(authorization\\s*:\\s*bearer\\s+)[A-Za-z0-9._~+/=-]+/gi, '$1[REDACTED]') // ggignore\n .replace(/\\bbearer\\s+[A-Za-z0-9._~+/=-]+/gi, 'Bearer [REDACTED]') // ggignore\n .replace(/([?&]token=)[A-Za-z0-9._~+/=-]+/gi, '$1[REDACTED]'); // ggignore\n}\n\n/** Per-agent options view: per-entry overrides shadow run-level defaults. */\nfunction buildAgentOptions(entry: AgentEntry, options: StoryboardRunOptions): StoryboardRunOptions {\n return {\n ...options,\n auth: entry.auth ?? options.auth,\n protocol: entry.transport ?? options.protocol,\n // _client, _profile, and agents are run-scoped — never inherit into\n // per-agent views. `_profile` is the load-bearing one: when comply()\n // sets it on the run-level options, `getOrDiscoverProfile` (`client.ts`)\n // short-circuits to that cached profile and skips the actual probe.\n // Without this clear, every per-agent discovery would return\n // comply()'s primary-tenant profile instead of probing the real\n // tenant — silently breaking the protocol-claim index that routing\n // depends on.\n _client: undefined,\n _profile: undefined,\n agents: undefined,\n agentTools: undefined,\n };\n}\n\nexport interface AgentRoutingContext {\n /** Per-agent transport client. Lifecycle owned by the runner. */\n clients: Map<string, TestClient>;\n /** Per-agent discovered profile (`get_adcp_capabilities` result). */\n profiles: Map<string, AgentProfile>;\n /** Protocol → keys of agents that claim it. */\n protocolIndex: Map<AdcpProtocol, string[]>;\n /** Resolved (key → URL) for echo on the storyboard result. */\n agentMap: Record<string, string>;\n /**\n * Agents whose discovery failed when `discovery_resilient: true` was set.\n * Empty in the default (hard-failure) mode — if any agent failed and\n * resilient mode is off, `buildRoutingContext` throws `DiscoveryFailure`\n * instead of returning. The runner echoes this list onto\n * `StoryboardResult.discovery_failures` so operators see the topology\n * breakage even when the storyboard otherwise completes.\n */\n discoveryFailures: DiscoveryFailure[];\n}\n\nexport class RoutingError extends Error {\n constructor(\n message: string,\n public readonly task: string,\n public readonly hint: string\n ) {\n super(message);\n this.name = 'RoutingError';\n }\n}\n\nexport class DiscoveryFailure extends Error {\n constructor(\n message: string,\n public readonly agentKey: string,\n public readonly url: string,\n public readonly underlying: string\n ) {\n super(message);\n this.name = 'DiscoveryFailure';\n }\n}\n\n/**\n * Discover every agent in the map in parallel and build the routing index.\n *\n * Failure modes:\n * - default (`options.discovery_resilient !== true`): any agent's\n * discovery failure → throw `DiscoveryFailure` (caller surfaces as a\n * hard storyboard failure, never a per-step skip). Correct for\n * production multi-tenant flows where every tenant is load-bearing.\n * - resilient (`options.discovery_resilient === true`, #1367): failed\n * agents are excluded from `profiles` + `protocolIndex` and reported\n * on `AgentRoutingContext.discoveryFailures`. Per-step routing then\n * surfaces failures only for storyboards that actually need the\n * broken tenant — unrelated storyboards complete normally.\n * - protocol claimed by 2+ agents AND ≥1 storyboard step that needs it\n * lacks `step.agent` → `RoutingError` (conflict). Independent of\n * resilient mode.\n */\nexport async function buildRoutingContext(\n storyboard: Storyboard,\n options: StoryboardRunOptions\n): Promise<AgentRoutingContext> {\n const agents = options.agents!;\n const entries = Object.entries(agents);\n const resilient = options.discovery_resilient === true;\n\n const clients = new Map<string, TestClient>();\n const agentMap: Record<string, string> = {};\n for (const [key, entry] of entries) {\n const perAgentOptions = buildAgentOptions(entry, options);\n clients.set(key, getOrCreateClient(entry.url, perAgentOptions));\n agentMap[key] = entry.url;\n }\n\n // Parallel discovery — one tenant's slowness does not block another.\n const profiles = new Map<string, AgentProfile>();\n const discoveryFailures: DiscoveryFailure[] = [];\n const discoveryResults = await Promise.all(\n entries.map(async ([key, entry]) => {\n const perAgentOptions = buildAgentOptions(entry, options);\n try {\n const { profile, step } = await getOrDiscoverProfile(clients.get(key)!, perAgentOptions);\n return { key, profile, step };\n } catch (err) {\n return {\n key,\n profile: undefined,\n step: {\n step: 'Discover agent capabilities',\n passed: false,\n error: scrubAuthSecrets((err as Error)?.message || String(err)),\n },\n };\n }\n })\n );\n for (const r of discoveryResults) {\n if (!r.profile || r.step.passed === false) {\n // Bound the attacker-influenced upstream string. A malicious agent\n // could return an arbitrarily large error body during the discovery\n // probe; the unbounded string would flow into\n // `StoryboardResult.discovery_failures[].error` where downstream\n // dashboards / LLM contexts ingest it. 512 chars is enough for a\n // human to read the failure and grep logs for more.\n const rawDetail = scrubAuthSecrets(r.step.error ?? 'Discovery returned no profile.');\n const detail = rawDetail.length > 512 ? `${rawDetail.slice(0, 512)} …(truncated)` : rawDetail;\n // Default mode appends a signposted escape hatch so CI operators\n // discover the resilient flag without grep'ing the JSDoc. Suppressed\n // in resilient mode (the operator already opted in) so the hint\n // doesn't appear in every per-agent failure attached to the result.\n const baseMessage = `Discovery failed for agent \"${r.key}\" (${agents[r.key]!.url}): ${detail}`;\n const message = resilient\n ? baseMessage\n : `${baseMessage}\\n\\nIf this is hello-cluster / exploratory CI and you want unrelated storyboards to complete despite this failure, ` +\n `set \\`StoryboardRunOptions.discovery_resilient: true\\`. Do NOT set it in production — a topology with a broken tenant ` +\n `is a hard misconfiguration there.`;\n const failure = new DiscoveryFailure(message, r.key, agents[r.key]!.url, detail);\n if (!resilient) throw failure;\n discoveryFailures.push(failure);\n continue;\n }\n profiles.set(r.key, r.profile);\n }\n\n const protocolIndex = buildProtocolIndex(profiles);\n detectMultiClaimConflicts(storyboard, protocolIndex);\n\n return { clients, profiles, protocolIndex, agentMap, discoveryFailures };\n}\n\n/**\n * Test seam: build a routing context from pre-baked profiles instead of\n * running discovery. Lets unit tests exercise conflict detection and\n * per-step resolution without spinning up live agents. Production code\n * uses `buildRoutingContext`; this entry point is exported for the\n * `agent-routing.test.js` harness.\n */\nexport function buildRoutingContextFromProfiles(\n storyboard: Storyboard,\n options: StoryboardRunOptions,\n profiles: Map<string, AgentProfile>\n): AgentRoutingContext {\n const agents = options.agents!;\n const agentMap: Record<string, string> = {};\n for (const [key, entry] of Object.entries(agents)) {\n agentMap[key] = entry.url;\n }\n const protocolIndex = buildProtocolIndex(profiles);\n detectMultiClaimConflicts(storyboard, protocolIndex);\n // Empty client map — callers that only test routing shouldn't dispatch.\n return { clients: new Map(), profiles, protocolIndex, agentMap, discoveryFailures: [] };\n}\n\n/**\n * Reverse-index `AgentProfile.supported_protocols` so routing can pick an\n * agent by tool→protocol→agent in O(1).\n *\n * Sorts the agent-key list per protocol for deterministic conflict-error\n * output and reproducible tests.\n */\nfunction buildProtocolIndex(profiles: Map<string, AgentProfile>): Map<AdcpProtocol, string[]> {\n const index = new Map<AdcpProtocol, string[]>();\n for (const [key, profile] of profiles) {\n const protocols = profile.supported_protocols ?? [];\n for (const p of protocols) {\n if (!KNOWN_PROTOCOLS.has(p as AdcpProtocol)) continue;\n const proto = p as AdcpProtocol;\n const list = index.get(proto) ?? [];\n list.push(key);\n index.set(proto, list);\n }\n }\n for (const list of index.values()) list.sort();\n return index;\n}\n\n/**\n * Walk the storyboard once and surface any tool→protocol resolution that\n * has 2+ candidate agents AND no explicit `step.agent` override.\n *\n * We could defer this to per-step routing time, but a multi-claim is\n * almost always a topology bug (two tenants accidentally claiming the\n * same protocol) — surfacing it before the first non-discovery network\n * call gives a much better error than a half-run storyboard.\n */\nfunction detectMultiClaimConflicts(storyboard: Storyboard, protocolIndex: Map<AdcpProtocol, string[]>): void {\n const conflicts: Array<{ task: string; protocol: AdcpProtocol; agents: string[]; stepIds: string[] }> = [];\n for (const phase of storyboard.phases ?? []) {\n for (const step of phase.steps ?? []) {\n if (step.agent !== undefined) continue;\n const protocol = primaryProtocolFor(step.task);\n if (!protocol) continue;\n const candidates = protocolIndex.get(protocol);\n if (!candidates || candidates.length < 2) continue;\n const existing = conflicts.find(c => c.task === step.task && c.protocol === protocol);\n if (existing) {\n existing.stepIds.push(step.id);\n } else {\n conflicts.push({\n task: step.task,\n protocol,\n agents: candidates,\n stepIds: [step.id],\n });\n }\n }\n }\n if (conflicts.length === 0) return;\n\n const lines = conflicts.map(\n c =>\n ` - tool \"${c.task}\" (protocol ${c.protocol}) is claimed by [${c.agents.join(', ')}] ` +\n `but step(s) [${c.stepIds.join(', ')}] do not declare \\`agent:\\` override.`\n );\n throw new RoutingError(\n `Routing conflict: multiple agents claim the same protocol and the storyboard ` +\n `does not disambiguate.\\n${lines.join('\\n')}\\n` +\n `Fix: either remove one of the conflicting agents from the map, or add ` +\n `\\`agent: <key>\\` to each affected step.`,\n conflicts[0]!.task,\n `Conflicting agents: ${conflicts[0]!.agents.join(', ')}`\n );\n}\n\n/**\n * First protocol-typed feature in `TASK_FEATURE_MAP[task]`, or `undefined`\n * for tools intentionally unmapped (e.g. `sync_creatives`, which serves\n * both media-buy and creative domains and requires explicit per-step\n * routing in multi-agent mode).\n */\nfunction primaryProtocolFor(task: string): AdcpProtocol | undefined {\n const features = TASK_FEATURE_MAP[task];\n if (!features) return undefined;\n for (const f of features) {\n if (KNOWN_PROTOCOLS.has(f as AdcpProtocol)) return f as AdcpProtocol;\n }\n return undefined;\n}\n\n/**\n * Resolve a step to its target agent key. Throws `RoutingError` when no\n * route can be determined; callers convert to a synthetic step result\n * (see Stage 4 in the runner).\n */\nexport function resolveAgentForStep(\n step: StoryboardStep,\n options: StoryboardRunOptions,\n ctx: AgentRoutingContext\n): string {\n if (step.agent !== undefined) {\n // If the override targets an agent whose discovery failed under\n // resilient mode, surface that explicitly rather than handing\n // dispatch a transport client to a broken tenant (which would\n // otherwise fail at the wire layer with a misleading transport\n // error). Only meaningful when `discoveryFailures` is non-empty;\n // under default (hard-failure) mode `buildRoutingContext` throws\n // before we reach this branch.\n const failed = ctx.discoveryFailures.find(f => f.agentKey === step.agent);\n if (failed) {\n throw new RoutingError(\n `Step \"${step.id}\" targets agent \"${step.agent}\" via \\`step.agent\\` override, ` +\n `but that agent's discovery failed: ${failed.underlying} ` +\n `(${failed.url}). Either remove the override, fix the agent, or ` +\n `route the step to a healthy agent.`,\n step.task,\n `agent \"${step.agent}\" failed discovery`\n );\n }\n return step.agent;\n }\n const protocol = primaryProtocolFor(step.task);\n if (protocol) {\n const candidates = ctx.protocolIndex.get(protocol) ?? [];\n if (candidates.length === 1) return candidates[0]!;\n if (candidates.length > 1) {\n // Conflict already detected at build time, but `step.agent` is\n // unset here. This branch is unreachable in well-formed runs; keep\n // it as a fail-loud sanity check.\n throw new RoutingError(\n `Internal: step \"${step.id}\" task \"${step.task}\" maps to protocol ` +\n `\"${protocol}\" claimed by [${candidates.join(', ')}], no step.agent override. ` +\n `This should have been caught at routing-context build time.`,\n step.task,\n `agents: ${candidates.join(', ')}`\n );\n }\n // Zero candidates — no agent in the map claims this protocol.\n if (options.default_agent) return options.default_agent;\n // Under `discovery_resilient`, an agent that was supposed to claim\n // this protocol may have been excluded by a failed probe. Suffix the\n // error so the operator sees the connection without correlating logs.\n const failedHint =\n ctx.discoveryFailures.length > 0\n ? ` Discovery failed for: ${ctx.discoveryFailures.map(f => `${f.agentKey} (${f.url})`).join(', ')}.`\n : '';\n throw new RoutingError(\n `No agent in the map claims protocol \"${protocol}\" required by tool ` +\n `\"${step.task}\" (step \"${step.id}\"). Available agents: ` +\n `${[...ctx.profiles.keys()].join(', ') || '(none — every agent failed discovery)'}.${failedHint} ` +\n `Add an agent that supports ${protocol}, or set \\`default_agent\\` to fall back.`,\n step.task,\n `protocol ${protocol} unclaimed`\n );\n }\n // Tool not in TASK_FEATURE_MAP (e.g., sync_creatives, comply_test_controller,\n // get_adcp_capabilities post-discovery, future tasks).\n if (options.default_agent) return options.default_agent;\n throw new RoutingError(\n `Tool \"${step.task}\" (step \"${step.id}\") has no specialism mapping ` +\n `(it serves multiple domains or is unrecognized). Set \\`agent: <key>\\` ` +\n `on the step, or set \\`default_agent\\` on the run options.`,\n step.task,\n 'no protocol mapping'\n );\n}\n"],"mappings":";;;;;;AA2CA,SAAS,mBAAmB,4BAA4B;AAExD,SAAS,wBAA2C;AAWpD,MAAM,kBAA6C,oBAAI,IAAI;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAqBD,SAAS,iBAAiB,MAAsB;AAK9C,SAAO,KACJ,QAAQ,wDAAwD,cAAc,EAC9E,QAAQ,oCAAoC,mBAAmB,EAC/D,QAAQ,qCAAqC,cAAc;AAChE;AAGA,SAAS,kBAAkB,OAAmB,SAAqD;AACjG,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,MAAM,QAAQ,QAAQ;AAAA,IAC5B,UAAU,MAAM,aAAa,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASrC,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,YAAY;AAAA,EACd;AACF;AAsBO,MAAM,qBAAqB,MAAM;AAAA,EACtC,YACE,SACgB,MACA,MAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAAA,EACA;AAKpB;AAEO,MAAM,yBAAyB,MAAM;AAAA,EAC1C,YACE,SACgB,UACA,KACA,YAChB;AACA,UAAM,OAAO;AAJG;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EANkB;AAAA,EACA;AAAA,EACA;AAKpB;AAmBA,eAAsB,oBACpB,YACA,SAC8B;AAC9B,QAAM,SAAS,QAAQ;AACvB,QAAM,UAAU,OAAO,QAAQ,MAAM;AACrC,QAAM,YAAY,QAAQ,wBAAwB;AAElD,QAAM,UAAU,oBAAI,IAAwB;AAC5C,QAAM,WAAmC,CAAC;AAC1C,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,UAAM,kBAAkB,kBAAkB,OAAO,OAAO;AACxD,YAAQ,IAAI,KAAK,kBAAkB,MAAM,KAAK,eAAe,CAAC;AAC9D,aAAS,GAAG,IAAI,MAAM;AAAA,EACxB;AAGA,QAAM,WAAW,oBAAI,IAA0B;AAC/C,QAAM,oBAAwC,CAAC;AAC/C,QAAM,mBAAmB,MAAM,QAAQ;AAAA,IACrC,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM;AAClC,YAAM,kBAAkB,kBAAkB,OAAO,OAAO;AACxD,UAAI;AACF,cAAM,EAAE,SAAS,KAAK,IAAI,MAAM,qBAAqB,QAAQ,IAAI,GAAG,GAAI,eAAe;AACvF,eAAO,EAAE,KAAK,SAAS,KAAK;AAAA,MAC9B,SAAS,KAAK;AACZ,eAAO;AAAA,UACL;AAAA,UACA,SAAS;AAAA,UACT,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,OAAO,iBAAkB,KAAe,WAAW,OAAO,GAAG,CAAC;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACA,aAAW,KAAK,kBAAkB;AAChC,QAAI,CAAC,EAAE,WAAW,EAAE,KAAK,WAAW,OAAO;AAOzC,YAAM,YAAY,iBAAiB,EAAE,KAAK,SAAS,gCAAgC;AACnF,YAAM,SAAS,UAAU,SAAS,MAAM,GAAG,UAAU,MAAM,GAAG,GAAG,CAAC,uBAAkB;AAKpF,YAAM,cAAc,+BAA+B,EAAE,GAAG,MAAM,OAAO,EAAE,GAAG,EAAG,GAAG,MAAM,MAAM;AAC5F,YAAM,UAAU,YACZ,cACA,GAAG,WAAW;AAAA;AAAA;AAGlB,YAAM,UAAU,IAAI,iBAAiB,SAAS,EAAE,KAAK,OAAO,EAAE,GAAG,EAAG,KAAK,MAAM;AAC/E,UAAI,CAAC,UAAW,OAAM;AACtB,wBAAkB,KAAK,OAAO;AAC9B;AAAA,IACF;AACA,aAAS,IAAI,EAAE,KAAK,EAAE,OAAO;AAAA,EAC/B;AAEA,QAAM,gBAAgB,mBAAmB,QAAQ;AACjD,4BAA0B,YAAY,aAAa;AAEnD,SAAO,EAAE,SAAS,UAAU,eAAe,UAAU,kBAAkB;AACzE;AASO,SAAS,gCACd,YACA,SACA,UACqB;AACrB,QAAM,SAAS,QAAQ;AACvB,QAAM,WAAmC,CAAC;AAC1C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,aAAS,GAAG,IAAI,MAAM;AAAA,EACxB;AACA,QAAM,gBAAgB,mBAAmB,QAAQ;AACjD,4BAA0B,YAAY,aAAa;AAEnD,SAAO,EAAE,SAAS,oBAAI,IAAI,GAAG,UAAU,eAAe,UAAU,mBAAmB,CAAC,EAAE;AACxF;AASA,SAAS,mBAAmB,UAAkE;AAC5F,QAAM,QAAQ,oBAAI,IAA4B;AAC9C,aAAW,CAAC,KAAK,OAAO,KAAK,UAAU;AACrC,UAAM,YAAY,QAAQ,uBAAuB,CAAC;AAClD,eAAW,KAAK,WAAW;AACzB,UAAI,CAAC,gBAAgB,IAAI,CAAiB,EAAG;AAC7C,YAAM,QAAQ;AACd,YAAM,OAAO,MAAM,IAAI,KAAK,KAAK,CAAC;AAClC,WAAK,KAAK,GAAG;AACb,YAAM,IAAI,OAAO,IAAI;AAAA,IACvB;AAAA,EACF;AACA,aAAW,QAAQ,MAAM,OAAO,EAAG,MAAK,KAAK;AAC7C,SAAO;AACT;AAWA,SAAS,0BAA0B,YAAwB,eAAkD;AAC3G,QAAM,YAAkG,CAAC;AACzG,aAAW,SAAS,WAAW,UAAU,CAAC,GAAG;AAC3C,eAAW,QAAQ,MAAM,SAAS,CAAC,GAAG;AACpC,UAAI,KAAK,UAAU,OAAW;AAC9B,YAAM,WAAW,mBAAmB,KAAK,IAAI;AAC7C,UAAI,CAAC,SAAU;AACf,YAAM,aAAa,cAAc,IAAI,QAAQ;AAC7C,UAAI,CAAC,cAAc,WAAW,SAAS,EAAG;AAC1C,YAAM,WAAW,UAAU,KAAK,OAAK,EAAE,SAAS,KAAK,QAAQ,EAAE,aAAa,QAAQ;AACpF,UAAI,UAAU;AACZ,iBAAS,QAAQ,KAAK,KAAK,EAAE;AAAA,MAC/B,OAAO;AACL,kBAAU,KAAK;AAAA,UACb,MAAM,KAAK;AAAA,UACX;AAAA,UACA,QAAQ;AAAA,UACR,SAAS,CAAC,KAAK,EAAE;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,WAAW,EAAG;AAE5B,QAAM,QAAQ,UAAU;AAAA,IACtB,OACE,aAAa,EAAE,IAAI,eAAe,EAAE,QAAQ,oBAAoB,EAAE,OAAO,KAAK,IAAI,CAAC,kBACnE,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,EACxC;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EAC6B,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,IAG7C,UAAU,CAAC,EAAG;AAAA,IACd,uBAAuB,UAAU,CAAC,EAAG,OAAO,KAAK,IAAI,CAAC;AAAA,EACxD;AACF;AAQA,SAAS,mBAAmB,MAAwC;AAClE,QAAM,WAAW,iBAAiB,IAAI;AACtC,MAAI,CAAC,SAAU,QAAO;AACtB,aAAW,KAAK,UAAU;AACxB,QAAI,gBAAgB,IAAI,CAAiB,EAAG,QAAO;AAAA,EACrD;AACA,SAAO;AACT;AAOO,SAAS,oBACd,MACA,SACA,KACQ;AACR,MAAI,KAAK,UAAU,QAAW;AAQ5B,UAAM,SAAS,IAAI,kBAAkB,KAAK,OAAK,EAAE,aAAa,KAAK,KAAK;AACxE,QAAI,QAAQ;AACV,YAAM,IAAI;AAAA,QACR,SAAS,KAAK,EAAE,oBAAoB,KAAK,KAAK,qEACN,OAAO,UAAU,KACnD,OAAO,GAAG;AAAA,QAEhB,KAAK;AAAA,QACL,UAAU,KAAK,KAAK;AAAA,MACtB;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AACA,QAAM,WAAW,mBAAmB,KAAK,IAAI;AAC7C,MAAI,UAAU;AACZ,UAAM,aAAa,IAAI,cAAc,IAAI,QAAQ,KAAK,CAAC;AACvD,QAAI,WAAW,WAAW,EAAG,QAAO,WAAW,CAAC;AAChD,QAAI,WAAW,SAAS,GAAG;AAIzB,YAAM,IAAI;AAAA,QACR,mBAAmB,KAAK,EAAE,WAAW,KAAK,IAAI,uBACxC,QAAQ,iBAAiB,WAAW,KAAK,IAAI,CAAC;AAAA,QAEpD,KAAK;AAAA,QACL,WAAW,WAAW,KAAK,IAAI,CAAC;AAAA,MAClC;AAAA,IACF;AAEA,QAAI,QAAQ,cAAe,QAAO,QAAQ;AAI1C,UAAM,aACJ,IAAI,kBAAkB,SAAS,IAC3B,0BAA0B,IAAI,kBAAkB,IAAI,OAAK,GAAG,EAAE,QAAQ,KAAK,EAAE,GAAG,GAAG,EAAE,KAAK,IAAI,CAAC,MAC/F;AACN,UAAM,IAAI;AAAA,MACR,wCAAwC,QAAQ,uBAC1C,KAAK,IAAI,YAAY,KAAK,EAAE,yBAC7B,CAAC,GAAG,IAAI,SAAS,KAAK,CAAC,EAAE,KAAK,IAAI,KAAK,4CAAuC,IAAI,UAAU,+BACjE,QAAQ;AAAA,MACxC,KAAK;AAAA,MACL,YAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AAGA,MAAI,QAAQ,cAAe,QAAO,QAAQ;AAC1C,QAAM,IAAI;AAAA,IACR,SAAS,KAAK,IAAI,YAAY,KAAK,EAAE;AAAA,IAGrC,KAAK;AAAA,IACL;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/agent-routing.ts"],"sourcesContent":["/**\n * Per-specialism agent routing for the storyboard runner (#1066).\n *\n * Resolves each step's `task` to one of N agents in\n * `StoryboardRunOptions.agents` so storyboards that span specialisms\n * (e.g., a `signal_marketplace/governance_denied` flow that calls\n * `sync_governance` then `activate_signal`) can hit the tenant that\n * actually owns each tool.\n *\n * Resolution order per step:\n * 1. Explicit `step.agent` (escape hatch for cross-domain tools)\n * 2. `TASK_FEATURE_MAP` → first protocol → unique claimant in the agents map\n * 3. `options.default_agent`\n * 4. Throw `RoutingError`\n *\n * Multi-claim conflicts (two agents claim the same protocol AND a step\n * relying on that protocol lacks an explicit `agent:` override) fail-fast\n * at routing-context build time, BEFORE any non-discovery network calls.\n *\n * ## Webhook receiver topology in routed mode\n *\n * When `StoryboardRunOptions.webhook_receiver` is set alongside `agents`,\n * the receiver is **shared** across all tenants — one HTTP server, one base\n * URL. The runner does not create per-tenant receivers and does not need to:\n * delivery correlation is by **step-keyed URL** (`/step/<step_id>/<op_id>`),\n * not by source agent. If both a governance tenant and a signals tenant\n * emit webhooks during the same run, the assertion harness matches each\n * delivery to its `expect_webhook*` step by URL path, regardless of which\n * tenant posted it. This means:\n *\n * - `{{runner.webhook_base}}` substitutes the same URL for every step\n * across all agents — no per-agent variable needed.\n * - `{{runner.webhook_url:<step_id>}}` is always sufficient to pin a\n * delivery to the step that requested it, even when multiple tenants\n * emit concurrently.\n * - Per-tenant receivers are not supported; if a future storyboard needs\n * delivery-source disambiguation, use distinct step IDs (they already\n * produce distinct URL paths).\n *\n * See `StoryboardRunOptions.webhook_receiver` JSDoc and `webhook-receiver.ts`\n * for implementation details.\n */\nimport type { TestClient } from '../client';\nimport { getOrCreateClient, getOrDiscoverProfile } from '../client';\nimport type { AgentProfile } from '../types';\nimport { TASK_FEATURE_MAP, type AdcpProtocol } from '../../utils/capabilities';\nimport type { AgentEntry, Storyboard, StoryboardRunOptions, StoryboardStep } from './types';\n\n// `compliance_testing` is on the wire as a top-level capability block, NOT\n// in `supported_protocols`. `parseCapabilitiesResponse`\n// (`src/lib/utils/capabilities.ts`) normalizes the block into the\n// `protocols[]` list before `getOrDiscoverProfile` writes it onto the\n// profile, so by the time routing reads `profile.supported_protocols`\n// the value is present. Any future refactor that strips that\n// normalization needs to either preserve it or drop `compliance_testing`\n// from this set.\nconst KNOWN_PROTOCOLS: ReadonlySet<AdcpProtocol> = new Set([\n 'media_buy',\n 'signals',\n 'governance',\n 'creative',\n 'sponsored_intelligence',\n 'trusted_match',\n 'compliance_testing',\n 'brand',\n]);\n\n/**\n * Redact common auth-token patterns before propagating an upstream error\n * message into runner output / CI logs / `StoryboardResult.error`. The\n * concrete leak path: a misconfigured agent that echoes its received\n * `Authorization: Bearer <token>` header in a 401 body would put the\n * caller's own bearer for that tenant into CI artifacts. The bearer is\n * already in the caller's CI environment, so this is parity with single-\n * agent mode rather than a fix for a new leak — but defense-in-depth is\n * cheap and the regex is bounded.\n *\n * Patterns covered:\n * - `Authorization: Bearer <token>` (any case, common in 401 echoes)\n * - `Bearer <token>` standalone\n * - `?token=<value>` / `&token=<value>` query-string tokens\n *\n * Best-effort. Anything unusual (custom-header schemes, base64-encoded\n * blobs in JSON bodies) is not caught — operators should still treat\n * upstream-error CI logs as sensitive.\n */\nfunction scrubAuthSecrets(text: string): string {\n // The character class `[A-Za-z0-9._~+/=-]+` looks like high-entropy\n // content to entropy-based secret scanners (GitGuardian/gitleaks). It\n // is the redaction pattern itself — no secret is encoded here.\n // ggignore\n return text\n .replace(/(authorization\\s*:\\s*bearer\\s+)[A-Za-z0-9._~+/=-]+/gi, '$1[REDACTED]') // ggignore\n .replace(/\\bbearer\\s+[A-Za-z0-9._~+/=-]+/gi, 'Bearer [REDACTED]') // ggignore\n .replace(/([?&]token=)[A-Za-z0-9._~+/=-]+/gi, '$1[REDACTED]'); // ggignore\n}\n\n/** Per-agent options view: per-entry overrides shadow run-level defaults. */\nfunction buildAgentOptions(entry: AgentEntry, options: StoryboardRunOptions): StoryboardRunOptions {\n return {\n ...options,\n auth: entry.auth ?? options.auth,\n protocol: entry.transport ?? options.protocol,\n // _client, _profile, and agents are run-scoped — never inherit into\n // per-agent views. `_profile` is the load-bearing one: when comply()\n // sets it on the run-level options, `getOrDiscoverProfile` (`client.ts`)\n // short-circuits to that cached profile and skips the actual probe.\n // Without this clear, every per-agent discovery would return\n // comply()'s primary-tenant profile instead of probing the real\n // tenant — silently breaking the protocol-claim index that routing\n // depends on.\n _client: undefined,\n _profile: undefined,\n agents: undefined,\n agentTools: undefined,\n };\n}\n\nexport interface AgentRoutingContext {\n /** Per-agent transport client. Lifecycle owned by the runner. */\n clients: Map<string, TestClient>;\n /** Per-agent discovered profile (`get_adcp_capabilities` result). */\n profiles: Map<string, AgentProfile>;\n /** Protocol → keys of agents that claim it. */\n protocolIndex: Map<AdcpProtocol, string[]>;\n /** Resolved (key → URL) for echo on the storyboard result. */\n agentMap: Record<string, string>;\n /**\n * Agents whose discovery failed when `discovery_resilient: true` was set.\n * Empty in the default (hard-failure) mode — if any agent failed and\n * resilient mode is off, `buildRoutingContext` throws `DiscoveryFailure`\n * instead of returning. The runner echoes this list onto\n * `StoryboardResult.discovery_failures` so operators see the topology\n * breakage even when the storyboard otherwise completes.\n */\n discoveryFailures: DiscoveryFailure[];\n}\n\nexport class RoutingError extends Error {\n constructor(\n message: string,\n public readonly task: string,\n public readonly hint: string\n ) {\n super(message);\n this.name = 'RoutingError';\n }\n}\n\nexport class DiscoveryFailure extends Error {\n constructor(\n message: string,\n public readonly agentKey: string,\n public readonly url: string,\n public readonly underlying: string\n ) {\n super(message);\n this.name = 'DiscoveryFailure';\n }\n}\n\n/**\n * Discover every agent in the map in parallel and build the routing index.\n *\n * Failure modes:\n * - default (`options.discovery_resilient !== true`): any agent's\n * discovery failure → throw `DiscoveryFailure` (caller surfaces as a\n * hard storyboard failure, never a per-step skip). Correct for\n * production multi-tenant flows where every tenant is load-bearing.\n * - resilient (`options.discovery_resilient === true`, #1367): failed\n * agents are excluded from `profiles` + `protocolIndex` and reported\n * on `AgentRoutingContext.discoveryFailures`. Per-step routing then\n * surfaces failures only for storyboards that actually need the\n * broken tenant — unrelated storyboards complete normally.\n * - protocol claimed by 2+ agents AND ≥1 storyboard step that needs it\n * lacks `step.agent` → `RoutingError` (conflict). Independent of\n * resilient mode.\n */\nexport async function buildRoutingContext(\n storyboard: Storyboard,\n options: StoryboardRunOptions\n): Promise<AgentRoutingContext> {\n const agents = options.agents!;\n const entries = Object.entries(agents);\n const resilient = options.discovery_resilient === true;\n\n const clients = new Map<string, TestClient>();\n const agentMap: Record<string, string> = {};\n for (const [key, entry] of entries) {\n const perAgentOptions = buildAgentOptions(entry, options);\n clients.set(key, getOrCreateClient(entry.url, perAgentOptions));\n agentMap[key] = entry.url;\n }\n\n // Parallel discovery — one tenant's slowness does not block another.\n const profiles = new Map<string, AgentProfile>();\n const discoveryFailures: DiscoveryFailure[] = [];\n const discoveryResults = await Promise.all(\n entries.map(async ([key, entry]) => {\n const perAgentOptions = buildAgentOptions(entry, options);\n try {\n const { profile, step } = await getOrDiscoverProfile(clients.get(key)!, perAgentOptions);\n return { key, profile, step };\n } catch (err) {\n return {\n key,\n profile: undefined,\n step: {\n step: 'Discover agent capabilities',\n passed: false,\n error: scrubAuthSecrets((err as Error)?.message || String(err)),\n },\n };\n }\n })\n );\n for (const r of discoveryResults) {\n if (!r.profile || r.step.passed === false) {\n // Bound the attacker-influenced upstream string. A malicious agent\n // could return an arbitrarily large error body during the discovery\n // probe; the unbounded string would flow into\n // `StoryboardResult.discovery_failures[].error` where downstream\n // dashboards / LLM contexts ingest it. 512 chars is enough for a\n // human to read the failure and grep logs for more.\n const rawDetail = scrubAuthSecrets(r.step.error ?? 'Discovery returned no profile.');\n const detail = rawDetail.length > 512 ? `${rawDetail.slice(0, 512)} …(truncated)` : rawDetail;\n // Default mode appends a signposted escape hatch so CI operators\n // discover the resilient flag without grep'ing the JSDoc. Suppressed\n // in resilient mode (the operator already opted in) so the hint\n // doesn't appear in every per-agent failure attached to the result.\n const baseMessage = `Discovery failed for agent \"${r.key}\" (${agents[r.key]!.url}): ${detail}`;\n const message = resilient\n ? baseMessage\n : `${baseMessage}\\n\\nIf this is hello-cluster / exploratory CI and you want unrelated storyboards to complete despite this failure, ` +\n `set \\`StoryboardRunOptions.discovery_resilient: true\\`. Do NOT set it in production — a topology with a broken tenant ` +\n `is a hard misconfiguration there.`;\n const failure = new DiscoveryFailure(message, r.key, agents[r.key]!.url, detail);\n if (!resilient) throw failure;\n discoveryFailures.push(failure);\n continue;\n }\n profiles.set(r.key, r.profile);\n }\n\n const protocolIndex = buildProtocolIndex(profiles);\n detectMultiClaimConflicts(storyboard, protocolIndex);\n\n return { clients, profiles, protocolIndex, agentMap, discoveryFailures };\n}\n\n/**\n * Test seam: build a routing context from pre-baked profiles instead of\n * running discovery. Lets unit tests exercise conflict detection and\n * per-step resolution without spinning up live agents. Production code\n * uses `buildRoutingContext`; this entry point is exported for the\n * `agent-routing.test.js` harness.\n */\nexport function buildRoutingContextFromProfiles(\n storyboard: Storyboard,\n options: StoryboardRunOptions,\n profiles: Map<string, AgentProfile>\n): AgentRoutingContext {\n const agents = options.agents!;\n const agentMap: Record<string, string> = {};\n for (const [key, entry] of Object.entries(agents)) {\n agentMap[key] = entry.url;\n }\n const protocolIndex = buildProtocolIndex(profiles);\n detectMultiClaimConflicts(storyboard, protocolIndex);\n // Empty client map — callers that only test routing shouldn't dispatch.\n return { clients: new Map(), profiles, protocolIndex, agentMap, discoveryFailures: [] };\n}\n\n/**\n * Reverse-index `AgentProfile.supported_protocols` so routing can pick an\n * agent by tool→protocol→agent in O(1).\n *\n * Sorts the agent-key list per protocol for deterministic conflict-error\n * output and reproducible tests.\n */\nfunction buildProtocolIndex(profiles: Map<string, AgentProfile>): Map<AdcpProtocol, string[]> {\n const index = new Map<AdcpProtocol, string[]>();\n for (const [key, profile] of profiles) {\n const protocols = profile.supported_protocols ?? [];\n for (const p of protocols) {\n if (!KNOWN_PROTOCOLS.has(p as AdcpProtocol)) continue;\n const proto = p as AdcpProtocol;\n const list = index.get(proto) ?? [];\n list.push(key);\n index.set(proto, list);\n }\n }\n for (const list of index.values()) list.sort();\n return index;\n}\n\n/**\n * Walk the storyboard once and surface any tool→protocol resolution that\n * has 2+ candidate agents AND no explicit `step.agent` override.\n *\n * We could defer this to per-step routing time, but a multi-claim is\n * almost always a topology bug (two tenants accidentally claiming the\n * same protocol) — surfacing it before the first non-discovery network\n * call gives a much better error than a half-run storyboard.\n */\nfunction detectMultiClaimConflicts(storyboard: Storyboard, protocolIndex: Map<AdcpProtocol, string[]>): void {\n const conflicts: Array<{ task: string; protocol: AdcpProtocol; agents: string[]; stepIds: string[] }> = [];\n for (const phase of storyboard.phases ?? []) {\n for (const step of phase.steps ?? []) {\n if (step.agent !== undefined) continue;\n const protocol = primaryProtocolFor(step.task);\n if (!protocol) continue;\n const candidates = protocolIndex.get(protocol);\n if (!candidates || candidates.length < 2) continue;\n const existing = conflicts.find(c => c.task === step.task && c.protocol === protocol);\n if (existing) {\n existing.stepIds.push(step.id);\n } else {\n conflicts.push({\n task: step.task,\n protocol,\n agents: candidates,\n stepIds: [step.id],\n });\n }\n }\n }\n if (conflicts.length === 0) return;\n\n const lines = conflicts.map(\n c =>\n ` - tool \"${c.task}\" (protocol ${c.protocol}) is claimed by [${c.agents.join(', ')}] ` +\n `but step(s) [${c.stepIds.join(', ')}] do not declare \\`agent:\\` override.`\n );\n throw new RoutingError(\n `Routing conflict: multiple agents claim the same protocol and the storyboard ` +\n `does not disambiguate.\\n${lines.join('\\n')}\\n` +\n `Fix: either remove one of the conflicting agents from the map, or add ` +\n `\\`agent: <key>\\` to each affected step.`,\n conflicts[0]!.task,\n `Conflicting agents: ${conflicts[0]!.agents.join(', ')}`\n );\n}\n\n/**\n * First protocol-typed feature in `TASK_FEATURE_MAP[task]`, or `undefined`\n * for tools intentionally unmapped (e.g. `sync_creatives`, which serves\n * both media-buy and creative domains and requires explicit per-step\n * routing in multi-agent mode).\n */\nfunction primaryProtocolFor(task: string): AdcpProtocol | undefined {\n const features = TASK_FEATURE_MAP[task];\n if (!features) return undefined;\n for (const f of features) {\n if (KNOWN_PROTOCOLS.has(f as AdcpProtocol)) return f as AdcpProtocol;\n }\n return undefined;\n}\n\n/**\n * Resolve a step to its target agent key. Throws `RoutingError` when no\n * route can be determined; callers convert to a synthetic step result\n * (see Stage 4 in the runner).\n */\nexport function resolveAgentForStep(\n step: StoryboardStep,\n options: StoryboardRunOptions,\n ctx: AgentRoutingContext\n): string {\n if (step.agent !== undefined) {\n // If the override targets an agent whose discovery failed under\n // resilient mode, surface that explicitly rather than handing\n // dispatch a transport client to a broken tenant (which would\n // otherwise fail at the wire layer with a misleading transport\n // error). Only meaningful when `discoveryFailures` is non-empty;\n // under default (hard-failure) mode `buildRoutingContext` throws\n // before we reach this branch.\n const failed = ctx.discoveryFailures.find(f => f.agentKey === step.agent);\n if (failed) {\n throw new RoutingError(\n `Step \"${step.id}\" targets agent \"${step.agent}\" via \\`step.agent\\` override, ` +\n `but that agent's discovery failed: ${failed.underlying} ` +\n `(${failed.url}). Either remove the override, fix the agent, or ` +\n `route the step to a healthy agent.`,\n step.task,\n `agent \"${step.agent}\" failed discovery`\n );\n }\n return step.agent;\n }\n const protocol = primaryProtocolFor(step.task);\n if (protocol) {\n const candidates = ctx.protocolIndex.get(protocol) ?? [];\n if (candidates.length === 1) return candidates[0]!;\n if (candidates.length > 1) {\n // Conflict already detected at build time, but `step.agent` is\n // unset here. This branch is unreachable in well-formed runs; keep\n // it as a fail-loud sanity check.\n throw new RoutingError(\n `Internal: step \"${step.id}\" task \"${step.task}\" maps to protocol ` +\n `\"${protocol}\" claimed by [${candidates.join(', ')}], no step.agent override. ` +\n `This should have been caught at routing-context build time.`,\n step.task,\n `agents: ${candidates.join(', ')}`\n );\n }\n // Zero candidates — no agent in the map claims this protocol.\n if (options.default_agent) return options.default_agent;\n // Under `discovery_resilient`, an agent that was supposed to claim\n // this protocol may have been excluded by a failed probe. Suffix the\n // error so the operator sees the connection without correlating logs.\n const failedHint =\n ctx.discoveryFailures.length > 0\n ? ` Discovery failed for: ${ctx.discoveryFailures.map(f => `${f.agentKey} (${f.url})`).join(', ')}.`\n : '';\n throw new RoutingError(\n `No agent in the map claims protocol \"${protocol}\" required by tool ` +\n `\"${step.task}\" (step \"${step.id}\"). Available agents: ` +\n `${[...ctx.profiles.keys()].join(', ') || '(none — every agent failed discovery)'}.${failedHint} ` +\n `Add an agent that supports ${protocol}, or set \\`default_agent\\` to fall back.`,\n step.task,\n `protocol ${protocol} unclaimed`\n );\n }\n // Tool not in TASK_FEATURE_MAP (e.g., sync_creatives, comply_test_controller,\n // get_adcp_capabilities post-discovery, future tasks).\n if (options.default_agent) return options.default_agent;\n throw new RoutingError(\n `Tool \"${step.task}\" (step \"${step.id}\") has no specialism mapping ` +\n `(it serves multiple domains or is unrecognized). Set \\`agent: <key>\\` ` +\n `on the step, or set \\`default_agent\\` on the run options.`,\n step.task,\n 'no protocol mapping'\n );\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
|
const registry = /* @__PURE__ */ new Map();
|
|
8
2
|
function registerAssertion(spec, options = {}) {
|
|
9
3
|
if (!spec.id) throw new Error("registerAssertion: spec.id is required");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/storyboard/assertions.ts"],"sourcesContent":["/**\n * Storyboard cross-step assertion registry.\n *\n * Storyboards express per-step checks inline (response_schema, field_value,\n * http_status, etc.). Assertions encode properties that must hold *across*\n * a whole run: idempotency dedup, governance denial never mutates, status\n * monotonic, context never echoes secrets on error. They're specialism- or\n * protocol-wide, so encoding them per-step duplicates path setup and\n * catches timing-dependent violations only by accident.\n *\n * Assertions are programmatic (TS), not declarative — the paths they walk,\n * the state they carry across steps, and the outcomes they report are too\n * varied for a uniform YAML schema. Storyboards reference them by id on\n * the top-level `invariants: [...]` array; the runner resolves the ids at\n * start and fails fast on unknowns.\n *\n * Registration is explicit: modules that define assertions call\n * `registerAssertion(...)` at import time, and the code driving `runStoryboard`\n * imports those modules before invoking the runner. No auto-discovery.\n *\n * See adcontextprotocol/adcp#2639 for the originating design.\n */\n\nimport type {\n AssertionResult,\n Storyboard,\n StoryboardInvariants,\n StoryboardRunOptions,\n StoryboardStepResult,\n StepInvariantsObject,\n} from './types';\n\n// ────────────────────────────────────────────────────────────\n// Public types\n// ────────────────────────────────────────────────────────────\n\n/**\n * Context passed to every assertion callback. `state` is the assertion's\n * private scratch space for the current run — the runner constructs one\n * per-assertion, per-run, so separate assertions and separate runs never\n * see each other's state.\n */\nexport interface AssertionContext {\n storyboard: Storyboard;\n agentUrl: string;\n options: StoryboardRunOptions;\n state: Record<string, unknown>;\n}\n\n/**\n * An assertion definition. All three hooks are optional — most assertions\n * only need one (e.g. idempotency dedup observes `onStep`; governance\n * denial mutation-block may do an `onEnd` scan over prior step results).\n *\n * Hook semantics:\n * - `onStart`: fires once after runner init, before the first step.\n * - `onStep`: fires after each step completes (including skips). Return\n * step-scoped `AssertionResult[]`; the runner appends each result's\n * pass/fail into the step's `validations[]` under `check: \"assertion\"`\n * AND into `StoryboardResult.assertions[]` with `scope: \"step\"`.\n * - `onEnd`: fires once after the last phase, before `overall_passed` is\n * computed. Return storyboard-scoped `AssertionResult[]`; they land in\n * `StoryboardResult.assertions[]` with `scope: \"storyboard\"`.\n *\n * The runner flips `overall_passed` to false when any assertion fails —\n * that's what makes them gating conformance signal, not advisory output.\n */\nexport interface AssertionSpec {\n id: string;\n description: string;\n /**\n * When true, the assertion runs on every storyboard unless explicitly\n * disabled via `storyboard.invariants.disable`. Defaults to `false` —\n * non-default assertions are opt-in through `invariants.enable` (object\n * form) or `invariants: [id, ...]` (legacy additive array form). The\n * bundled assertions in `default-invariants.ts` all set this to `true`\n * so forks and new specialisms inherit baseline cross-step gating\n * automatically; consumers registering custom assertions can opt in by\n * setting it on their own specs.\n */\n default?: boolean;\n onStart?(ctx: AssertionContext): void | Promise<void>;\n onStep?(\n ctx: AssertionContext,\n stepResult: StoryboardStepResult\n ): Omit<AssertionResult, 'assertion_id' | 'scope'>[] | Promise<Omit<AssertionResult, 'assertion_id' | 'scope'>[]>;\n onEnd?(\n ctx: AssertionContext\n ): Omit<AssertionResult, 'assertion_id' | 'scope'>[] | Promise<Omit<AssertionResult, 'assertion_id' | 'scope'>[]>;\n}\n\n// ────────────────────────────────────────────────────────────\n// Registry\n// ────────────────────────────────────────────────────────────\n\nconst registry = new Map<string, AssertionSpec>();\n\nexport interface RegisterAssertionOptions {\n /**\n * Replace an existing registration for the same id instead of throwing.\n * Intended for consumers that want to override a default assertion shipped\n * by this package (e.g. a stricter `context.no_secret_echo`) without\n * clearing the whole registry and re-registering every other default.\n * Defaults to `false` so the throw-on-duplicate behaviour still catches\n * two modules fighting over the same id unintentionally.\n */\n override?: boolean;\n}\n\n/**\n * Register an assertion. Throws on duplicate id unless `options.override` is\n * set — re-registration is almost always a sign of two modules fighting over\n * the same id, not an intent to override. Consumers that want to replace a\n * default shipped by this package should pass `{ override: true }`.\n */\nexport function registerAssertion(spec: AssertionSpec, options: RegisterAssertionOptions = {}): void {\n if (!spec.id) throw new Error('registerAssertion: spec.id is required');\n if (registry.has(spec.id) && !options.override) {\n throw new Error(`registerAssertion: \"${spec.id}\" is already registered`);\n }\n registry.set(spec.id, spec);\n}\n\n/** Look up a registered assertion. Returns undefined if the id is unknown. */\nexport function getAssertion(id: string): AssertionSpec | undefined {\n return registry.get(id);\n}\n\n/** List every registered assertion id. Useful for diagnostics / tooling. */\nexport function listAssertions(): string[] {\n return [...registry.keys()];\n}\n\n/**\n * List every assertion id registered with `default: true`. Used by\n * `resolveAssertions` to build the baseline set that applies when a\n * storyboard omits `invariants:` entirely or uses the object form's\n * `disable: [...]` escape hatch.\n */\nexport function listDefaultAssertions(): string[] {\n const out: string[] = [];\n for (const [id, spec] of registry) {\n if (spec.default) out.push(id);\n }\n return out;\n}\n\n/**\n * Remove all registrations. Scoped for tests — production runs rely on\n * module-init registration, and clearing the registry mid-run would break\n * any in-flight storyboard.\n */\nexport function clearAssertionRegistry(): void {\n registry.clear();\n}\n\n/**\n * Resolve a storyboard's `invariants` declaration to the ordered list of\n * `AssertionSpec`s the runner will drive. Every assertion registered with\n * `default: true` is in the result unless the object form explicitly\n * disables it; any ids supplied (legacy array form, or the object form's\n * `enable`) are merged in on top.\n *\n * Fails fast at runner start on:\n * - any unknown id in the caller-supplied enable / legacy-array list,\n * - any id in `disable` that is not registered as a default (typo guard —\n * silently no-opping would mask real coverage gaps).\n *\n * The return order is: default specs (in registration order, with disabled\n * ones filtered out) followed by the enable / legacy-array specs in the\n * order the caller supplied them. Duplicates are collapsed.\n *\n * Accepts `string[]` (legacy additive form) and the `{ disable?, enable? }`\n * object form from `Storyboard.invariants`; `undefined` means \"apply all\n * defaults\". The looser `StoryboardInvariants | undefined` parameter type\n * exists so callers can forward `storyboard.invariants` directly.\n */\nexport function resolveAssertions(invariants: StoryboardInvariants | undefined): AssertionSpec[] {\n const { disable, enable } = normaliseInvariants(invariants);\n\n const resolved = new Map<string, AssertionSpec>();\n const defaultIds: string[] = [];\n for (const [id, spec] of registry) {\n if (!spec.default) continue;\n defaultIds.push(id);\n if (!disable.includes(id)) resolved.set(id, spec);\n }\n\n const unknownEnable: string[] = [];\n for (const id of enable) {\n const spec = registry.get(id);\n if (!spec) unknownEnable.push(id);\n else resolved.set(id, spec);\n }\n\n const defaultIdSet = new Set(defaultIds);\n const unknownDisable: string[] = disable.filter(id => !defaultIdSet.has(id));\n\n if (unknownEnable.length > 0 || unknownDisable.length > 0) {\n const lines: string[] = [];\n if (unknownEnable.length > 0) {\n const registered = [...registry.keys()].sort().join(', ') || '(none registered)';\n lines.push(\n `Storyboard references unregistered assertion${unknownEnable.length > 1 ? 's' : ''}: ${unknownEnable.join(', ')}. ` +\n suggestionClause(unknownEnable, [...registry.keys()]) +\n `Registered ids: ${registered}. ` +\n `Import the module that calls registerAssertion(...) for each id before running the storyboard.`\n );\n }\n if (unknownDisable.length > 0) {\n const known = defaultIds.slice().sort().join(', ') || '(none registered)';\n lines.push(\n `Storyboard invariants.disable names id${unknownDisable.length > 1 ? 's' : ''} that are not default-on: ${unknownDisable.join(', ')}. ` +\n suggestionClause(unknownDisable, defaultIds) +\n `Known default-on ids: ${known}. Non-default assertions don't need to be disabled — omit them instead.`\n );\n }\n throw new Error(lines.join(' '));\n }\n\n return [...resolved.values()];\n}\n\ninterface NormalisedInvariants {\n disable: string[];\n enable: string[];\n}\n\n// Object form keys. Any other top-level key (common typo: `disabled`) is a\n// silent-no-op trap under the permissive spread, so we catch it at parse-time.\nconst INVARIANTS_OBJECT_KEYS: ReadonlySet<string> = new Set(['disable', 'enable']);\n\n// Step-level form accepts only `disable`. Enabling an assertion for one step\n// has no coherent meaning (assertions reason across steps), so `enable` at\n// this scope is a parse-time authoring error.\nconst STEP_INVARIANTS_OBJECT_KEYS: ReadonlySet<string> = new Set(['disable']);\n\n/**\n * Validate every step's `invariants.disable` against the resolved assertion\n * set for this run, and against the storyboard-level disable. Throws on\n * unknown fields, unknown ids, and ids that are dead code because they're\n * already disabled storyboard-wide. Called once at runner start so\n * authoring mistakes surface before the first step runs.\n *\n * Accepts the resolved specs rather than the registry so a step can only\n * reference assertions that actually run for this storyboard — same\n * principle as the storyboard-level check.\n */\nexport function validateStepInvariants(storyboard: Storyboard, resolvedAssertions: AssertionSpec[]): void {\n const resolvedIds = new Set(resolvedAssertions.map(spec => spec.id));\n const storyboardDisable = new Set<string>();\n if (storyboard.invariants && !Array.isArray(storyboard.invariants)) {\n for (const id of storyboard.invariants.disable ?? []) storyboardDisable.add(id);\n }\n\n const problems: string[] = [];\n for (const phase of storyboard.phases) {\n for (const step of phase.steps) {\n const stepInvariants = step.invariants;\n if (!stepInvariants) continue;\n const unknownField = Object.keys(stepInvariants).filter(k => !STEP_INVARIANTS_OBJECT_KEYS.has(k));\n if (unknownField.length > 0) {\n problems.push(\n `Step \"${step.id}\" invariants has unknown field${unknownField.length > 1 ? 's' : ''}: ${unknownField.join(', ')}. ` +\n `Supported step-level fields are: ${[...STEP_INVARIANTS_OBJECT_KEYS].sort().join(', ')}.`\n );\n continue;\n }\n for (const id of stepInvariants.disable ?? []) {\n // Check the run-wide `disable` first — an id there is filtered out\n // of the resolved set, so without this the \"dead code\" case would\n // fall through to the more generic \"not in resolved set\" message.\n if (storyboardDisable.has(id)) {\n problems.push(\n `Step \"${step.id}\" invariants.disable names \"${id}\", but the storyboard already disables it run-wide. ` +\n `The step-level directive is dead code — remove one.`\n );\n continue;\n }\n if (!resolvedIds.has(id)) {\n const candidates = [...resolvedIds];\n const suggestion = suggestionClause([id], candidates);\n problems.push(\n `Step \"${step.id}\" invariants.disable names \"${id}\", which is not in the resolved assertion set for this run. ` +\n suggestion +\n `Resolved ids: ${candidates.sort().join(', ') || '(none)'}.`\n );\n }\n }\n }\n }\n\n if (problems.length > 0) throw new Error(problems.join(' '));\n}\n\n/**\n * Test whether a step's `invariants.disable` names the given assertion id.\n * Used by the runner to skip calling `onStep` for disabled invariants on\n * the step — a single choke point that keeps individual assertion code\n * unaware of the escape hatch.\n */\nexport function stepDisablesAssertion(stepInvariants: StepInvariantsObject | undefined, assertionId: string): boolean {\n if (!stepInvariants?.disable) return false;\n return stepInvariants.disable.includes(assertionId);\n}\n\nfunction normaliseInvariants(invariants: StoryboardInvariants | undefined): NormalisedInvariants {\n if (!invariants) return { disable: [], enable: [] };\n if (Array.isArray(invariants)) return { disable: [], enable: invariants };\n const unknown = Object.keys(invariants).filter(k => !INVARIANTS_OBJECT_KEYS.has(k));\n if (unknown.length > 0) {\n throw new Error(\n `Storyboard invariants has unknown field${unknown.length > 1 ? 's' : ''}: ${unknown.join(', ')}. ` +\n `Supported fields are: ${[...INVARIANTS_OBJECT_KEYS].sort().join(', ')}.`\n );\n }\n return { disable: invariants.disable ?? [], enable: invariants.enable ?? [] };\n}\n\n/**\n * Render a `Did you mean \"X\"?` clause when one of the unknown ids has a\n * close Levenshtein match in the candidate set. Kept narrow (distance ≤ 2,\n * first hit wins) so typo suggestions don't bleed into legitimate near-\n * collisions between registered ids.\n */\nfunction suggestionClause(unknown: string[], candidates: string[]): string {\n for (const id of unknown) {\n const hit = closestMatch(id, candidates);\n if (hit) return `Did you mean \"${hit}\"? `;\n }\n return '';\n}\n\nfunction closestMatch(input: string, candidates: string[]): string | null {\n let best: { id: string; distance: number } | null = null;\n for (const c of candidates) {\n const d = levenshtein(input, c);\n if (d === 0) continue;\n if (d > 2) continue;\n if (!best || d < best.distance) best = { id: c, distance: d };\n }\n return best ? best.id : null;\n}\n\nfunction levenshtein(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n let prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n let curr = new Array<number>(b.length + 1).fill(0);\n for (let i = 1; i <= a.length; i++) {\n curr[0] = i;\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(curr[j - 1]! + 1, prev[j]! + 1, prev[j - 1]! + cost);\n }\n [prev, curr] = [curr, prev];\n }\n return prev[b.length]!;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/assertions.ts"],"sourcesContent":["/**\n * Storyboard cross-step assertion registry.\n *\n * Storyboards express per-step checks inline (response_schema, field_value,\n * http_status, etc.). Assertions encode properties that must hold *across*\n * a whole run: idempotency dedup, governance denial never mutates, status\n * monotonic, context never echoes secrets on error. They're specialism- or\n * protocol-wide, so encoding them per-step duplicates path setup and\n * catches timing-dependent violations only by accident.\n *\n * Assertions are programmatic (TS), not declarative — the paths they walk,\n * the state they carry across steps, and the outcomes they report are too\n * varied for a uniform YAML schema. Storyboards reference them by id on\n * the top-level `invariants: [...]` array; the runner resolves the ids at\n * start and fails fast on unknowns.\n *\n * Registration is explicit: modules that define assertions call\n * `registerAssertion(...)` at import time, and the code driving `runStoryboard`\n * imports those modules before invoking the runner. No auto-discovery.\n *\n * See adcontextprotocol/adcp#2639 for the originating design.\n */\n\nimport type {\n AssertionResult,\n Storyboard,\n StoryboardInvariants,\n StoryboardRunOptions,\n StoryboardStepResult,\n StepInvariantsObject,\n} from './types';\n\n// ────────────────────────────────────────────────────────────\n// Public types\n// ────────────────────────────────────────────────────────────\n\n/**\n * Context passed to every assertion callback. `state` is the assertion's\n * private scratch space for the current run — the runner constructs one\n * per-assertion, per-run, so separate assertions and separate runs never\n * see each other's state.\n */\nexport interface AssertionContext {\n storyboard: Storyboard;\n agentUrl: string;\n options: StoryboardRunOptions;\n state: Record<string, unknown>;\n}\n\n/**\n * An assertion definition. All three hooks are optional — most assertions\n * only need one (e.g. idempotency dedup observes `onStep`; governance\n * denial mutation-block may do an `onEnd` scan over prior step results).\n *\n * Hook semantics:\n * - `onStart`: fires once after runner init, before the first step.\n * - `onStep`: fires after each step completes (including skips). Return\n * step-scoped `AssertionResult[]`; the runner appends each result's\n * pass/fail into the step's `validations[]` under `check: \"assertion\"`\n * AND into `StoryboardResult.assertions[]` with `scope: \"step\"`.\n * - `onEnd`: fires once after the last phase, before `overall_passed` is\n * computed. Return storyboard-scoped `AssertionResult[]`; they land in\n * `StoryboardResult.assertions[]` with `scope: \"storyboard\"`.\n *\n * The runner flips `overall_passed` to false when any assertion fails —\n * that's what makes them gating conformance signal, not advisory output.\n */\nexport interface AssertionSpec {\n id: string;\n description: string;\n /**\n * When true, the assertion runs on every storyboard unless explicitly\n * disabled via `storyboard.invariants.disable`. Defaults to `false` —\n * non-default assertions are opt-in through `invariants.enable` (object\n * form) or `invariants: [id, ...]` (legacy additive array form). The\n * bundled assertions in `default-invariants.ts` all set this to `true`\n * so forks and new specialisms inherit baseline cross-step gating\n * automatically; consumers registering custom assertions can opt in by\n * setting it on their own specs.\n */\n default?: boolean;\n onStart?(ctx: AssertionContext): void | Promise<void>;\n onStep?(\n ctx: AssertionContext,\n stepResult: StoryboardStepResult\n ): Omit<AssertionResult, 'assertion_id' | 'scope'>[] | Promise<Omit<AssertionResult, 'assertion_id' | 'scope'>[]>;\n onEnd?(\n ctx: AssertionContext\n ): Omit<AssertionResult, 'assertion_id' | 'scope'>[] | Promise<Omit<AssertionResult, 'assertion_id' | 'scope'>[]>;\n}\n\n// ────────────────────────────────────────────────────────────\n// Registry\n// ────────────────────────────────────────────────────────────\n\nconst registry = new Map<string, AssertionSpec>();\n\nexport interface RegisterAssertionOptions {\n /**\n * Replace an existing registration for the same id instead of throwing.\n * Intended for consumers that want to override a default assertion shipped\n * by this package (e.g. a stricter `context.no_secret_echo`) without\n * clearing the whole registry and re-registering every other default.\n * Defaults to `false` so the throw-on-duplicate behaviour still catches\n * two modules fighting over the same id unintentionally.\n */\n override?: boolean;\n}\n\n/**\n * Register an assertion. Throws on duplicate id unless `options.override` is\n * set — re-registration is almost always a sign of two modules fighting over\n * the same id, not an intent to override. Consumers that want to replace a\n * default shipped by this package should pass `{ override: true }`.\n */\nexport function registerAssertion(spec: AssertionSpec, options: RegisterAssertionOptions = {}): void {\n if (!spec.id) throw new Error('registerAssertion: spec.id is required');\n if (registry.has(spec.id) && !options.override) {\n throw new Error(`registerAssertion: \"${spec.id}\" is already registered`);\n }\n registry.set(spec.id, spec);\n}\n\n/** Look up a registered assertion. Returns undefined if the id is unknown. */\nexport function getAssertion(id: string): AssertionSpec | undefined {\n return registry.get(id);\n}\n\n/** List every registered assertion id. Useful for diagnostics / tooling. */\nexport function listAssertions(): string[] {\n return [...registry.keys()];\n}\n\n/**\n * List every assertion id registered with `default: true`. Used by\n * `resolveAssertions` to build the baseline set that applies when a\n * storyboard omits `invariants:` entirely or uses the object form's\n * `disable: [...]` escape hatch.\n */\nexport function listDefaultAssertions(): string[] {\n const out: string[] = [];\n for (const [id, spec] of registry) {\n if (spec.default) out.push(id);\n }\n return out;\n}\n\n/**\n * Remove all registrations. Scoped for tests — production runs rely on\n * module-init registration, and clearing the registry mid-run would break\n * any in-flight storyboard.\n */\nexport function clearAssertionRegistry(): void {\n registry.clear();\n}\n\n/**\n * Resolve a storyboard's `invariants` declaration to the ordered list of\n * `AssertionSpec`s the runner will drive. Every assertion registered with\n * `default: true` is in the result unless the object form explicitly\n * disables it; any ids supplied (legacy array form, or the object form's\n * `enable`) are merged in on top.\n *\n * Fails fast at runner start on:\n * - any unknown id in the caller-supplied enable / legacy-array list,\n * - any id in `disable` that is not registered as a default (typo guard —\n * silently no-opping would mask real coverage gaps).\n *\n * The return order is: default specs (in registration order, with disabled\n * ones filtered out) followed by the enable / legacy-array specs in the\n * order the caller supplied them. Duplicates are collapsed.\n *\n * Accepts `string[]` (legacy additive form) and the `{ disable?, enable? }`\n * object form from `Storyboard.invariants`; `undefined` means \"apply all\n * defaults\". The looser `StoryboardInvariants | undefined` parameter type\n * exists so callers can forward `storyboard.invariants` directly.\n */\nexport function resolveAssertions(invariants: StoryboardInvariants | undefined): AssertionSpec[] {\n const { disable, enable } = normaliseInvariants(invariants);\n\n const resolved = new Map<string, AssertionSpec>();\n const defaultIds: string[] = [];\n for (const [id, spec] of registry) {\n if (!spec.default) continue;\n defaultIds.push(id);\n if (!disable.includes(id)) resolved.set(id, spec);\n }\n\n const unknownEnable: string[] = [];\n for (const id of enable) {\n const spec = registry.get(id);\n if (!spec) unknownEnable.push(id);\n else resolved.set(id, spec);\n }\n\n const defaultIdSet = new Set(defaultIds);\n const unknownDisable: string[] = disable.filter(id => !defaultIdSet.has(id));\n\n if (unknownEnable.length > 0 || unknownDisable.length > 0) {\n const lines: string[] = [];\n if (unknownEnable.length > 0) {\n const registered = [...registry.keys()].sort().join(', ') || '(none registered)';\n lines.push(\n `Storyboard references unregistered assertion${unknownEnable.length > 1 ? 's' : ''}: ${unknownEnable.join(', ')}. ` +\n suggestionClause(unknownEnable, [...registry.keys()]) +\n `Registered ids: ${registered}. ` +\n `Import the module that calls registerAssertion(...) for each id before running the storyboard.`\n );\n }\n if (unknownDisable.length > 0) {\n const known = defaultIds.slice().sort().join(', ') || '(none registered)';\n lines.push(\n `Storyboard invariants.disable names id${unknownDisable.length > 1 ? 's' : ''} that are not default-on: ${unknownDisable.join(', ')}. ` +\n suggestionClause(unknownDisable, defaultIds) +\n `Known default-on ids: ${known}. Non-default assertions don't need to be disabled — omit them instead.`\n );\n }\n throw new Error(lines.join(' '));\n }\n\n return [...resolved.values()];\n}\n\ninterface NormalisedInvariants {\n disable: string[];\n enable: string[];\n}\n\n// Object form keys. Any other top-level key (common typo: `disabled`) is a\n// silent-no-op trap under the permissive spread, so we catch it at parse-time.\nconst INVARIANTS_OBJECT_KEYS: ReadonlySet<string> = new Set(['disable', 'enable']);\n\n// Step-level form accepts only `disable`. Enabling an assertion for one step\n// has no coherent meaning (assertions reason across steps), so `enable` at\n// this scope is a parse-time authoring error.\nconst STEP_INVARIANTS_OBJECT_KEYS: ReadonlySet<string> = new Set(['disable']);\n\n/**\n * Validate every step's `invariants.disable` against the resolved assertion\n * set for this run, and against the storyboard-level disable. Throws on\n * unknown fields, unknown ids, and ids that are dead code because they're\n * already disabled storyboard-wide. Called once at runner start so\n * authoring mistakes surface before the first step runs.\n *\n * Accepts the resolved specs rather than the registry so a step can only\n * reference assertions that actually run for this storyboard — same\n * principle as the storyboard-level check.\n */\nexport function validateStepInvariants(storyboard: Storyboard, resolvedAssertions: AssertionSpec[]): void {\n const resolvedIds = new Set(resolvedAssertions.map(spec => spec.id));\n const storyboardDisable = new Set<string>();\n if (storyboard.invariants && !Array.isArray(storyboard.invariants)) {\n for (const id of storyboard.invariants.disable ?? []) storyboardDisable.add(id);\n }\n\n const problems: string[] = [];\n for (const phase of storyboard.phases) {\n for (const step of phase.steps) {\n const stepInvariants = step.invariants;\n if (!stepInvariants) continue;\n const unknownField = Object.keys(stepInvariants).filter(k => !STEP_INVARIANTS_OBJECT_KEYS.has(k));\n if (unknownField.length > 0) {\n problems.push(\n `Step \"${step.id}\" invariants has unknown field${unknownField.length > 1 ? 's' : ''}: ${unknownField.join(', ')}. ` +\n `Supported step-level fields are: ${[...STEP_INVARIANTS_OBJECT_KEYS].sort().join(', ')}.`\n );\n continue;\n }\n for (const id of stepInvariants.disable ?? []) {\n // Check the run-wide `disable` first — an id there is filtered out\n // of the resolved set, so without this the \"dead code\" case would\n // fall through to the more generic \"not in resolved set\" message.\n if (storyboardDisable.has(id)) {\n problems.push(\n `Step \"${step.id}\" invariants.disable names \"${id}\", but the storyboard already disables it run-wide. ` +\n `The step-level directive is dead code — remove one.`\n );\n continue;\n }\n if (!resolvedIds.has(id)) {\n const candidates = [...resolvedIds];\n const suggestion = suggestionClause([id], candidates);\n problems.push(\n `Step \"${step.id}\" invariants.disable names \"${id}\", which is not in the resolved assertion set for this run. ` +\n suggestion +\n `Resolved ids: ${candidates.sort().join(', ') || '(none)'}.`\n );\n }\n }\n }\n }\n\n if (problems.length > 0) throw new Error(problems.join(' '));\n}\n\n/**\n * Test whether a step's `invariants.disable` names the given assertion id.\n * Used by the runner to skip calling `onStep` for disabled invariants on\n * the step — a single choke point that keeps individual assertion code\n * unaware of the escape hatch.\n */\nexport function stepDisablesAssertion(stepInvariants: StepInvariantsObject | undefined, assertionId: string): boolean {\n if (!stepInvariants?.disable) return false;\n return stepInvariants.disable.includes(assertionId);\n}\n\nfunction normaliseInvariants(invariants: StoryboardInvariants | undefined): NormalisedInvariants {\n if (!invariants) return { disable: [], enable: [] };\n if (Array.isArray(invariants)) return { disable: [], enable: invariants };\n const unknown = Object.keys(invariants).filter(k => !INVARIANTS_OBJECT_KEYS.has(k));\n if (unknown.length > 0) {\n throw new Error(\n `Storyboard invariants has unknown field${unknown.length > 1 ? 's' : ''}: ${unknown.join(', ')}. ` +\n `Supported fields are: ${[...INVARIANTS_OBJECT_KEYS].sort().join(', ')}.`\n );\n }\n return { disable: invariants.disable ?? [], enable: invariants.enable ?? [] };\n}\n\n/**\n * Render a `Did you mean \"X\"?` clause when one of the unknown ids has a\n * close Levenshtein match in the candidate set. Kept narrow (distance ≤ 2,\n * first hit wins) so typo suggestions don't bleed into legitimate near-\n * collisions between registered ids.\n */\nfunction suggestionClause(unknown: string[], candidates: string[]): string {\n for (const id of unknown) {\n const hit = closestMatch(id, candidates);\n if (hit) return `Did you mean \"${hit}\"? `;\n }\n return '';\n}\n\nfunction closestMatch(input: string, candidates: string[]): string | null {\n let best: { id: string; distance: number } | null = null;\n for (const c of candidates) {\n const d = levenshtein(input, c);\n if (d === 0) continue;\n if (d > 2) continue;\n if (!best || d < best.distance) best = { id: c, distance: d };\n }\n return best ? best.id : null;\n}\n\nfunction levenshtein(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n let prev = Array.from({ length: b.length + 1 }, (_, i) => i);\n let curr = new Array<number>(b.length + 1).fill(0);\n for (let i = 1; i <= a.length; i++) {\n curr[0] = i;\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(curr[j - 1]! + 1, prev[j]! + 1, prev[j - 1]! + cost);\n }\n [prev, curr] = [curr, prev];\n }\n return prev[b.length]!;\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 { lookupV1Format, projectV1ProductToV2 } from "../../v2/projection/index.mjs";
|
|
8
2
|
import { resolvePath, toJsonPointer } from "./path.mjs";
|
|
9
3
|
const FORMAT_IDENTITY_KEYS = ["agent_url", "id", "width", "height", "duration_ms"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/storyboard/canonical-format-satisfaction.ts"],"sourcesContent":["import { lookupV1Format, projectV1ProductToV2 } from '../../v2/projection';\nimport type { V1FormatId, V2ProductFormatDeclaration } from '../../v2/projection';\nimport type { TaskResult } from '../types';\nimport type { RunnerRequestRecord, StoryboardContext, StoryboardValidation, ValidationResult } from './types';\nimport { resolvePath, toJsonPointer } from './path';\n\ntype BugClass = 'normalization' | 'directionality' | 'range_containment' | 'closed_set' | 'authoring';\n\ninterface SatisfactionVerdict {\n satisfied: boolean;\n bug_class: BugClass;\n detail: string;\n json_pointer: string | null;\n actual?: unknown;\n observations?: unknown[];\n}\n\ninterface CanonicalSelector {\n format_kind: string;\n params: Record<string, unknown>;\n pointer: string;\n}\n\nconst FORMAT_IDENTITY_KEYS = ['agent_url', 'id', 'width', 'height', 'duration_ms'] as const;\nconst HANDLED_CANONICAL_PARAM_KEYS = new Set([\n 'width',\n 'height',\n 'sizes',\n 'min_width',\n 'max_width',\n 'min_height',\n 'max_height',\n 'duration_ms',\n 'duration_ms_exact',\n 'duration_ms_range',\n]);\nconst ARRAY_SUBSET_PARAM_KEYS = new Set(['video_codecs', 'audio_codecs', 'mime_types', 'file_types', 'formats']);\n\nexport function validateCanonicalFormatSatisfaction(\n validation: StoryboardValidation,\n request: RunnerRequestRecord | undefined,\n context: StoryboardContext | undefined,\n taskResult: TaskResult\n): ValidationResult {\n if (typeof validation.value !== 'boolean') {\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n error:\n 'canonical_format_satisfaction requires boolean `value` (true = request should be accepted, false = rejected)',\n json_pointer: null,\n expected: 'boolean validation.value',\n actual: validation.value ?? null,\n };\n }\n\n const expectedAccepted = validation.value;\n const taskAccepted = taskResult.success === true;\n const requestPayload = request?.payload;\n if (!isRecord(requestPayload)) {\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n error: 'canonical_format_satisfaction requires the runner request payload, but none was recorded',\n json_pointer: null,\n expected: 'create_media_buy request payload',\n actual: requestPayload ?? null,\n };\n }\n\n const packages = resolvePackages(requestPayload, validation.path);\n if (!packages.ok) {\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n error: packages.error,\n path: validation.path,\n json_pointer: packages.pointer,\n expected: 'one PackageRequest object or packages[] array',\n actual: packages.actual,\n };\n }\n\n const products = Array.isArray(context?.products) ? (context!.products as unknown[]) : [];\n const packageVerdicts = packages.packages.map(({ value, pointer }, index) =>\n evaluatePackage(value, pointer, index, products)\n );\n const localSatisfied = packageVerdicts.every(v => v.satisfied);\n const firstFailure = packageVerdicts.find(v => !v.satisfied);\n const primary = firstFailure ?? packageVerdicts[0];\n\n const localMatchesExpectation = localSatisfied === expectedAccepted;\n const observedMatchesExpectation = taskAccepted === expectedAccepted;\n const rejection = extractRejectionInfo(taskResult);\n const negativeRejectionMatches =\n expectedAccepted || taskAccepted || localSatisfied ? true : rejectionSupportsFormatFailure(rejection);\n const passed = localMatchesExpectation && observedMatchesExpectation && negativeRejectionMatches;\n if (passed) {\n return {\n check: validation.check,\n passed: true,\n description: validation.description,\n path: validation.path,\n json_pointer: primary?.json_pointer ?? null,\n expected: { accepted: expectedAccepted, local_satisfied: expectedAccepted },\n actual: {\n accepted: taskAccepted,\n local_satisfied: localSatisfied,\n ...(!taskAccepted && rejection && { rejection }),\n },\n observations: packageVerdicts.map(v => ({\n satisfied: v.satisfied,\n bug_class: v.bug_class,\n detail: v.detail,\n json_pointer: v.json_pointer,\n })),\n };\n }\n\n const likely = classifyLikelyFailure(expectedAccepted, taskAccepted, localSatisfied, primary);\n const error =\n !expectedAccepted && !taskAccepted && !localSatisfied && !negativeRejectionMatches\n ? `Expected request to be rejected for canonical format satisfaction, and local matching says it does not satisfy the product, but the agent rejection did not identify a format-selector cause. Observed rejection: ${formatRejectionInfo(rejection)}`\n : likely;\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n path: validation.path,\n error,\n json_pointer: primary?.json_pointer ?? null,\n expected: { accepted: expectedAccepted, local_satisfied: expectedAccepted },\n actual: {\n accepted: taskAccepted,\n local_satisfied: localSatisfied,\n ...(!taskAccepted && rejection && { rejection }),\n bug_class: primary?.bug_class ?? 'authoring',\n detail: primary?.detail ?? 'No package verdict was produced',\n },\n remediation: remediationFor(primary?.bug_class),\n observations: packageVerdicts.map(v => ({\n satisfied: v.satisfied,\n bug_class: v.bug_class,\n detail: v.detail,\n json_pointer: v.json_pointer,\n ...(v.actual !== undefined && { actual: v.actual }),\n ...(v.observations && { observations: v.observations }),\n })),\n };\n}\n\nfunction resolvePackages(\n requestPayload: Record<string, unknown>,\n path?: string\n):\n | { ok: true; packages: Array<{ value: Record<string, unknown>; pointer: string }> }\n | { ok: false; error: string; pointer: string | null; actual: unknown } {\n if (path) {\n const resolved = resolvePath(requestPayload, path);\n const pointer = toJsonPointer(path);\n if (Array.isArray(resolved)) {\n if (resolved.length === 0) {\n return {\n ok: false,\n error: `Path \"${path}\" resolved to an empty package array`,\n pointer,\n actual: [],\n };\n }\n const packages = resolved\n .map((item, i) => (isRecord(item) ? { value: item, pointer: `${pointer}/${i}` } : undefined))\n .filter((p): p is { value: Record<string, unknown>; pointer: string } => Boolean(p));\n if (packages.length === resolved.length) return { ok: true, packages };\n }\n if (isRecord(resolved)) return { ok: true, packages: [{ value: resolved, pointer }] };\n return {\n ok: false,\n error: `Path \"${path}\" did not resolve to a package object or array of package objects`,\n pointer,\n actual: resolved ?? null,\n };\n }\n\n const rawPackages = requestPayload.packages;\n if (!Array.isArray(rawPackages) || rawPackages.length === 0) {\n return {\n ok: false,\n error:\n 'canonical_format_satisfaction requires create_media_buy.packages[] unless validation.path selects a package',\n pointer: '/packages',\n actual: rawPackages ?? null,\n };\n }\n\n const packages = rawPackages\n .map((item, i) => (isRecord(item) ? { value: item, pointer: `/packages/${i}` } : undefined))\n .filter((p): p is { value: Record<string, unknown>; pointer: string } => Boolean(p));\n if (packages.length === rawPackages.length) return { ok: true, packages };\n return {\n ok: false,\n error: 'create_media_buy.packages[] contains a non-object entry',\n pointer: '/packages',\n actual: rawPackages,\n };\n}\n\nfunction evaluatePackage(\n pkg: Record<string, unknown>,\n pointer: string,\n index: number,\n products: unknown[]\n): SatisfactionVerdict {\n const productId = typeof pkg.product_id === 'string' ? pkg.product_id : undefined;\n const product = products.find(p => isRecord(p) && p.product_id === productId);\n if (!isRecord(product)) {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `No prior get_products context product matched packages[${index}].product_id=${JSON.stringify(productId)}`,\n json_pointer: `${pointer}/product_id`,\n actual: productId ?? null,\n };\n }\n\n const formatOptionRefs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs : [];\n if (formatOptionRefs.length > 0) {\n return evaluateFormatOptionRefs(formatOptionRefs, product, pointer);\n }\n\n const formatIds = Array.isArray(pkg.format_ids) ? pkg.format_ids : [];\n if (formatIds.length > 0) {\n return evaluateLegacyFormatIds(formatIds, product, pointer, productId!);\n }\n\n const canonicalSelectors = extractCanonicalSelectors(pkg, pointer);\n if (canonicalSelectors.length > 0) {\n return evaluateCanonicalSelectors(canonicalSelectors, product);\n }\n\n return {\n satisfied: true,\n bug_class: 'directionality',\n detail: 'Package omitted format selectors; per PackageRequest semantics the seller default is all product formats',\n json_pointer: pointer,\n };\n}\n\nfunction evaluateFormatOptionRefs(\n refs: unknown[],\n product: Record<string, unknown>,\n packagePointer: string\n): SatisfactionVerdict {\n const declarations = productFormatOptions(product);\n if (declarations.length === 0) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: 'Request used format_option_refs but the target product has no format_options[] closed set',\n json_pointer: `${packagePointer}/format_option_refs`,\n actual: refs,\n };\n }\n\n for (let i = 0; i < refs.length; i++) {\n const ref = refs[i];\n if (!isRecord(ref)) {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_option_refs[${i}] is not an object`,\n json_pointer: `${packagePointer}/format_option_refs/${i}`,\n actual: ref,\n };\n }\n if (ref.scope !== undefined && ref.scope !== 'product' && ref.scope !== 'publisher') {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_option_refs[${i}].scope must be \"product\" or \"publisher\" when present`,\n json_pointer: `${packagePointer}/format_option_refs/${i}/scope`,\n actual: ref.scope,\n };\n }\n if (ref.scope === 'publisher' && typeof ref.publisher_domain !== 'string') {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_option_refs[${i}] with scope=\"publisher\" requires publisher_domain`,\n json_pointer: `${packagePointer}/format_option_refs/${i}/publisher_domain`,\n actual: ref,\n };\n }\n const match = declarations.find(decl => {\n if (ref.scope === 'publisher') {\n return (\n decl.publisher_domain === ref.publisher_domain &&\n decl.format_option_id === ref.format_option_id &&\n typeof ref.publisher_domain === 'string'\n );\n }\n return decl.format_option_id === ref.format_option_id && !decl.publisher_domain;\n });\n if (!match) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: `format_option_refs[${i}] does not resolve to the target product's format_options[] closed set`,\n json_pointer: `${packagePointer}/format_option_refs/${i}`,\n actual: ref,\n observations: [{ available_format_option_ids: declarations.map(declarationLabel).filter(Boolean) }],\n };\n }\n }\n\n return {\n satisfied: true,\n bug_class: 'directionality',\n detail: 'Every format_option_refs[] entry resolved to the target product format_options[] closed set',\n json_pointer: `${packagePointer}/format_option_refs`,\n };\n}\n\nfunction evaluateLegacyFormatIds(\n refs: unknown[],\n product: Record<string, unknown>,\n packagePointer: string,\n productId: string\n): SatisfactionVerdict {\n const declarations = productFormatOptions(product);\n for (let i = 0; i < refs.length; i++) {\n const ref = refs[i];\n if (!isFormatId(ref)) {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_ids[${i}] is not a structured FormatId object`,\n json_pointer: `${packagePointer}/format_ids/${i}`,\n actual: ref,\n };\n }\n\n const direct = declarations.find(decl => (decl.v1_format_ref ?? []).some(v1 => sameFormatId(v1, ref)));\n if (direct) continue;\n\n const projected = projectLegacyRef(ref, productId, `${packagePointer}/format_ids/${i}`);\n if (projected) {\n const match = declarations.find(decl => canonicalSelectorSatisfiesDeclaration(projected, decl).ok);\n if (match) continue;\n }\n\n if (\n declarations.length === 0 &&\n Array.isArray(product.format_ids) &&\n product.format_ids.some(fid => isFormatId(fid) && sameFormatId(fid, ref))\n ) {\n continue;\n }\n\n return {\n satisfied: false,\n bug_class: 'normalization',\n detail:\n `Legacy format_ids[${i}] did not normalize to any canonical declaration on product ${JSON.stringify(productId)}. ` +\n `Check v1_format_ref links and v1→canonical registry/catalog projection.`,\n json_pointer: `${packagePointer}/format_ids/${i}`,\n actual: ref,\n observations: [{ projected }],\n };\n }\n\n return {\n satisfied: true,\n bug_class: 'normalization',\n detail: 'Every legacy format_id normalized to a product canonical declaration or product legacy format_id',\n json_pointer: `${packagePointer}/format_ids`,\n };\n}\n\nfunction evaluateCanonicalSelectors(\n selectors: CanonicalSelector[],\n product: Record<string, unknown>\n): SatisfactionVerdict {\n const declarations = productFormatOptions(product);\n if (declarations.length === 0) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: 'Request used canonical format selectors but the target product has no format_options[] closed set',\n json_pointer: selectors[0]?.pointer ?? null,\n actual: selectors,\n };\n }\n\n for (const selector of selectors) {\n const candidates = declarations.filter(decl => decl.format_kind === selector.format_kind);\n if (candidates.length === 0) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: `Canonical selector format_kind=${JSON.stringify(selector.format_kind)} is outside the product format_options[] closed set`,\n json_pointer: selector.pointer,\n actual: selector,\n };\n }\n\n const checks = candidates.map(decl => canonicalSelectorSatisfiesDeclaration(selector, decl));\n if (checks.some(c => c.ok)) continue;\n const primary = checks.find(c => c.bug_class === 'range_containment') ?? checks[0]!;\n return {\n satisfied: false,\n bug_class: primary.bug_class,\n detail: primary.detail,\n json_pointer: selector.pointer,\n actual: selector,\n observations: checks.map(c => ({ ok: c.ok, bug_class: c.bug_class, detail: c.detail })),\n };\n }\n\n return {\n satisfied: true,\n bug_class: 'directionality',\n detail: 'Every canonical selector satisfies at least one product format_options[] declaration',\n json_pointer: selectors[0]?.pointer ?? null,\n };\n}\n\nfunction canonicalSelectorSatisfiesDeclaration(\n selector: CanonicalSelector,\n decl: V2ProductFormatDeclaration\n): { ok: true; detail: string; bug_class: BugClass } | { ok: false; detail: string; bug_class: BugClass } {\n if (selector.format_kind !== decl.format_kind) {\n return {\n ok: false,\n bug_class: 'closed_set',\n detail: `format_kind ${JSON.stringify(selector.format_kind)} does not match product declaration ${JSON.stringify(decl.format_kind)}`,\n };\n }\n const productParams = isRecord(decl.params) ? decl.params : {};\n const requestParams = selector.params;\n\n const fixedSize = requireFixedSize(productParams, requestParams);\n if (!fixedSize.ok) return fixedSize;\n\n const sizeList = requireSizeList(productParams, requestParams);\n if (!sizeList.ok) return sizeList;\n\n const dimensionRanges = requireNumericRangeContainment(\n productParams,\n requestParams,\n 'width',\n 'min_width',\n 'max_width'\n );\n if (!dimensionRanges.ok) return dimensionRanges;\n const heightRanges = requireNumericRangeContainment(\n productParams,\n requestParams,\n 'height',\n 'min_height',\n 'max_height'\n );\n if (!heightRanges.ok) return heightRanges;\n\n const duration = requireDurationContainment(productParams, requestParams);\n if (!duration.ok) return duration;\n\n const remainingParams = requireRemainingParamContainment(productParams, requestParams);\n if (!remainingParams.ok) return remainingParams;\n\n return {\n ok: true,\n bug_class: 'directionality',\n detail: 'Selector constraints satisfy product declaration constraints',\n };\n}\n\nfunction requireFixedSize(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n const hasFixedWidth = typeof productParams.width === 'number';\n const hasFixedHeight = typeof productParams.height === 'number';\n if (!hasFixedWidth && !hasFixedHeight) return { ok: true };\n\n for (const key of ['width', 'height'] as const) {\n if (typeof productParams[key] !== 'number') continue;\n if (requestParams[key] === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product fixes params.${key}=${productParams[key]}, but the request selector omits ${key}`,\n };\n }\n if (requestParams[key] !== productParams[key]) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector params.${key}=${JSON.stringify(requestParams[key])} does not equal fixed product params.${key}=${productParams[key]}`,\n };\n }\n }\n return { ok: true };\n}\n\nfunction requireRemainingParamContainment(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n for (const [key, productValue] of Object.entries(productParams)) {\n if (HANDLED_CANONICAL_PARAM_KEYS.has(key) || productValue === undefined) continue;\n if (Array.isArray(productValue) && productValue.length === 0) continue;\n\n if (requestParams[key] === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains params.${key}, but the request selector omits ${key}`,\n };\n }\n\n const requestValue = requestParams[key];\n if (ARRAY_SUBSET_PARAM_KEYS.has(key)) {\n const subset = requireArraySubset(key, productValue, requestValue);\n if (!subset.ok) return subset;\n continue;\n }\n\n if (!deepEqualJson(requestValue, productValue)) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector params.${key}=${JSON.stringify(requestValue)} does not equal product params.${key}=${JSON.stringify(productValue)}`,\n };\n }\n }\n\n return { ok: true };\n}\n\nfunction requireArraySubset(\n key: string,\n productValue: unknown,\n requestValue: unknown\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n if (!Array.isArray(productValue)) {\n if (deepEqualJson(requestValue, productValue)) return { ok: true };\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector params.${key}=${JSON.stringify(requestValue)} does not equal product params.${key}=${JSON.stringify(productValue)}`,\n };\n }\n if (!Array.isArray(requestValue) || requestValue.length === 0) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains params.${key}[], but the request selector omits a non-empty array`,\n };\n }\n const outside = requestValue.find(item => !productValue.some(allowed => deepEqualJson(item, allowed)));\n if (outside !== undefined) {\n return {\n ok: false,\n bug_class: 'closed_set',\n detail: `Selector params.${key} item ${JSON.stringify(outside)} is outside product params.${key}[]`,\n };\n }\n return { ok: true };\n}\n\nfunction requireSizeList(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n const productSizes = parseSizes(productParams.sizes);\n if (!productSizes.length) return { ok: true };\n const requestSizes = parseSizes(requestParams.sizes);\n const requestExact =\n typeof requestParams.width === 'number' && typeof requestParams.height === 'number'\n ? [{ width: requestParams.width, height: requestParams.height }]\n : [];\n const selected = requestSizes.length > 0 ? requestSizes : requestExact;\n if (selected.length === 0) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail:\n 'Under-specified selector: product declares params.sizes[], but the request omits sizes or exact width/height',\n };\n }\n const outside = selected.find(s => !productSizes.some(p => p.width === s.width && p.height === s.height));\n if (outside) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector size ${outside.width}x${outside.height} is outside product params.sizes[]`,\n };\n }\n return { ok: true };\n}\n\nfunction requireNumericRangeContainment(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>,\n exactKey: string,\n minKey: string,\n maxKey: string\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n const min = typeof productParams[minKey] === 'number' ? productParams[minKey] : undefined;\n const max = typeof productParams[maxKey] === 'number' ? productParams[maxKey] : undefined;\n if (min === undefined && max === undefined) return { ok: true };\n\n if (typeof requestParams[exactKey] === 'number') {\n const exact = requestParams[exactKey] as number;\n if ((min !== undefined && exact < min) || (max !== undefined && exact > max)) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector ${exactKey}=${exact} is outside product range ${rangeLabel(min, max)}`,\n };\n }\n return { ok: true };\n }\n\n const reqMin = typeof requestParams[minKey] === 'number' ? (requestParams[minKey] as number) : undefined;\n const reqMax = typeof requestParams[maxKey] === 'number' ? (requestParams[maxKey] as number) : undefined;\n if (reqMin === undefined && reqMax === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains ${exactKey} range ${rangeLabel(min, max)}, but the request omits ${exactKey}/${minKey}/${maxKey}`,\n };\n }\n if ((min !== undefined && (reqMin ?? -Infinity) < min) || (max !== undefined && (reqMax ?? Infinity) > max)) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector ${exactKey} range ${rangeLabel(reqMin, reqMax)} only overlaps or exceeds product range ${rangeLabel(min, max)}; request ranges must be contained`,\n };\n }\n return { ok: true };\n}\n\nfunction requireDurationContainment(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n if (typeof productParams.duration_ms_exact === 'number') {\n const exact = requestDurationExact(requestParams);\n if (exact === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product fixes duration_ms_exact=${productParams.duration_ms_exact}, but the request omits an exact duration`,\n };\n }\n if (exact !== productParams.duration_ms_exact) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector duration ${exact} does not equal product duration_ms_exact=${productParams.duration_ms_exact}`,\n };\n }\n return { ok: true };\n }\n\n const productRange = parseNumberPair(productParams.duration_ms_range);\n if (!productRange) return { ok: true };\n const exact = requestDurationExact(requestParams);\n if (exact !== undefined) {\n if (exact < productRange[0] || exact > productRange[1]) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector exact duration ${exact} is outside product duration_ms_range ${rangeLabel(productRange[0], productRange[1])}`,\n };\n }\n return { ok: true };\n }\n const requestRange = parseNumberPair(requestParams.duration_ms_range);\n if (!requestRange) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains duration_ms_range ${rangeLabel(productRange[0], productRange[1])}, but the request omits duration`,\n };\n }\n if (requestRange[0] < productRange[0] || requestRange[1] > productRange[1]) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector duration_ms_range ${rangeLabel(requestRange[0], requestRange[1])} only overlaps or exceeds product range ${rangeLabel(productRange[0], productRange[1])}; request ranges must be contained`,\n };\n }\n return { ok: true };\n}\n\nfunction extractCanonicalSelectors(pkg: Record<string, unknown>, packagePointer: string): CanonicalSelector[] {\n const selectors: CanonicalSelector[] = [];\n const arrays: Array<[unknown, string]> = [\n [pkg.format_options, `${packagePointer}/format_options`],\n [pkg.format_selectors, `${packagePointer}/format_selectors`],\n [pkg.formats, `${packagePointer}/formats`],\n ];\n for (const [value, pointer] of arrays) {\n if (!Array.isArray(value)) continue;\n for (let i = 0; i < value.length; i++) {\n const selector = canonicalSelectorFrom(value[i], `${pointer}/${i}`);\n if (selector) selectors.push(selector);\n }\n }\n const direct = canonicalSelectorFrom(pkg, packagePointer);\n if (direct) selectors.push(direct);\n const single = canonicalSelectorFrom(pkg.format_option, `${packagePointer}/format_option`);\n if (single) selectors.push(single);\n return selectors;\n}\n\nfunction canonicalSelectorFrom(value: unknown, pointer: string): CanonicalSelector | undefined {\n if (!isRecord(value) || typeof value.format_kind !== 'string') return undefined;\n const params = isRecord(value.params) ? { ...value.params } : {};\n for (const key of [\n 'width',\n 'height',\n 'sizes',\n 'min_width',\n 'max_width',\n 'min_height',\n 'max_height',\n 'duration_ms',\n 'duration_ms_exact',\n 'duration_ms_range',\n 'orientation',\n 'aspect_ratio',\n 'video_codecs',\n 'audio_codecs',\n 'mime_types',\n 'file_types',\n 'formats',\n 'slots',\n 'platform_extensions',\n 'tracking_extensions',\n ]) {\n if (value[key] !== undefined && params[key] === undefined) params[key] = value[key];\n }\n return { format_kind: value.format_kind, params, pointer };\n}\n\nfunction productFormatOptions(product: Record<string, unknown>): V2ProductFormatDeclaration[] {\n if (!Array.isArray(product.format_options)) return [];\n return product.format_options.filter(isRecord) as unknown as V2ProductFormatDeclaration[];\n}\n\nfunction projectLegacyRef(ref: V1FormatId, productId: string, pointer: string): CanonicalSelector | undefined {\n const { v2 } = projectV1ProductToV2({\n product_id: productId,\n name: productId,\n description: productId,\n format_ids: [ref],\n });\n const decl = v2.format_options[0];\n if (!decl) return undefined;\n const params = augmentProjectedParamsFromCatalog(ref, isRecord(decl.params) ? decl.params : {});\n return {\n format_kind: decl.format_kind,\n params,\n pointer,\n };\n}\n\nfunction augmentProjectedParamsFromCatalog(\n ref: V1FormatId,\n projectedParams: Record<string, unknown>\n): Record<string, unknown> {\n const out = { ...projectedParams };\n const catalogEntry = lookupV1Format(ref);\n if (!catalogEntry) return out;\n\n if (out.width === undefined || out.height === undefined) {\n const dimensions = firstCatalogDimensions(catalogEntry);\n if (dimensions) {\n if (out.width === undefined) out.width = dimensions.width;\n if (out.height === undefined) out.height = dimensions.height;\n }\n }\n\n if (out.duration_ms_exact === undefined) {\n const duration = firstCatalogDurationMs(catalogEntry);\n if (duration !== undefined) out.duration_ms_exact = duration;\n }\n\n return out;\n}\n\nfunction firstCatalogDimensions(catalogEntry: Record<string, unknown>): { width: number; height: number } | undefined {\n const renders = Array.isArray(catalogEntry.renders) ? catalogEntry.renders : [];\n for (const render of renders) {\n if (!isRecord(render) || !isRecord(render.dimensions)) continue;\n const { width, height } = render.dimensions;\n if (typeof width === 'number' && typeof height === 'number') return { width, height };\n }\n\n const assets = Array.isArray(catalogEntry.assets) ? catalogEntry.assets : [];\n for (const asset of assets) {\n if (!isRecord(asset) || !isRecord(asset.requirements)) continue;\n const { width, height } = asset.requirements;\n if (typeof width === 'number' && typeof height === 'number') return { width, height };\n }\n return undefined;\n}\n\ninterface RejectionInfo {\n codes: string[];\n fields: string[];\n messages: string[];\n}\n\nfunction extractRejectionInfo(taskResult: TaskResult): RejectionInfo | undefined {\n if (taskResult.success === true) return undefined;\n const codes = new Set<string>();\n const fields = new Set<string>();\n const messages = new Set<string>();\n collectRejectionInfo(taskResult, codes, fields, messages);\n return {\n codes: [...codes],\n fields: [...fields],\n messages: [...messages],\n };\n}\n\nfunction collectRejectionInfo(\n value: unknown,\n codes: Set<string>,\n fields: Set<string>,\n messages: Set<string>,\n depth = 0\n): void {\n if (depth > 5) return;\n if (typeof value === 'string') {\n messages.add(value);\n const prefixedCode = value.match(/^([A-Z][A-Z0-9_]+):/);\n if (prefixedCode?.[1]) codes.add(prefixedCode[1]);\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) collectRejectionInfo(item, codes, fields, messages, depth + 1);\n return;\n }\n if (!isRecord(value)) return;\n\n for (const key of ['code', 'error_code', 'reason'] as const) {\n const maybeCode = value[key];\n if (typeof maybeCode === 'string') codes.add(maybeCode);\n }\n for (const key of ['field', 'path', 'json_pointer'] as const) {\n const maybeField = value[key];\n if (typeof maybeField === 'string') fields.add(maybeField);\n }\n for (const key of ['message', 'error', 'detail', 'suggestion'] as const) {\n const maybeMessage = value[key];\n if (typeof maybeMessage === 'string') messages.add(maybeMessage);\n }\n for (const key of ['adcp_error', 'adcpError', 'data', 'details', 'errors', 'issues'] as const) {\n if (value[key] !== undefined) collectRejectionInfo(value[key], codes, fields, messages, depth + 1);\n }\n}\n\nfunction rejectionSupportsFormatFailure(rejection: RejectionInfo | undefined): boolean {\n if (!rejection) return false;\n if (rejection.codes.some(code => code.startsWith('FORMAT_'))) return true;\n return [...rejection.fields, ...rejection.messages].some(text =>\n /format|format_option|format_id|selector/i.test(text)\n );\n}\n\nfunction formatRejectionInfo(rejection: RejectionInfo | undefined): string {\n if (!rejection) return 'no structured rejection details';\n return JSON.stringify(rejection);\n}\n\nfunction deepEqualJson(a: unknown, b: unknown): boolean {\n return stableJson(a) === stableJson(b);\n}\n\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;\n if (isRecord(value)) {\n return `{${Object.keys(value)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableJson(value[key])}`)\n .join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\nfunction firstCatalogDurationMs(catalogEntry: Record<string, unknown>): number | undefined {\n const assets = Array.isArray(catalogEntry.assets) ? catalogEntry.assets : [];\n for (const asset of assets) {\n if (!isRecord(asset) || !isRecord(asset.requirements)) continue;\n const { duration_ms, duration_seconds } = asset.requirements;\n if (typeof duration_ms === 'number') return duration_ms;\n if (typeof duration_seconds === 'number') return duration_seconds * 1000;\n }\n return undefined;\n}\n\nfunction classifyLikelyFailure(\n expectedAccepted: boolean,\n taskAccepted: boolean,\n localSatisfied: boolean,\n primary: SatisfactionVerdict | undefined\n): string {\n const observed = taskAccepted ? 'accepted' : 'rejected';\n const expected = expectedAccepted ? 'accepted' : 'rejected';\n const local = localSatisfied ? 'satisfies' : 'does not satisfy';\n const bugClass = primary?.bug_class ?? 'authoring';\n const detail = primary?.detail ?? 'no local satisfaction verdict';\n if (expectedAccepted && !taskAccepted && localSatisfied) {\n return `Expected request to be accepted and local canonical matching says it satisfies the product, but the agent rejected it. Likely ${bugClass} failure: ${detail}`;\n }\n if (!expectedAccepted && taskAccepted && !localSatisfied) {\n return `Expected request to be rejected because local canonical matching says it does not satisfy the product, but the agent accepted it. Likely ${bugClass} failure: ${detail}`;\n }\n if (!localSatisfied && expectedAccepted) {\n return `Storyboard expected acceptance, but the authored request does not satisfy the product locally (${bugClass}): ${detail}`;\n }\n if (localSatisfied && !expectedAccepted) {\n return `Storyboard expected rejection, but the authored request satisfies the product locally: ${detail}`;\n }\n return `Expected ${expected}, observed ${observed}; local matcher says request ${local}. ${detail}`;\n}\n\nfunction remediationFor(bugClass: BugClass | undefined): string | undefined {\n switch (bugClass) {\n case 'normalization':\n return 'Normalize legacy format_ids through product v1_format_ref, catalog canonical annotations, or the v1-canonical registry before comparing to product format_options.';\n case 'directionality':\n return 'Apply directional product gating: the request selector must contain the product-declared fixed constraints; a bare canonical kind does not satisfy a fixed-size or fixed-duration product.';\n case 'range_containment':\n return 'Use containment for ranges: an exact request must be inside the product range, and a request range must be fully contained by the product range, not merely overlap it.';\n case 'closed_set':\n return 'Treat product format_options[] as a closed set and reject selectors that do not resolve to one of its declarations.';\n default:\n return undefined;\n }\n}\n\nfunction sameFormatId(a: V1FormatId, b: V1FormatId): boolean {\n for (const key of FORMAT_IDENTITY_KEYS) {\n const av = key === 'agent_url' ? normalizeAgentUrl(a[key]) : a[key];\n const bv = key === 'agent_url' ? normalizeAgentUrl(b[key]) : b[key];\n if (av !== bv) return false;\n }\n return true;\n}\n\nfunction normalizeAgentUrl(value: unknown): unknown {\n if (typeof value !== 'string') return value;\n try {\n const url = new URL(value);\n url.hash = '';\n if ((url.protocol === 'https:' && url.port === '443') || (url.protocol === 'http:' && url.port === '80')) {\n url.port = '';\n }\n return url.toString().replace(/\\/$/, '');\n } catch {\n return value.replace(/\\/$/, '');\n }\n}\n\nfunction isFormatId(value: unknown): value is V1FormatId {\n return isRecord(value) && typeof value.agent_url === 'string' && typeof value.id === 'string';\n}\n\nfunction declarationLabel(decl: V2ProductFormatDeclaration): string | undefined {\n if (!decl.format_option_id) return undefined;\n return decl.publisher_domain ? `${decl.publisher_domain}/${decl.format_option_id}` : decl.format_option_id;\n}\n\nfunction requestDurationExact(params: Record<string, unknown>): number | undefined {\n if (typeof params.duration_ms_exact === 'number') return params.duration_ms_exact;\n if (typeof params.duration_ms === 'number') return params.duration_ms;\n return undefined;\n}\n\nfunction parseNumberPair(value: unknown): [number, number] | undefined {\n if (!Array.isArray(value) || value.length !== 2) return undefined;\n return typeof value[0] === 'number' && typeof value[1] === 'number' ? [value[0], value[1]] : undefined;\n}\n\nfunction parseSizes(value: unknown): Array<{ width: number; height: number }> {\n if (!Array.isArray(value)) return [];\n return value\n .map(item => {\n if (!isRecord(item)) return undefined;\n const width = typeof item.width === 'number' ? item.width : typeof item.w === 'number' ? item.w : undefined;\n const height = typeof item.height === 'number' ? item.height : typeof item.h === 'number' ? item.h : undefined;\n return width !== undefined && height !== undefined ? { width, height } : undefined;\n })\n .filter((s): s is { width: number; height: number } => Boolean(s));\n}\n\nfunction rangeLabel(min: unknown, max: unknown): string {\n return `[${min ?? '-infinity'}, ${max ?? 'infinity'}]`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n"],"mappings":"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","names":["packages","exact"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/canonical-format-satisfaction.ts"],"sourcesContent":["import { lookupV1Format, projectV1ProductToV2 } from '../../v2/projection';\nimport type { V1FormatId, V2ProductFormatDeclaration } from '../../v2/projection';\nimport type { TaskResult } from '../types';\nimport type { RunnerRequestRecord, StoryboardContext, StoryboardValidation, ValidationResult } from './types';\nimport { resolvePath, toJsonPointer } from './path';\n\ntype BugClass = 'normalization' | 'directionality' | 'range_containment' | 'closed_set' | 'authoring';\n\ninterface SatisfactionVerdict {\n satisfied: boolean;\n bug_class: BugClass;\n detail: string;\n json_pointer: string | null;\n actual?: unknown;\n observations?: unknown[];\n}\n\ninterface CanonicalSelector {\n format_kind: string;\n params: Record<string, unknown>;\n pointer: string;\n}\n\nconst FORMAT_IDENTITY_KEYS = ['agent_url', 'id', 'width', 'height', 'duration_ms'] as const;\nconst HANDLED_CANONICAL_PARAM_KEYS = new Set([\n 'width',\n 'height',\n 'sizes',\n 'min_width',\n 'max_width',\n 'min_height',\n 'max_height',\n 'duration_ms',\n 'duration_ms_exact',\n 'duration_ms_range',\n]);\nconst ARRAY_SUBSET_PARAM_KEYS = new Set(['video_codecs', 'audio_codecs', 'mime_types', 'file_types', 'formats']);\n\nexport function validateCanonicalFormatSatisfaction(\n validation: StoryboardValidation,\n request: RunnerRequestRecord | undefined,\n context: StoryboardContext | undefined,\n taskResult: TaskResult\n): ValidationResult {\n if (typeof validation.value !== 'boolean') {\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n error:\n 'canonical_format_satisfaction requires boolean `value` (true = request should be accepted, false = rejected)',\n json_pointer: null,\n expected: 'boolean validation.value',\n actual: validation.value ?? null,\n };\n }\n\n const expectedAccepted = validation.value;\n const taskAccepted = taskResult.success === true;\n const requestPayload = request?.payload;\n if (!isRecord(requestPayload)) {\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n error: 'canonical_format_satisfaction requires the runner request payload, but none was recorded',\n json_pointer: null,\n expected: 'create_media_buy request payload',\n actual: requestPayload ?? null,\n };\n }\n\n const packages = resolvePackages(requestPayload, validation.path);\n if (!packages.ok) {\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n error: packages.error,\n path: validation.path,\n json_pointer: packages.pointer,\n expected: 'one PackageRequest object or packages[] array',\n actual: packages.actual,\n };\n }\n\n const products = Array.isArray(context?.products) ? (context!.products as unknown[]) : [];\n const packageVerdicts = packages.packages.map(({ value, pointer }, index) =>\n evaluatePackage(value, pointer, index, products)\n );\n const localSatisfied = packageVerdicts.every(v => v.satisfied);\n const firstFailure = packageVerdicts.find(v => !v.satisfied);\n const primary = firstFailure ?? packageVerdicts[0];\n\n const localMatchesExpectation = localSatisfied === expectedAccepted;\n const observedMatchesExpectation = taskAccepted === expectedAccepted;\n const rejection = extractRejectionInfo(taskResult);\n const negativeRejectionMatches =\n expectedAccepted || taskAccepted || localSatisfied ? true : rejectionSupportsFormatFailure(rejection);\n const passed = localMatchesExpectation && observedMatchesExpectation && negativeRejectionMatches;\n if (passed) {\n return {\n check: validation.check,\n passed: true,\n description: validation.description,\n path: validation.path,\n json_pointer: primary?.json_pointer ?? null,\n expected: { accepted: expectedAccepted, local_satisfied: expectedAccepted },\n actual: {\n accepted: taskAccepted,\n local_satisfied: localSatisfied,\n ...(!taskAccepted && rejection && { rejection }),\n },\n observations: packageVerdicts.map(v => ({\n satisfied: v.satisfied,\n bug_class: v.bug_class,\n detail: v.detail,\n json_pointer: v.json_pointer,\n })),\n };\n }\n\n const likely = classifyLikelyFailure(expectedAccepted, taskAccepted, localSatisfied, primary);\n const error =\n !expectedAccepted && !taskAccepted && !localSatisfied && !negativeRejectionMatches\n ? `Expected request to be rejected for canonical format satisfaction, and local matching says it does not satisfy the product, but the agent rejection did not identify a format-selector cause. Observed rejection: ${formatRejectionInfo(rejection)}`\n : likely;\n return {\n check: validation.check,\n passed: false,\n description: validation.description,\n path: validation.path,\n error,\n json_pointer: primary?.json_pointer ?? null,\n expected: { accepted: expectedAccepted, local_satisfied: expectedAccepted },\n actual: {\n accepted: taskAccepted,\n local_satisfied: localSatisfied,\n ...(!taskAccepted && rejection && { rejection }),\n bug_class: primary?.bug_class ?? 'authoring',\n detail: primary?.detail ?? 'No package verdict was produced',\n },\n remediation: remediationFor(primary?.bug_class),\n observations: packageVerdicts.map(v => ({\n satisfied: v.satisfied,\n bug_class: v.bug_class,\n detail: v.detail,\n json_pointer: v.json_pointer,\n ...(v.actual !== undefined && { actual: v.actual }),\n ...(v.observations && { observations: v.observations }),\n })),\n };\n}\n\nfunction resolvePackages(\n requestPayload: Record<string, unknown>,\n path?: string\n):\n | { ok: true; packages: Array<{ value: Record<string, unknown>; pointer: string }> }\n | { ok: false; error: string; pointer: string | null; actual: unknown } {\n if (path) {\n const resolved = resolvePath(requestPayload, path);\n const pointer = toJsonPointer(path);\n if (Array.isArray(resolved)) {\n if (resolved.length === 0) {\n return {\n ok: false,\n error: `Path \"${path}\" resolved to an empty package array`,\n pointer,\n actual: [],\n };\n }\n const packages = resolved\n .map((item, i) => (isRecord(item) ? { value: item, pointer: `${pointer}/${i}` } : undefined))\n .filter((p): p is { value: Record<string, unknown>; pointer: string } => Boolean(p));\n if (packages.length === resolved.length) return { ok: true, packages };\n }\n if (isRecord(resolved)) return { ok: true, packages: [{ value: resolved, pointer }] };\n return {\n ok: false,\n error: `Path \"${path}\" did not resolve to a package object or array of package objects`,\n pointer,\n actual: resolved ?? null,\n };\n }\n\n const rawPackages = requestPayload.packages;\n if (!Array.isArray(rawPackages) || rawPackages.length === 0) {\n return {\n ok: false,\n error:\n 'canonical_format_satisfaction requires create_media_buy.packages[] unless validation.path selects a package',\n pointer: '/packages',\n actual: rawPackages ?? null,\n };\n }\n\n const packages = rawPackages\n .map((item, i) => (isRecord(item) ? { value: item, pointer: `/packages/${i}` } : undefined))\n .filter((p): p is { value: Record<string, unknown>; pointer: string } => Boolean(p));\n if (packages.length === rawPackages.length) return { ok: true, packages };\n return {\n ok: false,\n error: 'create_media_buy.packages[] contains a non-object entry',\n pointer: '/packages',\n actual: rawPackages,\n };\n}\n\nfunction evaluatePackage(\n pkg: Record<string, unknown>,\n pointer: string,\n index: number,\n products: unknown[]\n): SatisfactionVerdict {\n const productId = typeof pkg.product_id === 'string' ? pkg.product_id : undefined;\n const product = products.find(p => isRecord(p) && p.product_id === productId);\n if (!isRecord(product)) {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `No prior get_products context product matched packages[${index}].product_id=${JSON.stringify(productId)}`,\n json_pointer: `${pointer}/product_id`,\n actual: productId ?? null,\n };\n }\n\n const formatOptionRefs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs : [];\n if (formatOptionRefs.length > 0) {\n return evaluateFormatOptionRefs(formatOptionRefs, product, pointer);\n }\n\n const formatIds = Array.isArray(pkg.format_ids) ? pkg.format_ids : [];\n if (formatIds.length > 0) {\n return evaluateLegacyFormatIds(formatIds, product, pointer, productId!);\n }\n\n const canonicalSelectors = extractCanonicalSelectors(pkg, pointer);\n if (canonicalSelectors.length > 0) {\n return evaluateCanonicalSelectors(canonicalSelectors, product);\n }\n\n return {\n satisfied: true,\n bug_class: 'directionality',\n detail: 'Package omitted format selectors; per PackageRequest semantics the seller default is all product formats',\n json_pointer: pointer,\n };\n}\n\nfunction evaluateFormatOptionRefs(\n refs: unknown[],\n product: Record<string, unknown>,\n packagePointer: string\n): SatisfactionVerdict {\n const declarations = productFormatOptions(product);\n if (declarations.length === 0) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: 'Request used format_option_refs but the target product has no format_options[] closed set',\n json_pointer: `${packagePointer}/format_option_refs`,\n actual: refs,\n };\n }\n\n for (let i = 0; i < refs.length; i++) {\n const ref = refs[i];\n if (!isRecord(ref)) {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_option_refs[${i}] is not an object`,\n json_pointer: `${packagePointer}/format_option_refs/${i}`,\n actual: ref,\n };\n }\n if (ref.scope !== undefined && ref.scope !== 'product' && ref.scope !== 'publisher') {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_option_refs[${i}].scope must be \"product\" or \"publisher\" when present`,\n json_pointer: `${packagePointer}/format_option_refs/${i}/scope`,\n actual: ref.scope,\n };\n }\n if (ref.scope === 'publisher' && typeof ref.publisher_domain !== 'string') {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_option_refs[${i}] with scope=\"publisher\" requires publisher_domain`,\n json_pointer: `${packagePointer}/format_option_refs/${i}/publisher_domain`,\n actual: ref,\n };\n }\n const match = declarations.find(decl => {\n if (ref.scope === 'publisher') {\n return (\n decl.publisher_domain === ref.publisher_domain &&\n decl.format_option_id === ref.format_option_id &&\n typeof ref.publisher_domain === 'string'\n );\n }\n return decl.format_option_id === ref.format_option_id && !decl.publisher_domain;\n });\n if (!match) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: `format_option_refs[${i}] does not resolve to the target product's format_options[] closed set`,\n json_pointer: `${packagePointer}/format_option_refs/${i}`,\n actual: ref,\n observations: [{ available_format_option_ids: declarations.map(declarationLabel).filter(Boolean) }],\n };\n }\n }\n\n return {\n satisfied: true,\n bug_class: 'directionality',\n detail: 'Every format_option_refs[] entry resolved to the target product format_options[] closed set',\n json_pointer: `${packagePointer}/format_option_refs`,\n };\n}\n\nfunction evaluateLegacyFormatIds(\n refs: unknown[],\n product: Record<string, unknown>,\n packagePointer: string,\n productId: string\n): SatisfactionVerdict {\n const declarations = productFormatOptions(product);\n for (let i = 0; i < refs.length; i++) {\n const ref = refs[i];\n if (!isFormatId(ref)) {\n return {\n satisfied: false,\n bug_class: 'authoring',\n detail: `format_ids[${i}] is not a structured FormatId object`,\n json_pointer: `${packagePointer}/format_ids/${i}`,\n actual: ref,\n };\n }\n\n const direct = declarations.find(decl => (decl.v1_format_ref ?? []).some(v1 => sameFormatId(v1, ref)));\n if (direct) continue;\n\n const projected = projectLegacyRef(ref, productId, `${packagePointer}/format_ids/${i}`);\n if (projected) {\n const match = declarations.find(decl => canonicalSelectorSatisfiesDeclaration(projected, decl).ok);\n if (match) continue;\n }\n\n if (\n declarations.length === 0 &&\n Array.isArray(product.format_ids) &&\n product.format_ids.some(fid => isFormatId(fid) && sameFormatId(fid, ref))\n ) {\n continue;\n }\n\n return {\n satisfied: false,\n bug_class: 'normalization',\n detail:\n `Legacy format_ids[${i}] did not normalize to any canonical declaration on product ${JSON.stringify(productId)}. ` +\n `Check v1_format_ref links and v1→canonical registry/catalog projection.`,\n json_pointer: `${packagePointer}/format_ids/${i}`,\n actual: ref,\n observations: [{ projected }],\n };\n }\n\n return {\n satisfied: true,\n bug_class: 'normalization',\n detail: 'Every legacy format_id normalized to a product canonical declaration or product legacy format_id',\n json_pointer: `${packagePointer}/format_ids`,\n };\n}\n\nfunction evaluateCanonicalSelectors(\n selectors: CanonicalSelector[],\n product: Record<string, unknown>\n): SatisfactionVerdict {\n const declarations = productFormatOptions(product);\n if (declarations.length === 0) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: 'Request used canonical format selectors but the target product has no format_options[] closed set',\n json_pointer: selectors[0]?.pointer ?? null,\n actual: selectors,\n };\n }\n\n for (const selector of selectors) {\n const candidates = declarations.filter(decl => decl.format_kind === selector.format_kind);\n if (candidates.length === 0) {\n return {\n satisfied: false,\n bug_class: 'closed_set',\n detail: `Canonical selector format_kind=${JSON.stringify(selector.format_kind)} is outside the product format_options[] closed set`,\n json_pointer: selector.pointer,\n actual: selector,\n };\n }\n\n const checks = candidates.map(decl => canonicalSelectorSatisfiesDeclaration(selector, decl));\n if (checks.some(c => c.ok)) continue;\n const primary = checks.find(c => c.bug_class === 'range_containment') ?? checks[0]!;\n return {\n satisfied: false,\n bug_class: primary.bug_class,\n detail: primary.detail,\n json_pointer: selector.pointer,\n actual: selector,\n observations: checks.map(c => ({ ok: c.ok, bug_class: c.bug_class, detail: c.detail })),\n };\n }\n\n return {\n satisfied: true,\n bug_class: 'directionality',\n detail: 'Every canonical selector satisfies at least one product format_options[] declaration',\n json_pointer: selectors[0]?.pointer ?? null,\n };\n}\n\nfunction canonicalSelectorSatisfiesDeclaration(\n selector: CanonicalSelector,\n decl: V2ProductFormatDeclaration\n): { ok: true; detail: string; bug_class: BugClass } | { ok: false; detail: string; bug_class: BugClass } {\n if (selector.format_kind !== decl.format_kind) {\n return {\n ok: false,\n bug_class: 'closed_set',\n detail: `format_kind ${JSON.stringify(selector.format_kind)} does not match product declaration ${JSON.stringify(decl.format_kind)}`,\n };\n }\n const productParams = isRecord(decl.params) ? decl.params : {};\n const requestParams = selector.params;\n\n const fixedSize = requireFixedSize(productParams, requestParams);\n if (!fixedSize.ok) return fixedSize;\n\n const sizeList = requireSizeList(productParams, requestParams);\n if (!sizeList.ok) return sizeList;\n\n const dimensionRanges = requireNumericRangeContainment(\n productParams,\n requestParams,\n 'width',\n 'min_width',\n 'max_width'\n );\n if (!dimensionRanges.ok) return dimensionRanges;\n const heightRanges = requireNumericRangeContainment(\n productParams,\n requestParams,\n 'height',\n 'min_height',\n 'max_height'\n );\n if (!heightRanges.ok) return heightRanges;\n\n const duration = requireDurationContainment(productParams, requestParams);\n if (!duration.ok) return duration;\n\n const remainingParams = requireRemainingParamContainment(productParams, requestParams);\n if (!remainingParams.ok) return remainingParams;\n\n return {\n ok: true,\n bug_class: 'directionality',\n detail: 'Selector constraints satisfy product declaration constraints',\n };\n}\n\nfunction requireFixedSize(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n const hasFixedWidth = typeof productParams.width === 'number';\n const hasFixedHeight = typeof productParams.height === 'number';\n if (!hasFixedWidth && !hasFixedHeight) return { ok: true };\n\n for (const key of ['width', 'height'] as const) {\n if (typeof productParams[key] !== 'number') continue;\n if (requestParams[key] === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product fixes params.${key}=${productParams[key]}, but the request selector omits ${key}`,\n };\n }\n if (requestParams[key] !== productParams[key]) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector params.${key}=${JSON.stringify(requestParams[key])} does not equal fixed product params.${key}=${productParams[key]}`,\n };\n }\n }\n return { ok: true };\n}\n\nfunction requireRemainingParamContainment(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n for (const [key, productValue] of Object.entries(productParams)) {\n if (HANDLED_CANONICAL_PARAM_KEYS.has(key) || productValue === undefined) continue;\n if (Array.isArray(productValue) && productValue.length === 0) continue;\n\n if (requestParams[key] === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains params.${key}, but the request selector omits ${key}`,\n };\n }\n\n const requestValue = requestParams[key];\n if (ARRAY_SUBSET_PARAM_KEYS.has(key)) {\n const subset = requireArraySubset(key, productValue, requestValue);\n if (!subset.ok) return subset;\n continue;\n }\n\n if (!deepEqualJson(requestValue, productValue)) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector params.${key}=${JSON.stringify(requestValue)} does not equal product params.${key}=${JSON.stringify(productValue)}`,\n };\n }\n }\n\n return { ok: true };\n}\n\nfunction requireArraySubset(\n key: string,\n productValue: unknown,\n requestValue: unknown\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n if (!Array.isArray(productValue)) {\n if (deepEqualJson(requestValue, productValue)) return { ok: true };\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector params.${key}=${JSON.stringify(requestValue)} does not equal product params.${key}=${JSON.stringify(productValue)}`,\n };\n }\n if (!Array.isArray(requestValue) || requestValue.length === 0) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains params.${key}[], but the request selector omits a non-empty array`,\n };\n }\n const outside = requestValue.find(item => !productValue.some(allowed => deepEqualJson(item, allowed)));\n if (outside !== undefined) {\n return {\n ok: false,\n bug_class: 'closed_set',\n detail: `Selector params.${key} item ${JSON.stringify(outside)} is outside product params.${key}[]`,\n };\n }\n return { ok: true };\n}\n\nfunction requireSizeList(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n const productSizes = parseSizes(productParams.sizes);\n if (!productSizes.length) return { ok: true };\n const requestSizes = parseSizes(requestParams.sizes);\n const requestExact =\n typeof requestParams.width === 'number' && typeof requestParams.height === 'number'\n ? [{ width: requestParams.width, height: requestParams.height }]\n : [];\n const selected = requestSizes.length > 0 ? requestSizes : requestExact;\n if (selected.length === 0) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail:\n 'Under-specified selector: product declares params.sizes[], but the request omits sizes or exact width/height',\n };\n }\n const outside = selected.find(s => !productSizes.some(p => p.width === s.width && p.height === s.height));\n if (outside) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector size ${outside.width}x${outside.height} is outside product params.sizes[]`,\n };\n }\n return { ok: true };\n}\n\nfunction requireNumericRangeContainment(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>,\n exactKey: string,\n minKey: string,\n maxKey: string\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n const min = typeof productParams[minKey] === 'number' ? productParams[minKey] : undefined;\n const max = typeof productParams[maxKey] === 'number' ? productParams[maxKey] : undefined;\n if (min === undefined && max === undefined) return { ok: true };\n\n if (typeof requestParams[exactKey] === 'number') {\n const exact = requestParams[exactKey] as number;\n if ((min !== undefined && exact < min) || (max !== undefined && exact > max)) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector ${exactKey}=${exact} is outside product range ${rangeLabel(min, max)}`,\n };\n }\n return { ok: true };\n }\n\n const reqMin = typeof requestParams[minKey] === 'number' ? (requestParams[minKey] as number) : undefined;\n const reqMax = typeof requestParams[maxKey] === 'number' ? (requestParams[maxKey] as number) : undefined;\n if (reqMin === undefined && reqMax === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains ${exactKey} range ${rangeLabel(min, max)}, but the request omits ${exactKey}/${minKey}/${maxKey}`,\n };\n }\n if ((min !== undefined && (reqMin ?? -Infinity) < min) || (max !== undefined && (reqMax ?? Infinity) > max)) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector ${exactKey} range ${rangeLabel(reqMin, reqMax)} only overlaps or exceeds product range ${rangeLabel(min, max)}; request ranges must be contained`,\n };\n }\n return { ok: true };\n}\n\nfunction requireDurationContainment(\n productParams: Record<string, unknown>,\n requestParams: Record<string, unknown>\n): { ok: true } | { ok: false; bug_class: BugClass; detail: string } {\n if (typeof productParams.duration_ms_exact === 'number') {\n const exact = requestDurationExact(requestParams);\n if (exact === undefined) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product fixes duration_ms_exact=${productParams.duration_ms_exact}, but the request omits an exact duration`,\n };\n }\n if (exact !== productParams.duration_ms_exact) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Selector duration ${exact} does not equal product duration_ms_exact=${productParams.duration_ms_exact}`,\n };\n }\n return { ok: true };\n }\n\n const productRange = parseNumberPair(productParams.duration_ms_range);\n if (!productRange) return { ok: true };\n const exact = requestDurationExact(requestParams);\n if (exact !== undefined) {\n if (exact < productRange[0] || exact > productRange[1]) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector exact duration ${exact} is outside product duration_ms_range ${rangeLabel(productRange[0], productRange[1])}`,\n };\n }\n return { ok: true };\n }\n const requestRange = parseNumberPair(requestParams.duration_ms_range);\n if (!requestRange) {\n return {\n ok: false,\n bug_class: 'directionality',\n detail: `Under-specified selector: product constrains duration_ms_range ${rangeLabel(productRange[0], productRange[1])}, but the request omits duration`,\n };\n }\n if (requestRange[0] < productRange[0] || requestRange[1] > productRange[1]) {\n return {\n ok: false,\n bug_class: 'range_containment',\n detail: `Selector duration_ms_range ${rangeLabel(requestRange[0], requestRange[1])} only overlaps or exceeds product range ${rangeLabel(productRange[0], productRange[1])}; request ranges must be contained`,\n };\n }\n return { ok: true };\n}\n\nfunction extractCanonicalSelectors(pkg: Record<string, unknown>, packagePointer: string): CanonicalSelector[] {\n const selectors: CanonicalSelector[] = [];\n const arrays: Array<[unknown, string]> = [\n [pkg.format_options, `${packagePointer}/format_options`],\n [pkg.format_selectors, `${packagePointer}/format_selectors`],\n [pkg.formats, `${packagePointer}/formats`],\n ];\n for (const [value, pointer] of arrays) {\n if (!Array.isArray(value)) continue;\n for (let i = 0; i < value.length; i++) {\n const selector = canonicalSelectorFrom(value[i], `${pointer}/${i}`);\n if (selector) selectors.push(selector);\n }\n }\n const direct = canonicalSelectorFrom(pkg, packagePointer);\n if (direct) selectors.push(direct);\n const single = canonicalSelectorFrom(pkg.format_option, `${packagePointer}/format_option`);\n if (single) selectors.push(single);\n return selectors;\n}\n\nfunction canonicalSelectorFrom(value: unknown, pointer: string): CanonicalSelector | undefined {\n if (!isRecord(value) || typeof value.format_kind !== 'string') return undefined;\n const params = isRecord(value.params) ? { ...value.params } : {};\n for (const key of [\n 'width',\n 'height',\n 'sizes',\n 'min_width',\n 'max_width',\n 'min_height',\n 'max_height',\n 'duration_ms',\n 'duration_ms_exact',\n 'duration_ms_range',\n 'orientation',\n 'aspect_ratio',\n 'video_codecs',\n 'audio_codecs',\n 'mime_types',\n 'file_types',\n 'formats',\n 'slots',\n 'platform_extensions',\n 'tracking_extensions',\n ]) {\n if (value[key] !== undefined && params[key] === undefined) params[key] = value[key];\n }\n return { format_kind: value.format_kind, params, pointer };\n}\n\nfunction productFormatOptions(product: Record<string, unknown>): V2ProductFormatDeclaration[] {\n if (!Array.isArray(product.format_options)) return [];\n return product.format_options.filter(isRecord) as unknown as V2ProductFormatDeclaration[];\n}\n\nfunction projectLegacyRef(ref: V1FormatId, productId: string, pointer: string): CanonicalSelector | undefined {\n const { v2 } = projectV1ProductToV2({\n product_id: productId,\n name: productId,\n description: productId,\n format_ids: [ref],\n });\n const decl = v2.format_options[0];\n if (!decl) return undefined;\n const params = augmentProjectedParamsFromCatalog(ref, isRecord(decl.params) ? decl.params : {});\n return {\n format_kind: decl.format_kind,\n params,\n pointer,\n };\n}\n\nfunction augmentProjectedParamsFromCatalog(\n ref: V1FormatId,\n projectedParams: Record<string, unknown>\n): Record<string, unknown> {\n const out = { ...projectedParams };\n const catalogEntry = lookupV1Format(ref);\n if (!catalogEntry) return out;\n\n if (out.width === undefined || out.height === undefined) {\n const dimensions = firstCatalogDimensions(catalogEntry);\n if (dimensions) {\n if (out.width === undefined) out.width = dimensions.width;\n if (out.height === undefined) out.height = dimensions.height;\n }\n }\n\n if (out.duration_ms_exact === undefined) {\n const duration = firstCatalogDurationMs(catalogEntry);\n if (duration !== undefined) out.duration_ms_exact = duration;\n }\n\n return out;\n}\n\nfunction firstCatalogDimensions(catalogEntry: Record<string, unknown>): { width: number; height: number } | undefined {\n const renders = Array.isArray(catalogEntry.renders) ? catalogEntry.renders : [];\n for (const render of renders) {\n if (!isRecord(render) || !isRecord(render.dimensions)) continue;\n const { width, height } = render.dimensions;\n if (typeof width === 'number' && typeof height === 'number') return { width, height };\n }\n\n const assets = Array.isArray(catalogEntry.assets) ? catalogEntry.assets : [];\n for (const asset of assets) {\n if (!isRecord(asset) || !isRecord(asset.requirements)) continue;\n const { width, height } = asset.requirements;\n if (typeof width === 'number' && typeof height === 'number') return { width, height };\n }\n return undefined;\n}\n\ninterface RejectionInfo {\n codes: string[];\n fields: string[];\n messages: string[];\n}\n\nfunction extractRejectionInfo(taskResult: TaskResult): RejectionInfo | undefined {\n if (taskResult.success === true) return undefined;\n const codes = new Set<string>();\n const fields = new Set<string>();\n const messages = new Set<string>();\n collectRejectionInfo(taskResult, codes, fields, messages);\n return {\n codes: [...codes],\n fields: [...fields],\n messages: [...messages],\n };\n}\n\nfunction collectRejectionInfo(\n value: unknown,\n codes: Set<string>,\n fields: Set<string>,\n messages: Set<string>,\n depth = 0\n): void {\n if (depth > 5) return;\n if (typeof value === 'string') {\n messages.add(value);\n const prefixedCode = value.match(/^([A-Z][A-Z0-9_]+):/);\n if (prefixedCode?.[1]) codes.add(prefixedCode[1]);\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) collectRejectionInfo(item, codes, fields, messages, depth + 1);\n return;\n }\n if (!isRecord(value)) return;\n\n for (const key of ['code', 'error_code', 'reason'] as const) {\n const maybeCode = value[key];\n if (typeof maybeCode === 'string') codes.add(maybeCode);\n }\n for (const key of ['field', 'path', 'json_pointer'] as const) {\n const maybeField = value[key];\n if (typeof maybeField === 'string') fields.add(maybeField);\n }\n for (const key of ['message', 'error', 'detail', 'suggestion'] as const) {\n const maybeMessage = value[key];\n if (typeof maybeMessage === 'string') messages.add(maybeMessage);\n }\n for (const key of ['adcp_error', 'adcpError', 'data', 'details', 'errors', 'issues'] as const) {\n if (value[key] !== undefined) collectRejectionInfo(value[key], codes, fields, messages, depth + 1);\n }\n}\n\nfunction rejectionSupportsFormatFailure(rejection: RejectionInfo | undefined): boolean {\n if (!rejection) return false;\n if (rejection.codes.some(code => code.startsWith('FORMAT_'))) return true;\n return [...rejection.fields, ...rejection.messages].some(text =>\n /format|format_option|format_id|selector/i.test(text)\n );\n}\n\nfunction formatRejectionInfo(rejection: RejectionInfo | undefined): string {\n if (!rejection) return 'no structured rejection details';\n return JSON.stringify(rejection);\n}\n\nfunction deepEqualJson(a: unknown, b: unknown): boolean {\n return stableJson(a) === stableJson(b);\n}\n\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`;\n if (isRecord(value)) {\n return `{${Object.keys(value)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableJson(value[key])}`)\n .join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\nfunction firstCatalogDurationMs(catalogEntry: Record<string, unknown>): number | undefined {\n const assets = Array.isArray(catalogEntry.assets) ? catalogEntry.assets : [];\n for (const asset of assets) {\n if (!isRecord(asset) || !isRecord(asset.requirements)) continue;\n const { duration_ms, duration_seconds } = asset.requirements;\n if (typeof duration_ms === 'number') return duration_ms;\n if (typeof duration_seconds === 'number') return duration_seconds * 1000;\n }\n return undefined;\n}\n\nfunction classifyLikelyFailure(\n expectedAccepted: boolean,\n taskAccepted: boolean,\n localSatisfied: boolean,\n primary: SatisfactionVerdict | undefined\n): string {\n const observed = taskAccepted ? 'accepted' : 'rejected';\n const expected = expectedAccepted ? 'accepted' : 'rejected';\n const local = localSatisfied ? 'satisfies' : 'does not satisfy';\n const bugClass = primary?.bug_class ?? 'authoring';\n const detail = primary?.detail ?? 'no local satisfaction verdict';\n if (expectedAccepted && !taskAccepted && localSatisfied) {\n return `Expected request to be accepted and local canonical matching says it satisfies the product, but the agent rejected it. Likely ${bugClass} failure: ${detail}`;\n }\n if (!expectedAccepted && taskAccepted && !localSatisfied) {\n return `Expected request to be rejected because local canonical matching says it does not satisfy the product, but the agent accepted it. Likely ${bugClass} failure: ${detail}`;\n }\n if (!localSatisfied && expectedAccepted) {\n return `Storyboard expected acceptance, but the authored request does not satisfy the product locally (${bugClass}): ${detail}`;\n }\n if (localSatisfied && !expectedAccepted) {\n return `Storyboard expected rejection, but the authored request satisfies the product locally: ${detail}`;\n }\n return `Expected ${expected}, observed ${observed}; local matcher says request ${local}. ${detail}`;\n}\n\nfunction remediationFor(bugClass: BugClass | undefined): string | undefined {\n switch (bugClass) {\n case 'normalization':\n return 'Normalize legacy format_ids through product v1_format_ref, catalog canonical annotations, or the v1-canonical registry before comparing to product format_options.';\n case 'directionality':\n return 'Apply directional product gating: the request selector must contain the product-declared fixed constraints; a bare canonical kind does not satisfy a fixed-size or fixed-duration product.';\n case 'range_containment':\n return 'Use containment for ranges: an exact request must be inside the product range, and a request range must be fully contained by the product range, not merely overlap it.';\n case 'closed_set':\n return 'Treat product format_options[] as a closed set and reject selectors that do not resolve to one of its declarations.';\n default:\n return undefined;\n }\n}\n\nfunction sameFormatId(a: V1FormatId, b: V1FormatId): boolean {\n for (const key of FORMAT_IDENTITY_KEYS) {\n const av = key === 'agent_url' ? normalizeAgentUrl(a[key]) : a[key];\n const bv = key === 'agent_url' ? normalizeAgentUrl(b[key]) : b[key];\n if (av !== bv) return false;\n }\n return true;\n}\n\nfunction normalizeAgentUrl(value: unknown): unknown {\n if (typeof value !== 'string') return value;\n try {\n const url = new URL(value);\n url.hash = '';\n if ((url.protocol === 'https:' && url.port === '443') || (url.protocol === 'http:' && url.port === '80')) {\n url.port = '';\n }\n return url.toString().replace(/\\/$/, '');\n } catch {\n return value.replace(/\\/$/, '');\n }\n}\n\nfunction isFormatId(value: unknown): value is V1FormatId {\n return isRecord(value) && typeof value.agent_url === 'string' && typeof value.id === 'string';\n}\n\nfunction declarationLabel(decl: V2ProductFormatDeclaration): string | undefined {\n if (!decl.format_option_id) return undefined;\n return decl.publisher_domain ? `${decl.publisher_domain}/${decl.format_option_id}` : decl.format_option_id;\n}\n\nfunction requestDurationExact(params: Record<string, unknown>): number | undefined {\n if (typeof params.duration_ms_exact === 'number') return params.duration_ms_exact;\n if (typeof params.duration_ms === 'number') return params.duration_ms;\n return undefined;\n}\n\nfunction parseNumberPair(value: unknown): [number, number] | undefined {\n if (!Array.isArray(value) || value.length !== 2) return undefined;\n return typeof value[0] === 'number' && typeof value[1] === 'number' ? [value[0], value[1]] : undefined;\n}\n\nfunction parseSizes(value: unknown): Array<{ width: number; height: number }> {\n if (!Array.isArray(value)) return [];\n return value\n .map(item => {\n if (!isRecord(item)) return undefined;\n const width = typeof item.width === 'number' ? item.width : typeof item.w === 'number' ? item.w : undefined;\n const height = typeof item.height === 'number' ? item.height : typeof item.h === 'number' ? item.h : undefined;\n return width !== undefined && height !== undefined ? { width, height } : undefined;\n })\n .filter((s): s is { width: number; height: number } => Boolean(s));\n}\n\nfunction rangeLabel(min: unknown, max: unknown): string {\n return `[${min ?? '-infinity'}, ${max ?? 'infinity'}]`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n"],"mappings":"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","names":["packages","exact"]}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { fileURLToPath as __adcpFileURLToPath } from
|
|
2
|
-
import { dirname as __adcpDirname } from
|
|
3
|
-
import { createRequire as __adcpCreateRequire } from
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const require = __adcpCreateRequire(import.meta.url);
|
|
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 __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));
|
|
5
|
+
const require2 = __adcpCreateRequire(import.meta.url);
|
|
7
6
|
import { readFileSync, readdirSync, existsSync, statSync } from "fs";
|
|
8
7
|
import { basename, dirname, join, resolve } from "path";
|
|
9
8
|
import { loadStoryboardFile } from "./loader.mjs";
|