@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
@@ -23,6 +23,8 @@ import { describe, it, expect } from 'vitest';
23
23
  import { driver } from '../lib/driver.js';
24
24
  import { behaviorGate } from '../lib/behavior-gate.js';
25
25
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
26
+ import { req } from '../lib/requirement-ids.js';
27
+ import { softSkip } from '../lib/soft-skip.js';
26
28
 
27
29
  const SEAM = '/v1/host/sample/agents/verify-run';
28
30
 
@@ -48,26 +50,26 @@ describe('verifier-gating (RFC 0090 §B)', () => {
48
50
 
49
51
  // FAIL verdict → must NOT complete as success; agent.verified{fail} emitted.
50
52
  const failRes = await driver.post(SEAM, { simulateVerdict: 'fail' });
51
- if (failRes.status === 404) return; // seam unwired — soft-skip
53
+ if (failRes.status === 404) return softSkip('blocked', 'precondition not met — `failRes.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
52
54
  expect(
53
55
  verifiedVerdict(failRes.json) === 'fail',
54
- driver.describe('RFC 0090 §A', 'a verify-run forcing a fail MUST emit agent.verified{verdict:"fail"}'),
56
+ req('openwop.it.verifier-gating.a-fail-verdict-blocks-commit-on-a-gating-host-a-pass-verdict-completes', 'RFC 0090 §A', 'a verify-run forcing a fail MUST emit agent.verified{verdict:"fail"}'),
55
57
  ).toBe(true);
56
58
  expect(
57
59
  !isSuccess(failRes.json),
58
- driver.describe('RFC 0090 §B', 'on a gating host a fail verdict MUST block commit/terminate-as-success'),
60
+ req('openwop.it.verifier-gating.a-fail-verdict-blocks-commit-on-a-gating-host-a-pass-verdict-completes', 'RFC 0090 §B', 'on a gating host a fail verdict MUST block commit/terminate-as-success'),
59
61
  ).toBe(true);
60
62
 
61
63
  // PASS verdict → completes normally.
62
64
  const passRes = await driver.post(SEAM, { simulateVerdict: 'pass' });
63
- if (passRes.status === 404) return;
65
+ if (passRes.status === 404) return softSkip('blocked', 'precondition not met — `passRes.status === 404` returned early (seam, prior step, or fixture unavailable)');
64
66
  expect(
65
67
  verifiedVerdict(passRes.json) === 'pass',
66
- driver.describe('RFC 0090 §A', 'a verify-run forcing a pass MUST emit agent.verified{verdict:"pass"}'),
68
+ req('openwop.it.verifier-gating.a-fail-verdict-blocks-commit-on-a-gating-host-a-pass-verdict-completes', 'RFC 0090 §A', 'a verify-run forcing a pass MUST emit agent.verified{verdict:"pass"}'),
67
69
  ).toBe(true);
68
70
  expect(
69
71
  isSuccess(passRes.json),
70
- driver.describe('RFC 0090 §B', 'a pass verdict MUST allow the turn to complete'),
72
+ req('openwop.it.verifier-gating.a-fail-verdict-blocks-commit-on-a-gating-host-a-pass-verdict-completes', 'RFC 0090 §B', 'a pass verdict MUST allow the turn to complete'),
71
73
  ).toBe(true);
72
74
  });
73
75
  });
@@ -39,6 +39,7 @@ import { driver, type OpenWOPResponse } from '../lib/driver.js';
39
39
  import { pollUntilTerminal } from '../lib/polling.js';
40
40
  import { isFixtureAdvertised } from '../lib/fixtures.js';
41
41
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
42
+ import { req } from '../lib/requirement-ids.js';
42
43
 
43
44
  const FIXTURE_ID = 'conformance-version-fold';
44
45
  const SKIP_NO_FIXTURE = !isFixtureAdvertised(FIXTURE_ID);
@@ -94,7 +95,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('version-fold: forced engine versions fold-best
94
95
  );
