@openwop/openwop-conformance 1.163.0 → 2.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (611) hide show
  1. package/README.md +11 -2
  2. package/dist/cli.js +262 -14
  3. package/dist/lib/certification-bundle-v3.js +142 -0
  4. package/dist/lib/paths.js +25 -3
  5. package/dist/lib/requirement-ids.js +57 -4
  6. package/dist/lib/requirement-ledger.js +1 -0
  7. package/dist/lib/scenario-disposition.js +6 -1
  8. package/dist/lib/spec-coherence.js +13 -32
  9. package/dist/spec-artifacts.lock.json +5 -0
  10. package/package.json +11 -33
  11. package/requirements.json +22892 -11701
  12. package/scenario-majors.json +1493 -0
  13. package/schemas/CORPUS-STAMP.json +137 -5
  14. package/src/cli.ts +236 -19
  15. package/src/global-setup.ts +3 -2
  16. package/src/lib/certification-bundle-v3.ts +175 -0
  17. package/src/lib/corpus-stamp.ts +29 -1
  18. package/src/lib/driver.ts +9 -1
  19. package/src/lib/era2-seed.ts +197 -0
  20. package/src/lib/paths.ts +25 -3
  21. package/src/lib/requirement-ids.ts +54 -4
  22. package/src/lib/requirement-ledger.ts +7 -1
  23. package/src/lib/scenario-disposition.ts +6 -1
  24. package/src/lib/seams.ts +45 -0
  25. package/src/lib/spec-coherence.ts +15 -32
  26. package/src/lib/v2.ts +62 -0
  27. package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
  28. package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
  29. package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
  30. package/src/scenarios/a2a-peer-authority.test.ts +7 -6
  31. package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
  32. package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
  33. package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
  34. package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
  35. package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
  36. package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
  37. package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
  38. package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
  39. package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
  40. package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
  41. package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
  42. package/src/scenarios/agent-deployment-shape.test.ts +22 -24
  43. package/src/scenarios/agent-eval-run.test.ts +19 -18
  44. package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
  45. package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
  46. package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
  47. package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
  48. package/src/scenarios/agent-live-structured-output.test.ts +7 -6
  49. package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
  50. package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
  51. package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
  52. package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
  53. package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
  54. package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
  55. package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
  56. package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
  57. package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
  58. package/src/scenarios/agent-platform-profile.test.ts +18 -19
  59. package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
  60. package/src/scenarios/agent-roster-attribution.test.ts +18 -17
  61. package/src/scenarios/agent-roster-shape.test.ts +17 -19
  62. package/src/scenarios/agent-verifier-shape.test.ts +11 -11
  63. package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
  64. package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
  65. package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
  66. package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
  67. package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
  68. package/src/scenarios/agentMessageReducer.test.ts +2 -1
  69. package/src/scenarios/agentMetadata.test.ts +2 -1
  70. package/src/scenarios/agentPackCatalog.test.ts +23 -21
  71. package/src/scenarios/agentPackExport.test.ts +4 -2
  72. package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
  73. package/src/scenarios/agentPackInstall.test.ts +4 -2
  74. package/src/scenarios/agentPackProvenance.test.ts +2 -1
  75. package/src/scenarios/agentReasoningEvents.test.ts +3 -2
  76. package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
  77. package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
  78. package/src/scenarios/ai-envelope-shape.test.ts +31 -29
  79. package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
  80. package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
  81. package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
  82. package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
  83. package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
  84. package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
  85. package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
  86. package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
  87. package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
  88. package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
  89. package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
  90. package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
  91. package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
  92. package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
  93. package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
  94. package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
  95. package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
  96. package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
  97. package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
  98. package/src/scenarios/append-ordering.test.ts +7 -5
  99. package/src/scenarios/approval-gate-events.test.ts +4 -3
  100. package/src/scenarios/approval-gate-flow.test.ts +4 -3
  101. package/src/scenarios/approval-payload.test.ts +5 -4
  102. package/src/scenarios/artifact-auth.test.ts +7 -6
  103. package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
  104. package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
  105. package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
  106. package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
  107. package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
  108. package/src/scenarios/audit-log-integrity.test.ts +8 -6
  109. package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
  110. package/src/scenarios/auth-mtls.test.ts +22 -20
  111. package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
  112. package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
  113. package/src/scenarios/auth-saml-profile.test.ts +14 -12
  114. package/src/scenarios/auth-scim-profile.test.ts +3 -2
  115. package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
  116. package/src/scenarios/auth-subject-link.test.ts +11 -10
  117. package/src/scenarios/auth.test.ts +5 -4
  118. package/src/scenarios/authorization-fail-closed.test.ts +3 -2
  119. package/src/scenarios/authorization-roles-shape.test.ts +9 -7
  120. package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
  121. package/src/scenarios/blob-presign-expiry.test.ts +12 -10
  122. package/src/scenarios/blob-roundtrip.test.ts +0 -0
  123. package/src/scenarios/budget-enforcement.test.ts +15 -14
  124. package/src/scenarios/budget-policy-shape.test.ts +18 -19
  125. package/src/scenarios/bulk-cancel.test.ts +9 -8
  126. package/src/scenarios/byok-auth-modes.test.ts +13 -14
  127. package/src/scenarios/byok-roundtrip.test.ts +12 -10
  128. package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
  129. package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
  130. package/src/scenarios/callai-multimodal.test.ts +5 -3
  131. package/src/scenarios/cancellation.test.ts +6 -5
  132. package/src/scenarios/cap-breach.test.ts +15 -14
  133. package/src/scenarios/capability-arm-witness.test.ts +5 -3
  134. package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
  135. package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
  136. package/src/scenarios/certification-bundle-v2.test.ts +11 -10
  137. package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
  138. package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
  139. package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
  140. package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
  141. package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
  142. package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
  143. package/src/scenarios/channel-presence-shape.test.ts +11 -12
  144. package/src/scenarios/channel-ttl.test.ts +6 -5
  145. package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
  146. package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
  147. package/src/scenarios/commitment-fired.test.ts +6 -5
  148. package/src/scenarios/compensation-behavior.test.ts +24 -23
  149. package/src/scenarios/compensation-recovery.test.ts +28 -27
  150. package/src/scenarios/configurable-schema.test.ts +8 -6
  151. package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
  152. package/src/scenarios/conformance-execution-witness.test.ts +9 -8
  153. package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
  154. package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
  155. package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
  156. package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
  157. package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
  158. package/src/scenarios/connection-provider-resolution.test.ts +18 -16
  159. package/src/scenarios/connector-manifest-validity.test.ts +8 -7
  160. package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
  161. package/src/scenarios/context-summarization-replay.test.ts +14 -12
  162. package/src/scenarios/contract-provenance.test.ts +18 -18
  163. package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
  164. package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
  165. package/src/scenarios/conversationLifecycle.test.ts +2 -1
  166. package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
  167. package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
  168. package/src/scenarios/core-standard-profile.test.ts +8 -9
  169. package/src/scenarios/cost-attribution.test.ts +23 -21
  170. package/src/scenarios/credential-payload-redaction.test.ts +4 -3
  171. package/src/scenarios/credentials-capability-shape.test.ts +5 -4
  172. package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
  173. package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
  174. package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
  175. package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
  176. package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
  177. package/src/scenarios/data-residency-admission.test.ts +15 -14
  178. package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
  179. package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
  180. package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
  181. package/src/scenarios/debugBundle.test.ts +25 -23
  182. package/src/scenarios/discovery-families-view.test.ts +5 -4
  183. package/src/scenarios/discovery.test.ts +30 -29
  184. package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
  185. package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
  186. package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
  187. package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
  188. package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
  189. package/src/scenarios/dispatchLoop.test.ts +3 -2
  190. package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
  191. package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
  192. package/src/scenarios/distillation-shape.test.ts +4 -4
  193. package/src/scenarios/distillation-stable-archive.test.ts +6 -6
  194. package/src/scenarios/distillation-token-budget.test.ts +5 -5
  195. package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
  196. package/src/scenarios/egress-audience-binding.test.ts +11 -10
  197. package/src/scenarios/egress-decision-content-free.test.ts +6 -5
  198. package/src/scenarios/egress-provenance-shape.test.ts +17 -18
  199. package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
  200. package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
  201. package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
  202. package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
  203. package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
  204. package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
  205. package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
  206. package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
  207. package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
  208. package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
  209. package/src/scenarios/envelope-truncated.test.ts +19 -17
  210. package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
  211. package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
  212. package/src/scenarios/errors.test.ts +20 -19
  213. package/src/scenarios/eventOrdering.test.ts +16 -14
  214. package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
  215. package/src/scenarios/experimental-tier-shape.test.ts +17 -15
  216. package/src/scenarios/export-bundle-portability.test.ts +17 -17
  217. package/src/scenarios/failure-path.test.ts +7 -6
  218. package/src/scenarios/feedback-capability-shape.test.ts +4 -3
  219. package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
  220. package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
  221. package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
  222. package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
  223. package/src/scenarios/feedback-record-and-list.test.ts +2 -1
  224. package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
  225. package/src/scenarios/fixtures-gating.test.ts +29 -28
  226. package/src/scenarios/fixtures-valid.test.ts +16 -15
  227. package/src/scenarios/form-content-instantiation.test.ts +15 -14
  228. package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
  229. package/src/scenarios/fs-path-traversal.test.ts +14 -12
  230. package/src/scenarios/goal-standing-continuation.test.ts +21 -21
  231. package/src/scenarios/grpc-transport.test.ts +9 -7
  232. package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
  233. package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
  234. package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
  235. package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
  236. package/src/scenarios/highConcurrency.test.ts +14 -13
  237. package/src/scenarios/host-callback-declaration.test.ts +8 -7
  238. package/src/scenarios/http-client-ssrf.test.ts +7 -5
  239. package/src/scenarios/i18n-negotiation.test.ts +14 -12
  240. package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
  241. package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
  242. package/src/scenarios/idempotency.test.ts +8 -7
  243. package/src/scenarios/idempotencyRetry.test.ts +13 -11
  244. package/src/scenarios/identity-owner-shape.test.ts +6 -5
  245. package/src/scenarios/identity-passthrough.test.ts +4 -3
  246. package/src/scenarios/interrupt-approval.test.ts +6 -5
  247. package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
  248. package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
  249. package/src/scenarios/interrupt-clarification.test.ts +4 -3
  250. package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
  251. package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
  252. package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
  253. package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
  254. package/src/scenarios/interruptRace.test.ts +12 -10
  255. package/src/scenarios/kv-atomic-increment.test.ts +11 -9
  256. package/src/scenarios/kv-cas.test.ts +14 -12
  257. package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
  258. package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
  259. package/src/scenarios/localized-content-delivery.test.ts +24 -26
  260. package/src/scenarios/maliciousManifest.test.ts +10 -8
  261. package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
  262. package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
  263. package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
  264. package/src/scenarios/mcp-discoverability.test.ts +9 -7
  265. package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
  266. package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
  267. package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
  268. package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
  269. package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
  270. package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
  271. package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
  272. package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
  273. package/src/scenarios/mcp-stateless-request.test.ts +11 -10
  274. package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
  275. package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
  276. package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
  277. package/src/scenarios/media-url-inline-cap.test.ts +21 -19
  278. package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
  279. package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
  280. package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
  281. package/src/scenarios/memory-attribution-shape.test.ts +4 -3
  282. package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
  283. package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
  284. package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
  285. package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
  286. package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
  287. package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
  288. package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
  289. package/src/scenarios/memory-degraded-projection.test.ts +10 -9
  290. package/src/scenarios/memory-injection-budget.test.ts +15 -14
  291. package/src/scenarios/metric-emission.test.ts +4 -3
  292. package/src/scenarios/model-capability-insufficient.test.ts +19 -17
  293. package/src/scenarios/model-capability-substituted.test.ts +20 -18
  294. package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
  295. package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
  296. package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
  297. package/src/scenarios/multi-node-ordering.test.ts +4 -3
  298. package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
  299. package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
  300. package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
  301. package/src/scenarios/multi-region-idempotency.test.ts +6 -5
  302. package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
  303. package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
  304. package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
  305. package/src/scenarios/oauth-capability-shape.test.ts +5 -4
  306. package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
  307. package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
  308. package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
  309. package/src/scenarios/orchestratorDispatch.test.ts +2 -1
  310. package/src/scenarios/orchestratorTermination.test.ts +2 -1
  311. package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
  312. package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
  313. package/src/scenarios/otel-emission-grpc.test.ts +3 -2
  314. package/src/scenarios/otel-emission.test.ts +6 -5
  315. package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
  316. package/src/scenarios/otel-trace-propagation.test.ts +2 -1
  317. package/src/scenarios/owner-subject-echo.test.ts +13 -12
  318. package/src/scenarios/owner-subject-shape.test.ts +11 -10
  319. package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
  320. package/src/scenarios/pack-registry-isolation.test.ts +4 -3
  321. package/src/scenarios/pack-registry-publish.test.ts +65 -63
  322. package/src/scenarios/pack-registry.test.ts +38 -36
  323. package/src/scenarios/pause-resume.test.ts +18 -16
  324. package/src/scenarios/policies.test.ts +20 -18
  325. package/src/scenarios/production-backpressure.test.ts +18 -16
  326. package/src/scenarios/production-retention-expiry.test.ts +8 -6
  327. package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
  328. package/src/scenarios/profileDerivation.test.ts +34 -33
  329. package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
  330. package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
  331. package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
  332. package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
  333. package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
  334. package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
  335. package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
  336. package/src/scenarios/prompt-pack-install.test.ts +14 -12
  337. package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
  338. package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
  339. package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
  340. package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
  341. package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
  342. package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
  343. package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
  344. package/src/scenarios/prompt-template-shape.test.ts +30 -28
  345. package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
  346. package/src/scenarios/protocol-versions-array.test.ts +10 -9
  347. package/src/scenarios/provider-usage.test.ts +17 -15
  348. package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
  349. package/src/scenarios/purpose-propagation.test.ts +23 -21
  350. package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
  351. package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
  352. package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
  353. package/src/scenarios/rate-limit-envelope.test.ts +6 -5
  354. package/src/scenarios/redaction.test.ts +13 -11
  355. package/src/scenarios/redactionAdversarial.test.ts +11 -9
  356. package/src/scenarios/registry-public.test.ts +12 -11
  357. package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
  358. package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
  359. package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
  360. package/src/scenarios/replay-fork.test.ts +20 -19
  361. package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
  362. package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
  363. package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
  364. package/src/scenarios/replay-retention-expiry.test.ts +11 -9
  365. package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
  366. package/src/scenarios/replayDeterminism.test.ts +13 -12
  367. package/src/scenarios/requirement-ledger.test.ts +15 -14
  368. package/src/scenarios/restart-during-run.test.ts +3 -2
  369. package/src/scenarios/route-coverage.test.ts +20 -19
  370. package/src/scenarios/run-diff.test.ts +22 -20
  371. package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
  372. package/src/scenarios/run-transport-economy.test.ts +13 -11
  373. package/src/scenarios/runner-ledger.test.ts +17 -16
  374. package/src/scenarios/runs-lifecycle.test.ts +7 -6
  375. package/src/scenarios/runtime-capabilities.test.ts +12 -10
  376. package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
  377. package/src/scenarios/runtime-requires-shape.test.ts +7 -6
  378. package/src/scenarios/safefetch-behavior.test.ts +22 -21
  379. package/src/scenarios/safefetch-live-audit.test.ts +14 -13
  380. package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
  381. package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
  382. package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
  383. package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
  384. package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
  385. package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
  386. package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
  387. package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
  388. package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
  389. package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
  390. package/src/scenarios/self-hosted-runner.test.ts +26 -24
  391. package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
  392. package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
  393. package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
  394. package/src/scenarios/sql-injection-rejection.test.ts +8 -6
  395. package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
  396. package/src/scenarios/staleClaim.test.ts +5 -4
  397. package/src/scenarios/stream-modes-buffer.test.ts +8 -7
  398. package/src/scenarios/stream-modes-mixed.test.ts +10 -9
  399. package/src/scenarios/stream-modes.test.ts +12 -11
  400. package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
  401. package/src/scenarios/stream-text-fixture.test.ts +14 -13
  402. package/src/scenarios/streamReconnect.test.ts +13 -11
  403. package/src/scenarios/strict-behavior-gate.test.ts +9 -8
  404. package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
  405. package/src/scenarios/subrun-approval-gate.test.ts +3 -3
  406. package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
  407. package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
  408. package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
  409. package/src/scenarios/subworkflow.test.ts +10 -9
  410. package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
  411. package/src/scenarios/table-cursor-pagination.test.ts +8 -6
  412. package/src/scenarios/table-schema-enforcement.test.ts +7 -5
  413. package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
  414. package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
  415. package/src/scenarios/tool-catalog-projection.test.ts +11 -9
  416. package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
  417. package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
  418. package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
  419. package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
  420. package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
  421. package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
  422. package/src/scenarios/tool-hooks-shape.test.ts +3 -3
  423. package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
  424. package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
  425. package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
  426. package/src/scenarios/trigger-ingestion.test.ts +19 -17
  427. package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
  428. package/src/scenarios/v2-approver-enforced.test.ts +97 -0
  429. package/src/scenarios/v2-assurance-downgrade-audited.test.ts +75 -0
  430. package/src/scenarios/v2-bundle-v3-signed.test.ts +96 -0
  431. package/src/scenarios/v2-capabilities-root-closed.test.ts +63 -0
  432. package/src/scenarios/v2-capability-record-shape.test.ts +104 -0
  433. package/src/scenarios/v2-chain-pin-exact.test.ts +118 -0
  434. package/src/scenarios/v2-coherence-not-in-bundle.test.ts +98 -0
  435. package/src/scenarios/v2-compensation-read-projection.test.ts +85 -0
  436. package/src/scenarios/v2-configurable-closed.test.ts +67 -0
  437. package/src/scenarios/v2-dual-stack-negotiation.test.ts +118 -0
  438. package/src/scenarios/v2-effect-identity-business-key.test.ts +132 -0
  439. package/src/scenarios/v2-effect-seam-manifest.test.ts +163 -0
  440. package/src/scenarios/v2-enum-growth-rule.test.ts +69 -0
  441. package/src/scenarios/v2-era-key.test.ts +86 -0
  442. package/src/scenarios/v2-error-registry.test.ts +89 -0
  443. package/src/scenarios/v2-event-type-closed.test.ts +97 -0
  444. package/src/scenarios/v2-fork-a-v1-run.test.ts +109 -0
  445. package/src/scenarios/v2-form-when-reuses-edge-conditions.test.ts +70 -0
  446. package/src/scenarios/v2-header-scheme.test.ts +67 -0
  447. package/src/scenarios/v2-id-grammar.test.ts +77 -0
  448. package/src/scenarios/v2-idempotency-key-grammar.test.ts +65 -0
  449. package/src/scenarios/v2-interrupt-token-scheme.test.ts +55 -0
  450. package/src/scenarios/v2-lane-issuer-advertised.test.ts +62 -0
  451. package/src/scenarios/v2-legacy-profiles-absent.test.ts +78 -0
  452. package/src/scenarios/v2-manifest-ceiling-refused.test.ts +130 -0
  453. package/src/scenarios/v2-manifest-hatch-carried.test.ts +120 -0
  454. package/src/scenarios/v2-min-client-version.test.ts +48 -0
  455. package/src/scenarios/v2-minimum-version-refused.test.ts +141 -0
  456. package/src/scenarios/v2-mrtr-rounds-ceiling.test.ts +95 -0
  457. package/src/scenarios/v2-negotiation-authenticated.test.ts +125 -0
  458. package/src/scenarios/v2-negotiation-decided-emitted.test.ts +149 -0
  459. package/src/scenarios/v2-no-transport-advertisement.test.ts +57 -0
  460. package/src/scenarios/v2-owner-subject-required.test.ts +72 -0
  461. package/src/scenarios/v2-pack-isolation.test.ts +147 -0
  462. package/src/scenarios/v2-payload-registry-closed.test.ts +110 -0
  463. package/src/scenarios/v2-peer-dependency-declared.test.ts +132 -0
  464. package/src/scenarios/v2-pinned-run-disposition.test.ts +124 -0
  465. package/src/scenarios/v2-poll-cursor-v2.test.ts +114 -0
  466. package/src/scenarios/v2-preferred-version-default.test.ts +83 -0
  467. package/src/scenarios/v2-profiles-derived-only.test.ts +70 -0
  468. package/src/scenarios/v2-provider-conflict.test.ts +115 -0
  469. package/src/scenarios/v2-refresh-sla.test.ts +78 -0
  470. package/src/scenarios/v2-relaxation-recorded.test.ts +134 -0
  471. package/src/scenarios/v2-revocation-honored.test.ts +66 -0
  472. package/src/scenarios/v2-subject-link-record.test.ts +102 -0
  473. package/src/scenarios/v2-unmapped-type-refused.test.ts +95 -0
  474. package/src/scenarios/v2-v1-events-translated.test.ts +105 -0
  475. package/src/scenarios/v2-v1-signed-webhook-accepted.test.ts +109 -0
  476. package/src/scenarios/v2-webhook-durable-delivery.test.ts +238 -0
  477. package/src/scenarios/v2-well-known-one-resource.test.ts +129 -0
  478. package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
  479. package/src/scenarios/verifier-gating.test.ts +8 -6
  480. package/src/scenarios/version-fold.test.ts +9 -8
  481. package/src/scenarios/version-negotiation.test.ts +12 -11
  482. package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
  483. package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
  484. package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
  485. package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
  486. package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
  487. package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
  488. package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
  489. package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
  490. package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
  491. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
  492. package/src/scenarios/wasm-pack-load.test.ts +4 -3
  493. package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
  494. package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
  495. package/src/scenarios/webhook-negative.test.ts +11 -9
  496. package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
  497. package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
  498. package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
  499. package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
  500. package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
  501. package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
  502. package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
  503. package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
  504. package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
  505. package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
  506. package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
  507. package/src/scenarios/workflow-variable-format.test.ts +24 -24
  508. package/src/scenarios/workload-identity-behavior.test.ts +15 -13
  509. package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
  510. package/src/scenarios/workspace-behavior.test.ts +19 -18
  511. package/src/scenarios/workspace-capability-shape.test.ts +3 -2
  512. package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
  513. package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
  514. package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
  515. package/src/setup.ts +44 -6
  516. package/vitest.config.ts +5 -1
  517. package/api/.redocly.lint-ignore.yaml +0 -22
  518. package/api/asyncapi.yaml +0 -834
  519. package/api/grpc/openwop.proto +0 -251
  520. package/api/openapi.yaml +0 -2693
  521. package/api/redocly.yaml +0 -23
  522. package/schemas/README.md +0 -144
  523. package/schemas/a2a-task-state.schema.json +0 -78
  524. package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
  525. package/schemas/agent-deployment-transition.schema.json +0 -49
  526. package/schemas/agent-deployment.schema.json +0 -54
  527. package/schemas/agent-eval-suite.schema.json +0 -140
  528. package/schemas/agent-inventory-response.schema.json +0 -115
  529. package/schemas/agent-manifest.schema.json +0 -156
  530. package/schemas/agent-org-chart.schema.json +0 -82
  531. package/schemas/agent-ref.schema.json +0 -63
  532. package/schemas/agent-roster-entry.schema.json +0 -81
  533. package/schemas/agent-roster-response.schema.json +0 -21
  534. package/schemas/ai-envelope.schema.json +0 -134
  535. package/schemas/annotation-create.schema.json +0 -37
  536. package/schemas/annotation.schema.json +0 -56
  537. package/schemas/artifact-type-pack-manifest.schema.json +0 -244
  538. package/schemas/audit-verify-result.schema.json +0 -90
  539. package/schemas/budget-policy.schema.json +0 -18
  540. package/schemas/capabilities.schema.json +0 -4160
  541. package/schemas/certification-bundle-v2.schema.json +0 -118
  542. package/schemas/channel-presence-payload.schema.json +0 -41
  543. package/schemas/channel-written-payload.schema.json +0 -55
  544. package/schemas/chat-card-pack-manifest.schema.json +0 -253
  545. package/schemas/compact-tool-descriptor.schema.json +0 -51
  546. package/schemas/compensation-policy.schema.json +0 -64
  547. package/schemas/conformance-certification-bundle.schema.json +0 -86
  548. package/schemas/connection-pack-manifest.schema.json +0 -353
  549. package/schemas/conversation-event.schema.json +0 -168
  550. package/schemas/conversation-turn.schema.json +0 -117
  551. package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
  552. package/schemas/credential-provenance.schema.json +0 -18
  553. package/schemas/credential-reference.schema.json +0 -21
  554. package/schemas/debug-bundle.schema.json +0 -196
  555. package/schemas/dispatch-config.schema.json +0 -112
  556. package/schemas/envelopes/clarification.request.schema.json +0 -52
  557. package/schemas/envelopes/error.schema.json +0 -30
  558. package/schemas/envelopes/media.audio.schema.json +0 -38
  559. package/schemas/envelopes/media.file.schema.json +0 -37
  560. package/schemas/envelopes/media.image.schema.json +0 -33
  561. package/schemas/envelopes/schema.request.schema.json +0 -26
  562. package/schemas/envelopes/schema.response.schema.json +0 -22
  563. package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
  564. package/schemas/error-envelope.schema.json +0 -25
  565. package/schemas/eval-summary.schema.json +0 -92
  566. package/schemas/export-bundle.schema.json +0 -66
  567. package/schemas/form-content-pack-manifest.schema.json +0 -243
  568. package/schemas/frontend-plugin-manifest.schema.json +0 -109
  569. package/schemas/goal.schema.json +0 -104
  570. package/schemas/heartbeat-evaluated.schema.json +0 -14
  571. package/schemas/heartbeat-state-changed.schema.json +0 -14
  572. package/schemas/localized-content-language-settings.schema.json +0 -26
  573. package/schemas/localized-content-page-response.schema.json +0 -60
  574. package/schemas/localized-content-page.schema.json +0 -62
  575. package/schemas/localized-content-section.schema.json +0 -51
  576. package/schemas/memory-entry.schema.json +0 -36
  577. package/schemas/memory-list-options.schema.json +0 -37
  578. package/schemas/node-pack-manifest.schema.json +0 -654
  579. package/schemas/orchestrator-decision.schema.json +0 -90
  580. package/schemas/org-chart-responsibility-view.schema.json +0 -26
  581. package/schemas/pack-lockfile.schema.json +0 -108
  582. package/schemas/prompt-kind.schema.json +0 -8
  583. package/schemas/prompt-pack-manifest.schema.json +0 -117
  584. package/schemas/prompt-ref.schema.json +0 -40
  585. package/schemas/prompt-template.schema.json +0 -149
  586. package/schemas/proposal.schema.json +0 -84
  587. package/schemas/registry-version-manifest.schema.json +0 -208
  588. package/schemas/residency.schema.json +0 -16
  589. package/schemas/run-ancestry-response.schema.json +0 -54
  590. package/schemas/run-diff-response.schema.json +0 -64
  591. package/schemas/run-event-payloads.schema.json +0 -4452
  592. package/schemas/run-event.schema.json +0 -211
  593. package/schemas/run-options.schema.json +0 -80
  594. package/schemas/run-orchestrator-decided-event.schema.json +0 -20
  595. package/schemas/run-snapshot.schema.json +0 -148
  596. package/schemas/security-advisory.schema.json +0 -109
  597. package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
  598. package/schemas/self-hosted-runner-registration.schema.json +0 -53
  599. package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
  600. package/schemas/subject.schema.json +0 -56
  601. package/schemas/suspend-request.schema.json +0 -207
  602. package/schemas/tool-descriptor.schema.json +0 -63
  603. package/schemas/trigger-event.schema.json +0 -222
  604. package/schemas/trigger-subscription-registration.schema.json +0 -67
  605. package/schemas/trigger-subscription.schema.json +0 -26
  606. package/schemas/ui-plugin-message.schema.json +0 -90
  607. package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
  608. package/schemas/workflow-definition.schema.json +0 -850
  609. package/schemas/workload-identity.schema.json +0 -79
  610. package/schemas/workspace-file-create.schema.json +0 -20
  611. package/schemas/workspace-file.schema.json +0 -39
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Suite 2.0.0 — the seams profile (RFC 0168 §C; `openwop-conformance-seams-v2`).
3
+ *
4
+ * v1 scenarios reach the host-sample seams at `/v1/host/sample/…`,
5
+ * `/v1/host/workspace/files…` and `/v1/packs-test/…`. In v2 those operations
6
+ * leave the canonical API for `api/seams-v2.yaml` under `/conformance/seams/…`
7
+ * (RFC 0168 §C.2). Under target major 2 the driver rewrites the v1 seam path
8
+ * to its v2 address, so the 165 scenarios that name a seam keep working
9
+ * without a sweep; the sweep to `seamPath()` is the P3-F polish.
10
+ *
11
+ * How a v2 host advertises the profile: RFC 0168 §C.1 forbids a `testSeams`
12
+ * capability flag and RFC 0169 §C.1 removes the root `profiles[]`; the
13
+ * reconciliation (recorded against RFC 0168 at its flip) is the
14
+ * `conformance` METADATA key (RFC 0169 §A.1a): `conformance.seamsProfile:
15
+ * "openwop-conformance-seams-v2"`. Metadata, not a capability family.
16
+ */
17
+ export const SEAMS_PROFILE_ID = 'openwop-conformance-seams-v2';
18
+ export const SEAMS_PREFIX = '/conformance/seams';
19
+
20
+ const V1_SEAM_PREFIXES: ReadonlyArray<readonly [RegExp, string]> = [
21
+ [/^\/v1\/host\/sample\//, `${SEAMS_PREFIX}/sample/`],
22
+ [/^\/v1\/host\/workspace\/files/, `${SEAMS_PREFIX}/workspace/files`],
23
+ [/^\/v1\/packs-test\//, `${SEAMS_PREFIX}/packs-test/`],
24
+ ];
25
+
26
+ /** The v2 address of a v1 seam path; a non-seam path is returned unchanged. */
27
+ export function seamPath(v1Path: string): string {
28
+ for (const [re, to] of V1_SEAM_PREFIXES) if (re.test(v1Path)) return v1Path.replace(re, to);
29
+ return v1Path;
30
+ }
31
+
32
+ export function isSeamPath(path: string): boolean {
33
+ return V1_SEAM_PREFIXES.some(([re]) => re.test(path)) || path.startsWith(`${SEAMS_PREFIX}/`);
34
+ }
35
+
36
+ /** Whether a (v2) discovery document advertises the seams profile. */
37
+ export function seamsProfileAdvertised(doc: Readonly<Record<string, unknown>> | null | undefined): boolean {
38
+ const conf = doc?.['conformance'];
39
+ return typeof conf === 'object' && conf !== null && (conf as Record<string, unknown>)['seamsProfile'] === SEAMS_PROFILE_ID;
40
+ }
41
+
42
+ /** The target major the runner selected (RFC 0168 §D.3); 1 when unset. */
43
+ export function targetMajor(): 1 | 2 {
44
+ return process.env['OPENWOP_TARGET_MAJOR'] === '2' ? 2 : 1;
45
+ }
@@ -80,38 +80,21 @@
80
80
  * is no longer the only place the exclusion reason lives.
81
81
  */
82
82
 
83
- /** Scenarios whose subject is the corpus. Kept honest by `spec-coherence-registry.test.ts`. */
84
- export const SPEC_COHERENCE_SCENARIOS: ReadonlySet<string> = new Set([
85
- 'artifact-schema-compile-bounded.test.ts',
86
- 'artifact-type-legacy-ids.test.ts',
87
- 'capability-example-root-layout.test.ts',
88
- 'certification-floor-enforcement.test.ts',
89
- 'chain-subchain-unsupported-refused.test.ts',
90
- 'compensation-profile.test.ts',
91
- 'core-manifest-and-extension-registry.test.ts',
92
- 'discovery-canonical-family-no-shadow.test.ts',
93
- 'edge-condition-truthy-falsy.test.ts',
94
- 'effect-identity-composition.test.ts',
95
- 'effect-identity-cross-scope.test.ts',
96
- 'error-envelope-canonical-shape.test.ts',
97
- 'event-codemap-complete.test.ts',
98
- 'form-content-packs.test.ts',
99
- 'multi-region-effect-vocabulary.test.ts',
100
- 'normative-example-extraction.test.ts',
101
- 'openapi-asyncapi-sdk-parity.test.ts',
102
- 'pack-manifest-extensions.test.ts',
103
- 'protocol-version-grammar.test.ts',
104
- 'registry-declarative-kinds.test.ts',
105
- 'rfc-0147-self-audit.test.ts',
106
- 'rfc-lifecycle-coherence.test.ts',
107
- 'semantic-digest-v2.test.ts',
108
- 'spec-corpus-validity.test.ts',
109
- 'spec-section-citations.test.ts',
110
- 'tool-result-trust-monotone.test.ts',
111
- 'versioned-composition-profiles.test.ts',
112
- 'workflow-chain-internal-flag.test.ts',
113
- 'workload-identity-profile.test.ts',
114
- ]);
83
+ /**
84
+ * Scenarios whose subject is the corpus. Suite 2.0.0 (RFC 0168 §D.1): they
85
+ * live in `src/coherence/`, not `src/scenarios/`, and the set is the DIRECTORY
86
+ * LISTING — one source of truth instead of four (this list, the package.json
87
+ * negations, spec-coherence-scenarios.json and the registry self-test used to
88
+ * each carry a copy). They run in the spec repo's CI (scripts/check-spec-coherence.mjs)
89
+ * and never enter a host bundle; the published tarball excludes the directory.
90
+ */
91
+ import { existsSync, readdirSync } from 'node:fs';
92
+ import { fileURLToPath } from 'node:url';
93
+ import { dirname, join } from 'node:path';
94
+ const COHERENCE_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', 'coherence');
95
+ export const SPEC_COHERENCE_SCENARIOS: ReadonlySet<string> = new Set(
96
+ existsSync(COHERENCE_DIR) ? readdirSync(COHERENCE_DIR).filter((f) => f.endsWith('.test.ts')).sort() : [],
97
+ );
115
98
 
116
99
  /**
117
100
  * Scenarios that gate on `V1_DIR` **and** drive the host, so their `blocked` is
package/src/lib/v2.ts ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Suite 2.0.0 — helpers for v2 scenarios (`v2-*.test.ts`, target major 2).
3
+ *
4
+ * v2Discovery() the v2 representation of /.well-known/openwop
5
+ * (OpenWOP-Version: 2.0), memoized per worker.
6
+ * familyAdvertised(key) RFC 0169 §A.2: presence of the family record IS the
7
+ * claim; there is no `supported` field. Returns the
8
+ * record or null.
9
+ * v2Validator(name) an Ajv 2020 validator for schemas/v2/<name>, with the
10
+ * whole v2 tree registered so cross-file $refs resolve
11
+ * (SCHEMAS_DIR is the spec-artifacts peer in the
12
+ * published layout — lib/paths.ts).
13
+ * gateFamily(key) the RFC 0148 §B gate for a v2 family: records
14
+ * `inapplicable` (family absent) or `skipped`
15
+ * (opted out) through behaviorGate under the
16
+ * requirement id `openwop.family.<key>`, and returns
17
+ * the record when advertised.
18
+ */
19
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
20
+ import { join } from 'node:path';
21
+ import { Ajv2020 } from 'ajv/dist/2020.js';
22
+ import addFormats from 'ajv-formats';
23
+ import { driver } from './driver.js';
24
+ import { SCHEMAS_DIR } from './paths.js';
25
+ import { behaviorGate } from './behavior-gate.js';
26
+
27
+ let cached: Record<string, unknown> | null | undefined;
28
+ export async function v2Discovery(): Promise<Record<string, unknown> | null> {
29
+ if (cached !== undefined) return cached;
30
+ const res = await driver.get('/.well-known/openwop', { authenticated: false, headers: { 'OpenWOP-Version': '2.0' } });
31
+ cached = res.status === 200 && res.json && typeof res.json === 'object' ? (res.json as Record<string, unknown>) : null;
32
+ return cached;
33
+ }
34
+ export function resetV2Discovery(): void { cached = undefined; }
35
+
36
+ export async function familyAdvertised(key: string): Promise<Record<string, unknown> | null> {
37
+ const doc = await v2Discovery();
38
+ const rec = doc?.[key];
39
+ return rec && typeof rec === 'object' && !Array.isArray(rec) ? (rec as Record<string, unknown>) : null;
40
+ }
41
+
42
+ export async function gateFamily(key: string): Promise<Record<string, unknown> | null> {
43
+ const rec = await familyAdvertised(key);
44
+ return behaviorGate(`family.${key}`, rec !== null) ? rec : null;
45
+ }
46
+
47
+ let ajv: Ajv2020 | undefined;
48
+ function v2Ajv(): Ajv2020 {
49
+ if (ajv) return ajv;
50
+ ajv = new Ajv2020({ allErrors: true, strict: false });
51
+ addFormats(ajv);
52
+ const root = join(SCHEMAS_DIR, 'v2');
53
+ const walk = (d: string): string[] => readdirSync(d).flatMap((n) => { const p = join(d, n); return statSync(p).isDirectory() ? walk(p) : p.endsWith('.schema.json') ? [p] : []; });
54
+ for (const p of walk(root)) { try { ajv.addSchema(JSON.parse(readFileSync(p, 'utf8')) as Record<string, unknown>); } catch { /* a duplicate $id is registered once */ } }
55
+ return ajv;
56
+ }
57
+ export function v2Validator(name: string): (doc: unknown) => { ok: boolean; errors: string } {
58
+ const id = `https://openwop.dev/spec/v2/${name.endsWith('.schema.json') ? name : `${name}.schema.json`}`;
59
+ const a = v2Ajv();
60
+ const validate = a.getSchema(id) ?? a.compile(JSON.parse(readFileSync(join(SCHEMAS_DIR, 'v2', ...name.split('/')), 'utf8')) as Record<string, unknown>);
61
+ return (doc: unknown) => ({ ok: validate(doc) as boolean, errors: a.errorsText(validate.errors, { separator: '; ' }) });
62
+ }
@@ -34,6 +34,7 @@
34
34
 
35
35
  import { describe, it, expect, beforeAll, afterAll } from 'vitest';
36
36
  import { A2AFakePeer } from '../lib/a2a-fake-peer.js';
37
+ import { req } from '../lib/requirement-ids.js';
37
38
 
38
39
  export const HOST_CALLBACK_NOT_REQUIRED = 'the suite drives both ends itself: it boots the dual-era A2AFakePeer in-process and reads its agent card directly; no host connection is originated';
39
40
 
@@ -57,24 +58,24 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
57
58
  expect(res.status).toBe(200);
58
59
  const card = (await res.json()) as Record<string, unknown>;
59
60
  const ifaces = card['supportedInterfaces'] as Array<{ url: string; protocolBinding: string; protocolVersion: string }>;
60
- expect(Array.isArray(ifaces) && ifaces.length > 0, '1.0 REQUIRES supportedInterfaces[]').toBe(true);
61
+ expect(Array.isArray(ifaces) && ifaces.length > 0, req('openwop.it.a2a-1-0-agent-card.the-agent-card-is-1-0-shaped-supportedinterfaces-no-top-level-url-protocolversio', 'RFC 0152 §A/§B/§C/§D', '1.0 REQUIRES supportedInterfaces[]')).toBe(true);
61
62
  expect(ifaces.map((i) => i.protocolVersion)).toEqual(['1.0', '0.3']);
62
63
  for (const i of ifaces) {
63
64
  expect(i.protocolBinding).toBe('JSONRPC');
64
65
  expect(i.url.startsWith(peer.endpoint())).toBe(true);
65
66
  }
66
- expect(card['url'], '1.0 removed top-level url').toBeUndefined();
67
- expect(card['protocolVersion'], '1.0 removed top-level protocolVersion (it is per interface)').toBeUndefined();
67
+ expect(card['url'], req('openwop.it.a2a-1-0-agent-card.the-agent-card-is-1-0-shaped-supportedinterfaces-no-top-level-url-protocolversio', 'RFC 0152 §A/§B/§C/§D', '1.0 removed top-level url')).toBeUndefined();
68
+ expect(card['protocolVersion'], req('openwop.it.a2a-1-0-agent-card.the-agent-card-is-1-0-shaped-supportedinterfaces-no-top-level-url-protocolversio', 'RFC 0152 §A/§B/§C/§D', '1.0 removed top-level protocolVersion (it is per interface)')).toBeUndefined();
68
69
  const caps = card['capabilities'] as Record<string, unknown>;
69
70
  expect(caps['extendedAgentCard']).toBe(false);
70
- expect(Array.isArray(card['skills']) && (card['skills'] as unknown[]).length > 0, 'skills[] REQUIRED').toBe(true);
71
- for (const k of ['name', 'description', 'version', 'defaultInputModes', 'defaultOutputModes']) expect(card[k], `${k} REQUIRED`).toBeDefined();
71
+ expect(Array.isArray(card['skills']) && (card['skills'] as unknown[]).length > 0, req('openwop.it.a2a-1-0-agent-card.the-agent-card-is-1-0-shaped-supportedinterfaces-no-top-level-url-protocolversio', 'RFC 0152 §A/§B/§C/§D', 'skills[] REQUIRED')).toBe(true);
72
+ for (const k of ['name', 'description', 'version', 'defaultInputModes', 'defaultOutputModes']) expect(card[k], req('openwop.it.a2a-1-0-agent-card.the-agent-card-is-1-0-shaped-supportedinterfaces-no-top-level-url-protocolversio', 'RFC 0152 §A/§B/§C/§D', `${k} REQUIRED`)).toBeDefined();
72
73
  });
