@adcp/sdk 13.0.0-rc.10 → 13.0.0-rc.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/lib/core/AgentClient.d.mts +12 -3
  2. package/dist/lib/core/AgentClient.d.ts +12 -3
  3. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  4. package/dist/lib/core/AgentClient.js +12 -3
  5. package/dist/lib/core/AgentClient.js.map +1 -1
  6. package/dist/lib/core/AgentClient.mjs +12 -3
  7. package/dist/lib/core/AgentClient.mjs.map +1 -1
  8. package/dist/lib/core/SingleAgentClient.d.mts +13 -3
  9. package/dist/lib/core/SingleAgentClient.d.ts +13 -3
  10. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  11. package/dist/lib/core/SingleAgentClient.js +52 -31
  12. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  13. package/dist/lib/core/SingleAgentClient.mjs +52 -31
  14. package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
  15. package/dist/lib/index.d.mts +1 -1
  16. package/dist/lib/index.d.ts +1 -1
  17. package/dist/lib/index.d.ts.map +1 -1
  18. package/dist/lib/index.js +8 -0
  19. package/dist/lib/index.js.map +1 -1
  20. package/dist/lib/index.mjs +8 -0
  21. package/dist/lib/index.mjs.map +1 -1
  22. package/dist/lib/registry/types.generated.d.mts +48 -1
  23. package/dist/lib/registry/types.generated.d.ts +48 -1
  24. package/dist/lib/registry/types.generated.d.ts.map +1 -1
  25. package/dist/lib/registry/types.generated.js.map +1 -1
  26. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  27. package/dist/lib/server/decisioning/runtime/from-platform.d.mts +1 -1
  28. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +1 -1
  29. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  30. package/dist/lib/server/decisioning/runtime/from-platform.js +389 -65
  31. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  32. package/dist/lib/server/decisioning/runtime/from-platform.mjs +389 -65
  33. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  34. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  35. package/dist/lib/testing/compliance/comply.js +8 -2
  36. package/dist/lib/testing/compliance/comply.js.map +1 -1
  37. package/dist/lib/testing/compliance/comply.mjs +8 -2
  38. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  39. package/dist/lib/testing/compliance/spec-conformance.d.ts.map +1 -1
  40. package/dist/lib/testing/compliance/spec-conformance.js +2 -0
  41. package/dist/lib/testing/compliance/spec-conformance.js.map +1 -1
  42. package/dist/lib/testing/compliance/spec-conformance.mjs +2 -0
  43. package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
  44. package/dist/lib/testing/compliance/summary.d.mts +2 -0
  45. package/dist/lib/testing/compliance/summary.d.ts +2 -0
  46. package/dist/lib/testing/compliance/summary.d.ts.map +1 -1
  47. package/dist/lib/testing/compliance/summary.js +3 -2
  48. package/dist/lib/testing/compliance/summary.js.map +1 -1
  49. package/dist/lib/testing/compliance/summary.mjs +3 -2
  50. package/dist/lib/testing/compliance/summary.mjs.map +1 -1
  51. package/dist/lib/testing/compliance/types.d.mts +4 -0
  52. package/dist/lib/testing/compliance/types.d.ts +4 -0
  53. package/dist/lib/testing/compliance/types.d.ts.map +1 -1
  54. package/dist/lib/testing/compliance/types.js.map +1 -1
  55. package/dist/lib/testing/storyboard/junit.js +49 -32
  56. package/dist/lib/testing/storyboard/junit.js.map +1 -1
  57. package/dist/lib/testing/storyboard/junit.mjs +49 -32
  58. package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
  59. package/dist/lib/testing/storyboard/loader.d.ts.map +1 -1
  60. package/dist/lib/testing/storyboard/loader.js +26 -0
  61. package/dist/lib/testing/storyboard/loader.js.map +1 -1
  62. package/dist/lib/testing/storyboard/loader.mjs +26 -0
  63. package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
  64. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  65. package/dist/lib/testing/storyboard/runner.js +66 -15
  66. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  67. package/dist/lib/testing/storyboard/runner.mjs +70 -16
  68. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  69. package/dist/lib/testing/storyboard/types.d.mts +26 -1
  70. package/dist/lib/testing/storyboard/types.d.ts +26 -1
  71. package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
  72. package/dist/lib/testing/storyboard/types.js.map +1 -1
  73. package/dist/lib/testing/storyboard/types.mjs.map +1 -1
  74. package/dist/lib/testing/storyboard/validations.d.mts +11 -0
  75. package/dist/lib/testing/storyboard/validations.d.ts +11 -0
  76. package/dist/lib/testing/storyboard/validations.d.ts.map +1 -1
  77. package/dist/lib/testing/storyboard/validations.js +30 -13
  78. package/dist/lib/testing/storyboard/validations.js.map +1 -1
  79. package/dist/lib/testing/storyboard/validations.mjs +27 -13
  80. package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
  81. package/dist/lib/v2/projection/augment-response.d.mts +45 -0
  82. package/dist/lib/v2/projection/augment-response.d.ts +45 -0
  83. package/dist/lib/v2/projection/augment-response.d.ts.map +1 -1
  84. package/dist/lib/v2/projection/augment-response.js +54 -0
  85. package/dist/lib/v2/projection/augment-response.js.map +1 -1
  86. package/dist/lib/v2/projection/augment-response.mjs +52 -0
  87. package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
  88. package/dist/lib/v2/projection/index.d.mts +7 -1
  89. package/dist/lib/v2/projection/index.d.ts +7 -1
  90. package/dist/lib/v2/projection/index.d.ts.map +1 -1
  91. package/dist/lib/v2/projection/index.js +9 -0
  92. package/dist/lib/v2/projection/index.js.map +1 -1
  93. package/dist/lib/v2/projection/index.mjs +10 -0
  94. package/dist/lib/v2/projection/index.mjs.map +1 -1
  95. package/dist/lib/v2/projection/legacy-routes.d.mts +24 -0
  96. package/dist/lib/v2/projection/legacy-routes.d.ts +25 -0
  97. package/dist/lib/v2/projection/legacy-routes.d.ts.map +1 -0
  98. package/dist/lib/v2/projection/legacy-routes.js +163 -0
  99. package/dist/lib/v2/projection/legacy-routes.js.map +1 -0
  100. package/dist/lib/v2/projection/legacy-routes.mjs +138 -0
  101. package/dist/lib/v2/projection/legacy-routes.mjs.map +1 -0
  102. package/dist/lib/v2/projection/v1-to-v2.d.mts +3 -0
  103. package/dist/lib/v2/projection/v1-to-v2.d.ts +3 -0
  104. package/dist/lib/v2/projection/v1-to-v2.d.ts.map +1 -1
  105. package/dist/lib/v2/projection/v1-to-v2.js +2 -1
  106. package/dist/lib/v2/projection/v1-to-v2.js.map +1 -1
  107. package/dist/lib/v2/projection/v1-to-v2.mjs +2 -1
  108. package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
  109. package/dist/lib/version.d.mts +3 -3
  110. package/dist/lib/version.d.ts +3 -3
  111. package/dist/lib/version.js +3 -3
  112. package/dist/lib/version.js.map +1 -1
  113. package/dist/lib/version.mjs +3 -3
  114. package/dist/lib/version.mjs.map +1 -1
  115. package/docs/migration-12-to-13.md +56 -2
  116. package/package.json +3 -1
@@ -1 +1 @@
1
- {"version":3,"file":"spec-conformance.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,2CAA2C,CAAC;AAgC7F;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAkD1G"}
1
+ {"version":3,"file":"spec-conformance.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,2CAA2C,CAAC;AAgC7F;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAmD1G"}
@@ -22,6 +22,7 @@ __export(spec_conformance_exports, {
22
22
  checkAccountDiscoveryGate: () => checkAccountDiscoveryGate
23
23
  });
24
24
  module.exports = __toCommonJS(spec_conformance_exports);
25
+ var import_version = require('../../version.js');
25
26
  const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = "__spec_conformance__/account_discovery";