95
96
  expect(
96
97
  versions.length,
97
- driver.describe(
98
+ req('openwop.it.version-fold.each-version-in-min-current-max-completes-snapshot-and-event-log-stay-readable',
98
99
  'version-negotiation.md §Conformance via X-Force-Engine-Version',
99
100
  'forceEngineVersionRange MUST describe a non-empty integer range (min <= max)',
100
101
  ),
@@ -109,7 +110,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('version-fold: forced engine versions fold-best
109
110
  }
110
111
  expect(
111
112
  create.status,
112
- driver.describe(
113
+ req('openwop.it.version-fold.each-version-in-min-current-max-completes-snapshot-and-event-log-stay-readable',
113
114
  'version-negotiation.md §Conformance via X-Force-Engine-Version',
114
115
  `POST /v1/runs with X-Force-Engine-Version: ${v} (within the advertised range) MUST be accepted on a test key`,
115
116
  ),
@@ -120,7 +121,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('version-fold: forced engine versions fold-best
120
121
  const terminal = await pollUntilTerminal(runId);
121
122
  expect(
122
123
  terminal.status,
123
- driver.describe(
124
+ req('openwop.it.version-fold.each-version-in-min-current-max-completes-snapshot-and-event-log-stay-readable',
124
125
  'version-negotiation.md §Cross-version interop matrix',
125
126
  `the conformance-version-fold noop run MUST complete under forced engine version ${v} (fold-best-effort)`,
126
127
  ),
@@ -130,7 +131,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('version-fold: forced engine versions fold-best
130
131
  const snap = await driver.get(`/v1/runs/${encodeURIComponent(runId)}`);
131
132
  expect(
132
133
  snap.status,
133
- driver.describe(
134
+ req('openwop.it.version-fold.each-version-in-min-current-max-completes-snapshot-and-event-log-stay-readable',
134
135
  'version-negotiation.md §Cross-version interop matrix',
135
136
  `GET /v1/runs/{runId} MUST return a readable RunSnapshot under forced engine version ${v}`,
136
137
  ),
@@ -145,7 +146,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('version-fold: forced engine versions fold-best
145
146
  );
146
147
  expect(
147
148
  events.status,
148
- driver.describe(
149
+ req('openwop.it.version-fold.each-version-in-min-current-max-completes-snapshot-and-event-log-stay-readable',
149
150
  'version-negotiation.md §Conformance via X-Force-Engine-Version',
150
151
  `the event log MUST be readable via events/poll under forced engine version ${v}`,
151
152
  ),
@@ -153,7 +154,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('version-fold: forced engine versions fold-best
153
154
  const eventList = (events.json as { events?: unknown[] } | undefined)?.events ?? [];
154
155
  expect(
155
156
  eventList.length,
156
- driver.describe(
157
+ req('openwop.it.version-fold.each-version-in-min-current-max-completes-snapshot-and-event-log-stay-readable',
157
158
  'version-negotiation.md §Conformance via X-Force-Engine-Version',
158
159
  `events/poll MUST return a non-empty events[] for the forced-version run (v=${v})`,
159
160
  ),
@@ -178,14 +179,14 @@ describe.skipIf(SKIP_NO_FIXTURE)('version-fold: forced engine versions fold-best
178
179
  }
179
180
  expect(
180
181
  create.status,
181
- driver.describe(
182
+ req('openwop.it.version-fold.a-forced-version-outside-the-advertised-range-is-rejected-with-400-unsupported-f',
182
183
  'version-negotiation.md §Conformance via X-Force-Engine-Version',
183
184
  `X-Force-Engine-Version: ${outOfRange} (outside the advertised range) MUST return 400`,
184
185
  ),
185
186
  ).toBe(400);
186
187
  expect(
187
188
  errCode(create.json),
188
- driver.describe(
189
+ req('openwop.it.version-fold.a-forced-version-outside-the-advertised-range-is-rejected-with-400-unsupported-f',
189
190
  'version-negotiation.md §Conformance via X-Force-Engine-Version',
190
191
  'the out-of-range refusal MUST carry the canonical unsupported_force_engine_version code',
191
192
  ),
@@ -26,6 +26,7 @@ import { describe, it, expect } from 'vitest';
26
26
  import { driver } from '../lib/driver.js';
27
27
  import { pollUntilTerminal } from '../lib/polling.js';
28
28
  import { isFixtureAdvertised } from '../lib/fixtures.js';
29
+ import { req } from '../lib/requirement-ids.js';
29
30
 
30
31
  const NOOP_WORKFLOW_ID = 'conformance-noop';
31
32
  const SKIP_NO_NOOP = !isFixtureAdvertised(NOOP_WORKFLOW_ID);
@@ -47,7 +48,7 @@ describe('version-negotiation: Capabilities advertises a protocolVersion', () =>
47
48
  expect(res.status).toBe(200);
48
49
 
49
50
  const caps = res.json as { protocolVersion?: unknown };
50
- expect(typeof caps.protocolVersion, driver.describe(
51
+ expect(typeof caps.protocolVersion, req('openwop.it.version-negotiation.get-well-known-openwop-returns-capabilities-with-protocolversion-string',
51
52
  'capabilities.md §3 + version-negotiation.md',
52
53
  'Capabilities.protocolVersion MUST be a non-empty string',
53
54
  )).toBe('string');
@@ -69,34 +70,34 @@ describe.skipIf(SKIP_NO_NOOP)('version-negotiation: persisted events carry the c
69
70
  expect(eventsRes.status).toBe(200);
70
71
 
71
72
  const events = (eventsRes.json as { events?: RunEvent[] } | undefined)?.events ?? [];
72
- expect(events.length, 'noop run MUST emit at least one event').toBeGreaterThan(0);
73
+ expect(events.length, req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json', 'run-event.schema.json §required', 'noop run MUST emit at least one event')).toBeGreaterThan(0);
73
74
 
74
75
  for (const e of events) {
75
- expect(typeof e.eventId, driver.describe(
76
+ expect(typeof e.eventId, req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json',
76
77
  'run-event.schema.json §required',
77
78
  'eventId MUST be a string',
78
79
  )).toBe('string');
79
- expect(typeof e.runId, driver.describe(
80
+ expect(typeof e.runId, req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json',
80
81
  'run-event.schema.json §required',
81
82
  'runId MUST be a string',
82
83
  )).toBe('string');
83
- expect(typeof e.type, driver.describe(
84
+ expect(typeof e.type, req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json',
84
85
  'run-event.schema.json §required',
85
86
  'type MUST be a string (RunEventType discriminator)',
86
87
  )).toBe('string');
87
- expect(e.payload, driver.describe(
88
+ expect(e.payload, req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json',
88
89
  'run-event.schema.json §required',
89
90
  'payload MUST be present (any JSON value, including null)',
90
91
  )).not.toBe(undefined);
91
- expect(typeof e.timestamp, driver.describe(
92
+ expect(typeof e.timestamp, req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json',
92
93
  'run-event.schema.json §required',
93
94
  'timestamp MUST be an ISO 8601 string',
94
95
  )).toBe('string');
95
- expect(Number.isInteger(e.sequence), driver.describe(
96
+ expect(Number.isInteger(e.sequence), req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json',
96
97
  'run-event.schema.json §required',
97
98
  'sequence MUST be a non-negative integer',
98
99
  )).toBe(true);
99
- expect(e.sequence, 'sequence MUST be >= 0').toBeGreaterThanOrEqual(0);
100
+ expect(e.sequence, req('openwop.it.version-negotiation.every-event-has-the-6-required-runeventdoc-fields-per-run-event-schema-json', 'run-event.schema.json §required', 'sequence MUST be >= 0')).toBeGreaterThanOrEqual(0);
100
101
  }
101
102
  });
102
103
 
@@ -118,7 +119,7 @@ describe.skipIf(SKIP_NO_NOOP)('version-negotiation: persisted events carry the c
118
119
  const curr = sequences[i] ?? -1;
119
120
  expect(
120
121
  curr,
121
- driver.describe(
122
+ req('openwop.it.version-negotiation.event-sequences-within-a-run-are-strictly-monotonic',
122
123
  'run-event.schema.json §sequence + idempotency.md',
123
124
  `event[${i}].sequence (${curr}) MUST be > event[${i - 1}].sequence (${prev}) — strictly monotonic per run`,
124
125
  ),
@@ -144,7 +145,7 @@ describe.skipIf(SKIP_NO_NOOP)('version-negotiation: events/poll forward-compat t
144
145
 
145
146
  expect(
146
147
  eventsRes.status,
147
- driver.describe(
148
+ req('openwop.it.version-negotiation.events-poll-with-lastsequence-past-current-end-returns-empty-events-iscomplete',
148
149
  'rest-endpoints.md GET /v1/runs/{runId}/events/poll',
149
150
  'lastSequence beyond the current end MUST return 200 with empty events, not 4xx',
150
151
  ),
@@ -21,6 +21,8 @@ import { describe, it, expect } from 'vitest';
21
21
  import { driver } from '../lib/driver.js';
22
22
  import { behaviorGate } from '../lib/behavior-gate.js';
23
23
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
24
+ import { req } from '../lib/requirement-ids.js';
25
+ import { softSkip } from '../lib/soft-skip.js';
24
26
 
25
27
  const SEAM = '/v1/host/sample/voice/barge-in';
26
28
 
@@ -40,22 +42,22 @@ describe('voice-bargein-no-partial-leak (RFC 0106 §F INV-3)', () => {
40
42
  if (!behaviorGate('openwop-voice-bargein', advertised)) return;
41
43
 
42
44
  const res = await driver.post(SEAM, {});
43
- if (res.status === 404) return; // seam unwired — soft-skip
45
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
44
46
 
45
- expect(res.status === 200, driver.describe('RFC 0106 §F', 'the barge-in seam MUST return 200')).toBe(true);
47
+ expect(res.status === 200, req('openwop.it.voice-bargein-no-partial-leak.barge-in-cancels-with-no-synthesis-chunk-emitted-after-voice-cancelled', 'RFC 0106 §F', 'the barge-in seam MUST return 200')).toBe(true);
46
48
 
47
49
  const types = eventsOf(res.json).map((e) => e.type);
48
50
  const bargeIdx = types.indexOf('voice.barge_in');
49
51
  const cancelIdx = types.indexOf('voice.cancelled');
50
- expect(bargeIdx >= 0, driver.describe('RFC 0106 §D', 'a barge-in MUST emit voice.barge_in')).toBe(true);
51
- expect(cancelIdx >= 0, driver.describe('RFC 0106 §D', 'a barge-in that cancels work MUST emit voice.cancelled')).toBe(true);
52
- expect(cancelIdx > bargeIdx, driver.describe('RFC 0106 §D', 'voice.cancelled MUST follow voice.barge_in')).toBe(true);
52
+ expect(bargeIdx >= 0, req('openwop.it.voice-bargein-no-partial-leak.barge-in-cancels-with-no-synthesis-chunk-emitted-after-voice-cancelled', 'RFC 0106 §D', 'a barge-in MUST emit voice.barge_in')).toBe(true);
53
+ expect(cancelIdx >= 0, req('openwop.it.voice-bargein-no-partial-leak.barge-in-cancels-with-no-synthesis-chunk-emitted-after-voice-cancelled', 'RFC 0106 §D', 'a barge-in that cancels work MUST emit voice.cancelled')).toBe(true);
54
+ expect(cancelIdx > bargeIdx, req('openwop.it.voice-bargein-no-partial-leak.barge-in-cancels-with-no-synthesis-chunk-emitted-after-voice-cancelled', 'RFC 0106 §D', 'voice.cancelled MUST follow voice.barge_in')).toBe(true);
53
55
 
54
56
  // The load-bearing INV-3 assertion: nothing partial after the cancel.
55
57
  const afterCancel = types.slice(cancelIdx + 1);
56
58
  expect(
57
59
  !afterCancel.includes('voice.synthesis_chunk'),
58
- driver.describe('RFC 0106 §F INV-3', 'NO voice.synthesis_chunk (partial output) may be emitted AFTER voice.cancelled'),
60
+ req('openwop.it.voice-bargein-no-partial-leak.barge-in-cancels-with-no-synthesis-chunk-emitted-after-voice-cancelled', 'RFC 0106 §F INV-3', 'NO voice.synthesis_chunk (partial output) may be emitted AFTER voice.cancelled'),
59
61
  ).toBe(true);
60
62
  });
61
63
  });
@@ -32,8 +32,7 @@ import { join } from 'node:path';
32
32
  import Ajv2020 from 'ajv/dist/2020.js';
33
33
  import addFormats from 'ajv-formats';
34
34
  import { SCHEMAS_DIR } from '../lib/paths.js';
35
-
36
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
35
+ import { req } from '../lib/requirement-ids.js';
37
36
 
38
37
  function loadSchema(name: string): Record<string, any> {
39
38
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, any>;
@@ -63,7 +62,7 @@ describe('voice-event-payloads-shape: the voice.* run-event taxonomy (RFC 0106
63
62
  it('all seven voice.* types are in the RunEventType enum', () => {
64
63
  const enumVals: string[] = loadSchema('run-event.schema.json').$defs.RunEventType.enum;
65
64
  for (const t of VOICE_TYPES) {
66
- expect(enumVals.includes(t), why('run-event.schema.json §RunEventType', `${t} MUST be a RunEventType`)).toBe(true);
65
+ expect(enumVals.includes(t), req('openwop.it.voice-event-payloads-shape.all-seven-voice-types-are-in-the-runeventtype-enum', 'run-event.schema.json §RunEventType', `${t} MUST be a RunEventType`)).toBe(true);
67
66
  }
68
67
  });
69
68
 
@@ -71,8 +70,8 @@ describe('voice-event-payloads-shape: the voice.* run-event taxonomy (RFC 0106
71
70
  const payloads = loadSchema('run-event-payloads.schema.json');
72
71
  const typeIndex = payloads.$defs._typeIndex.properties as Record<string, { $ref: string }>;
73
72
  for (const t of VOICE_TYPES) {
74
- expect(typeIndex[t], why('run-event-payloads.schema.json §typeIndex', `${t} MUST map to a $def`)).toBeDefined();
75
- expect(payloads.$defs[DEF_KEY[t]], why('run-event-payloads.schema.json', `$defs.${DEF_KEY[t]} MUST exist`)).toBeDefined();
73
+ expect(typeIndex[t], req('openwop.it.voice-event-payloads-shape.each-voice-type-has-a-payload-def-reachable-via-typeindex', 'run-event-payloads.schema.json §typeIndex', `${t} MUST map to a $def`)).toBeDefined();
74
+ expect(payloads.$defs[DEF_KEY[t]], req('openwop.it.voice-event-payloads-shape.each-voice-type-has-a-payload-def-reachable-via-typeindex', 'run-event-payloads.schema.json', `$defs.${DEF_KEY[t]} MUST exist`)).toBeDefined();
76
75
  }
77
76
  });
78
77
 
@@ -84,15 +83,15 @@ describe('voice-event-payloads-shape: the voice.* run-event taxonomy (RFC 0106
84
83
 
85
84
  expect(
86
85
  validate({ text: 'book a table', isFinal: true, atMs: 1200, contentTrust: 'untrusted' }),
87
- why('RFC 0106 §F INV-2', 'a transcript marked untrusted MUST validate'),
86
+ req('openwop.it.voice-event-payloads-shape.voice-transcript-requires-contenttrust-untrusted-security-voice-transcript-untru', 'RFC 0106 §F INV-2', 'a transcript marked untrusted MUST validate'),
88
87
  ).toBe(true);
89
88
  expect(
90
89
  validate({ text: 'book a table', isFinal: true, atMs: 1200 }),
91
- why('RFC 0106 §F INV-2 (voice-transcript-untrusted)', 'a transcript WITHOUT contentTrust MUST be rejected'),
90
+ req('openwop.it.voice-event-payloads-shape.voice-transcript-requires-contenttrust-untrusted-security-voice-transcript-untru', 'RFC 0106 §F INV-2 (voice-transcript-untrusted)', 'a transcript WITHOUT contentTrust MUST be rejected'),
92
91
  ).toBe(false);
93
92
  expect(
94
93
  validate({ text: 'book a table', isFinal: true, atMs: 1200, contentTrust: 'trusted' }),
95
- why('RFC 0106 §F INV-2 (voice-transcript-untrusted)', 'contentTrust MUST be the const "untrusted" — never promoted'),
94
+ req('openwop.it.voice-event-payloads-shape.voice-transcript-requires-contenttrust-untrusted-security-voice-transcript-untru', 'RFC 0106 §F INV-2 (voice-transcript-untrusted)', 'contentTrust MUST be the const "untrusted" — never promoted'),
96
95
  ).toBe(false);
97
96
  });
98
97
 
@@ -104,11 +103,11 @@ describe('voice-event-payloads-shape: the voice.* run-event taxonomy (RFC 0106
104
103
 
105
104
  expect(
106
105
  validate({ seq: 0, mimeType: 'audio/mpeg', durationMs: 240, url: 'https://host/seg/0', final: false }),
107
- why('RFC 0106 §C', 'a metadata chunk referencing bytes by url MUST validate'),
106
+ req('openwop.it.voice-event-payloads-shape.voice-synthesis-chunk-is-metadata-shaped-seq-mimetype-required-bytes-by-referenc', 'RFC 0106 §C', 'a metadata chunk referencing bytes by url MUST validate'),
108
107
  ).toBe(true);
109
108
  expect(
110
109
  validate({ mimeType: 'audio/mpeg' }),
111
- why('RFC 0106 §C', 'a chunk without seq MUST be rejected'),
110
+ req('openwop.it.voice-event-payloads-shape.voice-synthesis-chunk-is-metadata-shaped-seq-mimetype-required-bytes-by-referenc', 'RFC 0106 §C', 'a chunk without seq MUST be rejected'),
112
111
  ).toBe(false);
113
112
  });
114
113
 
@@ -120,7 +119,7 @@ describe('voice-event-payloads-shape: the voice.* run-event taxonomy (RFC 0106
120
119
  const validate = ajv.compile(payloads.$defs[key]);
121
120
  expect(
122
121
  validate({ atMs: 100, transcriptBody: 'should not be here' }),
123
- why('RFC 0106 §D', `${key} MUST reject an unknown (content-bearing) property`),
122
+ req('openwop.it.voice-event-payloads-shape.content-free-voice-events-reject-unknown-properties-additionalproperties-false', 'RFC 0106 §D', `${key} MUST reject an unknown (content-bearing) property`),
124
123
  ).toBe(false);
125
124
  }
126
125
  });
@@ -20,6 +20,8 @@ import { describe, it, expect } from 'vitest';
20
20
  import { driver } from '../lib/driver.js';
21
21
  import { behaviorGate } from '../lib/behavior-gate.js';
22
22
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
23
+ import { req } from '../lib/requirement-ids.js';
24
+ import { softSkip } from '../lib/soft-skip.js';
23
25
 
24
26
  const SEAM = '/v1/host/sample/ai/call-transcriber';
25
27
 
@@ -42,18 +44,18 @@ describe('voice-interim-not-durable (RFC 0106 §F INV-1)', () => {
42
44
  if (!behaviorGate('openwop-voice-interim-not-durable', advertised)) return;
43
45
 
44
46
  const res = await driver.post(SEAM, { audio: { streamRef: 'stream:conformance/mic' }, interimResults: true });
45
- if (res.status === 404) return; // seam unwired — soft-skip
46
- if (errCode(res.json) === 'transcription_unsupported') return; // §E live transport / no test-seam arm — soft-skip
47
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
48
+ if (errCode(res.json) === 'transcription_unsupported') return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `errCode(res.json) === \'transcription_unsupported\'` returned early (§E live transport / no test-seam arm — soft-skip)'); // §E live transport / no test-seam arm — soft-skip
47
49
 
48
50
  const events = eventsOf(res.json);
49
- if (events.length === 0) return; // host returned only the result envelope — nothing observable to assert
51
+ if (events.length === 0) return softSkip('blocked', 'precondition not met — `events.length === 0` returned early (host returned only the result envelope — nothing observable to assert) (seam, prior step, or fixture unavailable)'); // host returned only the result envelope — nothing observable to assert
50
52
 
51
53
  const commitIdx = events.findIndex((e) => e.type === 'voice.turn_commit');
52
- if (commitIdx < 0) return; // no commit observed — soft-skip
54
+ if (commitIdx < 0) return softSkip('blocked', 'precondition not met — `commitIdx < 0` returned early (no commit observed — soft-skip) (seam, prior step, or fixture unavailable)'); // no commit observed — soft-skip
53
55
  const afterCommit = events.slice(commitIdx + 1);
54
56
  expect(
55
57
  !afterCommit.some((e) => e.type === 'voice.transcript' && (e.payload ?? {}).isFinal === false),
56
- driver.describe('RFC 0106 §F INV-1', 'a provisional (isFinal:false) transcript MUST NOT appear after voice.turn_commit'),
58
+ req('openwop.it.voice-interim-not-durable.no-provisional-isfinal-false-transcript-is-durable-past-voice-turn-commit', 'RFC 0106 §F INV-1', 'a provisional (isFinal:false) transcript MUST NOT appear after voice.turn_commit'),
57
59
  ).toBe(true);
58
60
  });
59
61
  });
@@ -22,6 +22,8 @@ import { readErrorCode } from '../lib/error-envelope.js';
22
22
  import { driver } from '../lib/driver.js';
23
23
  import { behaviorGate } from '../lib/behavior-gate.js';
24
24
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
25
+ import { req } from '../lib/requirement-ids.js';
26
+ import { softSkip } from '../lib/soft-skip.js';
25
27
 
26
28
  const SEAM = '/v1/host/sample/ai/call-transcriber';
27
29
 
@@ -44,8 +46,8 @@ describe('voice-streamref-tenant-bound (RFC 0106 §F INV-4)', () => {
44
46
  // conduit to bind cross-tenant — soft-skip (the invariant stays reference-impl
45
47
  // until a host with live streamRef transport proves it).
46
48
  const res = await driver.post(SEAM, { audio: { streamRef: 'stream:tenant-a/mic' } });
47
- if (res.status === 404) return;
48
- if (errCode(res.json) === 'transcription_unsupported') return; // §E — no live transport on this host
49
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
50
+ if (errCode(res.json) === 'transcription_unsupported') return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `errCode(res.json) === \'transcription_unsupported\'` returned early (§E — no live transport on this host)'); // §E — no live transport on this host
49
51
 
50
52
  // A host that DOES accept a live streamRef must bind it: a second tenant presenting
51
53
  // tenant-A's streamRef MUST be rejected (cross-handle read forbidden). Exercising the
@@ -54,7 +56,7 @@ describe('voice-streamref-tenant-bound (RFC 0106 §F INV-4)', () => {
54
56
  // another tenant's buffered audio for an unknown streamRef.
55
57
  expect(
56
58
  res.status !== 200 || (res.json as { finalText?: unknown })?.finalText !== undefined,
57
- driver.describe('RFC 0106 §F INV-4', 'a host honoring a live streamRef MUST bind it to its tenant+session'),
59
+ req('openwop.it.voice-streamref-tenant-bound.a-live-streamref-is-tenant-session-bound-host-internal-transport-per-e-soft-skip', 'RFC 0106 §F INV-4', 'a host honoring a live streamRef MUST bind it to its tenant+session'),
58
60
  ).toBe(true);
59
61
  });
60
62
  });
@@ -23,6 +23,8 @@ import { describe, it, expect } from 'vitest';
23
23
  import { driver } from '../lib/driver.js';
24
24
  import { behaviorGate } from '../lib/behavior-gate.js';
25
25
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
26
+ import { req } from '../lib/requirement-ids.js';
27
+ import { softSkip } from '../lib/soft-skip.js';
26
28
 
27
29
  const SEAM = '/v1/host/sample/ai/call-speech-synthesizer';
28
30
 
@@ -42,36 +44,36 @@ describe('voice-synthesis-streaming (RFC 0106 §C)', () => {
42
44
  if (!behaviorGate('openwop-voice-synthesis', advertised)) return;
43
45
 
44
46
  const res = await driver.post(SEAM, { text: 'Welcome to the weekly digest.', voiceId: 'host:narrator-test', stream: true });
45
- if (res.status === 404) return; // seam unwired — soft-skip
47
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
46
48
 
47
49
  expect(
48
50
  res.status === 200,
49
- driver.describe('RFC 0106 §C', 'an advertised host MUST resolve stream:true with 200'),
51
+ req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C', 'an advertised host MUST resolve stream:true with 200'),
50
52
  ).toBe(true);
51
53
 
52
54
  const audio = (res.json as { audio?: Record<string, unknown> })?.audio;
53
- expect(audio !== undefined, driver.describe('RFC 0106 §C', 'the response MUST carry the finalized `audio` asset')).toBe(true);
55
+ expect(audio !== undefined, req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C', 'the response MUST carry the finalized `audio` asset')).toBe(true);
54
56
  if (audio) {
55
57
  const hasUrl = typeof audio.url === 'string' && (audio.url as string).length > 0;
56
58
  const hasB64 = typeof audio.base64 === 'string' && (audio.base64 as string).length > 0;
57
- expect(hasUrl !== hasB64, driver.describe('RFC 0106 §C', 'audio MUST carry EXACTLY ONE of url/base64')).toBe(true);
59
+ expect(hasUrl !== hasB64, req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C', 'audio MUST carry EXACTLY ONE of url/base64')).toBe(true);
58
60
  }
59
61
 
60
62
  const chunks = eventsOf(res.json).filter((e) => e.type === 'voice.synthesis_chunk');
61
- expect(chunks.length >= 1, driver.describe('RFC 0106 §C', 'MUST emit ≥1 voice.synthesis_chunk run-event')).toBe(true);
63
+ expect(chunks.length >= 1, req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C', 'MUST emit ≥1 voice.synthesis_chunk run-event')).toBe(true);
62
64
  for (const c of chunks) {
63
65
  const p = c.payload ?? {};
64
- expect(typeof p.seq === 'number', driver.describe('RFC 0106 §C', 'each chunk carries a numeric seq')).toBe(true);
65
- expect(typeof p.mimeType === 'string', driver.describe('RFC 0106 §C', 'each chunk carries a mimeType')).toBe(true);
66
+ expect(typeof p.seq === 'number', req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C', 'each chunk carries a numeric seq')).toBe(true);
67
+ expect(typeof p.mimeType === 'string', req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C', 'each chunk carries a mimeType')).toBe(true);
66
68
  // Metadata-only: bytes by reference. An inline base64 is permitted ONLY under the host cap;
67
69
  // a chunk over the RFC 0055 256 KiB inline cap MUST be a url/streamRef reference.
68
70
  if (typeof p.base64 === 'string') {
69
- expect((p.base64 as string).length <= 262144, driver.describe('RFC 0106 §C (G8)', 'inline chunk base64 MUST stay under the 256 KiB cap; else url/streamRef')).toBe(true);
71
+ expect((p.base64 as string).length <= 262144, req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C (G8)', 'inline chunk base64 MUST stay under the 256 KiB cap; else url/streamRef')).toBe(true);
70
72
  }
71
73
  }
72
74
  expect(
73
75
  chunks.some((c) => (c.payload ?? {}).final === true),
74
- driver.describe('RFC 0106 §C', 'a terminal chunk MUST carry final:true'),
76
+ req('openwop.it.voice-synthesis-streaming.stream-true-resolves-the-finalized-asset-and-emits-metadata-only-voice-synthesis', 'RFC 0106 §C', 'a terminal chunk MUST carry final:true'),
75
77
  ).toBe(true);
76
78
  });
77
79
  });
@@ -23,6 +23,8 @@ import { readErrorCode } from '../lib/error-envelope.js';
23
23
  import { driver } from '../lib/driver.js';
24
24
  import { behaviorGate } from '../lib/behavior-gate.js';
25
25
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
26
+ import { req } from '../lib/requirement-ids.js';
27
+ import { softSkip } from '../lib/soft-skip.js';
26
28
 
27
29
  const SEAM = '/v1/host/sample/ai/call-transcriber';
28
30
 
@@ -45,21 +47,21 @@ describe('voice-transcription-streaming (RFC 0106 §B)', () => {
45
47
  if (!behaviorGate('openwop-voice-transcription', advertised)) return;
46
48
 
47
49
  const res = await driver.post(SEAM, { audio: { streamRef: 'stream:conformance/mic' }, languageCode: 'en-US' });
48
- if (res.status === 404) return; // seam unwired — soft-skip
50
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
49
51
  // §E: a stateless host with no live transport honestly rejects a live streamRef.
50
- if (errCode(res.json) === 'transcription_unsupported') return; // soft-skip (no live transport / no test-seam arm)
52
+ if (errCode(res.json) === 'transcription_unsupported') return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `errCode(res.json) === \'transcription_unsupported\'` returned early (soft-skip (no live transport / no test-seam arm))'); // soft-skip (no live transport / no test-seam arm)
51
53
 
52
- expect(res.status === 200, driver.describe('RFC 0106 §B', 'a produced turn MUST return 200')).toBe(true);
54
+ expect(res.status === 200, req('openwop.it.voice-transcription-streaming.resolves-a-settled-turn-at-voice-turn-commit-with-untrusted-transcript-events', 'RFC 0106 §B', 'a produced turn MUST return 200')).toBe(true);
53
55
 
54
56
  const finalText = (res.json as { finalText?: unknown })?.finalText;
55
- expect(typeof finalText === 'string' && (finalText as string).length > 0, driver.describe('RFC 0106 §B', 'the turn MUST resolve a non-empty finalText at turn_commit')).toBe(true);
57
+ expect(typeof finalText === 'string' && (finalText as string).length > 0, req('openwop.it.voice-transcription-streaming.resolves-a-settled-turn-at-voice-turn-commit-with-untrusted-transcript-events', 'RFC 0106 §B', 'the turn MUST resolve a non-empty finalText at turn_commit')).toBe(true);
56
58
 
57
59
  const events = eventsOf(res.json);
58
60
  if (events.length > 0) {
59
61
  for (const ev of events.filter((e) => e.type === 'voice.transcript')) {
60
- expect((ev.payload ?? {}).contentTrust === 'untrusted', driver.describe('RFC 0106 §F INV-2', 'every voice.transcript MUST carry contentTrust:"untrusted"')).toBe(true);
62
+ expect((ev.payload ?? {}).contentTrust === 'untrusted', req('openwop.it.voice-transcription-streaming.resolves-a-settled-turn-at-voice-turn-commit-with-untrusted-transcript-events', 'RFC 0106 §F INV-2', 'every voice.transcript MUST carry contentTrust:"untrusted"')).toBe(true);
61
63
  }
62
- expect(events.some((e) => e.type === 'voice.turn_commit'), driver.describe('RFC 0106 §B', 'the turn MUST terminate with voice.turn_commit')).toBe(true);
64
+ expect(events.some((e) => e.type === 'voice.turn_commit'), req('openwop.it.voice-transcription-streaming.resolves-a-settled-turn-at-voice-turn-commit-with-untrusted-transcript-events', 'RFC 0106 §B', 'the turn MUST terminate with voice.turn_commit')).toBe(true);
63
65
  }
64
66
  });
65
67
  });
@@ -18,6 +18,8 @@ import { readErrorCode } from '../lib/error-envelope.js';
18
18
  import { driver } from '../lib/driver.js';
19
19
  import { behaviorGate } from '../lib/behavior-gate.js';
20
20
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
21
+ import { req } from '../lib/requirement-ids.js';
22
+ import { softSkip } from '../lib/soft-skip.js';
21
23
 
22
24
  const SEAM = '/v1/host/sample/ai/call-transcriber';
23
25
 
@@ -36,12 +38,12 @@ describe('voice-transcription-unadvertised (RFC 0106 §B)', () => {
36
38
  if (!behaviorGate('openwop-voice-transcription-unadvertised', !advertised)) return;
37
39
 
38
40
  const res = await driver.post(SEAM, { audio: { streamRef: 'stream:conformance/mic' } });
39
- if (res.status === 404) return; // seam unwired — soft-skip
41
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
40
42
 
41
- expect(res.status !== 200, driver.describe('RFC 0106 §B', 'an unadvertising host MUST NOT return a 200 (never a no-op)')).toBe(true);
43
+ expect(res.status !== 200, req('openwop.it.voice-transcription-unadvertised.a-host-not-advertising-realtimevoice-transcription-must-reject-with-transcriptio', 'RFC 0106 §B', 'an unadvertising host MUST NOT return a 200 (never a no-op)')).toBe(true);
42
44
  expect(
43
45
  errCode(res.json) === 'transcription_unsupported',
44
- driver.describe('RFC 0106 §B', 'the call MUST be rejected with `transcription_unsupported`'),
46
+ req('openwop.it.voice-transcription-unadvertised.a-host-not-advertising-realtimevoice-transcription-must-reject-with-transcriptio', 'RFC 0106 §B', 'the call MUST be rejected with `transcription_unsupported`'),
45
47
  ).toBe(true);
46
48
  });
47
49
  });
@@ -28,6 +28,7 @@ import { describe, it, expect } from 'vitest';
28
28
  import { softSkip } from '../lib/soft-skip.js';
29
29
  import { driver } from '../lib/driver.js';
30
30
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
31
+ import { req } from '../lib/requirement-ids.js';
31
32
 
32
33
  const MISBEHAVING_PACK_NAME = 'vendor.openwop.misbehaving-abi';
33
34
  const WELL_BEHAVED_PACK_NAME = 'vendor.openwop.rust-hello';
@@ -40,7 +41,7 @@ describe('wasm-pack-abi-version-rejection: host advertises supported ABI version
40
41
 
41
42
  if (!wasm?.supported) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!wasm?.supported` returned early');
42
43
 
43
- expect(Array.isArray(wasm.abiVersions), driver.describe(
44
+ expect(Array.isArray(wasm.abiVersions), req('openwop.it.wasm-pack-abi-version-rejection.abiversions-contains-positive-integers-loader-rejects-unsupported-versions',
44
45
  'RFCS/0008-wasm-abi.md §H',
45
46
  'capabilities.nodePackRuntimes.wasm.abiVersions MUST be an array',
46
47
  )).toBe(true);
@@ -90,7 +91,7 @@ describe('wasm-pack-abi-version-rejection: positive path via misbehaving pack',
90
91
 
91
92
  // Core assertion: ABI 999 pack MUST NOT be in loadedPacks[]
92
93
  // regardless of filesystem state. The host's loader rejected it.
93
- expect(wasm.loadedPacks.includes(MISBEHAVING_PACK_NAME), driver.describe(
94
+ expect(wasm.loadedPacks.includes(MISBEHAVING_PACK_NAME), req('openwop.it.wasm-pack-abi-version-rejection.misbehaving-abi-pack-declares-abi-999-must-not-appear-in-loadedpacks',
94
95
  'RFCS/0008-wasm-abi.md §H',
95
96
  `host MUST reject packs whose declared ABI is not in abiVersions[]; ${MISBEHAVING_PACK_NAME} declares 999 and MUST NOT appear in loadedPacks[]`,
96
97
  )).toBe(false);
@@ -18,6 +18,7 @@ import { driver } from '../lib/driver.js';
18
18
  import { pollUntilTerminal } from '../lib/polling.js';
19
19
  import { isFixtureAdvertised } from '../lib/fixtures.js';
20
20
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
21
+ import { req } from '../lib/requirement-ids.js';
21
22
 
22
23
  const FIXTURE = 'conformance-wasm-pack-roundtrip';
23
24
 
@@ -45,7 +46,7 @@ describe('wasm-pack-invoke-completed: round-trip output', () => {
45
46
  const runId = (create.json as { runId: string }).runId;
46
47
 
47
48
  const terminal = await pollUntilTerminal(runId, { timeoutMs: 15_000 });
48
- expect(terminal.status, driver.describe(
49
+ expect(terminal.status, req('openwop.it.wasm-pack-invoke-completed.greet-node-returns-hello-name-and-run-reaches-completed',
49
50
  'RFCS/0008-wasm-abi.md §D',
50
51
  "WASM 'completed' outcome MUST drive terminal 'completed' run status",
51
52
  )).toBe('completed');
@@ -61,7 +62,7 @@ describe('wasm-pack-invoke-completed: round-trip output', () => {
61
62
  const fullLog = JSON.stringify(list).toLowerCase();
62
63
  expect(
63
64
  haystack.includes('hello, openwop') || fullLog.includes('hello, openwop'),
64
- driver.describe(
65
+ req('openwop.it.wasm-pack-invoke-completed.greet-node-returns-hello-name-and-run-reaches-completed',
65
66
  'RFCS/0008-wasm-abi.md §D',
66
67
  "WASM completion output MUST be surfaced somewhere in the run's event log so consumers can read it",
67
68
  ),
@@ -22,6 +22,7 @@ import { driver } from '../lib/driver.js';
22
22
  import { pollUntilTerminal } from '../lib/polling.js';
23
23
  import { isFixtureAdvertised } from '../lib/fixtures.js';
24
24
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
25
+ import { req } from '../lib/requirement-ids.js';
25
26
 
26
27
  const FIXTURE = 'conformance-wasm-pack-roundtrip';
27
28
 
@@ -60,11 +61,11 @@ describe('wasm-pack-invoke-suspended: suspend → resume round-trip', () => {
60
61
  const ok =
61
62
  haystack.includes('wasm_suspend_not_implemented') ||
62
63
  haystack.includes('suspend_not_supported');
63
- expect(ok, driver.describe(
64
+ expect(ok, req('openwop.it.wasm-pack-invoke-suspended.host-either-suspends-the-run-or-explicitly-reports-wasm-suspend-not-implemented',
64
65
  'RFCS/0008-wasm-abi.md §D',
65
66
  "if a host doesn't implement WASM-driven suspends it MUST surface a recognizable code",
66
67
  )).toBe(true);
67
- return;
68
+ return softSkip('blocked', 'precondition not met — `terminal.status === \'failed\'` returned early (seam, prior step, or fixture unavailable)');
68
69
  }
69
70
 
70
71
  // Completed path: the reference pack never suspends. Asserting
@@ -17,6 +17,7 @@ import { softSkip } from '../lib/soft-skip.js';
17
17
  import { driver } from '../lib/driver.js';
18
18
  import { isFixtureAdvertised } from '../lib/fixtures.js';
19
19
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
20
+ import { req } from '../lib/requirement-ids.js';
20
21
 
21
22
  const FIXTURE = 'conformance-wasm-pack-roundtrip';
22
23
 
@@ -42,11 +43,11 @@ describe('wasm-pack-load: discovery surfaces WASM runtime support', () => {
42
43
  console.warn('[wasm-pack-load] host does not advertise WASM support; skipping');
43
44
  return softSkip('inapplicable', '[wasm-pack-load] host does not advertise WASM support; skipping');
44
45
  }
45
- expect(Array.isArray(wasm.abiVersions), driver.describe(
46
+ expect(Array.isArray(wasm.abiVersions), req('openwop.it.wasm-pack-load.a-host-claiming-wasm-support-advertises-abiversions-including-1',
46
47
  'RFCS/0008-wasm-abi.md §H',
47
48
  'capabilities.nodePackRuntimes.wasm.abiVersions MUST be an array',
48
49
  )).toBe(true);
49
- expect(wasm.abiVersions?.includes(1), driver.describe(
50
+ expect(wasm.abiVersions?.includes(1), req('openwop.it.wasm-pack-load.a-host-claiming-wasm-support-advertises-abiversions-including-1',
50
51
  'RFCS/0008-wasm-abi.md §H',
51
52
  'abiVersions MUST include 1 (this RFC) when supported',
52
53
  )).toBe(true);
@@ -66,7 +67,7 @@ describe('wasm-pack-load: loaded pack typeIds are dispatchable', () => {
66
67
  // WASM-provided typeId. A host that loaded the pack accepts the
67
68
  // POST /v1/runs; one that didn't would return 400/404.
68
69
  const create = await driver.post('/v1/runs', { workflowId: FIXTURE, inputs: { name: 'world' } });
69
- expect(create.status, driver.describe(
70
+ expect(create.status, req('openwop.it.wasm-pack-load.host-accepts-a-workflow-whose-node-typeid-is-provided-by-a-loaded-wasm-pack',
70
71
  'RFCS/0008-wasm-abi.md §B + node-packs.md §Reserved typeIds',
71
72
  'host MUST accept runs whose nodes reference loaded-pack typeIds',
72
73
  )).toBe(201);