73
74
 
74
75
  it('the card shape follows the era asked for: A2A-Version: 0.3 on the GET returns the 0.3 card from the same peer', async () => {
75
76
  const res = await fetch(`${peer.endpoint()}/.well-known/agent-card.json`, { headers: { 'A2A-Version': '0.3' } });
76
77
  const card = (await res.json()) as Record<string, unknown>;
77
- expect(card['protocolVersion']).toBe('0.3.0');
78
+ expect(card['protocolVersion'], req('openwop.it.a2a-1-0-agent-card.the-card-shape-follows-the-era-asked-for-a2a-version-0-3-on-the-get-returns-the', 'RFC 0152 §A/§B/§C/§D', 'the card shape follows the era asked for: A2A-Version: 0.3 on the GET returns the 0.3 card from the same peer')).toBe('0.3.0');
78
79
  expect(typeof card['url']).toBe('string');
79
80
  expect(card['supportedInterfaces']).toBeUndefined();
80
81
  // and the default-constructed peer (0.3-first) serves the 0.3 card to a header-less GET
@@ -95,7 +96,7 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
95
96
  await legacy.start(0);
96
97
  try {
97
98
  const card = (await (await fetch(`${legacy.endpoint()}/.well-known/agent-card.json`)).json()) as Record<string, unknown>;
98
- expect(card['protocolVersion']).toBe('0.3.0');
99
+ expect(card['protocolVersion'], req('openwop.it.a2a-1-0-agent-card.a-legacy-only-peer-serves-the-0-3-card-shape-follows-revision-not-calendar', 'RFC 0152 §A/§B/§C/§D', 'a legacy-only peer serves the 0.3 card — shape follows revision, not calendar')).toBe('0.3.0');
99
100
  expect(typeof card['url']).toBe('string');
100
101
  expect(card['supportedInterfaces']).toBeUndefined();
101
102
  } finally {
@@ -105,14 +106,14 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
105
106
 
106
107
  it('A2A-Version absent ⇒ 0.3 semantics; message/send returns a 0.3 task', async () => {
107
108
  const r = await rpc(peer.endpoint(), 'message/send', { message: { kind: 'message', messageId: 'm1', role: 'user', parts: [{ kind: 'text', text: 'hi' }] } });
108
- expect(r.error).toBeUndefined();
109
+ expect(r.error, req('openwop.it.a2a-1-0-agent-card.a2a-version-absent-0-3-semantics-message-send-returns-a-0-3-task', 'RFC 0152 §A/§B/§C/§D', 'A2A-Version absent ⇒ 0.3 semantics; message/send returns a 0.3 task')).toBeUndefined();
109
110
  expect(r.result?.['kind']).toBe('task');
110
111
  expect((r.result?.['status'] as { state: string }).state).toBe('submitted');
111
112
  });
112
113
 
113
114
  it('an unsupported version fails -32009 VERSION_NOT_SUPPORTED with supportedVersions[] (HTTP 400)', async () => {
114
115
  const r = await rpc(peer.endpoint(), 'SendMessage', { message: { messageId: 'm2', role: 'ROLE_USER', parts: [{ text: 'hi' }] } }, '99.0');
115
- expect(r.status).toBe(400);
116
+ expect(r.status, req('openwop.it.a2a-1-0-agent-card.an-unsupported-version-fails-32009-version-not-supported-with-supportedversions', 'RFC 0152 §A/§B/§C/§D', 'an unsupported version fails -32009 VERSION_NOT_SUPPORTED with supportedVersions[] (HTTP 400)')).toBe(400);
116
117
  expect(r.error?.code).toBe(-32009);
117
118
  expect(r.error?.data?.['reason']).toBe('VERSION_NOT_SUPPORTED');
118
119
  expect(r.error?.data?.['supportedVersions']).toEqual(['1.0', '0.3']); // constructor order
@@ -123,7 +124,7 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
123
124
  await only10.start(0);
124
125
  try {
125
126
  const r = await rpc(only10.endpoint(), 'message/send', { message: { parts: [] } });
126
- expect(r.error?.code).toBe(-32009);
127
+ expect(r.error?.code, req('openwop.it.a2a-1-0-agent-card.a-1-0-only-peer-rejects-a-header-less-request-which-is-0-3-by-rule', 'RFC 0152 §A/§B/§C/§D', 'a 1.0-only peer rejects a header-less request (which is 0.3 by rule)')).toBe(-32009);
127
128
  expect(r.error?.data?.['requested']).toBe('0.3');
128
129
  } finally {
129
130
  await only10.stop();
@@ -135,8 +136,8 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
135
136
  const r = await rpc(peer.endpoint(), 'SendMessage', { message: { messageId: 'm3', role: 'ROLE_USER', parts: [{ text: 'hello 1.0' }] } }, '1.0');
136
137
  expect(r.error).toBeUndefined();
137
138
  const task = r.result?.['task'] as Record<string, unknown>;
138
- expect(task, 'SendMessageResponse is a oneof payload: { task } | { message }').toBeDefined();
139
- expect(task['kind'], '1.0 removed the kind discriminator').toBeUndefined();
139
+ expect(task, req('openwop.it.a2a-1-0-agent-card.sendmessage-1-0-returns-task-with-task-state-role-part-oneof-no-kind-status-time', 'RFC 0152 §A/§B/§C/§D', 'SendMessageResponse is a oneof payload: { task } | { message }')).toBeDefined();
140
+ expect(task['kind'], req('openwop.it.a2a-1-0-agent-card.sendmessage-1-0-returns-task-with-task-state-role-part-oneof-no-kind-status-time', 'RFC 0152 §A/§B/§C/§D', '1.0 removed the kind discriminator')).toBeUndefined();
140
141
  const status = task['status'] as { state: string; timestamp?: string };
141
142
  expect(status.state).toBe('TASK_STATE_SUBMITTED');
142
143
  expect(typeof status.timestamp).toBe('string');
@@ -144,7 +145,7 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
144
145
  expect(history[0]?.['role']).toBe('ROLE_USER');
145
146
  const part = (history[0]?.['parts'] as Array<Record<string, unknown>>)[0]!;
146
147
  expect(part['text']).toBe('hello 1.0');
147
- expect(part['kind'], 'Part is a oneof — discriminate by member presence').toBeUndefined();
148
+ expect(part['kind'], req('openwop.it.a2a-1-0-agent-card.sendmessage-1-0-returns-task-with-task-state-role-part-oneof-no-kind-status-time', 'RFC 0152 §A/§B/§C/§D', 'Part is a oneof — discriminate by member presence')).toBeUndefined();
148
149
  expect(Array.isArray(task['artifacts'])).toBe(true);
149
150
  });
150
151
 
@@ -153,7 +154,7 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
153
154
  const sent = await rpc(peer.endpoint(), 'SendMessage', { message: { messageId: 'm4', role: 'ROLE_USER', parts: [{ text: 'x' }] } }, '1.0');
154
155
  const id = (sent.result?.['task'] as { id: string }).id;
155
156
  const got = await rpc(peer.endpoint(), 'GetTask', { id }, '1.0');
156
- expect((got.result as { status: { state: string } }).status.state).toBe('TASK_STATE_SUBMITTED');
157
+ expect((got.result as { status: { state: string } }).status.state, req('openwop.it.a2a-1-0-agent-card.gettask-canceltask-listtasks-per-d-1-incl-task-not-cancelable-on-a-terminal-task', 'RFC 0152 §A/§B/§C/§D', 'GetTask / CancelTask / ListTasks per §D.1, incl. TASK_NOT_CANCELABLE on a terminal task')).toBe('TASK_STATE_SUBMITTED');
157
158
  const listed = await rpc(peer.endpoint(), 'ListTasks', { status: 'TASK_STATE_SUBMITTED' }, '1.0');
158
159
  expect((listed.result as { totalSize: number }).totalSize).toBe(1);
159
160
  const cancelled = await rpc(peer.endpoint(), 'CancelTask', { id }, '1.0');
@@ -168,12 +169,12 @@ describe('RFC 0152 — the suite peer speaks A2A 1.0 (dual-era A2AFakePeer)', ()
168
169
 
169
170
  it('a 0.3 method name under a 1.0 header is method-not-found — loudly', async () => {
170
171
  const r = await rpc(peer.endpoint(), 'message/send', { message: { parts: [] } }, '1.0');
171
- expect(r.status).toBe(404);
172
+ expect(r.status, req('openwop.it.a2a-1-0-agent-card.a-0-3-method-name-under-a-1-0-header-is-method-not-found-loudly', 'RFC 0152 §A/§B/§C/§D', 'a 0.3 method name under a 1.0 header is method-not-found — loudly')).toBe(404);
172
173
  expect(r.error?.code).toBe(-32601);
173
174
  });
174
175
 
175
176
  it('streaming is honestly unsupported: SubscribeToTask ⇒ UNSUPPORTED_OPERATION, matching capabilities.streaming=false', async () => {
176
177
  const r = await rpc(peer.endpoint(), 'SubscribeToTask', { id: 'task-1' }, '1.0');
177
- expect(r.error?.code).toBe(-32004);
178
+ expect(r.error?.code, req('openwop.it.a2a-1-0-agent-card.streaming-is-honestly-unsupported-subscribetotask-unsupported-operation-matching', 'RFC 0152 §A/§B/§C/§D', 'streaming is honestly unsupported: SubscribeToTask ⇒ UNSUPPORTED_OPERATION, matching capabilities.streaming=false')).toBe(-32004);
178
179
  });
179
180
  });
@@ -27,6 +27,7 @@ import { describe, it, expect } from 'vitest';
27
27
  import { driver } from '../lib/driver.js';
28
28
  import { behaviorGate } from '../lib/behavior-gate.js';
29
29
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
30
+ import { req } from '../lib/requirement-ids.js';
30
31
 
31
32
  const PROFILE = 'a2a-1.0';
32
33
  const STATES_10 = [
@@ -75,27 +76,27 @@ describe('RFC 0152 §D — a2a-1.0-task-roundtrip (host as A2A 1.0 server, gated
75
76
  it('SendMessage @1.0 creates a task whose id is the runId, in 1.0 spelling; GetTask reads it back; unknown id is TASK_NOT_FOUND', async () => {
76
77
  if (!behaviorGate(PROFILE, await claims10())) return;
77
78
  const url = await jsonrpc10Url();
78
- expect(url, driver.describe('a2a-integration.md §C', 'a `a2a-1.0` host MUST publish a JSONRPC/1.0 interface in its card')).not.toBeNull();
79
+ expect(url, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §C', 'a `a2a-1.0` host MUST publish a JSONRPC/1.0 interface in its card')).not.toBeNull();
79
80
  const sent = await rpc10(url!, 'SendMessage', {
80
81
  message: { messageId: `conf-${Date.now()}`, role: 'ROLE_USER', parts: [{ text: 'openwop conformance a2a-1.0 roundtrip' }] },
81
82
  configuration: { returnImmediately: true },
82
83
  }, 1);
83
- expect(sent.status, driver.describe('a2a-integration.md §D.1', 'SendMessage MUST be accepted on the 1.0 interface')).toBe(200);
84
- expect(sent.error, driver.describe('a2a-integration.md §D.1', `SendMessage MUST NOT error: ${JSON.stringify(sent.error)}`)).toBeUndefined();
84
+ expect(sent.status, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.1', 'SendMessage MUST be accepted on the 1.0 interface')).toBe(200);
85
+ expect(sent.error, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.1', `SendMessage MUST NOT error: ${JSON.stringify(sent.error)}`)).toBeUndefined();
85
86
  const result = sent.result ?? {};
86
87
  // SendMessageResponse is a oneof: { task } | { message }. A run-creating host answers with a task.
87
88
  const task = (result['task'] ?? (result['id'] !== undefined ? result : undefined)) as { id?: string; contextId?: string; status?: { state?: string; timestamp?: string }; history?: Array<{ role?: string; parts?: Array<Record<string, unknown>> }>; kind?: unknown } | undefined;
88
- expect(task, driver.describe('a2a-integration.md §D.1', 'SendMessage without taskId MUST create a run and return `{ task }`')).toBeDefined();
89
- expect(task!.kind, driver.describe('a2a-integration.md §D.5', '1.0 has no `kind` discriminator')).toBeUndefined();
89
+ expect(task, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.1', 'SendMessage without taskId MUST create a run and return `{ task }`')).toBeDefined();
90
+ expect(task!.kind, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.5', '1.0 has no `kind` discriminator')).toBeUndefined();
90
91
  expect(typeof task!.id).toBe('string');
91
- expect(STATES_10, driver.describe('a2a-integration.md §D.4', 'status.state MUST use the 1.0 TASK_STATE_* spelling')).toContain(task!.status?.state);
92
+ expect(STATES_10, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.4', 'status.state MUST use the 1.0 TASK_STATE_* spelling')).toContain(task!.status?.state);
92
93
  for (const m of task!.history ?? []) {
93
- expect(['ROLE_USER', 'ROLE_AGENT'], driver.describe('a2a-integration.md §D.2', 'history roles are ROLE_*')).toContain(m.role);
94
- for (const p of m.parts ?? []) expect(p['kind'], driver.describe('a2a-integration.md §D.3', 'Part is a oneof — no `kind`')).toBeUndefined();
94
+ expect(['ROLE_USER', 'ROLE_AGENT'], req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.2', 'history roles are ROLE_*')).toContain(m.role);
95
+ for (const p of m.parts ?? []) expect(p['kind'], req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.3', 'Part is a oneof — no `kind`')).toBeUndefined();
95
96
  }
96
97
  // Task.id IS the runId (RFC 0100): the OpenWOP snapshot for it MUST exist for the same caller.
97
98
  const snap = await driver.get(`/v1/runs/${encodeURIComponent(task!.id!)}`);
98
- expect(snap.status, driver.describe('a2a-integration.md §D.4', '`Task.id` MUST be the backing runId — GET /v1/runs/{id} resolves it for the same principal')).toBe(200);
99
+ expect(snap.status, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.4', '`Task.id` MUST be the backing runId — GET /v1/runs/{id} resolves it for the same principal')).toBe(200);
99
100
  // GetTask reads it back with the same id and a valid 1.0 state.
100
101
  const got = await rpc10(url!, 'GetTask', { id: task!.id }, 2);
101
102
  expect(got.error).toBeUndefined();
@@ -104,7 +105,7 @@ describe('RFC 0152 §D — a2a-1.0-task-roundtrip (host as A2A 1.0 server, gated
104
105
  expect(STATES_10).toContain(gotTask.status?.state);
105
106
  // Unknown id — and, per §E, a cross-tenant id — MUST be TASK_NOT_FOUND, never forbidden.
106
107
  const missing = await rpc10(url!, 'GetTask', { id: `run_does_not_exist_${Date.now()}` }, 3);
107
- expect(missing.error?.code, driver.describe('a2a-integration.md §D.7/§E', 'an unknown or unreadable task MUST be TASK_NOT_FOUND (-32001) — no enumeration')).toBe(-32001);
108
+ expect(missing.error?.code, req('openwop.it.a2a-1-0-task-roundtrip.sendmessage-1-0-creates-a-task-whose-id-is-the-runid-in-1-0-spelling-gettask-rea', 'a2a-integration.md §D.7/§E', 'an unknown or unreadable task MUST be TASK_NOT_FOUND (-32001) — no enumeration')).toBe(-32001);
108
109
  // Tidy: cancel the run we created (best effort; terminal runs answer TASK_NOT_CANCELABLE which is fine).
109
110
  await rpc10(url!, 'CancelTask', { id: task!.id }, 4);
110
111
  });
@@ -29,6 +29,7 @@ import { softSkip } from '../lib/soft-skip.js';
29
29
  import { driver } from '../lib/driver.js';
30
30
  import { behaviorGate } from '../lib/behavior-gate.js';
31
31
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
32
+ import { req } from '../lib/requirement-ids.js';
32
33
 
33
34
  const PROFILE = 'a2a-1.0';
34
35
 
@@ -81,14 +82,14 @@ describe('RFC 0152 §C — a2a-card-runtime-consistent (gated on a2a.profiles
81
82
  if (!behaviorGate(PROFILE, await claims10())) return;
82
83
  const caps = (await a2a())!;
83
84
  const card = await fetchCard(caps);
84
- expect(card, driver.describe('a2a-integration.md §C', '`agentCardUrl` MUST resolve to the Agent Card (200)')).not.toBeNull();
85
+ expect(card, req('openwop.it.a2a-card-runtime-consistency.the-card-is-1-0-shaped-and-reachable-at-agentcardurl', 'a2a-integration.md §C', '`agentCardUrl` MUST resolve to the Agent Card (200)')).not.toBeNull();
85
86
  expect(
86
87
  Array.isArray(card!.supportedInterfaces) && card!.supportedInterfaces!.length > 0,
87
- driver.describe('a2a-integration.md §C', 'a host claiming `a2a-1.0` MUST publish a 1.0 card: `supportedInterfaces[]` REQUIRED (≥1)'),
88
+ req('openwop.it.a2a-card-runtime-consistency.the-card-is-1-0-shaped-and-reachable-at-agentcardurl', 'a2a-integration.md §C', 'a host claiming `a2a-1.0` MUST publish a 1.0 card: `supportedInterfaces[]` REQUIRED (≥1)'),
88
89
  ).toBe(true);
89
- expect(card!.url, driver.describe('a2a-integration.md §C', '1.0 removed the top-level `url` — a card with both shapes is neither')).toBeUndefined();
90
- expect(card!.protocolVersion, driver.describe('a2a-integration.md §C', '1.0 removed the top-level `protocolVersion` (per interface now)')).toBeUndefined();
91
- expect(Array.isArray(card!.skills) && card!.skills!.length > 0, driver.describe('a2a-integration.md §C', '`skills[]` MUST be non-empty — one per invocable workflow')).toBe(true);
90
+ expect(card!.url, req('openwop.it.a2a-card-runtime-consistency.the-card-is-1-0-shaped-and-reachable-at-agentcardurl', 'a2a-integration.md §C', '1.0 removed the top-level `url` — a card with both shapes is neither')).toBeUndefined();
91
+ expect(card!.protocolVersion, req('openwop.it.a2a-card-runtime-consistency.the-card-is-1-0-shaped-and-reachable-at-agentcardurl', 'a2a-integration.md §C', '1.0 removed the top-level `protocolVersion` (per interface now)')).toBeUndefined();
92
+ expect(Array.isArray(card!.skills) && card!.skills!.length > 0, req('openwop.it.a2a-card-runtime-consistency.the-card-is-1-0-shaped-and-reachable-at-agentcardurl', 'a2a-integration.md §C', '`skills[]` MUST be non-empty — one per invocable workflow')).toBe(true);
92
93
  });
93
94
 
94
95
  it('a header-less card GET returns the 0.3-shaped card while a2a-0.3-legacy is advertised (§B receiver rule applied to discovery — S18 Q1)', async () => {
@@ -97,17 +98,17 @@ describe('RFC 0152 §C — a2a-card-runtime-consistent (gated on a2a.profiles
97
98
  if (typeof caps.agentCardUrl !== 'string') return softSkip('blocked', 'no agentCardUrl advertised');
98
99
  const legacy = (caps.protocolVersions ?? []).includes('0.3');
99
100
  const res = await fetch(caps.agentCardUrl, { headers: { accept: 'application/json' } });
100
- expect(res.status, driver.describe('a2a-integration.md §C', 'a header-less card GET MUST succeed — discovery must not fail')).toBe(200);
101
+ expect(res.status, req('openwop.it.a2a-card-runtime-consistency.a-header-less-card-get-returns-the-0-3-shaped-card-while-a2a-0-3-legacy-is-adver', 'a2a-integration.md §C', 'a header-less card GET MUST succeed — discovery must not fail')).toBe(200);
101
102
  const card = (await res.json()) as Card10 & { url?: string; protocolVersion?: string };
102
103
  if (legacy) {
103
104
  // While 0.3 is advertised the header-less card is the 0.3 shape: an
104
105
  // external 0.3 client reading `card.url` keeps working through the
105
106
  // legacy window — the point of advertising `a2a-0.3-legacy` at all.
106
- expect(typeof card.url, driver.describe('a2a-integration.md §C', 'header-less = 0.3 (§B receiver rule): the card MUST carry the 0.3 top-level `url` while `protocolVersions ∋ 0.3`')).toBe('string');
107
- expect(card.supportedInterfaces, driver.describe('a2a-integration.md §C', 'the header-less card MUST NOT be the 1.0 shape while 0.3 is advertised (a card with both shapes is neither)')).toBeUndefined();
107
+ expect(typeof card.url, req('openwop.it.a2a-card-runtime-consistency.a-header-less-card-get-returns-the-0-3-shaped-card-while-a2a-0-3-legacy-is-adver', 'a2a-integration.md §C', 'header-less = 0.3 (§B receiver rule): the card MUST carry the 0.3 top-level `url` while `protocolVersions ∋ 0.3`')).toBe('string');
108
+ expect(card.supportedInterfaces, req('openwop.it.a2a-card-runtime-consistency.a-header-less-card-get-returns-the-0-3-shaped-card-while-a2a-0-3-legacy-is-adver', 'a2a-integration.md §C', 'the header-less card MUST NOT be the 1.0 shape while 0.3 is advertised (a card with both shapes is neither)')).toBeUndefined();
108
109
  } else {
109
110
  // 0.3 dropped: the preferred-version (1.0) card is served header-less.
110
- expect(Array.isArray(card.supportedInterfaces) && card.supportedInterfaces!.length > 0, driver.describe('a2a-integration.md §C', 'with 0.3 dropped, the header-less card is the preferredVersion (1.0) card')).toBe(true);
111
+ expect(Array.isArray(card.supportedInterfaces) && card.supportedInterfaces!.length > 0, req('openwop.it.a2a-card-runtime-consistency.a-header-less-card-get-returns-the-0-3-shaped-card-while-a2a-0-3-legacy-is-adver', 'a2a-integration.md §C', 'with 0.3 dropped, the header-less card is the preferredVersion (1.0) card')).toBe(true);
111
112
  }
112
113
  });
113
114
 
@@ -115,12 +116,12 @@ describe('RFC 0152 §C — a2a-card-runtime-consistent (gated on a2a.profiles
115
116
  if (!behaviorGate(PROFILE, await claims10())) return;
116
117
  const caps = (await a2a())!;
117
118
  const card = await fetchCard(caps);
118
- if (card === null) return; // asserted above
119
+ if (card === null) return softSkip('blocked', 'precondition not met — `card === null` returned early (asserted above) (seam, prior step, or fixture unavailable)'); // asserted above
119
120
  const fromCard = [...new Set((card.supportedInterfaces ?? []).map((i) => i.protocolVersion).filter((v): v is string => typeof v === 'string'))].sort();
120
121
  const fromDiscovery = [...new Set(caps.protocolVersions ?? [])].sort();
121
122
  expect(
122
123
  fromCard,
123
- driver.describe(
124
+ req('openwop.it.a2a-card-runtime-consistency.the-set-of-supportedinterfaces-protocolversion-equals-capabilities-a2a-protocolv',
124
125
  'a2a-integration.md §C',
125
126
  'the SET of `supportedInterfaces[].protocolVersion` MUST equal `capabilities.a2a.protocolVersions` — two documents, one fact; ' +
126
127
  'a version advertised in one and not the other is card/runtime drift (`a2a-card-runtime-consistent`)',
@@ -132,14 +133,14 @@ describe('RFC 0152 §C — a2a-card-runtime-consistent (gated on a2a.profiles
132
133
  if (!behaviorGate(PROFILE, await claims10())) return;
133
134
  const caps = (await a2a())!;
134
135
  const card = await fetchCard(caps);
135
- if (card === null) return;
136
+ if (card === null) return softSkip('blocked', 'precondition not met — `card === null` returned early (seam, prior step, or fixture unavailable)');
136
137
  const ifaces = card.supportedInterfaces ?? [];
137
138
  expect(
138
139
  ifaces.some((i) => i.protocolBinding === 'JSONRPC' && i.protocolVersion === '1.0' && typeof i.url === 'string'),
139
- driver.describe('a2a-integration.md §C', 'the `a2a-1.0` profile floor is the JSON-RPC binding at 1.0; HTTP+JSON / gRPC are optional additions'),
140
+ req('openwop.it.a2a-card-runtime-consistency.a2a-1-0-must-serve-the-json-rpc-binding-at-1-0-the-mandatory-floor-and-should-li', 'a2a-integration.md §C', 'the `a2a-1.0` profile floor is the JSON-RPC binding at 1.0; HTTP+JSON / gRPC are optional additions'),
140
141
  ).toBe(true);
141
142
  for (const i of ifaces) {
142
- expect(['JSONRPC', 'GRPC', 'HTTP+JSON'], driver.describe('a2a-integration.md §C', 'protocolBinding uses the upstream binding names')).toContain(i.protocolBinding);
143
+ expect(['JSONRPC', 'GRPC', 'HTTP+JSON'], req('openwop.it.a2a-card-runtime-consistency.a2a-1-0-must-serve-the-json-rpc-binding-at-1-0-the-mandatory-floor-and-should-li', 'a2a-integration.md §C', 'protocolBinding uses the upstream binding names')).toContain(i.protocolBinding);
143
144
  }
144
145
  if (typeof caps.preferredVersion === 'string' && ifaces.length > 0) {
145
146
  // SHOULD, so a soft expectation: report, do not fail.
@@ -154,14 +155,14 @@ describe('RFC 0152 §C — a2a-card-runtime-consistent (gated on a2a.profiles
154
155
  if (!behaviorGate(PROFILE, await claims10())) return;
155
156
  const caps = (await a2a())!;
156
157
  const card = await fetchCard(caps);
157
- if (card === null) return;
158
+ if (card === null) return softSkip('blocked', 'precondition not met — `card === null` returned early (seam, prior step, or fixture unavailable)');
158
159
  expect(
159
160
  card.capabilities?.streaming === true,
160
- driver.describe('a2a-integration.md §C', '`capabilities.streaming` on the card MUST equal `capabilities.a2a.streaming` on discovery'),
161
+ req('openwop.it.a2a-card-runtime-consistency.card-capabilities-streaming-pushnotifications-equal-the-discovery-flags', 'a2a-integration.md §C', '`capabilities.streaming` on the card MUST equal `capabilities.a2a.streaming` on discovery'),
161
162
  ).toBe(caps.streaming === true);
162
163
  expect(
163
164
  card.capabilities?.pushNotifications === true,
164
- driver.describe('a2a-integration.md §C', '`capabilities.pushNotifications` on the card MUST equal `capabilities.a2a.pushNotifications`'),
165
+ req('openwop.it.a2a-card-runtime-consistency.card-capabilities-streaming-pushnotifications-equal-the-discovery-flags', 'a2a-integration.md §C', '`capabilities.pushNotifications` on the card MUST equal `capabilities.a2a.pushNotifications`'),
165
166
  ).toBe(caps.pushNotifications === true);
166
167
  });
167
168
  });
@@ -33,6 +33,7 @@ import { driver } from '../lib/driver.js';
33
33
  import { behaviorGate } from '../lib/behavior-gate.js';
34
34
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
35
35
  import { getA2AFakePeer } from '../lib/a2a-fake-peer.js';
36
+ import { req } from '../lib/requirement-ids.js';
36
37
 
37
38
  export const REQUIRES_HOST_CALLBACK = "the host issues A2A JSON-RPC calls to the suite's fake peer via /v1/host/sample/a2a/invoke (peerUrl), which the peer records";
38
39
 
@@ -75,25 +76,25 @@ describe('RFC 0152 §E — a2a-peer-no-authority-escalation (host as A2A client,
75
76
  // The peer must actually have answered with the authority-asserting message,
76
77
  // or this leg is vacuous.
77
78
  const created = peer.taskCount();
78
- expect(created, driver.describe('RFCS/0152 §E', 'the host MUST have created a task on the peer for this leg to mean anything')).toBeGreaterThan(0);
79
+ expect(created, req('openwop.it.a2a-peer-authority.a-peer-reply-that-asserts-approval-scopes-and-a-foreign-task-reference-changes-n', 'RFCS/0152 §E', 'the host MUST have created a task on the peer for this leg to mean anything')).toBeGreaterThan(0);
79
80
  const report = (drive.json as { peerAuthority?: PeerAuthorityReport }).peerAuthority;
80
81
  if (report === undefined) {
81
82
  // Additive seam field not yet implemented: blocked, not passed.
82
83
  expect(
83
84
  report,
84
- driver.describe(
85
+ req('openwop.it.a2a-peer-authority.a-peer-reply-that-asserts-approval-scopes-and-a-foreign-task-reference-changes-n',
85
86
  'host-sample-test-seams.md §22',
86
87
  'the invoke seam SHOULD report `peerAuthority: { approvalAdvanced, scopesWidened, referencedTaskDereferenced }` for ' +
87
88
  'scenario "peer-asserts-authority"; until it does this requirement is unobservable and resolves to `blocked`, not passed',
88
89
  ),
89
90
  ).toBeDefined();
90
- return;
91
+ return softSkip('blocked', 'precondition not met — `report === undefined` returned early (seam, prior step, or fixture unavailable)');
91
92
  }
92
- expect(report.approvalAdvanced, driver.describe('RFCS/0152 §E', 'peer content MUST NOT advance an approval gate (a2a-peer-no-authority-escalation)')).toBe(false);
93
- expect(report.scopesWidened, driver.describe('RFCS/0152 §E', 'peer content MUST NOT widen the run’s scopes or tool allowlist')).toBe(false);
93
+ expect(report.approvalAdvanced, req('openwop.it.a2a-peer-authority.a-peer-reply-that-asserts-approval-scopes-and-a-foreign-task-reference-changes-n', 'RFCS/0152 §E', 'peer content MUST NOT advance an approval gate (a2a-peer-no-authority-escalation)')).toBe(false);
94
+ expect(report.scopesWidened, req('openwop.it.a2a-peer-authority.a-peer-reply-that-asserts-approval-scopes-and-a-foreign-task-reference-changes-n', 'RFCS/0152 §E', 'peer content MUST NOT widen the run’s scopes or tool allowlist')).toBe(false);
94
95
  expect(
95
96
  report.referencedTaskDereferenced,
96
- driver.describe('a2a-integration.md §D.2', '`referenceTaskIds[]` are opaque hints — MUST NOT be dereferenced on the peer’s say-so'),
97
+ req('openwop.it.a2a-peer-authority.a-peer-reply-that-asserts-approval-scopes-and-a-foreign-task-reference-changes-n', 'a2a-integration.md §D.2', '`referenceTaskIds[]` are opaque hints — MUST NOT be dereferenced on the peer’s say-so'),
97
98
  ).toBe(false);
98
99
  });
99
100
  });