26
27
  function isAccountBearingSpecialism(specialism) {
27
28
  if (specialism.startsWith("sales-")) return true;
@@ -71,6 +72,7 @@ function checkAccountDiscoveryGate(profile, agentUrl) {
71
72
  passed_count: 0,
72
73
  failed_count: 1,
73
74
  skipped_count: 0,
75
+ runner_capability_version: import_version.LIBRARY_VERSION,
74
76
  tested_at: now,
75
77
  notices: []
76
78
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"sourcesContent":["/**\n * Cross-storyboard spec conformance gates.\n *\n * Some AdCP rules are universal (apply to any seller agent regardless of\n * which specialism they're testing) rather than per-storyboard. Encoding\n * them as per-storyboard `required_tools` predicates would mean tagging\n * every relevant scenario, and the rule would still drift for adopters\n * authoring third-party storyboards.\n *\n * This module emits synthetic `StoryboardResult`s for those rules — the\n * comply orchestrator pushes them into the storyboard-results array\n * before track grouping. Pipeline downstream (failure extraction, track\n * mapping, summary, skip-cause aggregator) treats them as any other\n * storyboard result.\n *\n * Currently wires one gate:\n *\n * - **Account discovery (adcp-client#1624 / adcp#4302).** Every seller\n * agent (any specialism in `sales-*` / `audience-sync` / `governance-*`)\n * MUST advertise at least one of `list_accounts` or `sync_accounts`.\n * Spec normative as of AdCP 3.0.9; the requirement existed before the\n * explicit MUST landed. The runner honors AdCP 3.1\n * `required_any_of_tools` tags when present, but this fallback remains\n * until upstream storyboards carry the tag consistently.\n */\n\nimport type { AgentProfile } from '../types';\nimport type { StoryboardResult } from '../storyboard/types';\n\n/**\n * Synthetic storyboard ID emitted when the account-discovery gate fails.\n * Stable across releases — dashboards / badges can grep for it. Distinct\n * from any real storyboard ID; the gate runs cross-storyboard.\n */\nexport const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = '__spec_conformance__/account_discovery';\n\n/**\n * Specialisms that operate on accounts and therefore require the agent\n * to expose `list_accounts` OR `sync_accounts`. Per AdCP 3.0.9\n * `accounts/overview.mdx`. Adopters claiming any of these specialisms\n * without an account-discovery tool are non-conformant.\n *\n * Match rules:\n * - `sales-*` prefix — every selling specialism operates on accounts.\n * - exact `audience-sync` — audiences belong to accounts.\n * - `governance-*` prefix — governance applies per-account.\n * - exact `creative-generative` — dual-role specialism. A generative\n * seller (selling inventory + generating creatives) is an account-\n * bearing adopter even if they only claim `creative-generative`,\n * not a `sales-*` specialism. The upstream storyboard at\n * `compliance/cache/<v>/specialisms/creative-generative/generative-seller.yaml`\n * exercises `sync_accounts` directly, confirming this scope.\n *\n * Other creative specialisms (`creative-ad-server`, `creative-template`)\n * are stand-alone — those agents don't sell inventory and don't need\n * account discovery. Same for `signal-*`, `brand-rights`,\n * `signed-requests`.\n */\nfunction isAccountBearingSpecialism(specialism: string): boolean {\n if (specialism.startsWith('sales-')) return true;\n if (specialism === 'audience-sync') return true;\n if (specialism.startsWith('governance-')) return true;\n if (specialism === 'creative-generative') return true;\n return false;\n}\n\n/**\n * Run the account-discovery conformance gate. Returns `null` when the\n * gate doesn't apply (agent declared no account-bearing specialism,\n * couldn't enumerate specialisms, or already advertises a discovery\n * tool). Returns a synthetic failing `StoryboardResult` when the agent\n * is non-conformant.\n *\n * The returned result has:\n * - `overall_passed: false` so it counts toward `failed` in summaries\n * - one synthetic phase + step that surfaces the specific specialism(s)\n * triggering the gate so operators can act\n * - `track` is left unset on the synthetic id; `extractFailures` falls\n * back to `'core'` for any storyboard not in the applicable-storyboards\n * lookup, which is correct — account discovery is a core protocol\n * invariant, not a specialism-specific concern\n *\n * Note: when the agent doesn't expose `get_adcp_capabilities` (so\n * `profile.specialisms` is undefined), the gate is a no-op. The runner\n * separately surfaces an observation about the missing capability call;\n * we don't double-report.\n *\n * TODO(adcp-client#1642): delete this synthesis path when upstream\n * storyboards in `compliance/cache/` carry `required_any_of_tools`\n * consistently for every account-bearing scenario.\n */\nexport function checkAccountDiscoveryGate(profile: AgentProfile, agentUrl: string): StoryboardResult | null {\n const accountBearing = (profile.specialisms ?? []).filter(isAccountBearingSpecialism);\n if (accountBearing.length === 0) return null;\n\n if (profile.tools.includes('list_accounts') || profile.tools.includes('sync_accounts')) {\n return null;\n }\n\n const now = new Date().toISOString();\n const detail =\n `Agent declared account-bearing specialism(s) [${accountBearing.join(', ')}] but advertises ` +\n `neither list_accounts nor sync_accounts. AdCP 3.0.9 §accounts/overview requires every seller ` +\n `agent to expose at least one of these tools. Agent tools: [${profile.tools.join(', ')}].`;\n\n return {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n storyboard_title: 'Spec conformance: account discovery',\n agent_url: agentUrl,\n overall_passed: false,\n phases: [\n {\n phase_id: 'account_discovery_gate',\n phase_title: 'Account discovery',\n passed: false,\n duration_ms: 0,\n steps: [\n {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n step_id: 'list_or_sync_accounts',\n phase_id: 'account_discovery_gate',\n title: 'Seller agent must advertise list_accounts or sync_accounts',\n task: '',\n passed: false,\n duration_ms: 0,\n validations: [],\n context: {},\n error: detail,\n extraction: { path: 'none' },\n },\n ],\n },\n ],\n context: {},\n total_duration_ms: 0,\n passed_count: 0,\n failed_count: 1,\n skipped_count: 0,\n tested_at: now,\n notices: [],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCO,MAAM,uCAAuC;AAwBpD,SAAS,2BAA2B,YAA6B;AAC/D,MAAI,WAAW,WAAW,QAAQ,EAAG,QAAO;AAC5C,MAAI,eAAe,gBAAiB,QAAO;AAC3C,MAAI,WAAW,WAAW,aAAa,EAAG,QAAO;AACjD,MAAI,eAAe,sBAAuB,QAAO;AACjD,SAAO;AACT;AA2BO,SAAS,0BAA0B,SAAuB,UAA2C;AAC1G,QAAM,kBAAkB,QAAQ,eAAe,CAAC,GAAG,OAAO,0BAA0B;AACpF,MAAI,eAAe,WAAW,EAAG,QAAO;AAExC,MAAI,QAAQ,MAAM,SAAS,eAAe,KAAK,QAAQ,MAAM,SAAS,eAAe,GAAG;AACtF,WAAO;AAAA,EACT;AAEA,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,SACJ,iDAAiD,eAAe,KAAK,IAAI,CAAC,+KAEZ,QAAQ,MAAM,KAAK,IAAI,CAAC;AAExF,SAAO;AAAA,IACL,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,QAAQ;AAAA,MACN;AAAA,QACE,UAAU;AAAA,QACV,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,OAAO;AAAA,UACL;AAAA,YACE,eAAe;AAAA,YACf,SAAS;AAAA,YACT,UAAU;AAAA,YACV,OAAO;AAAA,YACP,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,aAAa,CAAC;AAAA,YACd,SAAS,CAAC;AAAA,YACV,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,OAAO;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA,IACV,mBAAmB;AAAA,IACnB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,SAAS,CAAC;AAAA,EACZ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"sourcesContent":["/**\n * Cross-storyboard spec conformance gates.\n *\n * Some AdCP rules are universal (apply to any seller agent regardless of\n * which specialism they're testing) rather than per-storyboard. Encoding\n * them as per-storyboard `required_tools` predicates would mean tagging\n * every relevant scenario, and the rule would still drift for adopters\n * authoring third-party storyboards.\n *\n * This module emits synthetic `StoryboardResult`s for those rules — the\n * comply orchestrator pushes them into the storyboard-results array\n * before track grouping. Pipeline downstream (failure extraction, track\n * mapping, summary, skip-cause aggregator) treats them as any other\n * storyboard result.\n *\n * Currently wires one gate:\n *\n * - **Account discovery (adcp-client#1624 / adcp#4302).** Every seller\n * agent (any specialism in `sales-*` / `audience-sync` / `governance-*`)\n * MUST advertise at least one of `list_accounts` or `sync_accounts`.\n * Spec normative as of AdCP 3.0.9; the requirement existed before the\n * explicit MUST landed. The runner honors AdCP 3.1\n * `required_any_of_tools` tags when present, but this fallback remains\n * until upstream storyboards carry the tag consistently.\n */\n\nimport type { AgentProfile } from '../types';\nimport type { StoryboardResult } from '../storyboard/types';\nimport { LIBRARY_VERSION } from '../../version';\n\n/**\n * Synthetic storyboard ID emitted when the account-discovery gate fails.\n * Stable across releases — dashboards / badges can grep for it. Distinct\n * from any real storyboard ID; the gate runs cross-storyboard.\n */\nexport const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = '__spec_conformance__/account_discovery';\n\n/**\n * Specialisms that operate on accounts and therefore require the agent\n * to expose `list_accounts` OR `sync_accounts`. Per AdCP 3.0.9\n * `accounts/overview.mdx`. Adopters claiming any of these specialisms\n * without an account-discovery tool are non-conformant.\n *\n * Match rules:\n * - `sales-*` prefix — every selling specialism operates on accounts.\n * - exact `audience-sync` — audiences belong to accounts.\n * - `governance-*` prefix — governance applies per-account.\n * - exact `creative-generative` — dual-role specialism. A generative\n * seller (selling inventory + generating creatives) is an account-\n * bearing adopter even if they only claim `creative-generative`,\n * not a `sales-*` specialism. The upstream storyboard at\n * `compliance/cache/<v>/specialisms/creative-generative/generative-seller.yaml`\n * exercises `sync_accounts` directly, confirming this scope.\n *\n * Other creative specialisms (`creative-ad-server`, `creative-template`)\n * are stand-alone — those agents don't sell inventory and don't need\n * account discovery. Same for `signal-*`, `brand-rights`,\n * `signed-requests`.\n */\nfunction isAccountBearingSpecialism(specialism: string): boolean {\n if (specialism.startsWith('sales-')) return true;\n if (specialism === 'audience-sync') return true;\n if (specialism.startsWith('governance-')) return true;\n if (specialism === 'creative-generative') return true;\n return false;\n}\n\n/**\n * Run the account-discovery conformance gate. Returns `null` when the\n * gate doesn't apply (agent declared no account-bearing specialism,\n * couldn't enumerate specialisms, or already advertises a discovery\n * tool). Returns a synthetic failing `StoryboardResult` when the agent\n * is non-conformant.\n *\n * The returned result has:\n * - `overall_passed: false` so it counts toward `failed` in summaries\n * - one synthetic phase + step that surfaces the specific specialism(s)\n * triggering the gate so operators can act\n * - `track` is left unset on the synthetic id; `extractFailures` falls\n * back to `'core'` for any storyboard not in the applicable-storyboards\n * lookup, which is correct — account discovery is a core protocol\n * invariant, not a specialism-specific concern\n *\n * Note: when the agent doesn't expose `get_adcp_capabilities` (so\n * `profile.specialisms` is undefined), the gate is a no-op. The runner\n * separately surfaces an observation about the missing capability call;\n * we don't double-report.\n *\n * TODO(adcp-client#1642): delete this synthesis path when upstream\n * storyboards in `compliance/cache/` carry `required_any_of_tools`\n * consistently for every account-bearing scenario.\n */\nexport function checkAccountDiscoveryGate(profile: AgentProfile, agentUrl: string): StoryboardResult | null {\n const accountBearing = (profile.specialisms ?? []).filter(isAccountBearingSpecialism);\n if (accountBearing.length === 0) return null;\n\n if (profile.tools.includes('list_accounts') || profile.tools.includes('sync_accounts')) {\n return null;\n }\n\n const now = new Date().toISOString();\n const detail =\n `Agent declared account-bearing specialism(s) [${accountBearing.join(', ')}] but advertises ` +\n `neither list_accounts nor sync_accounts. AdCP 3.0.9 §accounts/overview requires every seller ` +\n `agent to expose at least one of these tools. Agent tools: [${profile.tools.join(', ')}].`;\n\n return {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n storyboard_title: 'Spec conformance: account discovery',\n agent_url: agentUrl,\n overall_passed: false,\n phases: [\n {\n phase_id: 'account_discovery_gate',\n phase_title: 'Account discovery',\n passed: false,\n duration_ms: 0,\n steps: [\n {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n step_id: 'list_or_sync_accounts',\n phase_id: 'account_discovery_gate',\n title: 'Seller agent must advertise list_accounts or sync_accounts',\n task: '',\n passed: false,\n duration_ms: 0,\n validations: [],\n context: {},\n error: detail,\n extraction: { path: 'none' },\n },\n ],\n },\n ],\n context: {},\n total_duration_ms: 0,\n passed_count: 0,\n failed_count: 1,\n skipped_count: 0,\n runner_capability_version: LIBRARY_VERSION,\n tested_at: now,\n notices: [],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BA,qBAAgC;AAOzB,MAAM,uCAAuC;AAwBpD,SAAS,2BAA2B,YAA6B;AAC/D,MAAI,WAAW,WAAW,QAAQ,EAAG,QAAO;AAC5C,MAAI,eAAe,gBAAiB,QAAO;AAC3C,MAAI,WAAW,WAAW,aAAa,EAAG,QAAO;AACjD,MAAI,eAAe,sBAAuB,QAAO;AACjD,SAAO;AACT;AA2BO,SAAS,0BAA0B,SAAuB,UAA2C;AAC1G,QAAM,kBAAkB,QAAQ,eAAe,CAAC,GAAG,OAAO,0BAA0B;AACpF,MAAI,eAAe,WAAW,EAAG,QAAO;AAExC,MAAI,QAAQ,MAAM,SAAS,eAAe,KAAK,QAAQ,MAAM,SAAS,eAAe,GAAG;AACtF,WAAO;AAAA,EACT;AAEA,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,SACJ,iDAAiD,eAAe,KAAK,IAAI,CAAC,+KAEZ,QAAQ,MAAM,KAAK,IAAI,CAAC;AAExF,SAAO;AAAA,IACL,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,QAAQ;AAAA,MACN;AAAA,QACE,UAAU;AAAA,QACV,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,OAAO;AAAA,UACL;AAAA,YACE,eAAe;AAAA,YACf,SAAS;AAAA,YACT,UAAU;AAAA,YACV,OAAO;AAAA,YACP,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,aAAa,CAAC;AAAA,YACd,SAAS,CAAC;AAAA,YACV,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,OAAO;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA,IACV,mBAAmB;AAAA,IACnB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,eAAe;AAAA,IACf,2BAA2B;AAAA,IAC3B,WAAW;AAAA,IACX,SAAS,CAAC;AAAA,EACZ;AACF;","names":[]}
@@ -1,3 +1,4 @@
1
+ import { LIBRARY_VERSION } from "../../version.mjs";
1
2
  const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = "__spec_conformance__/account_discovery";
2
3
  function isAccountBearingSpecialism(specialism) {
3
4
  if (specialism.startsWith("sales-")) return true;
@@ -47,6 +48,7 @@ function checkAccountDiscoveryGate(profile, agentUrl) {
47
48
  passed_count: 0,
48
49
  failed_count: 1,
49
50
  skipped_count: 0,
51
+ runner_capability_version: LIBRARY_VERSION,
50
52
  tested_at: now,
51
53
  notices: []
52
54
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"sourcesContent":["/**\n * Cross-storyboard spec conformance gates.\n *\n * Some AdCP rules are universal (apply to any seller agent regardless of\n * which specialism they're testing) rather than per-storyboard. Encoding\n * them as per-storyboard `required_tools` predicates would mean tagging\n * every relevant scenario, and the rule would still drift for adopters\n * authoring third-party storyboards.\n *\n * This module emits synthetic `StoryboardResult`s for those rules — the\n * comply orchestrator pushes them into the storyboard-results array\n * before track grouping. Pipeline downstream (failure extraction, track\n * mapping, summary, skip-cause aggregator) treats them as any other\n * storyboard result.\n *\n * Currently wires one gate:\n *\n * - **Account discovery (adcp-client#1624 / adcp#4302).** Every seller\n * agent (any specialism in `sales-*` / `audience-sync` / `governance-*`)\n * MUST advertise at least one of `list_accounts` or `sync_accounts`.\n * Spec normative as of AdCP 3.0.9; the requirement existed before the\n * explicit MUST landed. The runner honors AdCP 3.1\n * `required_any_of_tools` tags when present, but this fallback remains\n * until upstream storyboards carry the tag consistently.\n */\n\nimport type { AgentProfile } from '../types';\nimport type { StoryboardResult } from '../storyboard/types';\n\n/**\n * Synthetic storyboard ID emitted when the account-discovery gate fails.\n * Stable across releases — dashboards / badges can grep for it. Distinct\n * from any real storyboard ID; the gate runs cross-storyboard.\n */\nexport const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = '__spec_conformance__/account_discovery';\n\n/**\n * Specialisms that operate on accounts and therefore require the agent\n * to expose `list_accounts` OR `sync_accounts`. Per AdCP 3.0.9\n * `accounts/overview.mdx`. Adopters claiming any of these specialisms\n * without an account-discovery tool are non-conformant.\n *\n * Match rules:\n * - `sales-*` prefix — every selling specialism operates on accounts.\n * - exact `audience-sync` — audiences belong to accounts.\n * - `governance-*` prefix — governance applies per-account.\n * - exact `creative-generative` — dual-role specialism. A generative\n * seller (selling inventory + generating creatives) is an account-\n * bearing adopter even if they only claim `creative-generative`,\n * not a `sales-*` specialism. The upstream storyboard at\n * `compliance/cache/<v>/specialisms/creative-generative/generative-seller.yaml`\n * exercises `sync_accounts` directly, confirming this scope.\n *\n * Other creative specialisms (`creative-ad-server`, `creative-template`)\n * are stand-alone — those agents don't sell inventory and don't need\n * account discovery. Same for `signal-*`, `brand-rights`,\n * `signed-requests`.\n */\nfunction isAccountBearingSpecialism(specialism: string): boolean {\n if (specialism.startsWith('sales-')) return true;\n if (specialism === 'audience-sync') return true;\n if (specialism.startsWith('governance-')) return true;\n if (specialism === 'creative-generative') return true;\n return false;\n}\n\n/**\n * Run the account-discovery conformance gate. Returns `null` when the\n * gate doesn't apply (agent declared no account-bearing specialism,\n * couldn't enumerate specialisms, or already advertises a discovery\n * tool). Returns a synthetic failing `StoryboardResult` when the agent\n * is non-conformant.\n *\n * The returned result has:\n * - `overall_passed: false` so it counts toward `failed` in summaries\n * - one synthetic phase + step that surfaces the specific specialism(s)\n * triggering the gate so operators can act\n * - `track` is left unset on the synthetic id; `extractFailures` falls\n * back to `'core'` for any storyboard not in the applicable-storyboards\n * lookup, which is correct — account discovery is a core protocol\n * invariant, not a specialism-specific concern\n *\n * Note: when the agent doesn't expose `get_adcp_capabilities` (so\n * `profile.specialisms` is undefined), the gate is a no-op. The runner\n * separately surfaces an observation about the missing capability call;\n * we don't double-report.\n *\n * TODO(adcp-client#1642): delete this synthesis path when upstream\n * storyboards in `compliance/cache/` carry `required_any_of_tools`\n * consistently for every account-bearing scenario.\n */\nexport function checkAccountDiscoveryGate(profile: AgentProfile, agentUrl: string): StoryboardResult | null {\n const accountBearing = (profile.specialisms ?? []).filter(isAccountBearingSpecialism);\n if (accountBearing.length === 0) return null;\n\n if (profile.tools.includes('list_accounts') || profile.tools.includes('sync_accounts')) {\n return null;\n }\n\n const now = new Date().toISOString();\n const detail =\n `Agent declared account-bearing specialism(s) [${accountBearing.join(', ')}] but advertises ` +\n `neither list_accounts nor sync_accounts. AdCP 3.0.9 §accounts/overview requires every seller ` +\n `agent to expose at least one of these tools. Agent tools: [${profile.tools.join(', ')}].`;\n\n return {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n storyboard_title: 'Spec conformance: account discovery',\n agent_url: agentUrl,\n overall_passed: false,\n phases: [\n {\n phase_id: 'account_discovery_gate',\n phase_title: 'Account discovery',\n passed: false,\n duration_ms: 0,\n steps: [\n {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n step_id: 'list_or_sync_accounts',\n phase_id: 'account_discovery_gate',\n title: 'Seller agent must advertise list_accounts or sync_accounts',\n task: '',\n passed: false,\n duration_ms: 0,\n validations: [],\n context: {},\n error: detail,\n extraction: { path: 'none' },\n },\n ],\n },\n ],\n context: {},\n total_duration_ms: 0,\n passed_count: 0,\n failed_count: 1,\n skipped_count: 0,\n tested_at: now,\n notices: [],\n };\n}\n"],"mappings":"AAkCO,MAAM,uCAAuC;AAwBpD,SAAS,2BAA2B,YAA6B;AAC/D,MAAI,WAAW,WAAW,QAAQ,EAAG,QAAO;AAC5C,MAAI,eAAe,gBAAiB,QAAO;AAC3C,MAAI,WAAW,WAAW,aAAa,EAAG,QAAO;AACjD,MAAI,eAAe,sBAAuB,QAAO;AACjD,SAAO;AACT;AA2BO,SAAS,0BAA0B,SAAuB,UAA2C;AAC1G,QAAM,kBAAkB,QAAQ,eAAe,CAAC,GAAG,OAAO,0BAA0B;AACpF,MAAI,eAAe,WAAW,EAAG,QAAO;AAExC,MAAI,QAAQ,MAAM,SAAS,eAAe,KAAK,QAAQ,MAAM,SAAS,eAAe,GAAG;AACtF,WAAO;AAAA,EACT;AAEA,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,SACJ,iDAAiD,eAAe,KAAK,IAAI,CAAC,+KAEZ,QAAQ,MAAM,KAAK,IAAI,CAAC;AAExF,SAAO;AAAA,IACL,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,QAAQ;AAAA,MACN;AAAA,QACE,UAAU;AAAA,QACV,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,OAAO;AAAA,UACL;AAAA,YACE,eAAe;AAAA,YACf,SAAS;AAAA,YACT,UAAU;AAAA,YACV,OAAO;AAAA,YACP,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,aAAa,CAAC;AAAA,YACd,SAAS,CAAC;AAAA,YACV,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,OAAO;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA,IACV,mBAAmB;AAAA,IACnB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,SAAS,CAAC;AAAA,EACZ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/compliance/spec-conformance.ts"],"sourcesContent":["/**\n * Cross-storyboard spec conformance gates.\n *\n * Some AdCP rules are universal (apply to any seller agent regardless of\n * which specialism they're testing) rather than per-storyboard. Encoding\n * them as per-storyboard `required_tools` predicates would mean tagging\n * every relevant scenario, and the rule would still drift for adopters\n * authoring third-party storyboards.\n *\n * This module emits synthetic `StoryboardResult`s for those rules — the\n * comply orchestrator pushes them into the storyboard-results array\n * before track grouping. Pipeline downstream (failure extraction, track\n * mapping, summary, skip-cause aggregator) treats them as any other\n * storyboard result.\n *\n * Currently wires one gate:\n *\n * - **Account discovery (adcp-client#1624 / adcp#4302).** Every seller\n * agent (any specialism in `sales-*` / `audience-sync` / `governance-*`)\n * MUST advertise at least one of `list_accounts` or `sync_accounts`.\n * Spec normative as of AdCP 3.0.9; the requirement existed before the\n * explicit MUST landed. The runner honors AdCP 3.1\n * `required_any_of_tools` tags when present, but this fallback remains\n * until upstream storyboards carry the tag consistently.\n */\n\nimport type { AgentProfile } from '../types';\nimport type { StoryboardResult } from '../storyboard/types';\nimport { LIBRARY_VERSION } from '../../version';\n\n/**\n * Synthetic storyboard ID emitted when the account-discovery gate fails.\n * Stable across releases — dashboards / badges can grep for it. Distinct\n * from any real storyboard ID; the gate runs cross-storyboard.\n */\nexport const ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID = '__spec_conformance__/account_discovery';\n\n/**\n * Specialisms that operate on accounts and therefore require the agent\n * to expose `list_accounts` OR `sync_accounts`. Per AdCP 3.0.9\n * `accounts/overview.mdx`. Adopters claiming any of these specialisms\n * without an account-discovery tool are non-conformant.\n *\n * Match rules:\n * - `sales-*` prefix — every selling specialism operates on accounts.\n * - exact `audience-sync` — audiences belong to accounts.\n * - `governance-*` prefix — governance applies per-account.\n * - exact `creative-generative` — dual-role specialism. A generative\n * seller (selling inventory + generating creatives) is an account-\n * bearing adopter even if they only claim `creative-generative`,\n * not a `sales-*` specialism. The upstream storyboard at\n * `compliance/cache/<v>/specialisms/creative-generative/generative-seller.yaml`\n * exercises `sync_accounts` directly, confirming this scope.\n *\n * Other creative specialisms (`creative-ad-server`, `creative-template`)\n * are stand-alone — those agents don't sell inventory and don't need\n * account discovery. Same for `signal-*`, `brand-rights`,\n * `signed-requests`.\n */\nfunction isAccountBearingSpecialism(specialism: string): boolean {\n if (specialism.startsWith('sales-')) return true;\n if (specialism === 'audience-sync') return true;\n if (specialism.startsWith('governance-')) return true;\n if (specialism === 'creative-generative') return true;\n return false;\n}\n\n/**\n * Run the account-discovery conformance gate. Returns `null` when the\n * gate doesn't apply (agent declared no account-bearing specialism,\n * couldn't enumerate specialisms, or already advertises a discovery\n * tool). Returns a synthetic failing `StoryboardResult` when the agent\n * is non-conformant.\n *\n * The returned result has:\n * - `overall_passed: false` so it counts toward `failed` in summaries\n * - one synthetic phase + step that surfaces the specific specialism(s)\n * triggering the gate so operators can act\n * - `track` is left unset on the synthetic id; `extractFailures` falls\n * back to `'core'` for any storyboard not in the applicable-storyboards\n * lookup, which is correct — account discovery is a core protocol\n * invariant, not a specialism-specific concern\n *\n * Note: when the agent doesn't expose `get_adcp_capabilities` (so\n * `profile.specialisms` is undefined), the gate is a no-op. The runner\n * separately surfaces an observation about the missing capability call;\n * we don't double-report.\n *\n * TODO(adcp-client#1642): delete this synthesis path when upstream\n * storyboards in `compliance/cache/` carry `required_any_of_tools`\n * consistently for every account-bearing scenario.\n */\nexport function checkAccountDiscoveryGate(profile: AgentProfile, agentUrl: string): StoryboardResult | null {\n const accountBearing = (profile.specialisms ?? []).filter(isAccountBearingSpecialism);\n if (accountBearing.length === 0) return null;\n\n if (profile.tools.includes('list_accounts') || profile.tools.includes('sync_accounts')) {\n return null;\n }\n\n const now = new Date().toISOString();\n const detail =\n `Agent declared account-bearing specialism(s) [${accountBearing.join(', ')}] but advertises ` +\n `neither list_accounts nor sync_accounts. AdCP 3.0.9 §accounts/overview requires every seller ` +\n `agent to expose at least one of these tools. Agent tools: [${profile.tools.join(', ')}].`;\n\n return {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n storyboard_title: 'Spec conformance: account discovery',\n agent_url: agentUrl,\n overall_passed: false,\n phases: [\n {\n phase_id: 'account_discovery_gate',\n phase_title: 'Account discovery',\n passed: false,\n duration_ms: 0,\n steps: [\n {\n storyboard_id: ACCOUNT_DISCOVERY_GATE_STORYBOARD_ID,\n step_id: 'list_or_sync_accounts',\n phase_id: 'account_discovery_gate',\n title: 'Seller agent must advertise list_accounts or sync_accounts',\n task: '',\n passed: false,\n duration_ms: 0,\n validations: [],\n context: {},\n error: detail,\n extraction: { path: 'none' },\n },\n ],\n },\n ],\n context: {},\n total_duration_ms: 0,\n passed_count: 0,\n failed_count: 1,\n skipped_count: 0,\n runner_capability_version: LIBRARY_VERSION,\n tested_at: now,\n notices: [],\n };\n}\n"],"mappings":"AA4BA,SAAS,uBAAuB;AAOzB,MAAM,uCAAuC;AAwBpD,SAAS,2BAA2B,YAA6B;AAC/D,MAAI,WAAW,WAAW,QAAQ,EAAG,QAAO;AAC5C,MAAI,eAAe,gBAAiB,QAAO;AAC3C,MAAI,WAAW,WAAW,aAAa,EAAG,QAAO;AACjD,MAAI,eAAe,sBAAuB,QAAO;AACjD,SAAO;AACT;AA2BO,SAAS,0BAA0B,SAAuB,UAA2C;AAC1G,QAAM,kBAAkB,QAAQ,eAAe,CAAC,GAAG,OAAO,0BAA0B;AACpF,MAAI,eAAe,WAAW,EAAG,QAAO;AAExC,MAAI,QAAQ,MAAM,SAAS,eAAe,KAAK,QAAQ,MAAM,SAAS,eAAe,GAAG;AACtF,WAAO;AAAA,EACT;AAEA,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,SACJ,iDAAiD,eAAe,KAAK,IAAI,CAAC,+KAEZ,QAAQ,MAAM,KAAK,IAAI,CAAC;AAExF,SAAO;AAAA,IACL,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,QAAQ;AAAA,MACN;AAAA,QACE,UAAU;AAAA,QACV,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,OAAO;AAAA,UACL;AAAA,YACE,eAAe;AAAA,YACf,SAAS;AAAA,YACT,UAAU;AAAA,YACV,OAAO;AAAA,YACP,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,aAAa,CAAC;AAAA,YACd,SAAS,CAAC;AAAA,YACV,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,OAAO;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA,IACV,mBAAmB;AAAA,IACnB,cAAc;AAAA,IACd,cAAc;AAAA,IACd,eAAe;AAAA,IACf,2BAA2B;AAAA,IAC3B,WAAW;AAAA,IACX,SAAS,CAAC;AAAA,EACZ;AACF;","names":[]}
@@ -42,6 +42,8 @@ export interface ComplianceSummaryArtifact {
42
42
  overall_status: OverallStatus;
43
43
  passed: number;
44
44
  failed: number;
45
+ /** Failed advisory validations; does not affect the failed-step count. */
46
+ validations_advisory_failed?: number;
45
47
  skipped: number;
46
48
  /**
47
49
  * Validation results graded `not_applicable`. Present only when non-zero so
@@ -42,6 +42,8 @@ export interface ComplianceSummaryArtifact {
42
42
  overall_status: OverallStatus;
43
43
  passed: number;
44
44
  failed: number;
45
+ /** Failed advisory validations; does not affect the failed-step count. */
46
+ validations_advisory_failed?: number;
45
47
  skipped: number;
46
48
  /**
47
49
  * Validation results graded `not_applicable`. Present only when non-zero so
@@ -1 +1 @@
1
- {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/compliance/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAEV,2BAA2B,EAC3B,gBAAgB,EAChB,eAAe,EACf,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAKnF;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,mGAAmG;IACnG,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,aAAa,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC;IACvE,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,YAAY,CAAC,EAAE,2BAA2B,EAAE,CAAC;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,EAAE,wBAAwB,EAAE,CAAC;IACrC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,0BAA0B,EAAE,CAAC;CAC5C;AAED;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GACpC,OAAO,CAAC,sEAAsE,GAC9E,YAAY,CAAC,0EAA0E,GACvF,mBAAmB,CAAC,iFAAiF,GACrG,aAAa,CAAC,CAAC,2DAA2D;AAE9E,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,eAAe,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,4BAA4B,CAAC;CAC3C;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,mBAAmB,GAAG,yBAAyB,CAwBrH;AAsND;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,yBAAyB,GAAG,MAAM,CA2DhF;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,CAAC,EAAE,yBAAyB,GAAG,MAAM,CA2DpF;AASD;;;;;;GAMG;AACH,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,yBAAyB,CA2B3F"}
1
+ {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/compliance/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAEV,2BAA2B,EAC3B,gBAAgB,EAChB,eAAe,EACf,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAKnF;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,mGAAmG;IACnG,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,aAAa,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC;IACvE,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,YAAY,CAAC,EAAE,2BAA2B,EAAE,CAAC;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,EAAE,wBAAwB,EAAE,CAAC;IACrC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,0BAA0B,EAAE,CAAC;CAC5C;AAED;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GACpC,OAAO,CAAC,sEAAsE,GAC9E,YAAY,CAAC,0EAA0E,GACvF,mBAAmB,CAAC,iFAAiF,GACrG,aAAa,CAAC,CAAC,2DAA2D;AAE9E,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,eAAe,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,4BAA4B,CAAC;CAC3C;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,mBAAmB,GAAG,yBAAyB,CA2BrH;AAsND;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,yBAAyB,GAAG,MAAM,CA2DhF;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,CAAC,EAAE,yBAAyB,GAAG,MAAM,CA2DpF;AASD;;;;;;GAMG;AACH,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,yBAAyB,CA2B3F"}
@@ -36,6 +36,7 @@ function buildComplianceSummary(result, opts) {
36
36
  overall_status: result.overall_status,
37
37
  passed: result.summary.steps_passed ?? 0,
38
38
  failed: result.summary.steps_failed ?? 0,
39
+ ...result.summary.validations_advisory_failed ? { validations_advisory_failed: result.summary.validations_advisory_failed } : {},
39
40
  skipped: result.summary.steps_skipped ?? 0,
40
41
  ...result.summary.validations_not_applicable ? { validations_not_applicable: result.summary.validations_not_applicable } : {},
41
42
  not_selected_count: result.summary.steps_not_selected ?? 0,
@@ -201,7 +202,7 @@ function formatComplianceSummaryText(s) {
201
202
  lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);
202
203
  lines.push(`Status: ${s.overall_status}`);
203
204
  lines.push(
204
- `Steps: ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
205
+ `Steps: ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
205
206
  );
206
207
  const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);
207
208
  if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);
@@ -251,7 +252,7 @@ function formatComplianceSummaryMarkdown(s) {
251
252
  lines.push(`- **SDK:** \`@adcp/sdk ${s.sdk_version}\` (AdCP \`${s.adcp_version}\`)`);
252
253
  lines.push(`- **Status:** \`${s.overall_status}\``);
253
254
  lines.push(
254
- `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
255
+ `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
255
256
  );
256
257
  const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);
257
258
  if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/compliance/summary.ts"],"sourcesContent":["/**\n * Narrow, schema-stable summary artifact for compliance runs.\n *\n * `formatComplianceResultsJSON` serializes the full ComplianceResult — that\n * shape evolves with the protocol. Downstream tooling (badges, Slack bots,\n * dashboards) wants a thin contract: pass/fail counts and a flat list of\n * failures with stable IDs. That's what this module provides.\n *\n * Three renderers:\n * - `buildComplianceSummary` → ComplianceSummaryArtifact (the JSON contract)\n * - `formatComplianceSummaryText` → stderr block with greppable `STORYBOARD-FAIL` prefix\n * - `formatComplianceSummaryMarkdown` → table for $GITHUB_STEP_SUMMARY\n *\n * The v2 summary separates selected-but-skipped steps from not-selected\n * exclusions. Treat unknown fields as ignorable per schema_version semantics.\n * Crash-path summaries built by `buildCrashSummary` omit `skip_causes`\n * because the runner never reached the storyboard execution phase.\n */\n\nimport type {\n ComplianceFailure,\n ComplianceNotSelectedRecord,\n ComplianceResult,\n ComplianceTrack,\n OverallStatus,\n} from './types';\nimport type { RunnerSelectionReason, RunnerSkipReason } from '../storyboard/types';\nimport { DETAILED_SKIP_TO_CANONICAL, type RunnerDetailedSkipReason } from '../storyboard/types';\n\nconst SUMMARY_SCHEMA_VERSION = 2;\n\n/**\n * A grouped skip-cause entry for the always-on summary block.\n * Only actionable causes are included — internal runner routing skips\n * (peer_branch_taken, not_applicable, etc.) are filtered out.\n */\nexport interface ComplianceSummarySkipCause {\n cause: string;\n count: number;\n detail: string;\n /** Scenario IDs affected (capped at SKIP_CAUSE_AFFECTED_LIMIT; remainder noted in text output). */\n affected: string[];\n}\n\n/**\n * Stable, schema-versioned summary. Adopters depending on this shape should\n * gate on `schema_version` and treat unknown fields as ignorable.\n */\nexport interface ComplianceSummaryArtifact {\n schema_version: number;\n agent_url: string;\n sdk_version: string;\n adcp_version: string;\n overall_status: OverallStatus;\n passed: number;\n failed: number;\n skipped: number;\n /**\n * Validation results graded `not_applicable`. Present only when non-zero so\n * CI/badge consumers can distinguish clean passes from downgraded coverage.\n */\n validations_not_applicable?: number;\n not_selected_count: number;\n not_selected_by_reason: Partial<Record<RunnerSelectionReason, number>>;\n skipped_by_reason: Partial<Record<RunnerSkipReason | string, number>>;\n not_selected?: ComplianceNotSelectedRecord[];\n total_duration_ms: number;\n tested_at: string;\n storyboards_executed: string[];\n failures: ComplianceSummaryFailure[];\n /** Actionable skip causes grouped by reason. Present only when skipped > 0. */\n skip_causes?: ComplianceSummarySkipCause[];\n}\n\n/**\n * Discriminator for `reason`. Lets a Slack bot color-code or filter without\n * regexing the reason string. Pinned at v1; new kinds are additive.\n */\nexport type ComplianceSummaryFailureKind =\n | 'error' /** The step itself raised — network, transport, runtime exception. */\n | 'validation' /** A storyboard validation check failed (schema, field_present, etc.). */\n | 'expected_mismatch' /** No structured validation; reason derived from the step's `expected:` text. */\n | 'unspecified'; /** Failure with no extractable reason — should be rare. */\n\nexport interface ComplianceSummaryFailure {\n track: ComplianceTrack;\n storyboard_id: string;\n step_id: string;\n reason: string;\n reason_kind: ComplianceSummaryFailureKind;\n}\n\nexport interface BuildSummaryOptions {\n sdkVersion: string;\n adcpVersion: string;\n}\n\nexport function buildComplianceSummary(result: ComplianceResult, opts: BuildSummaryOptions): ComplianceSummaryArtifact {\n const skipCauses = buildSkipCauses(result);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: result.agent_url,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: result.overall_status,\n passed: result.summary.steps_passed ?? 0,\n failed: result.summary.steps_failed ?? 0,\n skipped: result.summary.steps_skipped ?? 0,\n ...(result.summary.validations_not_applicable\n ? { validations_not_applicable: result.summary.validations_not_applicable }\n : {}),\n not_selected_count: result.summary.steps_not_selected ?? 0,\n not_selected_by_reason: result.summary.not_selected_by_reason ?? {},\n skipped_by_reason: result.summary.skipped_by_reason ?? {},\n ...(result.summary.not_selected?.length ? { not_selected: result.summary.not_selected } : {}),\n total_duration_ms: result.total_duration_ms,\n tested_at: result.tested_at,\n storyboards_executed: result.storyboards_executed ?? [],\n failures: (result.failures ?? []).map(toSummaryFailure),\n ...(skipCauses.length > 0 ? { skip_causes: skipCauses } : {}),\n };\n}\n\nfunction toSummaryFailure(f: ComplianceFailure): ComplianceSummaryFailure {\n const { reason, reason_kind } = deriveReason(f);\n return {\n track: f.track,\n storyboard_id: f.storyboard_id,\n step_id: f.step_id,\n reason,\n reason_kind,\n };\n}\n\nconst REASON_MAX_CHARS = 500;\n\nfunction deriveReason(f: ComplianceFailure): { reason: string; reason_kind: ComplianceSummaryFailureKind } {\n if (f.error) return { reason: truncate(f.error, REASON_MAX_CHARS), reason_kind: 'error' };\n if (f.validation?.description) {\n const desc = f.validation.description;\n const ptr = f.validation.json_pointer ? ` at ${f.validation.json_pointer}` : '';\n return { reason: truncate(`${desc}${ptr}`, REASON_MAX_CHARS), reason_kind: 'validation' };\n }\n if (f.expected) {\n return { reason: truncate(f.expected.split('\\n')[0]!, REASON_MAX_CHARS), reason_kind: 'expected_mismatch' };\n }\n return { reason: 'failed', reason_kind: 'unspecified' };\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// Skip-cause aggregation\n// ────────────────────────────────────────────────────────────────────────────\n\nconst SKIP_CAUSE_AFFECTED_LIMIT = 5;\n\n// Actionable canonical reasons — gaps the adopter can close. Internal\n// runner-routing reasons (peer_branch_taken, not_applicable, …) are excluded\n// because they are expected behavior, not agent deficiencies. Detailed\n// skip reasons (e.g. `controller_seeding_failed`, `capability_unsupported`,\n// `requirement_unmet` per adcp-client#1626) are normalized via\n// `DETAILED_SKIP_TO_CANONICAL` before this lookup; the runner writes\n// detailed forms to `step.skip_reason` directly per types.ts so consumers\n// of `step.skip_reason` see the more specific value.\nconst ACTIONABLE_CANONICAL_REASONS = new Set<string>([\n 'missing_tool',\n 'missing_test_controller',\n 'prerequisite_failed',\n 'unsatisfied_contract',\n 'no_phases',\n 'requirement_unmet',\n]);\n\n/**\n * True when the skip reason is something the adopter can act on.\n * Accepts both canonical `RunnerSkipReason` and detailed\n * `RunnerDetailedSkipReason` strings — detailed forms are mapped to their\n * canonical equivalent before the actionability check, so e.g.\n * `controller_seeding_failed` (detailed) → `prerequisite_failed`\n * (canonical, actionable) is correctly surfaced rather than silently\n * dropped.\n */\nfunction isActionableSkipReason(reason: string): boolean {\n if (ACTIONABLE_CANONICAL_REASONS.has(reason)) return true;\n const canonical = DETAILED_SKIP_TO_CANONICAL[reason as RunnerDetailedSkipReason];\n return canonical !== undefined && ACTIONABLE_CANONICAL_REASONS.has(canonical);\n}\n\nfunction extractMissingToolNames(warning: string): string[] {\n // Step-level: `Agent did not advertise tool \"sync_accounts\"; agent tools: [...]`\n const stepMatch = warning.match(/Agent did not advertise tool \"([^\"]+)\"/i);\n if (stepMatch) return [stepMatch[1]!];\n // Storyboard-level: `agent does not advertise any of [sync_accounts, list_accounts]`\n // Each tool is a separate gap — emit one cause per tool so dashboards see\n // the full list, not a single comma-joined \"tool name\".\n const sbMatch = warning.match(/agent does not advertise any of \\[([^\\]]+)\\]/i);\n if (sbMatch) {\n return sbMatch[1]!\n .split(/,\\s*/)\n .map(t => t.trim())\n .filter(Boolean);\n }\n return [];\n}\n\nfunction skipCauseDetail(reason: string): string {\n switch (reason) {\n case 'missing_test_controller':\n return \"agent doesn't expose comply_test_controller\";\n case 'missing_tool':\n return \"agent doesn't advertise tool\";\n case 'prerequisite_failed':\n return 'prerequisite step did not pass';\n case 'unsatisfied_contract':\n return 'test-kit contract out of scope';\n case 'no_phases':\n return 'storyboard has no executable phases';\n case 'requirement_unmet':\n return 'storyboard requires a runtime that is not available on this run';\n case 'controller_seeding_failed':\n return 'pre-flight controller seeding failed';\n case 'capability_unsupported':\n return 'agent self-declared capability unsupported';\n default:\n return reason;\n }\n}\n\nfunction buildSkipCauses(result: ComplianceResult): ComplianceSummarySkipCause[] {\n const causeMap = new Map<string, { count: number; detail: string; affectedSet: Set<string> }>();\n\n const recordCause = (causeKey: string, baseReason: string, scenarioId: string) => {\n if (!causeMap.has(causeKey)) {\n causeMap.set(causeKey, {\n count: 0,\n detail: skipCauseDetail(baseReason),\n affectedSet: new Set(),\n });\n }\n const entry = causeMap.get(causeKey)!;\n entry.count++;\n entry.affectedSet.add(scenarioId);\n };\n\n for (const track of result.tracks) {\n for (const scenario of track.scenarios) {\n const scenarioId = String(scenario.scenario);\n for (const step of scenario.steps ?? []) {\n if (!step.skipped || !step.skip_reason) continue;\n if (step.selection_reason) continue;\n if (!isActionableSkipReason(step.skip_reason)) continue;\n\n // missing_tool: sub-group by tool name. Storyboard-level matches\n // can carry multiple tools (one cause per tool); step-level matches\n // are always single-tool. extractMissingToolNames returns [] when\n // the warning text doesn't match either pattern, in which case we\n // fall through to the un-grouped reason.\n if (step.skip_reason === 'missing_tool' && step.warnings?.[0]) {\n const toolNames = extractMissingToolNames(step.warnings[0]);\n if (toolNames.length > 0) {\n for (const toolName of toolNames) {\n recordCause(`missing_tool: ${toolName}`, 'missing_tool', scenarioId);\n }\n continue;\n }\n }\n\n // requirement_unmet: sub-group by the unmet requirement name\n // (adcp-client#1626). The runner emits `step.skip.requirement`\n // which `toComplianceStep` propagates as `step.requirement` on\n // the flattened `TestStepResult`, so per-requirement aggregation\n // works without parsing the warning text.\n if (step.skip_reason === 'requirement_unmet' && step.requirement) {\n recordCause(`requirement_unmet: ${step.requirement}`, 'requirement_unmet', scenarioId);\n continue;\n }\n if (step.skip_reason === 'requirement_unmet' && step.warnings?.[0]) {\n const requiredFamily = parseMissingRequiredToolFamilyCause(step.warnings[0]);\n if (requiredFamily) {\n recordCause(requiredFamily, 'requirement_unmet', scenarioId);\n continue;\n }\n }\n\n recordCause(step.skip_reason, step.skip_reason, scenarioId);\n }\n }\n }\n\n return Array.from(causeMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([cause, { count, detail, affectedSet }]) => ({\n cause,\n count,\n detail,\n // Cap at aggregator level so JSON consumers see the same bound the\n // text/markdown renderers honor — keeps the JSON contract truthful\n // about the cap documented on `ComplianceSummarySkipCause.affected`.\n affected: Array.from(affectedSet).slice(0, SKIP_CAUSE_AFFECTED_LIMIT),\n }));\n}\n\nfunction parseMissingRequiredToolFamilyCause(warning: string): string | null {\n const match = warning.match(/^missing_required_tool_family: needs\\s+([\\s\\S]*)$/);\n if (!match) return null;\n const family = match[1]!.replace(/\\s*[;(][\\s\\S]*$/, '').trim();\n return family ? `missing_required_tool_family: needs ${family}` : null;\n}\n\n/**\n * Hard-failure statuses — runs that should never look green to CI. `partial`\n * is intentionally not in this set: it means some tracks ran silent (wired\n * but unexercised), which is a reportable observation, not a CI block.\n */\nconst HARD_FAIL_STATUSES = new Set<OverallStatus>(['failing', 'unreachable', 'auth_required']);\n\nfunction isHardFail(s: ComplianceSummaryArtifact): boolean {\n return HARD_FAIL_STATUSES.has(s.overall_status) || s.failures.length > 0;\n}\n\nfunction formatReasonCounts(counts: Partial<Record<string, number>> | undefined): string | undefined {\n if (!counts) return undefined;\n const entries = Object.entries(counts).filter(\n (entry): entry is [string, number] => typeof entry[1] === 'number' && entry[1] > 0\n );\n if (entries.length === 0) return undefined;\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([reason, count]) => `${reason}=${count}`)\n .join(', ');\n}\n\n/**\n * stderr-style summary block. Always starts with `STORYBOARD-FAIL` (kebab,\n * no spaces) on any hard-failing run, so CI scripts can `grep -q STORYBOARD-FAIL`\n * regardless of how the workflow handles the exit code. `partial` runs render\n * `STORYBOARD-PARTIAL` — distinct from both green and red so dashboards can\n * surface \"wired but unexercised\" without false-alarming CI.\n */\nexport function formatComplianceSummaryText(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n lines.push('');\n lines.push(`──── Storyboard Summary ────`);\n lines.push(`Agent: ${s.agent_url}`);\n lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);\n lines.push(`Status: ${s.overall_status}`);\n lines.push(\n `Steps: ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`Skipped: ${skippedReasons}`);\n if (s.skip_causes?.length) {\n const countWidth = String(Math.max(...s.skip_causes.map(c => c.count))).length;\n // \" [\" + countWidth chars + \"] \" — derived so Affected: aligns under the cause text\n const affectedIndent = ' '.repeat(4 + 1 + countWidth + 1 + 1);\n lines.push(` Skip causes:`);\n for (const cause of s.skip_causes) {\n const count = String(cause.count).padStart(countWidth);\n lines.push(` [${count}] ${cause.cause} — ${cause.detail}`);\n // Overflow is the difference between the total count for this cause\n // and how many distinct scenario IDs we kept after the aggregator's\n // SKIP_CAUSE_AFFECTED_LIMIT cap. The slice here is defensive — the\n // aggregator already caps, but if a future caller hands us an\n // uncapped artifact (e.g. JSON re-input from an older runner), we\n // still bound the visible list.\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText = overflow > 0 ? `${visible.join(', ')}, … ${overflow} more` : visible.join(', ');\n lines.push(`${affectedIndent}Affected: ${affectedText}`);\n }\n }\n lines.push(`Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (!isHardFail(s)) {\n if (s.overall_status === 'passing') {\n lines.push(`STORYBOARD-OK ${s.passed}/${s.passed + s.failed + s.skipped} selected steps passed`);\n } else {\n // `partial` and `silent` — some tracks were wired but not exercised.\n // Distinct marker so dashboards can surface this without lighting CI red.\n lines.push(`STORYBOARD-PARTIAL ${s.passed} steps passed, run ended ${s.overall_status}`);\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n if (s.failures.length === 0) {\n lines.push(`STORYBOARD-FAIL run ended ${s.overall_status} with no graded steps`);\n } else {\n lines.push(`STORYBOARD-FAIL ${s.failures.length} step(s):`);\n for (const f of s.failures) {\n lines.push(` - ${f.storyboard_id}/${f.step_id} [${f.track}]: ${f.reason}`);\n }\n }\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Markdown for `$GITHUB_STEP_SUMMARY`. Renders in the PR UI summary panel,\n * so reviewers see failures without opening the run log.\n */\nexport function formatComplianceSummaryMarkdown(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n const heading = !isHardFail(s)\n ? s.overall_status === 'passing'\n ? '✅ Storyboard run passed'\n : `⚠️ Storyboard run ended ${s.overall_status} (wired but partly unexercised)`\n : s.failures.length === 0\n ? `❌ Storyboard run: ended ${s.overall_status} with no graded steps`\n : `❌ Storyboard run: ${s.failures.length} failure(s)`;\n lines.push(`## ${heading}`);\n lines.push('');\n lines.push(`- **Agent:** \\`${s.agent_url}\\``);\n lines.push(`- **SDK:** \\`@adcp/sdk ${s.sdk_version}\\` (AdCP \\`${s.adcp_version}\\`)`);\n lines.push(`- **Status:** \\`${s.overall_status}\\``);\n lines.push(\n `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`- **Skipped:** ${skippedReasons}`);\n lines.push(`- **Duration:** ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (s.failures.length > 0) {\n lines.push('| Track | Storyboard | Step | Reason |');\n lines.push('| --- | --- | --- | --- |');\n for (const f of s.failures) {\n lines.push(`| \\`${f.track}\\` | \\`${f.storyboard_id}\\` | \\`${f.step_id}\\` | ${escapeTableCell(f.reason)} |`);\n }\n lines.push('');\n }\n\n if (s.skip_causes?.length) {\n const total = s.skip_causes.reduce((n, c) => n + c.count, 0);\n lines.push(`<details>`);\n lines.push(\n `<summary>Skip causes (${s.skip_causes.length} cause${s.skip_causes.length === 1 ? '' : 's'}, ${total} skipped step${total === 1 ? '' : 's'})</summary>`\n );\n lines.push('');\n lines.push('| Count | Cause | Detail | Affected |');\n lines.push('| --- | --- | --- | --- |');\n for (const cause of s.skip_causes) {\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText =\n overflow > 0\n ? `${visible.map(escapeTableCell).join(', ')}, … ${overflow} more`\n : visible.map(escapeTableCell).join(', ');\n lines.push(\n `| ${cause.count} | \\`${escapeTableCell(cause.cause)}\\` | ${escapeTableCell(cause.detail)} | ${affectedText} |`\n );\n }\n lines.push('');\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction escapeTableCell(s: string): string {\n // Escape backslashes first so a `\\|` in the input doesn't combine with\n // the pipe-escape below and produce `\\\\|` (literal backslash + raw pipe,\n // which breaks the table). Order matters: `\\` → `\\\\` then `|` → `\\|`.\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n\n/**\n * Synthesize a summary artifact when the runner itself crashed before\n * `comply()` produced a result (network down, capabilities parse error,\n * auth handshake exception). Schema-stable on the same summary artifact\n * contract so a Slack bot built against the artifact sees a valid payload\n * — rather than nothing — precisely when the agent is broken hardest.\n */\nexport interface BuildCrashSummaryOptions extends BuildSummaryOptions {\n agentUrl: string;\n error: Error | string;\n startedAt: string;\n durationMs: number;\n}\n\nexport function buildCrashSummary(opts: BuildCrashSummaryOptions): ComplianceSummaryArtifact {\n const message = opts.error instanceof Error ? opts.error.message : String(opts.error);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: opts.agentUrl,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: 'unreachable',\n passed: 0,\n failed: 1,\n skipped: 0,\n not_selected_count: 0,\n not_selected_by_reason: {},\n skipped_by_reason: {},\n total_duration_ms: opts.durationMs,\n tested_at: opts.startedAt,\n storyboards_executed: [],\n failures: [\n {\n track: 'core',\n storyboard_id: 'pre-flight',\n step_id: 'comply',\n reason: message.length > 500 ? `${message.slice(0, 499)}…` : message,\n reason_kind: 'error',\n },\n ],\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/compliance/summary.ts"],"sourcesContent":["/**\n * Narrow, schema-stable summary artifact for compliance runs.\n *\n * `formatComplianceResultsJSON` serializes the full ComplianceResult — that\n * shape evolves with the protocol. Downstream tooling (badges, Slack bots,\n * dashboards) wants a thin contract: pass/fail counts and a flat list of\n * failures with stable IDs. That's what this module provides.\n *\n * Three renderers:\n * - `buildComplianceSummary` → ComplianceSummaryArtifact (the JSON contract)\n * - `formatComplianceSummaryText` → stderr block with greppable `STORYBOARD-FAIL` prefix\n * - `formatComplianceSummaryMarkdown` → table for $GITHUB_STEP_SUMMARY\n *\n * The v2 summary separates selected-but-skipped steps from not-selected\n * exclusions. Treat unknown fields as ignorable per schema_version semantics.\n * Crash-path summaries built by `buildCrashSummary` omit `skip_causes`\n * because the runner never reached the storyboard execution phase.\n */\n\nimport type {\n ComplianceFailure,\n ComplianceNotSelectedRecord,\n ComplianceResult,\n ComplianceTrack,\n OverallStatus,\n} from './types';\nimport type { RunnerSelectionReason, RunnerSkipReason } from '../storyboard/types';\nimport { DETAILED_SKIP_TO_CANONICAL, type RunnerDetailedSkipReason } from '../storyboard/types';\n\nconst SUMMARY_SCHEMA_VERSION = 2;\n\n/**\n * A grouped skip-cause entry for the always-on summary block.\n * Only actionable causes are included — internal runner routing skips\n * (peer_branch_taken, not_applicable, etc.) are filtered out.\n */\nexport interface ComplianceSummarySkipCause {\n cause: string;\n count: number;\n detail: string;\n /** Scenario IDs affected (capped at SKIP_CAUSE_AFFECTED_LIMIT; remainder noted in text output). */\n affected: string[];\n}\n\n/**\n * Stable, schema-versioned summary. Adopters depending on this shape should\n * gate on `schema_version` and treat unknown fields as ignorable.\n */\nexport interface ComplianceSummaryArtifact {\n schema_version: number;\n agent_url: string;\n sdk_version: string;\n adcp_version: string;\n overall_status: OverallStatus;\n passed: number;\n failed: number;\n /** Failed advisory validations; does not affect the failed-step count. */\n validations_advisory_failed?: number;\n skipped: number;\n /**\n * Validation results graded `not_applicable`. Present only when non-zero so\n * CI/badge consumers can distinguish clean passes from downgraded coverage.\n */\n validations_not_applicable?: number;\n not_selected_count: number;\n not_selected_by_reason: Partial<Record<RunnerSelectionReason, number>>;\n skipped_by_reason: Partial<Record<RunnerSkipReason | string, number>>;\n not_selected?: ComplianceNotSelectedRecord[];\n total_duration_ms: number;\n tested_at: string;\n storyboards_executed: string[];\n failures: ComplianceSummaryFailure[];\n /** Actionable skip causes grouped by reason. Present only when skipped > 0. */\n skip_causes?: ComplianceSummarySkipCause[];\n}\n\n/**\n * Discriminator for `reason`. Lets a Slack bot color-code or filter without\n * regexing the reason string. Pinned at v1; new kinds are additive.\n */\nexport type ComplianceSummaryFailureKind =\n | 'error' /** The step itself raised — network, transport, runtime exception. */\n | 'validation' /** A storyboard validation check failed (schema, field_present, etc.). */\n | 'expected_mismatch' /** No structured validation; reason derived from the step's `expected:` text. */\n | 'unspecified'; /** Failure with no extractable reason — should be rare. */\n\nexport interface ComplianceSummaryFailure {\n track: ComplianceTrack;\n storyboard_id: string;\n step_id: string;\n reason: string;\n reason_kind: ComplianceSummaryFailureKind;\n}\n\nexport interface BuildSummaryOptions {\n sdkVersion: string;\n adcpVersion: string;\n}\n\nexport function buildComplianceSummary(result: ComplianceResult, opts: BuildSummaryOptions): ComplianceSummaryArtifact {\n const skipCauses = buildSkipCauses(result);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: result.agent_url,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: result.overall_status,\n passed: result.summary.steps_passed ?? 0,\n failed: result.summary.steps_failed ?? 0,\n ...(result.summary.validations_advisory_failed\n ? { validations_advisory_failed: result.summary.validations_advisory_failed }\n : {}),\n skipped: result.summary.steps_skipped ?? 0,\n ...(result.summary.validations_not_applicable\n ? { validations_not_applicable: result.summary.validations_not_applicable }\n : {}),\n not_selected_count: result.summary.steps_not_selected ?? 0,\n not_selected_by_reason: result.summary.not_selected_by_reason ?? {},\n skipped_by_reason: result.summary.skipped_by_reason ?? {},\n ...(result.summary.not_selected?.length ? { not_selected: result.summary.not_selected } : {}),\n total_duration_ms: result.total_duration_ms,\n tested_at: result.tested_at,\n storyboards_executed: result.storyboards_executed ?? [],\n failures: (result.failures ?? []).map(toSummaryFailure),\n ...(skipCauses.length > 0 ? { skip_causes: skipCauses } : {}),\n };\n}\n\nfunction toSummaryFailure(f: ComplianceFailure): ComplianceSummaryFailure {\n const { reason, reason_kind } = deriveReason(f);\n return {\n track: f.track,\n storyboard_id: f.storyboard_id,\n step_id: f.step_id,\n reason,\n reason_kind,\n };\n}\n\nconst REASON_MAX_CHARS = 500;\n\nfunction deriveReason(f: ComplianceFailure): { reason: string; reason_kind: ComplianceSummaryFailureKind } {\n if (f.error) return { reason: truncate(f.error, REASON_MAX_CHARS), reason_kind: 'error' };\n if (f.validation?.description) {\n const desc = f.validation.description;\n const ptr = f.validation.json_pointer ? ` at ${f.validation.json_pointer}` : '';\n return { reason: truncate(`${desc}${ptr}`, REASON_MAX_CHARS), reason_kind: 'validation' };\n }\n if (f.expected) {\n return { reason: truncate(f.expected.split('\\n')[0]!, REASON_MAX_CHARS), reason_kind: 'expected_mismatch' };\n }\n return { reason: 'failed', reason_kind: 'unspecified' };\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// Skip-cause aggregation\n// ────────────────────────────────────────────────────────────────────────────\n\nconst SKIP_CAUSE_AFFECTED_LIMIT = 5;\n\n// Actionable canonical reasons — gaps the adopter can close. Internal\n// runner-routing reasons (peer_branch_taken, not_applicable, …) are excluded\n// because they are expected behavior, not agent deficiencies. Detailed\n// skip reasons (e.g. `controller_seeding_failed`, `capability_unsupported`,\n// `requirement_unmet` per adcp-client#1626) are normalized via\n// `DETAILED_SKIP_TO_CANONICAL` before this lookup; the runner writes\n// detailed forms to `step.skip_reason` directly per types.ts so consumers\n// of `step.skip_reason` see the more specific value.\nconst ACTIONABLE_CANONICAL_REASONS = new Set<string>([\n 'missing_tool',\n 'missing_test_controller',\n 'prerequisite_failed',\n 'unsatisfied_contract',\n 'no_phases',\n 'requirement_unmet',\n]);\n\n/**\n * True when the skip reason is something the adopter can act on.\n * Accepts both canonical `RunnerSkipReason` and detailed\n * `RunnerDetailedSkipReason` strings — detailed forms are mapped to their\n * canonical equivalent before the actionability check, so e.g.\n * `controller_seeding_failed` (detailed) → `prerequisite_failed`\n * (canonical, actionable) is correctly surfaced rather than silently\n * dropped.\n */\nfunction isActionableSkipReason(reason: string): boolean {\n if (ACTIONABLE_CANONICAL_REASONS.has(reason)) return true;\n const canonical = DETAILED_SKIP_TO_CANONICAL[reason as RunnerDetailedSkipReason];\n return canonical !== undefined && ACTIONABLE_CANONICAL_REASONS.has(canonical);\n}\n\nfunction extractMissingToolNames(warning: string): string[] {\n // Step-level: `Agent did not advertise tool \"sync_accounts\"; agent tools: [...]`\n const stepMatch = warning.match(/Agent did not advertise tool \"([^\"]+)\"/i);\n if (stepMatch) return [stepMatch[1]!];\n // Storyboard-level: `agent does not advertise any of [sync_accounts, list_accounts]`\n // Each tool is a separate gap — emit one cause per tool so dashboards see\n // the full list, not a single comma-joined \"tool name\".\n const sbMatch = warning.match(/agent does not advertise any of \\[([^\\]]+)\\]/i);\n if (sbMatch) {\n return sbMatch[1]!\n .split(/,\\s*/)\n .map(t => t.trim())\n .filter(Boolean);\n }\n return [];\n}\n\nfunction skipCauseDetail(reason: string): string {\n switch (reason) {\n case 'missing_test_controller':\n return \"agent doesn't expose comply_test_controller\";\n case 'missing_tool':\n return \"agent doesn't advertise tool\";\n case 'prerequisite_failed':\n return 'prerequisite step did not pass';\n case 'unsatisfied_contract':\n return 'test-kit contract out of scope';\n case 'no_phases':\n return 'storyboard has no executable phases';\n case 'requirement_unmet':\n return 'storyboard requires a runtime that is not available on this run';\n case 'controller_seeding_failed':\n return 'pre-flight controller seeding failed';\n case 'capability_unsupported':\n return 'agent self-declared capability unsupported';\n default:\n return reason;\n }\n}\n\nfunction buildSkipCauses(result: ComplianceResult): ComplianceSummarySkipCause[] {\n const causeMap = new Map<string, { count: number; detail: string; affectedSet: Set<string> }>();\n\n const recordCause = (causeKey: string, baseReason: string, scenarioId: string) => {\n if (!causeMap.has(causeKey)) {\n causeMap.set(causeKey, {\n count: 0,\n detail: skipCauseDetail(baseReason),\n affectedSet: new Set(),\n });\n }\n const entry = causeMap.get(causeKey)!;\n entry.count++;\n entry.affectedSet.add(scenarioId);\n };\n\n for (const track of result.tracks) {\n for (const scenario of track.scenarios) {\n const scenarioId = String(scenario.scenario);\n for (const step of scenario.steps ?? []) {\n if (!step.skipped || !step.skip_reason) continue;\n if (step.selection_reason) continue;\n if (!isActionableSkipReason(step.skip_reason)) continue;\n\n // missing_tool: sub-group by tool name. Storyboard-level matches\n // can carry multiple tools (one cause per tool); step-level matches\n // are always single-tool. extractMissingToolNames returns [] when\n // the warning text doesn't match either pattern, in which case we\n // fall through to the un-grouped reason.\n if (step.skip_reason === 'missing_tool' && step.warnings?.[0]) {\n const toolNames = extractMissingToolNames(step.warnings[0]);\n if (toolNames.length > 0) {\n for (const toolName of toolNames) {\n recordCause(`missing_tool: ${toolName}`, 'missing_tool', scenarioId);\n }\n continue;\n }\n }\n\n // requirement_unmet: sub-group by the unmet requirement name\n // (adcp-client#1626). The runner emits `step.skip.requirement`\n // which `toComplianceStep` propagates as `step.requirement` on\n // the flattened `TestStepResult`, so per-requirement aggregation\n // works without parsing the warning text.\n if (step.skip_reason === 'requirement_unmet' && step.requirement) {\n recordCause(`requirement_unmet: ${step.requirement}`, 'requirement_unmet', scenarioId);\n continue;\n }\n if (step.skip_reason === 'requirement_unmet' && step.warnings?.[0]) {\n const requiredFamily = parseMissingRequiredToolFamilyCause(step.warnings[0]);\n if (requiredFamily) {\n recordCause(requiredFamily, 'requirement_unmet', scenarioId);\n continue;\n }\n }\n\n recordCause(step.skip_reason, step.skip_reason, scenarioId);\n }\n }\n }\n\n return Array.from(causeMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([cause, { count, detail, affectedSet }]) => ({\n cause,\n count,\n detail,\n // Cap at aggregator level so JSON consumers see the same bound the\n // text/markdown renderers honor — keeps the JSON contract truthful\n // about the cap documented on `ComplianceSummarySkipCause.affected`.\n affected: Array.from(affectedSet).slice(0, SKIP_CAUSE_AFFECTED_LIMIT),\n }));\n}\n\nfunction parseMissingRequiredToolFamilyCause(warning: string): string | null {\n const match = warning.match(/^missing_required_tool_family: needs\\s+([\\s\\S]*)$/);\n if (!match) return null;\n const family = match[1]!.replace(/\\s*[;(][\\s\\S]*$/, '').trim();\n return family ? `missing_required_tool_family: needs ${family}` : null;\n}\n\n/**\n * Hard-failure statuses — runs that should never look green to CI. `partial`\n * is intentionally not in this set: it means some tracks ran silent (wired\n * but unexercised), which is a reportable observation, not a CI block.\n */\nconst HARD_FAIL_STATUSES = new Set<OverallStatus>(['failing', 'unreachable', 'auth_required']);\n\nfunction isHardFail(s: ComplianceSummaryArtifact): boolean {\n return HARD_FAIL_STATUSES.has(s.overall_status) || s.failures.length > 0;\n}\n\nfunction formatReasonCounts(counts: Partial<Record<string, number>> | undefined): string | undefined {\n if (!counts) return undefined;\n const entries = Object.entries(counts).filter(\n (entry): entry is [string, number] => typeof entry[1] === 'number' && entry[1] > 0\n );\n if (entries.length === 0) return undefined;\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([reason, count]) => `${reason}=${count}`)\n .join(', ');\n}\n\n/**\n * stderr-style summary block. Always starts with `STORYBOARD-FAIL` (kebab,\n * no spaces) on any hard-failing run, so CI scripts can `grep -q STORYBOARD-FAIL`\n * regardless of how the workflow handles the exit code. `partial` runs render\n * `STORYBOARD-PARTIAL` — distinct from both green and red so dashboards can\n * surface \"wired but unexercised\" without false-alarming CI.\n */\nexport function formatComplianceSummaryText(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n lines.push('');\n lines.push(`──── Storyboard Summary ────`);\n lines.push(`Agent: ${s.agent_url}`);\n lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);\n lines.push(`Status: ${s.overall_status}`);\n lines.push(\n `Steps: ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`Skipped: ${skippedReasons}`);\n if (s.skip_causes?.length) {\n const countWidth = String(Math.max(...s.skip_causes.map(c => c.count))).length;\n // \" [\" + countWidth chars + \"] \" — derived so Affected: aligns under the cause text\n const affectedIndent = ' '.repeat(4 + 1 + countWidth + 1 + 1);\n lines.push(` Skip causes:`);\n for (const cause of s.skip_causes) {\n const count = String(cause.count).padStart(countWidth);\n lines.push(` [${count}] ${cause.cause} — ${cause.detail}`);\n // Overflow is the difference between the total count for this cause\n // and how many distinct scenario IDs we kept after the aggregator's\n // SKIP_CAUSE_AFFECTED_LIMIT cap. The slice here is defensive — the\n // aggregator already caps, but if a future caller hands us an\n // uncapped artifact (e.g. JSON re-input from an older runner), we\n // still bound the visible list.\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText = overflow > 0 ? `${visible.join(', ')}, … ${overflow} more` : visible.join(', ');\n lines.push(`${affectedIndent}Affected: ${affectedText}`);\n }\n }\n lines.push(`Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (!isHardFail(s)) {\n if (s.overall_status === 'passing') {\n lines.push(`STORYBOARD-OK ${s.passed}/${s.passed + s.failed + s.skipped} selected steps passed`);\n } else {\n // `partial` and `silent` — some tracks were wired but not exercised.\n // Distinct marker so dashboards can surface this without lighting CI red.\n lines.push(`STORYBOARD-PARTIAL ${s.passed} steps passed, run ended ${s.overall_status}`);\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n if (s.failures.length === 0) {\n lines.push(`STORYBOARD-FAIL run ended ${s.overall_status} with no graded steps`);\n } else {\n lines.push(`STORYBOARD-FAIL ${s.failures.length} step(s):`);\n for (const f of s.failures) {\n lines.push(` - ${f.storyboard_id}/${f.step_id} [${f.track}]: ${f.reason}`);\n }\n }\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Markdown for `$GITHUB_STEP_SUMMARY`. Renders in the PR UI summary panel,\n * so reviewers see failures without opening the run log.\n */\nexport function formatComplianceSummaryMarkdown(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n const heading = !isHardFail(s)\n ? s.overall_status === 'passing'\n ? '✅ Storyboard run passed'\n : `⚠️ Storyboard run ended ${s.overall_status} (wired but partly unexercised)`\n : s.failures.length === 0\n ? `❌ Storyboard run: ended ${s.overall_status} with no graded steps`\n : `❌ Storyboard run: ${s.failures.length} failure(s)`;\n lines.push(`## ${heading}`);\n lines.push('');\n lines.push(`- **Agent:** \\`${s.agent_url}\\``);\n lines.push(`- **SDK:** \\`@adcp/sdk ${s.sdk_version}\\` (AdCP \\`${s.adcp_version}\\`)`);\n lines.push(`- **Status:** \\`${s.overall_status}\\``);\n lines.push(\n `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`- **Skipped:** ${skippedReasons}`);\n lines.push(`- **Duration:** ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (s.failures.length > 0) {\n lines.push('| Track | Storyboard | Step | Reason |');\n lines.push('| --- | --- | --- | --- |');\n for (const f of s.failures) {\n lines.push(`| \\`${f.track}\\` | \\`${f.storyboard_id}\\` | \\`${f.step_id}\\` | ${escapeTableCell(f.reason)} |`);\n }\n lines.push('');\n }\n\n if (s.skip_causes?.length) {\n const total = s.skip_causes.reduce((n, c) => n + c.count, 0);\n lines.push(`<details>`);\n lines.push(\n `<summary>Skip causes (${s.skip_causes.length} cause${s.skip_causes.length === 1 ? '' : 's'}, ${total} skipped step${total === 1 ? '' : 's'})</summary>`\n );\n lines.push('');\n lines.push('| Count | Cause | Detail | Affected |');\n lines.push('| --- | --- | --- | --- |');\n for (const cause of s.skip_causes) {\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText =\n overflow > 0\n ? `${visible.map(escapeTableCell).join(', ')}, … ${overflow} more`\n : visible.map(escapeTableCell).join(', ');\n lines.push(\n `| ${cause.count} | \\`${escapeTableCell(cause.cause)}\\` | ${escapeTableCell(cause.detail)} | ${affectedText} |`\n );\n }\n lines.push('');\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction escapeTableCell(s: string): string {\n // Escape backslashes first so a `\\|` in the input doesn't combine with\n // the pipe-escape below and produce `\\\\|` (literal backslash + raw pipe,\n // which breaks the table). Order matters: `\\` → `\\\\` then `|` → `\\|`.\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n\n/**\n * Synthesize a summary artifact when the runner itself crashed before\n * `comply()` produced a result (network down, capabilities parse error,\n * auth handshake exception). Schema-stable on the same summary artifact\n * contract so a Slack bot built against the artifact sees a valid payload\n * — rather than nothing — precisely when the agent is broken hardest.\n */\nexport interface BuildCrashSummaryOptions extends BuildSummaryOptions {\n agentUrl: string;\n error: Error | string;\n startedAt: string;\n durationMs: number;\n}\n\nexport function buildCrashSummary(opts: BuildCrashSummaryOptions): ComplianceSummaryArtifact {\n const message = opts.error instanceof Error ? opts.error.message : String(opts.error);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: opts.agentUrl,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: 'unreachable',\n passed: 0,\n failed: 1,\n skipped: 0,\n not_selected_count: 0,\n not_selected_by_reason: {},\n skipped_by_reason: {},\n total_duration_ms: opts.durationMs,\n tested_at: opts.startedAt,\n storyboards_executed: [],\n failures: [\n {\n track: 'core',\n storyboard_id: 'pre-flight',\n step_id: 'comply',\n reason: message.length > 500 ? `${message.slice(0, 499)}…` : message,\n reason_kind: 'error',\n },\n ],\n };\n}\n"],"mappings":"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","names":[]}
@@ -10,6 +10,7 @@ function buildComplianceSummary(result, opts) {
10
10
  overall_status: result.overall_status,
11
11
  passed: result.summary.steps_passed ?? 0,
12
12
  failed: result.summary.steps_failed ?? 0,
13
+ ...result.summary.validations_advisory_failed ? { validations_advisory_failed: result.summary.validations_advisory_failed } : {},
13
14
  skipped: result.summary.steps_skipped ?? 0,
14
15
  ...result.summary.validations_not_applicable ? { validations_not_applicable: result.summary.validations_not_applicable } : {},
15
16
  not_selected_count: result.summary.steps_not_selected ?? 0,
@@ -175,7 +176,7 @@ function formatComplianceSummaryText(s) {
175
176
  lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);
176
177
  lines.push(`Status: ${s.overall_status}`);
177
178
  lines.push(
178
- `Steps: ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
179
+ `Steps: ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
179
180
  );
180
181
  const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);
181
182
  if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);
@@ -225,7 +226,7 @@ function formatComplianceSummaryMarkdown(s) {
225
226
  lines.push(`- **SDK:** \`@adcp/sdk ${s.sdk_version}\` (AdCP \`${s.adcp_version}\`)`);
226
227
  lines.push(`- **Status:** \`${s.overall_status}\``);
227
228
  lines.push(
228
- `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
229
+ `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`
229
230
  );
230
231
  const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);
231
232
  if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/compliance/summary.ts"],"sourcesContent":["/**\n * Narrow, schema-stable summary artifact for compliance runs.\n *\n * `formatComplianceResultsJSON` serializes the full ComplianceResult — that\n * shape evolves with the protocol. Downstream tooling (badges, Slack bots,\n * dashboards) wants a thin contract: pass/fail counts and a flat list of\n * failures with stable IDs. That's what this module provides.\n *\n * Three renderers:\n * - `buildComplianceSummary` → ComplianceSummaryArtifact (the JSON contract)\n * - `formatComplianceSummaryText` → stderr block with greppable `STORYBOARD-FAIL` prefix\n * - `formatComplianceSummaryMarkdown` → table for $GITHUB_STEP_SUMMARY\n *\n * The v2 summary separates selected-but-skipped steps from not-selected\n * exclusions. Treat unknown fields as ignorable per schema_version semantics.\n * Crash-path summaries built by `buildCrashSummary` omit `skip_causes`\n * because the runner never reached the storyboard execution phase.\n */\n\nimport type {\n ComplianceFailure,\n ComplianceNotSelectedRecord,\n ComplianceResult,\n ComplianceTrack,\n OverallStatus,\n} from './types';\nimport type { RunnerSelectionReason, RunnerSkipReason } from '../storyboard/types';\nimport { DETAILED_SKIP_TO_CANONICAL, type RunnerDetailedSkipReason } from '../storyboard/types';\n\nconst SUMMARY_SCHEMA_VERSION = 2;\n\n/**\n * A grouped skip-cause entry for the always-on summary block.\n * Only actionable causes are included — internal runner routing skips\n * (peer_branch_taken, not_applicable, etc.) are filtered out.\n */\nexport interface ComplianceSummarySkipCause {\n cause: string;\n count: number;\n detail: string;\n /** Scenario IDs affected (capped at SKIP_CAUSE_AFFECTED_LIMIT; remainder noted in text output). */\n affected: string[];\n}\n\n/**\n * Stable, schema-versioned summary. Adopters depending on this shape should\n * gate on `schema_version` and treat unknown fields as ignorable.\n */\nexport interface ComplianceSummaryArtifact {\n schema_version: number;\n agent_url: string;\n sdk_version: string;\n adcp_version: string;\n overall_status: OverallStatus;\n passed: number;\n failed: number;\n skipped: number;\n /**\n * Validation results graded `not_applicable`. Present only when non-zero so\n * CI/badge consumers can distinguish clean passes from downgraded coverage.\n */\n validations_not_applicable?: number;\n not_selected_count: number;\n not_selected_by_reason: Partial<Record<RunnerSelectionReason, number>>;\n skipped_by_reason: Partial<Record<RunnerSkipReason | string, number>>;\n not_selected?: ComplianceNotSelectedRecord[];\n total_duration_ms: number;\n tested_at: string;\n storyboards_executed: string[];\n failures: ComplianceSummaryFailure[];\n /** Actionable skip causes grouped by reason. Present only when skipped > 0. */\n skip_causes?: ComplianceSummarySkipCause[];\n}\n\n/**\n * Discriminator for `reason`. Lets a Slack bot color-code or filter without\n * regexing the reason string. Pinned at v1; new kinds are additive.\n */\nexport type ComplianceSummaryFailureKind =\n | 'error' /** The step itself raised — network, transport, runtime exception. */\n | 'validation' /** A storyboard validation check failed (schema, field_present, etc.). */\n | 'expected_mismatch' /** No structured validation; reason derived from the step's `expected:` text. */\n | 'unspecified'; /** Failure with no extractable reason — should be rare. */\n\nexport interface ComplianceSummaryFailure {\n track: ComplianceTrack;\n storyboard_id: string;\n step_id: string;\n reason: string;\n reason_kind: ComplianceSummaryFailureKind;\n}\n\nexport interface BuildSummaryOptions {\n sdkVersion: string;\n adcpVersion: string;\n}\n\nexport function buildComplianceSummary(result: ComplianceResult, opts: BuildSummaryOptions): ComplianceSummaryArtifact {\n const skipCauses = buildSkipCauses(result);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: result.agent_url,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: result.overall_status,\n passed: result.summary.steps_passed ?? 0,\n failed: result.summary.steps_failed ?? 0,\n skipped: result.summary.steps_skipped ?? 0,\n ...(result.summary.validations_not_applicable\n ? { validations_not_applicable: result.summary.validations_not_applicable }\n : {}),\n not_selected_count: result.summary.steps_not_selected ?? 0,\n not_selected_by_reason: result.summary.not_selected_by_reason ?? {},\n skipped_by_reason: result.summary.skipped_by_reason ?? {},\n ...(result.summary.not_selected?.length ? { not_selected: result.summary.not_selected } : {}),\n total_duration_ms: result.total_duration_ms,\n tested_at: result.tested_at,\n storyboards_executed: result.storyboards_executed ?? [],\n failures: (result.failures ?? []).map(toSummaryFailure),\n ...(skipCauses.length > 0 ? { skip_causes: skipCauses } : {}),\n };\n}\n\nfunction toSummaryFailure(f: ComplianceFailure): ComplianceSummaryFailure {\n const { reason, reason_kind } = deriveReason(f);\n return {\n track: f.track,\n storyboard_id: f.storyboard_id,\n step_id: f.step_id,\n reason,\n reason_kind,\n };\n}\n\nconst REASON_MAX_CHARS = 500;\n\nfunction deriveReason(f: ComplianceFailure): { reason: string; reason_kind: ComplianceSummaryFailureKind } {\n if (f.error) return { reason: truncate(f.error, REASON_MAX_CHARS), reason_kind: 'error' };\n if (f.validation?.description) {\n const desc = f.validation.description;\n const ptr = f.validation.json_pointer ? ` at ${f.validation.json_pointer}` : '';\n return { reason: truncate(`${desc}${ptr}`, REASON_MAX_CHARS), reason_kind: 'validation' };\n }\n if (f.expected) {\n return { reason: truncate(f.expected.split('\\n')[0]!, REASON_MAX_CHARS), reason_kind: 'expected_mismatch' };\n }\n return { reason: 'failed', reason_kind: 'unspecified' };\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// Skip-cause aggregation\n// ────────────────────────────────────────────────────────────────────────────\n\nconst SKIP_CAUSE_AFFECTED_LIMIT = 5;\n\n// Actionable canonical reasons — gaps the adopter can close. Internal\n// runner-routing reasons (peer_branch_taken, not_applicable, …) are excluded\n// because they are expected behavior, not agent deficiencies. Detailed\n// skip reasons (e.g. `controller_seeding_failed`, `capability_unsupported`,\n// `requirement_unmet` per adcp-client#1626) are normalized via\n// `DETAILED_SKIP_TO_CANONICAL` before this lookup; the runner writes\n// detailed forms to `step.skip_reason` directly per types.ts so consumers\n// of `step.skip_reason` see the more specific value.\nconst ACTIONABLE_CANONICAL_REASONS = new Set<string>([\n 'missing_tool',\n 'missing_test_controller',\n 'prerequisite_failed',\n 'unsatisfied_contract',\n 'no_phases',\n 'requirement_unmet',\n]);\n\n/**\n * True when the skip reason is something the adopter can act on.\n * Accepts both canonical `RunnerSkipReason` and detailed\n * `RunnerDetailedSkipReason` strings — detailed forms are mapped to their\n * canonical equivalent before the actionability check, so e.g.\n * `controller_seeding_failed` (detailed) → `prerequisite_failed`\n * (canonical, actionable) is correctly surfaced rather than silently\n * dropped.\n */\nfunction isActionableSkipReason(reason: string): boolean {\n if (ACTIONABLE_CANONICAL_REASONS.has(reason)) return true;\n const canonical = DETAILED_SKIP_TO_CANONICAL[reason as RunnerDetailedSkipReason];\n return canonical !== undefined && ACTIONABLE_CANONICAL_REASONS.has(canonical);\n}\n\nfunction extractMissingToolNames(warning: string): string[] {\n // Step-level: `Agent did not advertise tool \"sync_accounts\"; agent tools: [...]`\n const stepMatch = warning.match(/Agent did not advertise tool \"([^\"]+)\"/i);\n if (stepMatch) return [stepMatch[1]!];\n // Storyboard-level: `agent does not advertise any of [sync_accounts, list_accounts]`\n // Each tool is a separate gap — emit one cause per tool so dashboards see\n // the full list, not a single comma-joined \"tool name\".\n const sbMatch = warning.match(/agent does not advertise any of \\[([^\\]]+)\\]/i);\n if (sbMatch) {\n return sbMatch[1]!\n .split(/,\\s*/)\n .map(t => t.trim())\n .filter(Boolean);\n }\n return [];\n}\n\nfunction skipCauseDetail(reason: string): string {\n switch (reason) {\n case 'missing_test_controller':\n return \"agent doesn't expose comply_test_controller\";\n case 'missing_tool':\n return \"agent doesn't advertise tool\";\n case 'prerequisite_failed':\n return 'prerequisite step did not pass';\n case 'unsatisfied_contract':\n return 'test-kit contract out of scope';\n case 'no_phases':\n return 'storyboard has no executable phases';\n case 'requirement_unmet':\n return 'storyboard requires a runtime that is not available on this run';\n case 'controller_seeding_failed':\n return 'pre-flight controller seeding failed';\n case 'capability_unsupported':\n return 'agent self-declared capability unsupported';\n default:\n return reason;\n }\n}\n\nfunction buildSkipCauses(result: ComplianceResult): ComplianceSummarySkipCause[] {\n const causeMap = new Map<string, { count: number; detail: string; affectedSet: Set<string> }>();\n\n const recordCause = (causeKey: string, baseReason: string, scenarioId: string) => {\n if (!causeMap.has(causeKey)) {\n causeMap.set(causeKey, {\n count: 0,\n detail: skipCauseDetail(baseReason),\n affectedSet: new Set(),\n });\n }\n const entry = causeMap.get(causeKey)!;\n entry.count++;\n entry.affectedSet.add(scenarioId);\n };\n\n for (const track of result.tracks) {\n for (const scenario of track.scenarios) {\n const scenarioId = String(scenario.scenario);\n for (const step of scenario.steps ?? []) {\n if (!step.skipped || !step.skip_reason) continue;\n if (step.selection_reason) continue;\n if (!isActionableSkipReason(step.skip_reason)) continue;\n\n // missing_tool: sub-group by tool name. Storyboard-level matches\n // can carry multiple tools (one cause per tool); step-level matches\n // are always single-tool. extractMissingToolNames returns [] when\n // the warning text doesn't match either pattern, in which case we\n // fall through to the un-grouped reason.\n if (step.skip_reason === 'missing_tool' && step.warnings?.[0]) {\n const toolNames = extractMissingToolNames(step.warnings[0]);\n if (toolNames.length > 0) {\n for (const toolName of toolNames) {\n recordCause(`missing_tool: ${toolName}`, 'missing_tool', scenarioId);\n }\n continue;\n }\n }\n\n // requirement_unmet: sub-group by the unmet requirement name\n // (adcp-client#1626). The runner emits `step.skip.requirement`\n // which `toComplianceStep` propagates as `step.requirement` on\n // the flattened `TestStepResult`, so per-requirement aggregation\n // works without parsing the warning text.\n if (step.skip_reason === 'requirement_unmet' && step.requirement) {\n recordCause(`requirement_unmet: ${step.requirement}`, 'requirement_unmet', scenarioId);\n continue;\n }\n if (step.skip_reason === 'requirement_unmet' && step.warnings?.[0]) {\n const requiredFamily = parseMissingRequiredToolFamilyCause(step.warnings[0]);\n if (requiredFamily) {\n recordCause(requiredFamily, 'requirement_unmet', scenarioId);\n continue;\n }\n }\n\n recordCause(step.skip_reason, step.skip_reason, scenarioId);\n }\n }\n }\n\n return Array.from(causeMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([cause, { count, detail, affectedSet }]) => ({\n cause,\n count,\n detail,\n // Cap at aggregator level so JSON consumers see the same bound the\n // text/markdown renderers honor — keeps the JSON contract truthful\n // about the cap documented on `ComplianceSummarySkipCause.affected`.\n affected: Array.from(affectedSet).slice(0, SKIP_CAUSE_AFFECTED_LIMIT),\n }));\n}\n\nfunction parseMissingRequiredToolFamilyCause(warning: string): string | null {\n const match = warning.match(/^missing_required_tool_family: needs\\s+([\\s\\S]*)$/);\n if (!match) return null;\n const family = match[1]!.replace(/\\s*[;(][\\s\\S]*$/, '').trim();\n return family ? `missing_required_tool_family: needs ${family}` : null;\n}\n\n/**\n * Hard-failure statuses — runs that should never look green to CI. `partial`\n * is intentionally not in this set: it means some tracks ran silent (wired\n * but unexercised), which is a reportable observation, not a CI block.\n */\nconst HARD_FAIL_STATUSES = new Set<OverallStatus>(['failing', 'unreachable', 'auth_required']);\n\nfunction isHardFail(s: ComplianceSummaryArtifact): boolean {\n return HARD_FAIL_STATUSES.has(s.overall_status) || s.failures.length > 0;\n}\n\nfunction formatReasonCounts(counts: Partial<Record<string, number>> | undefined): string | undefined {\n if (!counts) return undefined;\n const entries = Object.entries(counts).filter(\n (entry): entry is [string, number] => typeof entry[1] === 'number' && entry[1] > 0\n );\n if (entries.length === 0) return undefined;\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([reason, count]) => `${reason}=${count}`)\n .join(', ');\n}\n\n/**\n * stderr-style summary block. Always starts with `STORYBOARD-FAIL` (kebab,\n * no spaces) on any hard-failing run, so CI scripts can `grep -q STORYBOARD-FAIL`\n * regardless of how the workflow handles the exit code. `partial` runs render\n * `STORYBOARD-PARTIAL` — distinct from both green and red so dashboards can\n * surface \"wired but unexercised\" without false-alarming CI.\n */\nexport function formatComplianceSummaryText(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n lines.push('');\n lines.push(`──── Storyboard Summary ────`);\n lines.push(`Agent: ${s.agent_url}`);\n lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);\n lines.push(`Status: ${s.overall_status}`);\n lines.push(\n `Steps: ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`Skipped: ${skippedReasons}`);\n if (s.skip_causes?.length) {\n const countWidth = String(Math.max(...s.skip_causes.map(c => c.count))).length;\n // \" [\" + countWidth chars + \"] \" — derived so Affected: aligns under the cause text\n const affectedIndent = ' '.repeat(4 + 1 + countWidth + 1 + 1);\n lines.push(` Skip causes:`);\n for (const cause of s.skip_causes) {\n const count = String(cause.count).padStart(countWidth);\n lines.push(` [${count}] ${cause.cause} — ${cause.detail}`);\n // Overflow is the difference between the total count for this cause\n // and how many distinct scenario IDs we kept after the aggregator's\n // SKIP_CAUSE_AFFECTED_LIMIT cap. The slice here is defensive — the\n // aggregator already caps, but if a future caller hands us an\n // uncapped artifact (e.g. JSON re-input from an older runner), we\n // still bound the visible list.\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText = overflow > 0 ? `${visible.join(', ')}, … ${overflow} more` : visible.join(', ');\n lines.push(`${affectedIndent}Affected: ${affectedText}`);\n }\n }\n lines.push(`Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (!isHardFail(s)) {\n if (s.overall_status === 'passing') {\n lines.push(`STORYBOARD-OK ${s.passed}/${s.passed + s.failed + s.skipped} selected steps passed`);\n } else {\n // `partial` and `silent` — some tracks were wired but not exercised.\n // Distinct marker so dashboards can surface this without lighting CI red.\n lines.push(`STORYBOARD-PARTIAL ${s.passed} steps passed, run ended ${s.overall_status}`);\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n if (s.failures.length === 0) {\n lines.push(`STORYBOARD-FAIL run ended ${s.overall_status} with no graded steps`);\n } else {\n lines.push(`STORYBOARD-FAIL ${s.failures.length} step(s):`);\n for (const f of s.failures) {\n lines.push(` - ${f.storyboard_id}/${f.step_id} [${f.track}]: ${f.reason}`);\n }\n }\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Markdown for `$GITHUB_STEP_SUMMARY`. Renders in the PR UI summary panel,\n * so reviewers see failures without opening the run log.\n */\nexport function formatComplianceSummaryMarkdown(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n const heading = !isHardFail(s)\n ? s.overall_status === 'passing'\n ? '✅ Storyboard run passed'\n : `⚠️ Storyboard run ended ${s.overall_status} (wired but partly unexercised)`\n : s.failures.length === 0\n ? `❌ Storyboard run: ended ${s.overall_status} with no graded steps`\n : `❌ Storyboard run: ${s.failures.length} failure(s)`;\n lines.push(`## ${heading}`);\n lines.push('');\n lines.push(`- **Agent:** \\`${s.agent_url}\\``);\n lines.push(`- **SDK:** \\`@adcp/sdk ${s.sdk_version}\\` (AdCP \\`${s.adcp_version}\\`)`);\n lines.push(`- **Status:** \\`${s.overall_status}\\``);\n lines.push(\n `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`- **Skipped:** ${skippedReasons}`);\n lines.push(`- **Duration:** ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (s.failures.length > 0) {\n lines.push('| Track | Storyboard | Step | Reason |');\n lines.push('| --- | --- | --- | --- |');\n for (const f of s.failures) {\n lines.push(`| \\`${f.track}\\` | \\`${f.storyboard_id}\\` | \\`${f.step_id}\\` | ${escapeTableCell(f.reason)} |`);\n }\n lines.push('');\n }\n\n if (s.skip_causes?.length) {\n const total = s.skip_causes.reduce((n, c) => n + c.count, 0);\n lines.push(`<details>`);\n lines.push(\n `<summary>Skip causes (${s.skip_causes.length} cause${s.skip_causes.length === 1 ? '' : 's'}, ${total} skipped step${total === 1 ? '' : 's'})</summary>`\n );\n lines.push('');\n lines.push('| Count | Cause | Detail | Affected |');\n lines.push('| --- | --- | --- | --- |');\n for (const cause of s.skip_causes) {\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText =\n overflow > 0\n ? `${visible.map(escapeTableCell).join(', ')}, … ${overflow} more`\n : visible.map(escapeTableCell).join(', ');\n lines.push(\n `| ${cause.count} | \\`${escapeTableCell(cause.cause)}\\` | ${escapeTableCell(cause.detail)} | ${affectedText} |`\n );\n }\n lines.push('');\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction escapeTableCell(s: string): string {\n // Escape backslashes first so a `\\|` in the input doesn't combine with\n // the pipe-escape below and produce `\\\\|` (literal backslash + raw pipe,\n // which breaks the table). Order matters: `\\` → `\\\\` then `|` → `\\|`.\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n\n/**\n * Synthesize a summary artifact when the runner itself crashed before\n * `comply()` produced a result (network down, capabilities parse error,\n * auth handshake exception). Schema-stable on the same summary artifact\n * contract so a Slack bot built against the artifact sees a valid payload\n * — rather than nothing — precisely when the agent is broken hardest.\n */\nexport interface BuildCrashSummaryOptions extends BuildSummaryOptions {\n agentUrl: string;\n error: Error | string;\n startedAt: string;\n durationMs: number;\n}\n\nexport function buildCrashSummary(opts: BuildCrashSummaryOptions): ComplianceSummaryArtifact {\n const message = opts.error instanceof Error ? opts.error.message : String(opts.error);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: opts.agentUrl,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: 'unreachable',\n passed: 0,\n failed: 1,\n skipped: 0,\n not_selected_count: 0,\n not_selected_by_reason: {},\n skipped_by_reason: {},\n total_duration_ms: opts.durationMs,\n tested_at: opts.startedAt,\n storyboards_executed: [],\n failures: [\n {\n track: 'core',\n storyboard_id: 'pre-flight',\n step_id: 'comply',\n reason: message.length > 500 ? `${message.slice(0, 499)}…` : message,\n reason_kind: 'error',\n },\n ],\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/compliance/summary.ts"],"sourcesContent":["/**\n * Narrow, schema-stable summary artifact for compliance runs.\n *\n * `formatComplianceResultsJSON` serializes the full ComplianceResult — that\n * shape evolves with the protocol. Downstream tooling (badges, Slack bots,\n * dashboards) wants a thin contract: pass/fail counts and a flat list of\n * failures with stable IDs. That's what this module provides.\n *\n * Three renderers:\n * - `buildComplianceSummary` → ComplianceSummaryArtifact (the JSON contract)\n * - `formatComplianceSummaryText` → stderr block with greppable `STORYBOARD-FAIL` prefix\n * - `formatComplianceSummaryMarkdown` → table for $GITHUB_STEP_SUMMARY\n *\n * The v2 summary separates selected-but-skipped steps from not-selected\n * exclusions. Treat unknown fields as ignorable per schema_version semantics.\n * Crash-path summaries built by `buildCrashSummary` omit `skip_causes`\n * because the runner never reached the storyboard execution phase.\n */\n\nimport type {\n ComplianceFailure,\n ComplianceNotSelectedRecord,\n ComplianceResult,\n ComplianceTrack,\n OverallStatus,\n} from './types';\nimport type { RunnerSelectionReason, RunnerSkipReason } from '../storyboard/types';\nimport { DETAILED_SKIP_TO_CANONICAL, type RunnerDetailedSkipReason } from '../storyboard/types';\n\nconst SUMMARY_SCHEMA_VERSION = 2;\n\n/**\n * A grouped skip-cause entry for the always-on summary block.\n * Only actionable causes are included — internal runner routing skips\n * (peer_branch_taken, not_applicable, etc.) are filtered out.\n */\nexport interface ComplianceSummarySkipCause {\n cause: string;\n count: number;\n detail: string;\n /** Scenario IDs affected (capped at SKIP_CAUSE_AFFECTED_LIMIT; remainder noted in text output). */\n affected: string[];\n}\n\n/**\n * Stable, schema-versioned summary. Adopters depending on this shape should\n * gate on `schema_version` and treat unknown fields as ignorable.\n */\nexport interface ComplianceSummaryArtifact {\n schema_version: number;\n agent_url: string;\n sdk_version: string;\n adcp_version: string;\n overall_status: OverallStatus;\n passed: number;\n failed: number;\n /** Failed advisory validations; does not affect the failed-step count. */\n validations_advisory_failed?: number;\n skipped: number;\n /**\n * Validation results graded `not_applicable`. Present only when non-zero so\n * CI/badge consumers can distinguish clean passes from downgraded coverage.\n */\n validations_not_applicable?: number;\n not_selected_count: number;\n not_selected_by_reason: Partial<Record<RunnerSelectionReason, number>>;\n skipped_by_reason: Partial<Record<RunnerSkipReason | string, number>>;\n not_selected?: ComplianceNotSelectedRecord[];\n total_duration_ms: number;\n tested_at: string;\n storyboards_executed: string[];\n failures: ComplianceSummaryFailure[];\n /** Actionable skip causes grouped by reason. Present only when skipped > 0. */\n skip_causes?: ComplianceSummarySkipCause[];\n}\n\n/**\n * Discriminator for `reason`. Lets a Slack bot color-code or filter without\n * regexing the reason string. Pinned at v1; new kinds are additive.\n */\nexport type ComplianceSummaryFailureKind =\n | 'error' /** The step itself raised — network, transport, runtime exception. */\n | 'validation' /** A storyboard validation check failed (schema, field_present, etc.). */\n | 'expected_mismatch' /** No structured validation; reason derived from the step's `expected:` text. */\n | 'unspecified'; /** Failure with no extractable reason — should be rare. */\n\nexport interface ComplianceSummaryFailure {\n track: ComplianceTrack;\n storyboard_id: string;\n step_id: string;\n reason: string;\n reason_kind: ComplianceSummaryFailureKind;\n}\n\nexport interface BuildSummaryOptions {\n sdkVersion: string;\n adcpVersion: string;\n}\n\nexport function buildComplianceSummary(result: ComplianceResult, opts: BuildSummaryOptions): ComplianceSummaryArtifact {\n const skipCauses = buildSkipCauses(result);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: result.agent_url,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: result.overall_status,\n passed: result.summary.steps_passed ?? 0,\n failed: result.summary.steps_failed ?? 0,\n ...(result.summary.validations_advisory_failed\n ? { validations_advisory_failed: result.summary.validations_advisory_failed }\n : {}),\n skipped: result.summary.steps_skipped ?? 0,\n ...(result.summary.validations_not_applicable\n ? { validations_not_applicable: result.summary.validations_not_applicable }\n : {}),\n not_selected_count: result.summary.steps_not_selected ?? 0,\n not_selected_by_reason: result.summary.not_selected_by_reason ?? {},\n skipped_by_reason: result.summary.skipped_by_reason ?? {},\n ...(result.summary.not_selected?.length ? { not_selected: result.summary.not_selected } : {}),\n total_duration_ms: result.total_duration_ms,\n tested_at: result.tested_at,\n storyboards_executed: result.storyboards_executed ?? [],\n failures: (result.failures ?? []).map(toSummaryFailure),\n ...(skipCauses.length > 0 ? { skip_causes: skipCauses } : {}),\n };\n}\n\nfunction toSummaryFailure(f: ComplianceFailure): ComplianceSummaryFailure {\n const { reason, reason_kind } = deriveReason(f);\n return {\n track: f.track,\n storyboard_id: f.storyboard_id,\n step_id: f.step_id,\n reason,\n reason_kind,\n };\n}\n\nconst REASON_MAX_CHARS = 500;\n\nfunction deriveReason(f: ComplianceFailure): { reason: string; reason_kind: ComplianceSummaryFailureKind } {\n if (f.error) return { reason: truncate(f.error, REASON_MAX_CHARS), reason_kind: 'error' };\n if (f.validation?.description) {\n const desc = f.validation.description;\n const ptr = f.validation.json_pointer ? ` at ${f.validation.json_pointer}` : '';\n return { reason: truncate(`${desc}${ptr}`, REASON_MAX_CHARS), reason_kind: 'validation' };\n }\n if (f.expected) {\n return { reason: truncate(f.expected.split('\\n')[0]!, REASON_MAX_CHARS), reason_kind: 'expected_mismatch' };\n }\n return { reason: 'failed', reason_kind: 'unspecified' };\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? `${s.slice(0, max - 1)}…` : s;\n}\n\n// ────────────────────────────────────────────────────────────────────────────\n// Skip-cause aggregation\n// ────────────────────────────────────────────────────────────────────────────\n\nconst SKIP_CAUSE_AFFECTED_LIMIT = 5;\n\n// Actionable canonical reasons — gaps the adopter can close. Internal\n// runner-routing reasons (peer_branch_taken, not_applicable, …) are excluded\n// because they are expected behavior, not agent deficiencies. Detailed\n// skip reasons (e.g. `controller_seeding_failed`, `capability_unsupported`,\n// `requirement_unmet` per adcp-client#1626) are normalized via\n// `DETAILED_SKIP_TO_CANONICAL` before this lookup; the runner writes\n// detailed forms to `step.skip_reason` directly per types.ts so consumers\n// of `step.skip_reason` see the more specific value.\nconst ACTIONABLE_CANONICAL_REASONS = new Set<string>([\n 'missing_tool',\n 'missing_test_controller',\n 'prerequisite_failed',\n 'unsatisfied_contract',\n 'no_phases',\n 'requirement_unmet',\n]);\n\n/**\n * True when the skip reason is something the adopter can act on.\n * Accepts both canonical `RunnerSkipReason` and detailed\n * `RunnerDetailedSkipReason` strings — detailed forms are mapped to their\n * canonical equivalent before the actionability check, so e.g.\n * `controller_seeding_failed` (detailed) → `prerequisite_failed`\n * (canonical, actionable) is correctly surfaced rather than silently\n * dropped.\n */\nfunction isActionableSkipReason(reason: string): boolean {\n if (ACTIONABLE_CANONICAL_REASONS.has(reason)) return true;\n const canonical = DETAILED_SKIP_TO_CANONICAL[reason as RunnerDetailedSkipReason];\n return canonical !== undefined && ACTIONABLE_CANONICAL_REASONS.has(canonical);\n}\n\nfunction extractMissingToolNames(warning: string): string[] {\n // Step-level: `Agent did not advertise tool \"sync_accounts\"; agent tools: [...]`\n const stepMatch = warning.match(/Agent did not advertise tool \"([^\"]+)\"/i);\n if (stepMatch) return [stepMatch[1]!];\n // Storyboard-level: `agent does not advertise any of [sync_accounts, list_accounts]`\n // Each tool is a separate gap — emit one cause per tool so dashboards see\n // the full list, not a single comma-joined \"tool name\".\n const sbMatch = warning.match(/agent does not advertise any of \\[([^\\]]+)\\]/i);\n if (sbMatch) {\n return sbMatch[1]!\n .split(/,\\s*/)\n .map(t => t.trim())\n .filter(Boolean);\n }\n return [];\n}\n\nfunction skipCauseDetail(reason: string): string {\n switch (reason) {\n case 'missing_test_controller':\n return \"agent doesn't expose comply_test_controller\";\n case 'missing_tool':\n return \"agent doesn't advertise tool\";\n case 'prerequisite_failed':\n return 'prerequisite step did not pass';\n case 'unsatisfied_contract':\n return 'test-kit contract out of scope';\n case 'no_phases':\n return 'storyboard has no executable phases';\n case 'requirement_unmet':\n return 'storyboard requires a runtime that is not available on this run';\n case 'controller_seeding_failed':\n return 'pre-flight controller seeding failed';\n case 'capability_unsupported':\n return 'agent self-declared capability unsupported';\n default:\n return reason;\n }\n}\n\nfunction buildSkipCauses(result: ComplianceResult): ComplianceSummarySkipCause[] {\n const causeMap = new Map<string, { count: number; detail: string; affectedSet: Set<string> }>();\n\n const recordCause = (causeKey: string, baseReason: string, scenarioId: string) => {\n if (!causeMap.has(causeKey)) {\n causeMap.set(causeKey, {\n count: 0,\n detail: skipCauseDetail(baseReason),\n affectedSet: new Set(),\n });\n }\n const entry = causeMap.get(causeKey)!;\n entry.count++;\n entry.affectedSet.add(scenarioId);\n };\n\n for (const track of result.tracks) {\n for (const scenario of track.scenarios) {\n const scenarioId = String(scenario.scenario);\n for (const step of scenario.steps ?? []) {\n if (!step.skipped || !step.skip_reason) continue;\n if (step.selection_reason) continue;\n if (!isActionableSkipReason(step.skip_reason)) continue;\n\n // missing_tool: sub-group by tool name. Storyboard-level matches\n // can carry multiple tools (one cause per tool); step-level matches\n // are always single-tool. extractMissingToolNames returns [] when\n // the warning text doesn't match either pattern, in which case we\n // fall through to the un-grouped reason.\n if (step.skip_reason === 'missing_tool' && step.warnings?.[0]) {\n const toolNames = extractMissingToolNames(step.warnings[0]);\n if (toolNames.length > 0) {\n for (const toolName of toolNames) {\n recordCause(`missing_tool: ${toolName}`, 'missing_tool', scenarioId);\n }\n continue;\n }\n }\n\n // requirement_unmet: sub-group by the unmet requirement name\n // (adcp-client#1626). The runner emits `step.skip.requirement`\n // which `toComplianceStep` propagates as `step.requirement` on\n // the flattened `TestStepResult`, so per-requirement aggregation\n // works without parsing the warning text.\n if (step.skip_reason === 'requirement_unmet' && step.requirement) {\n recordCause(`requirement_unmet: ${step.requirement}`, 'requirement_unmet', scenarioId);\n continue;\n }\n if (step.skip_reason === 'requirement_unmet' && step.warnings?.[0]) {\n const requiredFamily = parseMissingRequiredToolFamilyCause(step.warnings[0]);\n if (requiredFamily) {\n recordCause(requiredFamily, 'requirement_unmet', scenarioId);\n continue;\n }\n }\n\n recordCause(step.skip_reason, step.skip_reason, scenarioId);\n }\n }\n }\n\n return Array.from(causeMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([cause, { count, detail, affectedSet }]) => ({\n cause,\n count,\n detail,\n // Cap at aggregator level so JSON consumers see the same bound the\n // text/markdown renderers honor — keeps the JSON contract truthful\n // about the cap documented on `ComplianceSummarySkipCause.affected`.\n affected: Array.from(affectedSet).slice(0, SKIP_CAUSE_AFFECTED_LIMIT),\n }));\n}\n\nfunction parseMissingRequiredToolFamilyCause(warning: string): string | null {\n const match = warning.match(/^missing_required_tool_family: needs\\s+([\\s\\S]*)$/);\n if (!match) return null;\n const family = match[1]!.replace(/\\s*[;(][\\s\\S]*$/, '').trim();\n return family ? `missing_required_tool_family: needs ${family}` : null;\n}\n\n/**\n * Hard-failure statuses — runs that should never look green to CI. `partial`\n * is intentionally not in this set: it means some tracks ran silent (wired\n * but unexercised), which is a reportable observation, not a CI block.\n */\nconst HARD_FAIL_STATUSES = new Set<OverallStatus>(['failing', 'unreachable', 'auth_required']);\n\nfunction isHardFail(s: ComplianceSummaryArtifact): boolean {\n return HARD_FAIL_STATUSES.has(s.overall_status) || s.failures.length > 0;\n}\n\nfunction formatReasonCounts(counts: Partial<Record<string, number>> | undefined): string | undefined {\n if (!counts) return undefined;\n const entries = Object.entries(counts).filter(\n (entry): entry is [string, number] => typeof entry[1] === 'number' && entry[1] > 0\n );\n if (entries.length === 0) return undefined;\n return entries\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([reason, count]) => `${reason}=${count}`)\n .join(', ');\n}\n\n/**\n * stderr-style summary block. Always starts with `STORYBOARD-FAIL` (kebab,\n * no spaces) on any hard-failing run, so CI scripts can `grep -q STORYBOARD-FAIL`\n * regardless of how the workflow handles the exit code. `partial` runs render\n * `STORYBOARD-PARTIAL` — distinct from both green and red so dashboards can\n * surface \"wired but unexercised\" without false-alarming CI.\n */\nexport function formatComplianceSummaryText(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n lines.push('');\n lines.push(`──── Storyboard Summary ────`);\n lines.push(`Agent: ${s.agent_url}`);\n lines.push(`SDK: @adcp/sdk ${s.sdk_version} (AdCP ${s.adcp_version})`);\n lines.push(`Status: ${s.overall_status}`);\n lines.push(\n `Steps: ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`Not selected: ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`Skipped: ${skippedReasons}`);\n if (s.skip_causes?.length) {\n const countWidth = String(Math.max(...s.skip_causes.map(c => c.count))).length;\n // \" [\" + countWidth chars + \"] \" — derived so Affected: aligns under the cause text\n const affectedIndent = ' '.repeat(4 + 1 + countWidth + 1 + 1);\n lines.push(` Skip causes:`);\n for (const cause of s.skip_causes) {\n const count = String(cause.count).padStart(countWidth);\n lines.push(` [${count}] ${cause.cause} — ${cause.detail}`);\n // Overflow is the difference between the total count for this cause\n // and how many distinct scenario IDs we kept after the aggregator's\n // SKIP_CAUSE_AFFECTED_LIMIT cap. The slice here is defensive — the\n // aggregator already caps, but if a future caller hands us an\n // uncapped artifact (e.g. JSON re-input from an older runner), we\n // still bound the visible list.\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText = overflow > 0 ? `${visible.join(', ')}, … ${overflow} more` : visible.join(', ');\n lines.push(`${affectedIndent}Affected: ${affectedText}`);\n }\n }\n lines.push(`Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (!isHardFail(s)) {\n if (s.overall_status === 'passing') {\n lines.push(`STORYBOARD-OK ${s.passed}/${s.passed + s.failed + s.skipped} selected steps passed`);\n } else {\n // `partial` and `silent` — some tracks were wired but not exercised.\n // Distinct marker so dashboards can surface this without lighting CI red.\n lines.push(`STORYBOARD-PARTIAL ${s.passed} steps passed, run ended ${s.overall_status}`);\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n if (s.failures.length === 0) {\n lines.push(`STORYBOARD-FAIL run ended ${s.overall_status} with no graded steps`);\n } else {\n lines.push(`STORYBOARD-FAIL ${s.failures.length} step(s):`);\n for (const f of s.failures) {\n lines.push(` - ${f.storyboard_id}/${f.step_id} [${f.track}]: ${f.reason}`);\n }\n }\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Markdown for `$GITHUB_STEP_SUMMARY`. Renders in the PR UI summary panel,\n * so reviewers see failures without opening the run log.\n */\nexport function formatComplianceSummaryMarkdown(s: ComplianceSummaryArtifact): string {\n const lines: string[] = [];\n const heading = !isHardFail(s)\n ? s.overall_status === 'passing'\n ? '✅ Storyboard run passed'\n : `⚠️ Storyboard run ended ${s.overall_status} (wired but partly unexercised)`\n : s.failures.length === 0\n ? `❌ Storyboard run: ended ${s.overall_status} with no graded steps`\n : `❌ Storyboard run: ${s.failures.length} failure(s)`;\n lines.push(`## ${heading}`);\n lines.push('');\n lines.push(`- **Agent:** \\`${s.agent_url}\\``);\n lines.push(`- **SDK:** \\`@adcp/sdk ${s.sdk_version}\\` (AdCP \\`${s.adcp_version}\\`)`);\n lines.push(`- **Status:** \\`${s.overall_status}\\``);\n lines.push(\n `- **Steps:** ${s.passed} passed, ${s.failed} failed, ${s.validations_advisory_failed ?? 0} advisory validation(s) failed, ${s.skipped} skipped, ${s.not_selected_count} not selected`\n );\n const notSelectedReasons = formatReasonCounts(s.not_selected_by_reason);\n if (notSelectedReasons) lines.push(`- **Not selected:** ${notSelectedReasons}`);\n const skippedReasons = formatReasonCounts(s.skipped_by_reason);\n if (skippedReasons) lines.push(`- **Skipped:** ${skippedReasons}`);\n lines.push(`- **Duration:** ${(s.total_duration_ms / 1000).toFixed(1)}s`);\n lines.push('');\n\n if (s.failures.length > 0) {\n lines.push('| Track | Storyboard | Step | Reason |');\n lines.push('| --- | --- | --- | --- |');\n for (const f of s.failures) {\n lines.push(`| \\`${f.track}\\` | \\`${f.storyboard_id}\\` | \\`${f.step_id}\\` | ${escapeTableCell(f.reason)} |`);\n }\n lines.push('');\n }\n\n if (s.skip_causes?.length) {\n const total = s.skip_causes.reduce((n, c) => n + c.count, 0);\n lines.push(`<details>`);\n lines.push(\n `<summary>Skip causes (${s.skip_causes.length} cause${s.skip_causes.length === 1 ? '' : 's'}, ${total} skipped step${total === 1 ? '' : 's'})</summary>`\n );\n lines.push('');\n lines.push('| Count | Cause | Detail | Affected |');\n lines.push('| --- | --- | --- | --- |');\n for (const cause of s.skip_causes) {\n const visible = cause.affected.slice(0, SKIP_CAUSE_AFFECTED_LIMIT);\n const overflow = cause.count - visible.length;\n const affectedText =\n overflow > 0\n ? `${visible.map(escapeTableCell).join(', ')}, … ${overflow} more`\n : visible.map(escapeTableCell).join(', ');\n lines.push(\n `| ${cause.count} | \\`${escapeTableCell(cause.cause)}\\` | ${escapeTableCell(cause.detail)} | ${affectedText} |`\n );\n }\n lines.push('');\n lines.push('</details>');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction escapeTableCell(s: string): string {\n // Escape backslashes first so a `\\|` in the input doesn't combine with\n // the pipe-escape below and produce `\\\\|` (literal backslash + raw pipe,\n // which breaks the table). Order matters: `\\` → `\\\\` then `|` → `\\|`.\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n\n/**\n * Synthesize a summary artifact when the runner itself crashed before\n * `comply()` produced a result (network down, capabilities parse error,\n * auth handshake exception). Schema-stable on the same summary artifact\n * contract so a Slack bot built against the artifact sees a valid payload\n * — rather than nothing — precisely when the agent is broken hardest.\n */\nexport interface BuildCrashSummaryOptions extends BuildSummaryOptions {\n agentUrl: string;\n error: Error | string;\n startedAt: string;\n durationMs: number;\n}\n\nexport function buildCrashSummary(opts: BuildCrashSummaryOptions): ComplianceSummaryArtifact {\n const message = opts.error instanceof Error ? opts.error.message : String(opts.error);\n return {\n schema_version: SUMMARY_SCHEMA_VERSION,\n agent_url: opts.agentUrl,\n sdk_version: opts.sdkVersion,\n adcp_version: opts.adcpVersion,\n overall_status: 'unreachable',\n passed: 0,\n failed: 1,\n skipped: 0,\n not_selected_count: 0,\n not_selected_by_reason: {},\n skipped_by_reason: {},\n total_duration_ms: opts.durationMs,\n tested_at: opts.startedAt,\n storyboards_executed: [],\n failures: [\n {\n track: 'core',\n storyboard_id: 'pre-flight',\n step_id: 'comply',\n reason: message.length > 500 ? `${message.slice(0, 499)}…` : message,\n reason_kind: 'error',\n },\n ],\n };\n}\n"],"mappings":"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","names":[]}
@@ -182,6 +182,8 @@ export interface ComplianceSummary {
182
182
  steps_passed?: number;
183
183
  /** Storyboard steps that failed. */
184
184
  steps_failed?: number;
185
+ /** Failed advisory validations, reported separately from failed steps. */
186
+ validations_advisory_failed?: number;
185
187
  /** Storyboard steps that were skipped. */
186
188
  steps_skipped?: number;
187
189
  /** Storyboard steps excluded before execution by run selection. */
@@ -200,6 +202,8 @@ export interface ComplianceSummary {
200
202
  * run_summary optional field.
201
203
  */
202
204
  validations_not_applicable?: number;
205
+ /** Semver capability used to evaluate advisory validation expiry gates. */
206
+ runner_capability_version?: string;
203
207
  /**
204
208
  * Schemas applied across all storyboards. Implementors can re-validate
205
209
  * locally against the same artifacts the runner used.
@@ -182,6 +182,8 @@ export interface ComplianceSummary {
182
182
  steps_passed?: number;
183
183
  /** Storyboard steps that failed. */
184
184
  steps_failed?: number;
185
+ /** Failed advisory validations, reported separately from failed steps. */
186
+ validations_advisory_failed?: number;
185
187
  /** Storyboard steps that were skipped. */
186
188
  steps_skipped?: number;
187
189
  /** Storyboard steps excluded before execution by run selection. */
@@ -200,6 +202,8 @@ export interface ComplianceSummary {
200
202
  * run_summary optional field.
201
203
  */
202
204
  validations_not_applicable?: number;
205
+ /** Semver capability used to evaluate advisory validation expiry gates. */
206
+ runner_capability_version?: string;
203
207
  /**
204
208
  * Schemas applied across all storyboards. Implementors can re-validate
205
209
  * locally against the same artifacts the runner used.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/compliance/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/compliance/types.ts"],"names":[],"mappings":"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"}