@openwop/openwop-conformance 1.162.0 → 2.0.0-rc.0

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 (553) hide show
  1. package/README.md +11 -2
  2. package/dist/cli.js +54 -1
  3. package/dist/lib/paths.js +25 -3
  4. package/dist/lib/requirement-ids.js +34 -4
  5. package/dist/lib/scenario-disposition.js +1 -0
  6. package/dist/lib/spec-coherence.js +13 -32
  7. package/dist/spec-artifacts.lock.json +5 -0
  8. package/package.json +11 -33
  9. package/requirements.json +20303 -11809
  10. package/scenario-majors.json +1343 -0
  11. package/schemas/CORPUS-STAMP.json +138 -6
  12. package/src/cli.ts +47 -1
  13. package/src/global-setup.ts +3 -2
  14. package/src/lib/corpus-stamp.ts +29 -1
  15. package/src/lib/paths.ts +25 -3
  16. package/src/lib/requirement-ids.ts +33 -4
  17. package/src/lib/scenario-disposition.ts +1 -0
  18. package/src/lib/spec-coherence.ts +15 -32
  19. package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
  20. package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
  21. package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
  22. package/src/scenarios/a2a-peer-authority.test.ts +7 -6
  23. package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
  24. package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
  25. package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
  26. package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
  27. package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
  28. package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
  29. package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
  30. package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
  31. package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
  32. package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
  33. package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
  34. package/src/scenarios/agent-deployment-shape.test.ts +22 -24
  35. package/src/scenarios/agent-eval-run.test.ts +19 -18
  36. package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
  37. package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
  38. package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
  39. package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
  40. package/src/scenarios/agent-live-structured-output.test.ts +7 -6
  41. package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
  42. package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
  43. package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
  44. package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
  45. package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
  46. package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
  47. package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
  48. package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
  49. package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
  50. package/src/scenarios/agent-platform-profile.test.ts +18 -19
  51. package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
  52. package/src/scenarios/agent-roster-attribution.test.ts +18 -17
  53. package/src/scenarios/agent-roster-shape.test.ts +17 -19
  54. package/src/scenarios/agent-verifier-shape.test.ts +11 -11
  55. package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
  56. package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
  57. package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
  58. package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
  59. package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
  60. package/src/scenarios/agentMessageReducer.test.ts +2 -1
  61. package/src/scenarios/agentMetadata.test.ts +2 -1
  62. package/src/scenarios/agentPackCatalog.test.ts +23 -21
  63. package/src/scenarios/agentPackExport.test.ts +4 -2
  64. package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
  65. package/src/scenarios/agentPackInstall.test.ts +4 -2
  66. package/src/scenarios/agentPackProvenance.test.ts +2 -1
  67. package/src/scenarios/agentReasoningEvents.test.ts +3 -2
  68. package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
  69. package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
  70. package/src/scenarios/ai-envelope-shape.test.ts +31 -29
  71. package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
  72. package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
  73. package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
  74. package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
  75. package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
  76. package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
  77. package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
  78. package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
  79. package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
  80. package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
  81. package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
  82. package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
  83. package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
  84. package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
  85. package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
  86. package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
  87. package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
  88. package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
  89. package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
  90. package/src/scenarios/append-ordering.test.ts +7 -5
  91. package/src/scenarios/approval-gate-events.test.ts +4 -3
  92. package/src/scenarios/approval-gate-flow.test.ts +4 -3
  93. package/src/scenarios/approval-payload.test.ts +5 -4
  94. package/src/scenarios/artifact-auth.test.ts +7 -6
  95. package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
  96. package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
  97. package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
  98. package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
  99. package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
  100. package/src/scenarios/audit-log-integrity.test.ts +8 -6
  101. package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
  102. package/src/scenarios/auth-mtls.test.ts +22 -20
  103. package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
  104. package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
  105. package/src/scenarios/auth-saml-profile.test.ts +14 -12
  106. package/src/scenarios/auth-scim-profile.test.ts +3 -2
  107. package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
  108. package/src/scenarios/auth-subject-link.test.ts +11 -10
  109. package/src/scenarios/auth.test.ts +5 -4
  110. package/src/scenarios/authorization-fail-closed.test.ts +3 -2
  111. package/src/scenarios/authorization-roles-shape.test.ts +9 -7
  112. package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
  113. package/src/scenarios/blob-presign-expiry.test.ts +12 -10
  114. package/src/scenarios/blob-roundtrip.test.ts +0 -0
  115. package/src/scenarios/budget-enforcement.test.ts +15 -14
  116. package/src/scenarios/budget-policy-shape.test.ts +18 -19
  117. package/src/scenarios/bulk-cancel.test.ts +9 -8
  118. package/src/scenarios/byok-auth-modes.test.ts +13 -14
  119. package/src/scenarios/byok-roundtrip.test.ts +12 -10
  120. package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
  121. package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
  122. package/src/scenarios/callai-multimodal.test.ts +5 -3
  123. package/src/scenarios/cancellation.test.ts +6 -5
  124. package/src/scenarios/cap-breach.test.ts +15 -14
  125. package/src/scenarios/capability-arm-witness.test.ts +5 -3
  126. package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
  127. package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
  128. package/src/scenarios/certification-bundle-v2.test.ts +11 -10
  129. package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
  130. package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
  131. package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
  132. package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
  133. package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
  134. package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
  135. package/src/scenarios/channel-presence-shape.test.ts +11 -12
  136. package/src/scenarios/channel-ttl.test.ts +6 -5
  137. package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
  138. package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
  139. package/src/scenarios/commitment-fired.test.ts +6 -5
  140. package/src/scenarios/compensation-behavior.test.ts +24 -23
  141. package/src/scenarios/compensation-recovery.test.ts +28 -27
  142. package/src/scenarios/configurable-schema.test.ts +8 -6
  143. package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
  144. package/src/scenarios/conformance-execution-witness.test.ts +9 -8
  145. package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
  146. package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
  147. package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
  148. package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
  149. package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
  150. package/src/scenarios/connection-provider-resolution.test.ts +18 -16
  151. package/src/scenarios/connector-manifest-validity.test.ts +8 -7
  152. package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
  153. package/src/scenarios/context-summarization-replay.test.ts +14 -12
  154. package/src/scenarios/contract-provenance.test.ts +18 -18
  155. package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
  156. package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
  157. package/src/scenarios/conversationLifecycle.test.ts +2 -1
  158. package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
  159. package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
  160. package/src/scenarios/core-standard-profile.test.ts +8 -9
  161. package/src/scenarios/cost-attribution.test.ts +23 -21
  162. package/src/scenarios/credential-payload-redaction.test.ts +4 -3
  163. package/src/scenarios/credentials-capability-shape.test.ts +5 -4
  164. package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
  165. package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
  166. package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
  167. package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
  168. package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
  169. package/src/scenarios/data-residency-admission.test.ts +15 -14
  170. package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
  171. package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
  172. package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
  173. package/src/scenarios/debugBundle.test.ts +25 -23
  174. package/src/scenarios/discovery-families-view.test.ts +5 -4
  175. package/src/scenarios/discovery.test.ts +30 -29
  176. package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
  177. package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
  178. package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
  179. package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
  180. package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
  181. package/src/scenarios/dispatchLoop.test.ts +3 -2
  182. package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
  183. package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
  184. package/src/scenarios/distillation-shape.test.ts +4 -4
  185. package/src/scenarios/distillation-stable-archive.test.ts +6 -6
  186. package/src/scenarios/distillation-token-budget.test.ts +5 -5
  187. package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
  188. package/src/scenarios/egress-audience-binding.test.ts +11 -10
  189. package/src/scenarios/egress-decision-content-free.test.ts +6 -5
  190. package/src/scenarios/egress-provenance-shape.test.ts +17 -18
  191. package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
  192. package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
  193. package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
  194. package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
  195. package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
  196. package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
  197. package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
  198. package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
  199. package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
  200. package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
  201. package/src/scenarios/envelope-truncated.test.ts +19 -17
  202. package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
  203. package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
  204. package/src/scenarios/errors.test.ts +20 -19
  205. package/src/scenarios/eventOrdering.test.ts +16 -14
  206. package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
  207. package/src/scenarios/experimental-tier-shape.test.ts +17 -15
  208. package/src/scenarios/export-bundle-portability.test.ts +17 -17
  209. package/src/scenarios/failure-path.test.ts +7 -6
  210. package/src/scenarios/feedback-capability-shape.test.ts +4 -3
  211. package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
  212. package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
  213. package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
  214. package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
  215. package/src/scenarios/feedback-record-and-list.test.ts +2 -1
  216. package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
  217. package/src/scenarios/fixtures-gating.test.ts +29 -28
  218. package/src/scenarios/fixtures-valid.test.ts +16 -15
  219. package/src/scenarios/form-content-instantiation.test.ts +15 -14
  220. package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
  221. package/src/scenarios/fs-path-traversal.test.ts +14 -12
  222. package/src/scenarios/goal-standing-continuation.test.ts +21 -21
  223. package/src/scenarios/grpc-transport.test.ts +9 -7
  224. package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
  225. package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
  226. package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
  227. package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
  228. package/src/scenarios/highConcurrency.test.ts +14 -13
  229. package/src/scenarios/host-callback-declaration.test.ts +8 -7
  230. package/src/scenarios/http-client-ssrf.test.ts +7 -5
  231. package/src/scenarios/i18n-negotiation.test.ts +14 -12
  232. package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
  233. package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
  234. package/src/scenarios/idempotency.test.ts +8 -7
  235. package/src/scenarios/idempotencyRetry.test.ts +13 -11
  236. package/src/scenarios/identity-owner-shape.test.ts +6 -5
  237. package/src/scenarios/identity-passthrough.test.ts +4 -3
  238. package/src/scenarios/interrupt-approval.test.ts +6 -5
  239. package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
  240. package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
  241. package/src/scenarios/interrupt-clarification.test.ts +4 -3
  242. package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
  243. package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
  244. package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
  245. package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
  246. package/src/scenarios/interruptRace.test.ts +12 -10
  247. package/src/scenarios/kv-atomic-increment.test.ts +11 -9
  248. package/src/scenarios/kv-cas.test.ts +14 -12
  249. package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
  250. package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
  251. package/src/scenarios/localized-content-delivery.test.ts +24 -26
  252. package/src/scenarios/maliciousManifest.test.ts +10 -8
  253. package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
  254. package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
  255. package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
  256. package/src/scenarios/mcp-discoverability.test.ts +9 -7
  257. package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
  258. package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
  259. package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
  260. package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
  261. package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
  262. package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
  263. package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
  264. package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
  265. package/src/scenarios/mcp-stateless-request.test.ts +11 -10
  266. package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
  267. package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
  268. package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
  269. package/src/scenarios/media-url-inline-cap.test.ts +21 -19
  270. package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
  271. package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
  272. package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
  273. package/src/scenarios/memory-attribution-shape.test.ts +4 -3
  274. package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
  275. package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
  276. package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
  277. package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
  278. package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
  279. package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
  280. package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
  281. package/src/scenarios/memory-degraded-projection.test.ts +10 -9
  282. package/src/scenarios/memory-injection-budget.test.ts +15 -14
  283. package/src/scenarios/metric-emission.test.ts +4 -3
  284. package/src/scenarios/model-capability-insufficient.test.ts +19 -17
  285. package/src/scenarios/model-capability-substituted.test.ts +20 -18
  286. package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
  287. package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
  288. package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
  289. package/src/scenarios/multi-node-ordering.test.ts +4 -3
  290. package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
  291. package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
  292. package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
  293. package/src/scenarios/multi-region-idempotency.test.ts +6 -5
  294. package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
  295. package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
  296. package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
  297. package/src/scenarios/oauth-capability-shape.test.ts +5 -4
  298. package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
  299. package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
  300. package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
  301. package/src/scenarios/orchestratorDispatch.test.ts +2 -1
  302. package/src/scenarios/orchestratorTermination.test.ts +2 -1
  303. package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
  304. package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
  305. package/src/scenarios/otel-emission-grpc.test.ts +3 -2
  306. package/src/scenarios/otel-emission.test.ts +6 -5
  307. package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
  308. package/src/scenarios/otel-trace-propagation.test.ts +2 -1
  309. package/src/scenarios/owner-subject-echo.test.ts +13 -12
  310. package/src/scenarios/owner-subject-shape.test.ts +11 -10
  311. package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
  312. package/src/scenarios/pack-registry-isolation.test.ts +4 -3
  313. package/src/scenarios/pack-registry-publish.test.ts +65 -63
  314. package/src/scenarios/pack-registry.test.ts +38 -36
  315. package/src/scenarios/pause-resume.test.ts +18 -16
  316. package/src/scenarios/policies.test.ts +20 -18
  317. package/src/scenarios/production-backpressure.test.ts +18 -16
  318. package/src/scenarios/production-retention-expiry.test.ts +8 -6
  319. package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
  320. package/src/scenarios/profileDerivation.test.ts +34 -33
  321. package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
  322. package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
  323. package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
  324. package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
  325. package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
  326. package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
  327. package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
  328. package/src/scenarios/prompt-pack-install.test.ts +14 -12
  329. package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
  330. package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
  331. package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
  332. package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
  333. package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
  334. package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
  335. package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
  336. package/src/scenarios/prompt-template-shape.test.ts +30 -28
  337. package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
  338. package/src/scenarios/protocol-versions-array.test.ts +10 -9
  339. package/src/scenarios/provider-usage.test.ts +17 -15
  340. package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
  341. package/src/scenarios/purpose-propagation.test.ts +23 -21
  342. package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
  343. package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
  344. package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
  345. package/src/scenarios/rate-limit-envelope.test.ts +6 -5
  346. package/src/scenarios/redaction.test.ts +13 -11
  347. package/src/scenarios/redactionAdversarial.test.ts +11 -9
  348. package/src/scenarios/registry-public.test.ts +12 -11
  349. package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
  350. package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
  351. package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
  352. package/src/scenarios/replay-fork.test.ts +20 -19
  353. package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
  354. package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
  355. package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
  356. package/src/scenarios/replay-retention-expiry.test.ts +11 -9
  357. package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
  358. package/src/scenarios/replayDeterminism.test.ts +13 -12
  359. package/src/scenarios/requirement-ledger.test.ts +15 -14
  360. package/src/scenarios/restart-during-run.test.ts +3 -2
  361. package/src/scenarios/route-coverage.test.ts +20 -19
  362. package/src/scenarios/run-diff.test.ts +22 -20
  363. package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
  364. package/src/scenarios/run-transport-economy.test.ts +13 -11
  365. package/src/scenarios/runner-ledger.test.ts +17 -16
  366. package/src/scenarios/runs-lifecycle.test.ts +7 -6
  367. package/src/scenarios/runtime-capabilities.test.ts +12 -10
  368. package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
  369. package/src/scenarios/runtime-requires-shape.test.ts +7 -6
  370. package/src/scenarios/safefetch-behavior.test.ts +22 -21
  371. package/src/scenarios/safefetch-live-audit.test.ts +14 -13
  372. package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
  373. package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
  374. package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
  375. package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
  376. package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
  377. package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
  378. package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
  379. package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
  380. package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
  381. package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
  382. package/src/scenarios/self-hosted-runner.test.ts +26 -24
  383. package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
  384. package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
  385. package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
  386. package/src/scenarios/sql-injection-rejection.test.ts +8 -6
  387. package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
  388. package/src/scenarios/staleClaim.test.ts +5 -4
  389. package/src/scenarios/stream-modes-buffer.test.ts +8 -7
  390. package/src/scenarios/stream-modes-mixed.test.ts +10 -9
  391. package/src/scenarios/stream-modes.test.ts +12 -11
  392. package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
  393. package/src/scenarios/stream-text-fixture.test.ts +14 -13
  394. package/src/scenarios/streamReconnect.test.ts +13 -11
  395. package/src/scenarios/strict-behavior-gate.test.ts +9 -8
  396. package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
  397. package/src/scenarios/subrun-approval-gate.test.ts +3 -3
  398. package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
  399. package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
  400. package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
  401. package/src/scenarios/subworkflow.test.ts +10 -9
  402. package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
  403. package/src/scenarios/table-cursor-pagination.test.ts +8 -6
  404. package/src/scenarios/table-schema-enforcement.test.ts +7 -5
  405. package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
  406. package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
  407. package/src/scenarios/tool-catalog-projection.test.ts +11 -9
  408. package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
  409. package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
  410. package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
  411. package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
  412. package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
  413. package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
  414. package/src/scenarios/tool-hooks-shape.test.ts +3 -3
  415. package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
  416. package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
  417. package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
  418. package/src/scenarios/trigger-ingestion.test.ts +19 -17
  419. package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
  420. package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
  421. package/src/scenarios/verifier-gating.test.ts +8 -6
  422. package/src/scenarios/version-fold.test.ts +9 -8
  423. package/src/scenarios/version-negotiation.test.ts +12 -11
  424. package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
  425. package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
  426. package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
  427. package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
  428. package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
  429. package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
  430. package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
  431. package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
  432. package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
  433. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
  434. package/src/scenarios/wasm-pack-load.test.ts +4 -3
  435. package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
  436. package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
  437. package/src/scenarios/webhook-negative.test.ts +11 -9
  438. package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
  439. package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
  440. package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
  441. package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
  442. package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
  443. package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
  444. package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
  445. package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
  446. package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
  447. package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
  448. package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
  449. package/src/scenarios/workflow-variable-format.test.ts +24 -24
  450. package/src/scenarios/workload-identity-behavior.test.ts +15 -13
  451. package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
  452. package/src/scenarios/workspace-behavior.test.ts +19 -18
  453. package/src/scenarios/workspace-capability-shape.test.ts +3 -2
  454. package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
  455. package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
  456. package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
  457. package/src/setup.ts +4 -2
  458. package/vitest.config.ts +5 -1
  459. package/api/.redocly.lint-ignore.yaml +0 -22
  460. package/api/asyncapi.yaml +0 -834
  461. package/api/grpc/openwop.proto +0 -251
  462. package/api/openapi.yaml +0 -2693
  463. package/api/redocly.yaml +0 -23
  464. package/schemas/README.md +0 -144
  465. package/schemas/a2a-task-state.schema.json +0 -78
  466. package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
  467. package/schemas/agent-deployment-transition.schema.json +0 -49
  468. package/schemas/agent-deployment.schema.json +0 -54
  469. package/schemas/agent-eval-suite.schema.json +0 -140
  470. package/schemas/agent-inventory-response.schema.json +0 -115
  471. package/schemas/agent-manifest.schema.json +0 -156
  472. package/schemas/agent-org-chart.schema.json +0 -82
  473. package/schemas/agent-ref.schema.json +0 -63
  474. package/schemas/agent-roster-entry.schema.json +0 -81
  475. package/schemas/agent-roster-response.schema.json +0 -21
  476. package/schemas/ai-envelope.schema.json +0 -134
  477. package/schemas/annotation-create.schema.json +0 -37
  478. package/schemas/annotation.schema.json +0 -56
  479. package/schemas/artifact-type-pack-manifest.schema.json +0 -244
  480. package/schemas/audit-verify-result.schema.json +0 -90
  481. package/schemas/budget-policy.schema.json +0 -18
  482. package/schemas/capabilities.schema.json +0 -4124
  483. package/schemas/certification-bundle-v2.schema.json +0 -118
  484. package/schemas/channel-presence-payload.schema.json +0 -41
  485. package/schemas/channel-written-payload.schema.json +0 -55
  486. package/schemas/chat-card-pack-manifest.schema.json +0 -253
  487. package/schemas/compact-tool-descriptor.schema.json +0 -51
  488. package/schemas/compensation-policy.schema.json +0 -64
  489. package/schemas/conformance-certification-bundle.schema.json +0 -86
  490. package/schemas/connection-pack-manifest.schema.json +0 -353
  491. package/schemas/conversation-event.schema.json +0 -168
  492. package/schemas/conversation-turn.schema.json +0 -117
  493. package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
  494. package/schemas/credential-provenance.schema.json +0 -18
  495. package/schemas/credential-reference.schema.json +0 -21
  496. package/schemas/debug-bundle.schema.json +0 -196
  497. package/schemas/dispatch-config.schema.json +0 -112
  498. package/schemas/envelopes/clarification.request.schema.json +0 -52
  499. package/schemas/envelopes/error.schema.json +0 -30
  500. package/schemas/envelopes/media.audio.schema.json +0 -38
  501. package/schemas/envelopes/media.file.schema.json +0 -37
  502. package/schemas/envelopes/media.image.schema.json +0 -33
  503. package/schemas/envelopes/schema.request.schema.json +0 -26
  504. package/schemas/envelopes/schema.response.schema.json +0 -22
  505. package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
  506. package/schemas/error-envelope.schema.json +0 -25
  507. package/schemas/eval-summary.schema.json +0 -92
  508. package/schemas/export-bundle.schema.json +0 -66
  509. package/schemas/form-content-pack-manifest.schema.json +0 -243
  510. package/schemas/frontend-plugin-manifest.schema.json +0 -109
  511. package/schemas/goal.schema.json +0 -104
  512. package/schemas/heartbeat-evaluated.schema.json +0 -14
  513. package/schemas/heartbeat-state-changed.schema.json +0 -14
  514. package/schemas/localized-content-language-settings.schema.json +0 -26
  515. package/schemas/localized-content-page-response.schema.json +0 -60
  516. package/schemas/localized-content-page.schema.json +0 -62
  517. package/schemas/localized-content-section.schema.json +0 -51
  518. package/schemas/memory-entry.schema.json +0 -36
  519. package/schemas/memory-list-options.schema.json +0 -37
  520. package/schemas/node-pack-manifest.schema.json +0 -654
  521. package/schemas/orchestrator-decision.schema.json +0 -90
  522. package/schemas/org-chart-responsibility-view.schema.json +0 -26
  523. package/schemas/pack-lockfile.schema.json +0 -108
  524. package/schemas/prompt-kind.schema.json +0 -8
  525. package/schemas/prompt-pack-manifest.schema.json +0 -117
  526. package/schemas/prompt-ref.schema.json +0 -40
  527. package/schemas/prompt-template.schema.json +0 -149
  528. package/schemas/proposal.schema.json +0 -84
  529. package/schemas/registry-version-manifest.schema.json +0 -208
  530. package/schemas/residency.schema.json +0 -16
  531. package/schemas/run-ancestry-response.schema.json +0 -54
  532. package/schemas/run-diff-response.schema.json +0 -64
  533. package/schemas/run-event-payloads.schema.json +0 -4452
  534. package/schemas/run-event.schema.json +0 -211
  535. package/schemas/run-options.schema.json +0 -80
  536. package/schemas/run-orchestrator-decided-event.schema.json +0 -20
  537. package/schemas/run-snapshot.schema.json +0 -148
  538. package/schemas/security-advisory.schema.json +0 -109
  539. package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
  540. package/schemas/self-hosted-runner-registration.schema.json +0 -53
  541. package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
  542. package/schemas/subject.schema.json +0 -56
  543. package/schemas/suspend-request.schema.json +0 -207
  544. package/schemas/tool-descriptor.schema.json +0 -63
  545. package/schemas/trigger-event.schema.json +0 -222
  546. package/schemas/trigger-subscription-registration.schema.json +0 -67
  547. package/schemas/trigger-subscription.schema.json +0 -26
  548. package/schemas/ui-plugin-message.schema.json +0 -90
  549. package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
  550. package/schemas/workflow-definition.schema.json +0 -850
  551. package/schemas/workload-identity.schema.json +0 -79
  552. package/schemas/workspace-file-create.schema.json +0 -20
  553. package/schemas/workspace-file.schema.json +0 -39
@@ -35,8 +35,7 @@ import { join } from 'node:path';
35
35
  import Ajv2020 from 'ajv/dist/2020.js';
36
36
  import addFormats from 'ajv-formats';
37
37
  import { SCHEMAS_DIR } from '../lib/paths.js';
38
-
39
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
38
+ import { req } from '../lib/requirement-ids.js';
40
39
 
41
40
  function loadSchema(name: string): Record<string, unknown> {
42
41
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -52,17 +51,17 @@ describe('budget-policy-shape: BudgetPolicy (RFC 0084 §A, server-free)', () =>
52
51
  it('a conforming budget policy validates', () => {
53
52
  expect(
54
53
  validate({ maxTokens: 200000, maxCostUsd: 1.0, maxToolCalls: 50, maxRetries: 10, modelAllow: ['claude-*'], modelDeny: ['gpt-4-32k'], thresholdPercent: 80, onExhaustion: 'fail' }),
55
- why('budget-policy.md §A', 'a conforming BudgetPolicy MUST validate'),
54
+ req('openwop.it.budget-policy-shape.a-conforming-budget-policy-validates', 'budget-policy.md §A', 'a conforming BudgetPolicy MUST validate'),
56
55
  ).toBe(true);
57
56
  });
58
57
 
59
58
  it('the orthogonality guard: a wall-time field is rejected (it is RFC 0058 runTimeoutMs)', () => {
60
- expect(validate({ maxCostUsd: 1.0, maxWallTimeMs: 60000 }), why('budget-policy.md §A/§E', 'wall-time is NOT a budget dimension')).toBe(false);
59
+ expect(validate({ maxCostUsd: 1.0, maxWallTimeMs: 60000 }), req('openwop.it.budget-policy-shape.the-orthogonality-guard-a-wall-time-field-is-rejected-it-is-rfc-0058-runtimeoutm', 'budget-policy.md §A/§E', 'wall-time is NOT a budget dimension')).toBe(false);
61
60
  });
62
61
 
63
62
  it('rejects an out-of-range thresholdPercent and an out-of-enum onExhaustion', () => {
64
- expect(validate({ thresholdPercent: 120 }), why('budget-policy.md §A', 'thresholdPercent MUST be 0..100')).toBe(false);
65
- expect(validate({ onExhaustion: 'explode' }), why('budget-policy.md §A', 'onExhaustion is a closed enum')).toBe(false);
63
+ expect(validate({ thresholdPercent: 120 }), req('openwop.it.budget-policy-shape.rejects-an-out-of-range-thresholdpercent-and-an-out-of-enum-onexhaustion', 'budget-policy.md §A', 'thresholdPercent MUST be 0..100')).toBe(false);
64
+ expect(validate({ onExhaustion: 'explode' }), req('openwop.it.budget-policy-shape.rejects-an-out-of-range-thresholdpercent-and-an-out-of-enum-onexhaustion', 'budget-policy.md §A', 'onExhaustion is a closed enum')).toBe(false);
66
65
  });
67
66
  });
68
67
 
@@ -76,21 +75,21 @@ describe('budget-policy-shape: budget.* events + cap.breached kinds (RFC 0084 §
76
75
  } as Record<string, unknown>);
77
76
 
78
77
  it('the four budget.* payloads validate conforming content-free records', () => {
79
- expect(compile('budgetReserved')({ effectiveBudget: { maxCostUsd: 1.0 }, scope: 'run' }), why('budget-policy.md §C', 'budget.reserved MUST validate')).toBe(true);
80
- expect(compile('budgetConsumed')({ dimension: 'cost', consumed: 0.7, limit: 1.0, remaining: 0.3 }), why('budget-policy.md §C', 'budget.consumed MUST validate')).toBe(true);
81
- expect(compile('budgetThresholdCrossed')({ dimension: 'cost', consumed: 0.8, limit: 1.0, percent: 80 }), why('budget-policy.md §C', 'budget.threshold.crossed MUST validate')).toBe(true);
82
- expect(compile('budgetExhausted')({ dimension: 'cost', consumed: 1.02, limit: 1.0 }), why('budget-policy.md §C', 'budget.exhausted MUST validate')).toBe(true);
78
+ expect(compile('budgetReserved')({ effectiveBudget: { maxCostUsd: 1.0 }, scope: 'run' }), req('openwop.it.budget-policy-shape.the-four-budget-payloads-validate-conforming-content-free-records', 'budget-policy.md §C', 'budget.reserved MUST validate')).toBe(true);
79
+ expect(compile('budgetConsumed')({ dimension: 'cost', consumed: 0.7, limit: 1.0, remaining: 0.3 }), req('openwop.it.budget-policy-shape.the-four-budget-payloads-validate-conforming-content-free-records', 'budget-policy.md §C', 'budget.consumed MUST validate')).toBe(true);
80
+ expect(compile('budgetThresholdCrossed')({ dimension: 'cost', consumed: 0.8, limit: 1.0, percent: 80 }), req('openwop.it.budget-policy-shape.the-four-budget-payloads-validate-conforming-content-free-records', 'budget-policy.md §C', 'budget.threshold.crossed MUST validate')).toBe(true);
81
+ expect(compile('budgetExhausted')({ dimension: 'cost', consumed: 1.02, limit: 1.0 }), req('openwop.it.budget-policy-shape.the-four-budget-payloads-validate-conforming-content-free-records', 'budget-policy.md §C', 'budget.exhausted MUST validate')).toBe(true);
83
82
  });
84
83
 
85
84
  it('rejects an out-of-enum dimension and a missing required field', () => {
86
- expect(compile('budgetConsumed')({ dimension: 'vibes', consumed: 1, limit: 2 }), why('budget-policy.md §C', 'dimension is a closed enum')).toBe(false);
87
- expect(compile('budgetExhausted')({ dimension: 'cost', consumed: 1.0 }), why('budget-policy.md §C', 'limit is REQUIRED')).toBe(false);
85
+ expect(compile('budgetConsumed')({ dimension: 'vibes', consumed: 1, limit: 2 }), req('openwop.it.budget-policy-shape.rejects-an-out-of-enum-dimension-and-a-missing-required-field', 'budget-policy.md §C', 'dimension is a closed enum')).toBe(false);
86
+ expect(compile('budgetExhausted')({ dimension: 'cost', consumed: 1.0 }), req('openwop.it.budget-policy-shape.rejects-an-out-of-enum-dimension-and-a-missing-required-field', 'budget-policy.md §C', 'limit is REQUIRED')).toBe(false);
88
87
  });
89
88
 
90
89
  it('the cap.breached kind enum carries the four budget-* values', () => {
91
90
  const kinds = ((payloads.$defs as Record<string, { properties?: Record<string, { enum?: string[] }> }>).capBreached.properties?.kind?.enum) ?? [];
92
91
  for (const k of ['budget-tokens', 'budget-cost', 'budget-tool-calls', 'budget-retries']) {
93
- expect(kinds.includes(k), why('budget-policy.md §D', `cap.breached.kind MUST include ${k}`)).toBe(true);
92
+ expect(kinds.includes(k), req('openwop.it.budget-policy-shape.the-cap-breached-kind-enum-carries-the-four-budget-values', 'budget-policy.md §D', `cap.breached.kind MUST include ${k}`)).toBe(true);
94
93
  }
95
94
  });
96
95
 
@@ -98,7 +97,7 @@ describe('budget-policy-shape: budget.* events + cap.breached kinds (RFC 0084 §
98
97
  const runEvent = loadSchema('run-event.schema.json');
99
98
  const enumVals = ((runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum) ?? [];
100
99
  for (const name of ['budget.reserved', 'budget.consumed', 'budget.threshold.crossed', 'budget.exhausted']) {
101
- expect(enumVals.includes(name), why('run-event.schema.json', `${name} MUST be in the RunEventType enum`)).toBe(true);
100
+ expect(enumVals.includes(name), req('openwop.it.budget-policy-shape.all-four-budget-event-names-appear-in-the-runeventtype-enum', 'run-event.schema.json', `${name} MUST be in the RunEventType enum`)).toBe(true);
102
101
  }
103
102
  });
104
103
 
@@ -106,7 +105,7 @@ describe('budget-policy-shape: budget.* events + cap.breached kinds (RFC 0084 §
106
105
  const defs = payloads.$defs as Record<string, { properties?: Record<string, unknown> }>;
107
106
  for (const def of ['budgetReserved', 'budgetConsumed', 'budgetThresholdCrossed', 'budgetExhausted']) {
108
107
  for (const p of Object.keys(defs[def].properties ?? {})) {
109
- expect(PRICING_PROP_NAMES.includes(p.toLowerCase()), why('budget-no-pricing-leak', `${def} MUST NOT declare a pricing-bearing property (${p})`)).toBe(false);
108
+ expect(PRICING_PROP_NAMES.includes(p.toLowerCase()), req('openwop.it.budget-policy-shape.the-budget-payloads-declare-no-pricing-credential-property-budget-no-pricing-lea', 'budget-no-pricing-leak', `${def} MUST NOT declare a pricing-bearing property (${p})`)).toBe(false);
110
109
  }
111
110
  }
112
111
  });
@@ -114,10 +113,10 @@ describe('budget-policy-shape: budget.* events + cap.breached kinds (RFC 0084 §
114
113
  it('the budget.* payloads are additionalProperties:false — a rate-card field on an INSTANCE is rejected', () => {
115
114
  // The aggregate cost total (the user's own budget) is permitted; the host's per-unit rate card is not.
116
115
  // additionalProperties:false makes the rejection structural, not just a declared-property check.
117
- expect(compile('budgetConsumed')({ dimension: 'cost', consumed: 0.8, limit: 1.0 }), why('budget-policy.md §F', 'an aggregate cost total (the user budget) MUST validate')).toBe(true);
116
+ expect(compile('budgetConsumed')({ dimension: 'cost', consumed: 0.8, limit: 1.0 }), req('openwop.it.budget-policy-shape.the-budget-payloads-are-additionalproperties-false-a-rate-card-field-on-an-insta', 'budget-policy.md §F', 'an aggregate cost total (the user budget) MUST validate')).toBe(true);
118
117
  expect(
119
118
  compile('budgetConsumed')({ dimension: 'cost', consumed: 0.8, limit: 1.0, ratePerToken: 0.000003 }),
120
- why('budget-no-pricing-leak', 'a rate-card / per-token-price field MUST be rejected (additionalProperties:false)'),
119
+ req('openwop.it.budget-policy-shape.the-budget-payloads-are-additionalproperties-false-a-rate-card-field-on-an-insta', 'budget-no-pricing-leak', 'a rate-card / per-token-price field MUST be rejected (additionalProperties:false)'),
121
120
  ).toBe(false);
122
121
  });
123
122
  });
@@ -127,10 +126,10 @@ describe('budget-policy-shape: capability advertisement (RFC 0084 §E, server-fr
127
126
  const caps = loadSchema('capabilities.schema.json');
128
127
  const props = caps.properties as Record<string, { properties?: Record<string, unknown> }>;
129
128
  for (const flag of ['supported', 'dimensions', 'enforce', 'scopes']) {
130
- expect(props.budget?.properties?.[flag], why('budget-policy.md §E', `capabilities.budget.${flag} MUST be declared`)).toBeDefined();
129
+ expect(props.budget?.properties?.[flag], req('openwop.it.budget-policy-shape.capabilities-budget-limits-maxbudget-tokens-costusd-are-declared', 'budget-policy.md §E', `capabilities.budget.${flag} MUST be declared`)).toBeDefined();
131
130
  }
132
131
  for (const ceiling of ['maxBudgetTokens', 'maxBudgetCostUsd']) {
133
- expect(props.limits?.properties?.[ceiling], why('budget-policy.md §E', `limits.${ceiling} MUST be declared`)).toBeDefined();
132
+ expect(props.limits?.properties?.[ceiling], req('openwop.it.budget-policy-shape.capabilities-budget-limits-maxbudget-tokens-costusd-are-declared', 'budget-policy.md §E', `limits.${ceiling} MUST be declared`)).toBeDefined();
134
133
  }
135
134
  });
136
135
  });
@@ -20,6 +20,7 @@
20
20
  import { describe, it, expect } from 'vitest';
21
21
  import { driver } from '../lib/driver.js';
22
22
  import { isFixtureAdvertised } from '../lib/fixtures.js';
23
+ import { req } from '../lib/requirement-ids.js';
23
24
 
24
25
  const CANCELLABLE = 'conformance-cancellable';
25
26
  const NOOP = 'conformance-noop';
@@ -48,22 +49,22 @@ describe.skipIf(SKIP)('bulk-cancel: POST /v1/runs:bulk-cancel', () => {
48
49
  runIds: [inflightRunId, 'run-does-not-exist-xxxxxxxx'],
49
50
  reason: 'conformance bulk-cancel test',
50
51
  });
51
- expect(res.status, driver.describe(
52
+ expect(res.status, req('openwop.it.bulk-cancel.mixed-outcome-request-returns-per-id-results-in-order',
52
53
  'rest-endpoints.md §"POST /v1/runs:bulk-cancel"',
53
54
  'top-level operation MUST return 200 when the request reached the host (per-id outcomes carry partial failure)',
54
55
  )).toBe(200);
55
56
 
56
57
  const body = res.json as { results: BulkResult[] };
57
58
  expect(Array.isArray(body.results)).toBe(true);
58
- expect(body.results.length, 'results MUST have one entry per request runId').toBe(2);
59
+ expect(body.results.length, req('openwop.it.bulk-cancel.mixed-outcome-request-returns-per-id-results-in-order', 'rest-endpoints.md §"POST /v1/runs:bulk-cancel"', 'results MUST have one entry per request runId')).toBe(2);
59
60
 
60
- expect(body.results[0]!.runId, 'results order MUST mirror the request order').toBe(inflightRunId);
61
+ expect(body.results[0]!.runId, req('openwop.it.bulk-cancel.mixed-outcome-request-returns-per-id-results-in-order', 'rest-endpoints.md §"POST /v1/runs:bulk-cancel"', 'results order MUST mirror the request order')).toBe(inflightRunId);
61
62
  expect(body.results[0]!.ok).toBe(true);
62
63
  expect(['cancelling', 'cancelled']).toContain(body.results[0]!.status);
63
64
 
64
65
  expect(body.results[1]!.runId).toBe('run-does-not-exist-xxxxxxxx');
65
- expect(body.results[1]!.ok, 'unknown runId entry MUST have ok=false').toBe(false);
66
- expect(body.results[1]!.error?.code, driver.describe(
66
+ expect(body.results[1]!.ok, req('openwop.it.bulk-cancel.mixed-outcome-request-returns-per-id-results-in-order', 'rest-endpoints.md §"POST /v1/runs:bulk-cancel"', 'unknown runId entry MUST have ok=false')).toBe(false);
67
+ expect(body.results[1]!.error?.code, req('openwop.it.bulk-cancel.mixed-outcome-request-returns-per-id-results-in-order',
67
68
  'rest-endpoints.md §"POST /v1/runs:bulk-cancel"',
68
69
  'unknown runId outcomes carry `error.code === "not_found"`',
69
70
  )).toBe('not_found');
@@ -71,7 +72,7 @@ describe.skipIf(SKIP)('bulk-cancel: POST /v1/runs:bulk-cancel', () => {
71
72
 
72
73
  it('empty runIds array returns 400 validation_error', async () => {
73
74
  const res = await driver.post('/v1/runs:bulk-cancel', { runIds: [] });
74
- expect(res.status).toBe(400);
75
+ expect(res.status, req('openwop.it.bulk-cancel.empty-runids-array-returns-400-validation-error', 'rest-endpoints.md §Open', 'empty runIds array returns 400 validation_error')).toBe(400);
75
76
  const body = res.json as { error?: string };
76
77
  expect(body.error).toBe('validation_error');
77
78
  });
@@ -83,7 +84,7 @@ describe.skipIf(SKIP)('bulk-cancel: POST /v1/runs:bulk-cancel', () => {
83
84
  expect(res.status).toBe(400);
84
85
  const body = res.json as { error?: string; details?: { maxRunIds?: number } };
85
86
  expect(body.error).toBe('validation_error');
86
- expect(typeof body.details?.maxRunIds, driver.describe(
87
+ expect(typeof body.details?.maxRunIds, req('openwop.it.bulk-cancel.oversized-runids-array-returns-400-with-details-maxrunids',
87
88
  'rest-endpoints.md §"POST /v1/runs:bulk-cancel"',
88
89
  'over-cap request MUST carry details.maxRunIds disclosing the configured ceiling',
89
90
  )).toBe('number');
@@ -103,7 +104,7 @@ describe.skipIf(SKIP)('bulk-cancel: POST /v1/runs:bulk-cancel', () => {
103
104
  const second = await driver.post('/v1/runs:bulk-cancel', { runIds: [runId] });
104
105
  expect(second.status).toBe(200);
105
106
  const body = second.json as { results: BulkResult[] };
106
- expect(body.results[0]!.ok, driver.describe(
107
+ expect(body.results[0]!.ok, req('openwop.it.bulk-cancel.re-bulk-cancel-after-first-cancel-is-idempotent',
107
108
  'rest-endpoints.md §"POST /v1/runs:bulk-cancel" §Idempotency',
108
109
  're-cancelling an already-cancelling/cancelled run MUST be ok: true (idempotent)',
109
110
  )).toBe(true);
@@ -30,9 +30,8 @@ import Ajv2020 from 'ajv/dist/2020.js';
30
30
  import addFormats from 'ajv-formats';
31
31
  import { driver } from '../lib/driver.js';
32
32
  import { SCHEMAS_DIR } from '../lib/paths.js';
33
-
34
- /** Server-free assertion-message helper (mirrors driver.describe's "spec — requirement" shape without requiring OPENWOP_BASE_URL — used in the always-on shape group). */
35
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
33
+ import { req } from '../lib/requirement-ids.js';
34
+ import { softSkip } from '../lib/soft-skip.js';
36
35
 
37
36
  interface AuthModeCapabilities {
38
37
  aiProviders?: {
@@ -70,9 +69,9 @@ describe('byok-auth-modes: schema shape (RFC 0067, server-free)', () => {
70
69
  | undefined;
71
70
  expect(
72
71
  authModes,
73
- why('capabilities.md §aiProviders.authModes', 'the schema MUST declare aiProviders.authModes'),
72
+ req('openwop.it.byok-auth-modes.the-capabilities-schema-declares-aiproviders-authmodes-with-the-five-mode-enum', 'capabilities.md §aiProviders.authModes', 'the schema MUST declare aiProviders.authModes'),
74
73
  ).toBeDefined();
75
- expect(authModes?.additionalProperties?.items?.enum).toEqual([
74
+ expect(authModes?.additionalProperties?.items?.enum, req('openwop.it.byok-auth-modes.the-capabilities-schema-declares-aiproviders-authmodes-with-the-five-mode-enum', 'RFC 0067', 'the capabilities schema declares aiProviders.authModes with the five-mode enum')).toEqual([
76
75
  'apiKey',
77
76
  'oauth-pkce',
78
77
  'oauth-device',
@@ -85,10 +84,10 @@ describe('byok-auth-modes: schema shape (RFC 0067, server-free)', () => {
85
84
  const validate = authModesValidator();
86
85
  expect(
87
86
  validate({ anthropic: ['apiKey'], vertex: ['oauth-pkce'], ollama: ['none'] }),
88
- why('RFC 0067 §A', 'a conforming authModes map MUST validate'),
87
+ req('openwop.it.byok-auth-modes.a-conforming-authmodes-map-validates-malformed-maps-are-rejected', 'RFC 0067 §A', 'a conforming authModes map MUST validate'),
89
88
  ).toBe(true);
90
89
  // Negative: empty array fails minItems.
91
- expect(validate({ anthropic: [] })).toBe(false);
90
+ expect(validate({ anthropic: [] }), req('openwop.it.byok-auth-modes.a-conforming-authmodes-map-validates-malformed-maps-are-rejected', 'RFC 0067', 'a conforming authModes map validates; malformed maps are rejected')).toBe(false);
92
91
  // Negative: unknown mode (`device` — canonical is `oauth-device`) fails the enum.
93
92
  expect(validate({ anthropic: ['device'] })).toBe(false);
94
93
  });
@@ -97,10 +96,10 @@ describe('byok-auth-modes: schema shape (RFC 0067, server-free)', () => {
97
96
  describe('byok-auth-modes: cross-field consistency (gated on advertisement)', () => {
98
97
  it('a host advertising authModes MUST satisfy the §B contract', async () => {
99
98
  const res = await driver.get('/.well-known/openwop', { authenticated: false });
100
- if (res.status !== 200) return; // discovery unavailable — skip cleanly
99
+ if (res.status !== 200) return softSkip('blocked', 'precondition not met — `res.status !== 200` returned early (discovery unavailable — skip cleanly) (seam, prior step, or fixture unavailable)'); // discovery unavailable — skip cleanly
101
100
  const caps = res.json as AuthModeCapabilities;
102
101
  const authModes = caps.aiProviders?.authModes;
103
- if (!authModes) return; // host does not advertise authModes — gated skip
102
+ if (!authModes) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!authModes` returned early (host does not advertise authModes — gated skip)'); // host does not advertise authModes — gated skip
104
103
 
105
104
  const supported = new Set(caps.aiProviders?.supported ?? []);
106
105
  const byok = new Set(caps.aiProviders?.byok ?? []);
@@ -110,14 +109,14 @@ describe('byok-auth-modes: cross-field consistency (gated on advertisement)', ()
110
109
  // §B.1 — every key is in `supported`.
111
110
  expect(
112
111
  supported.has(provider),
113
- driver.describe('RFC 0067 §B.1', `authModes key '${provider}' MUST appear in aiProviders.supported`),
112
+ req('openwop.it.byok-auth-modes.a-host-advertising-authmodes-must-satisfy-the-b-contract', 'RFC 0067 §B.1', `authModes key '${provider}' MUST appear in aiProviders.supported`),
114
113
  ).toBe(true);
115
114
 
116
115
  // §B.2 — an `apiKey` provider is in `byok`.
117
116
  if (modes.includes('apiKey')) {
118
117
  expect(
119
118
  byok.has(provider),
120
- driver.describe('RFC 0067 §B.2', `provider '${provider}' with apiKey MUST appear in aiProviders.byok`),
119
+ req('openwop.it.byok-auth-modes.a-host-advertising-authmodes-must-satisfy-the-b-contract', 'RFC 0067 §B.2', `provider '${provider}' with apiKey MUST appear in aiProviders.byok`),
121
120
  ).toBe(true);
122
121
  }
123
122
 
@@ -125,7 +124,7 @@ describe('byok-auth-modes: cross-field consistency (gated on advertisement)', ()
125
124
  if (modes.includes('subscription')) {
126
125
  expect(
127
126
  byok.has(provider),
128
- driver.describe('RFC 0121 §B.7', `provider '${provider}' with subscription MUST appear in aiProviders.byok`),
127
+ req('openwop.it.byok-auth-modes.a-host-advertising-authmodes-must-satisfy-the-b-contract', 'RFC 0121 §B.7', `provider '${provider}' with subscription MUST appear in aiProviders.byok`),
129
128
  ).toBe(true);
130
129
  }
131
130
 
@@ -133,7 +132,7 @@ describe('byok-auth-modes: cross-field consistency (gated on advertisement)', ()
133
132
  if (modes.length === 1 && modes[0] === 'none') {
134
133
  expect(
135
134
  byok.has(provider),
136
- driver.describe('RFC 0067 §B.3', `provider '${provider}' with modes ["none"] MUST NOT appear in aiProviders.byok`),
135
+ req('openwop.it.byok-auth-modes.a-host-advertising-authmodes-must-satisfy-the-b-contract', 'RFC 0067 §B.3', `provider '${provider}' with modes ["none"] MUST NOT appear in aiProviders.byok`),
137
136
  ).toBe(false);
138
137
  }
139
138
 
@@ -142,7 +141,7 @@ describe('byok-auth-modes: cross-field consistency (gated on advertisement)', ()
142
141
  if ((modes.includes('oauth-pkce') || modes.includes('oauth-device')) && oauthIds.size > 0) {
143
142
  expect(
144
143
  oauthIds.has(provider),
145
- driver.describe('RFC 0067 §B.4', `oauth provider '${provider}' SHOULD have a matching capabilities.oauth.providers[].id`),
144
+ req('openwop.it.byok-auth-modes.a-host-advertising-authmodes-must-satisfy-the-b-contract', 'RFC 0067 §B.4', `oauth provider '${provider}' SHOULD have a matching capabilities.oauth.providers[].id`),
146
145
  ).toBe(true);
147
146
  }
148
147
  }
@@ -26,6 +26,8 @@ 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';
30
+ import { softSkip } from '../lib/soft-skip.js';
29
31
 
30
32
  /** SHA-256 hex regex — 64 lowercase hex chars exactly. */
31
33
  const SHA256_HEX_RE = /^[0-9a-f]{64}$/;
@@ -42,17 +44,17 @@ describe.skipIf(SKIP_NO_FIXTURE)('byok: end-to-end credentialRef resolution roun
42
44
  // Fixture absent OR canary not provisioned — host doesn't opt in.
43
45
  // Scenario passes trivially.
44
46
  if (create.status === 404 || create.status === 422) {
45
- return;
47
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `create.status === 404 || create.status === 422` returned early (Fixture absent OR canary not provisioned — host doesn\'t opt in. Scenario passes trivially.)');
46
48
  }
47
49
 
48
- expect(create.status, driver.describe(
50
+ expect(create.status, req('openwop.it.byok-roundtrip.the-canary-fixture-run-must-resolve-a-host-provisioned-secret-and-emit-sha-256-h',
49
51
  'rest-endpoints.md POST /v1/runs',
50
52
  'starting openwop-smoke-byok-roundtrip MUST succeed when OPENWOP_CONFORMANCE_FIXTURES=1 is advertised AND openwop-conformance-canary-secret is provisioned',
51
53
  )).toBe(201);
52
54
  const runId = (create.json as { runId: string }).runId;
53
55
 
54
56
  const terminal = await pollUntilTerminal(runId);
55
- expect(terminal.status, driver.describe(
57
+ expect(terminal.status, req('openwop.it.byok-roundtrip.the-canary-fixture-run-must-resolve-a-host-provisioned-secret-and-emit-sha-256-h',
56
58
  'auth.md §"Secret resolution"',
57
59
  'BYOK fixture run MUST reach terminal completed when canary is provisioned',
58
60
  )).toBe('completed');
@@ -79,17 +81,17 @@ describe.skipIf(SKIP_NO_FIXTURE)('byok: end-to-end credentialRef resolution roun
79
81
  // Host doesn't expose node outputs in variables/outputs map —
80
82
  // some hosts only expose them on the events stream. Skip the
81
83
  // shape check; the run-completed assertion above is sufficient.
82
- return;
84
+ return softSkip('blocked', 'precondition not met — `!candidate || typeof candidate !== \'object\'` returned early (Host doesn\'t expose node outputs in variables/outputs map — some hosts only expose them on the events stream. Skip the shape check; …');
83
85
  }
84
86
 
85
87
  if ('secretSha256' in candidate && typeof candidate.secretSha256 === 'string') {
86
- expect(candidate.secretSha256, driver.describe(
88
+ expect(candidate.secretSha256, req('openwop.it.byok-roundtrip.the-canary-fixture-run-must-resolve-a-host-provisioned-secret-and-emit-sha-256-h',
87
89
  'auth.md §"Secret resolution"',
88
90
  'fixture-emitted SHA-256 hex MUST be 64 lowercase hex chars',
89
91
  )).toMatch(SHA256_HEX_RE);
90
92
  }
91
93
  if ('secretLength' in candidate && typeof candidate.secretLength === 'number') {
92
- expect(candidate.secretLength, driver.describe(
94
+ expect(candidate.secretLength, req('openwop.it.byok-roundtrip.the-canary-fixture-run-must-resolve-a-host-provisioned-secret-and-emit-sha-256-h',
93
95
  'auth.md §"Secret resolution"',
94
96
  'resolved canary length MUST be > 0 (non-empty)',
95
97
  )).toBeGreaterThan(0);
@@ -101,7 +103,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('byok: end-to-end credentialRef resolution roun
101
103
  workflowId: 'openwop-smoke-byok-roundtrip',
102
104
  });
103
105
  if (create.status === 404 || create.status === 422) {
104
- return;
106
+ return softSkip('blocked', 'precondition not met — `create.status === 404 || create.status === 422` returned early (seam, prior step, or fixture unavailable)');
105
107
  }
106
108
  expect(create.status).toBe(201);
107
109
  const runId = (create.json as { runId: string }).runId;
@@ -116,7 +118,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('byok: end-to-end credentialRef resolution roun
116
118
  const completed = events.filter(
117
119
  (e) => e.type === 'node.completed' && e.nodeId === 'resolve-secret',
118
120
  );
119
- expect(completed.length, driver.describe(
121
+ expect(completed.length, req('openwop.it.byok-roundtrip.byok-fixture-run-must-emit-a-node-completed-event-for-the-resolve-step',
120
122
  'event-log.md §node.completed',
121
123
  'BYOK fixture node MUST emit exactly one node.completed event when secrets.resolve succeeds',
122
124
  )).toBe(1);
@@ -127,7 +129,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('byok: end-to-end credentialRef resolution roun
127
129
  workflowId: 'openwop-smoke-byok-roundtrip',
128
130
  });
129
131
  if (create.status === 404 || create.status === 422) {
130
- return;
132
+ return softSkip('blocked', 'precondition not met — `create.status === 404 || create.status === 422` returned early (seam, prior step, or fixture unavailable)');
131
133
  }
132
134
  expect(create.status).toBe(201);
133
135
  const runId = (create.json as { runId: string }).runId;
@@ -157,7 +159,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('byok: end-to-end credentialRef resolution roun
157
159
  /"raw_secret"\s*:\s*"[^"]{8,}"/,
158
160
  ];
159
161
  for (const pat of suspiciousPatterns) {
160
- expect(dump, driver.describe(
162
+ expect(dump, req('openwop.it.byok-roundtrip.byok-fixture-run-event-log-must-not-echo-the-resolved-secret-value-redaction',
161
163
  'observability.md §"Redaction"',
162
164
  `event log MUST NOT contain a payload matching ${pat} — secret.echo fixture only emits hash + length`,
163
165
  )).not.toMatch(pat);
@@ -10,6 +10,8 @@
10
10
  import { describe, it, expect } from 'vitest';
11
11
  import { driver } from '../lib/driver.js';
12
12
  import { discoveryFamilies } from '../lib/discovery-capabilities.js';
13
+ import { req } from '../lib/requirement-ids.js';
14
+ import { softSkip } from '../lib/soft-skip.js';
13
15
 
14
16
  interface DiscoveryDoc {
15
17
  capabilities?: Record<string, unknown>;
@@ -30,10 +32,10 @@ async function call(tenantId: string, op: string, args: Record<string, unknown>)
30
32
  describe('cache-cross-tenant-isolation: advertisement shape (RFC 0019)', () => {
31
33
  it('capabilities.cache is either absent or a well-formed object', async () => {
32
34
  const cap = await readCap();
33
- if (cap === null) return;
35
+ if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early');
34
36
  expect(
35
37
  typeof cap.supported,
36
- driver.describe(
38
+ req('openwop.it.cache-cross-tenant-isolation.capabilities-cache-is-either-absent-or-a-well-formed-object',
37
39
  'capabilities.schema.json §cache',
38
40
  'capabilities.cache.supported MUST be a boolean when present',
39
41
  ),
@@ -44,19 +46,19 @@ describe('cache-cross-tenant-isolation: advertisement shape (RFC 0019)', () => {
44
46
  describe('cache-cross-tenant-isolation: behavioral (RFC 0019 §B point 2)', () => {
45
47
  it('put under tenant A → get under tenant B returns miss', async () => {
46
48
  const cap = await readCap();
47
- if (!cap || cap.supported !== true) return;
49
+ if (!cap || cap.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!cap || cap.supported !== true` returned early');
48
50
  const key = `xtenant-cache-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
49
51
 
50
52
  const putRes = await call('tenant-a', 'put', { key, value: 'from-A', ttlSeconds: 60 });
51
- if (putRes.status === 404) return;
52
- expect(putRes.status, 'put MUST succeed').toBe(200);
53
+ if (putRes.status === 404) return softSkip('blocked', 'precondition not met — `putRes.status === 404` returned early (seam, prior step, or fixture unavailable)');
54
+ expect(putRes.status, req('openwop.it.cache-cross-tenant-isolation.put-under-tenant-a-get-under-tenant-b-returns-miss', 'RFC 0019 §B point 2', 'put MUST succeed')).toBe(200);
53
55
 
54
56
  const getRes = await call('tenant-b', 'get', { key });
55
57
  expect(getRes.status).toBe(200);
56
58
  const body = getRes.json as { hit?: boolean };
57
59
  expect(
58
60
  body.hit,
59
- driver.describe('RFC 0019 §B point 2', 'tenant B MUST NOT hit tenant A cache entry at same key'),
61
+ req('openwop.it.cache-cross-tenant-isolation.put-under-tenant-a-get-under-tenant-b-returns-miss', 'RFC 0019 §B point 2', 'tenant B MUST NOT hit tenant A cache entry at same key'),
60
62
  ).toBe(false);
61
63
  });
62
64
  });
@@ -16,6 +16,8 @@
16
16
  import { describe, it, expect } from 'vitest';
17
17
  import { driver } from '../lib/driver.js';
18
18
  import { discoveryFamilies } from '../lib/discovery-capabilities.js';
19
+ import { req } from '../lib/requirement-ids.js';
20
+ import { softSkip } from '../lib/soft-skip.js';
19
21
 
20
22
  interface DiscoveryDoc {
21
23
  capabilities?: Record<string, unknown>;
@@ -32,10 +34,10 @@ async function readCap(): Promise<Record<string, unknown> | null> {
32
34
  describe('cache-ttl-expiry: advertisement shape (RFC 0019)', () => {
33
35
  it('capabilities.cache is either absent or a well-formed object', async () => {
34
36
  const cap = await readCap();
35
- if (cap === null) return; // host doesn't advertise — skip
37
+ if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early (host doesn\'t advertise — skip)'); // host doesn't advertise — skip
36
38
  expect(
37
39
  typeof cap.supported,
38
- driver.describe(
40
+ req('openwop.it.cache-ttl-expiry.capabilities-cache-is-either-absent-or-a-well-formed-object',
39
41
  'capabilities.schema.json §cache',
40
42
  'capabilities.cache.supported MUST be a boolean when present',
41
43
  ),
@@ -50,7 +52,7 @@ async function call(op: string, args: Record<string, unknown>) {
50
52
  describe('cache-ttl-expiry: behavioral (RFC 0019 §B point 2 — 1s TTL drift)', () => {
51
53
  it('put with ttlSeconds=2 → hit within window; miss after expiry', async () => {
52
54
  const probe = await call('get', { key: '__cache-probe__' });
53
- if (probe.status === 404) return;
55
+ if (probe.status === 404) return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam, prior step, or fixture unavailable)');
54
56
  const key = `c-ttl-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
55
57
  const putRes = await call('put', { key, value: 'evicts-soon', ttlSeconds: 2 });
56
58
  expect(putRes.status).toBe(200);
@@ -59,7 +61,7 @@ describe('cache-ttl-expiry: behavioral (RFC 0019 §B point 2 — 1s TTL drift)',
59
61
  const withinBody = within.json as { value?: unknown; found?: boolean };
60
62
  expect(
61
63
  withinBody.value,
62
- driver.describe('RFC 0019 §B point 2', 'cache get within TTL MUST return the stored value'),
64
+ req('openwop.it.cache-ttl-expiry.put-with-ttlseconds-2-hit-within-window-miss-after-expiry', 'RFC 0019 §B point 2', 'cache get within TTL MUST return the stored value'),
63
65
  ).toBe('evicts-soon');
64
66
 
65
67
  await new Promise((r) => setTimeout(r, 3000));
@@ -68,7 +70,7 @@ describe('cache-ttl-expiry: behavioral (RFC 0019 §B point 2 — 1s TTL drift)',
68
70
  const afterBody = after.json as { value?: unknown; found?: boolean };
69
71
  expect(
70
72
  afterBody.found,
71
- driver.describe('RFC 0019 §B point 2', 'cache get after TTL expiry MUST surface as found:false (≤1s drift)'),
73
+ req('openwop.it.cache-ttl-expiry.put-with-ttlseconds-2-hit-within-window-miss-after-expiry', 'RFC 0019 §B point 2', 'cache get after TTL expiry MUST surface as found:false (≤1s drift)'),
72
74
  ).toBe(false);
73
75
  });
74
76
  });
@@ -22,6 +22,8 @@ import { describe, it, expect } from 'vitest';
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 ALL_MODALITIES = ['text', 'image', 'audio', 'document'];
27
29
 
@@ -60,10 +62,10 @@ describe('callai-multimodal (RFC 0091 §A/§B)', () => {
60
62
  const okRes = await driver.post(SEAM, {
61
63
  messages: [{ role: 'user', content: [{ type: 'text', text: 'describe this' }, okPart] }],
62
64
  });
63
- if (okRes.status === 404) return; // seam unwired — soft-skip the whole behavioral suite
65
+ if (okRes.status === 404) return softSkip('blocked', 'precondition not met — `okRes.status === 404` returned early (seam unwired — soft-skip the whole behavioral suite) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip the whole behavioral suite
64
66
  expect(
65
67
  errCode(okRes.json) !== 'unsupported_modality',
66
- driver.describe('RFC 0091 §B', `an advertised modality (${accepted}) MUST NOT be rejected as unsupported_modality`),
68
+ req('openwop.it.callai-multimodal.accepts-an-advertised-non-text-modality-and-rejects-an-unadvertised-one-with-uns', 'RFC 0091 §B', `an advertised modality (${accepted}) MUST NOT be rejected as unsupported_modality`),
67
69
  ).toBe(true);
68
70
 
69
71
  // 2) An unadvertised modality MUST be rejected with unsupported_modality.
@@ -79,7 +81,7 @@ describe('callai-multimodal (RFC 0091 §A/§B)', () => {
79
81
  });
80
82
  expect(
81
83
  errCode(badRes.json) === 'unsupported_modality',
82
- driver.describe('RFC 0091 §A', `an unadvertised modality (${unadvertised}) MUST be rejected with unsupported_modality (never silently dropped)`),
84
+ req('openwop.it.callai-multimodal.accepts-an-advertised-non-text-modality-and-rejects-an-unadvertised-one-with-uns', 'RFC 0091 §A', `an unadvertised modality (${unadvertised}) MUST be rejected with unsupported_modality (never silently dropped)`),
83
85
  ).toBe(true);
84
86
  }
85
87
  });
@@ -11,6 +11,7 @@ import { describe, it, expect } from 'vitest';
11
11
  import { driver } from '../lib/driver.js';
12
12
  import { pollUntilStatus } from '../lib/polling.js';
13
13
  import { isFixtureAdvertised } from '../lib/fixtures.js';
14
+ import { req } from '../lib/requirement-ids.js';
14
15
 
15
16
  const WORKFLOW_ID = 'conformance-cancellable';
16
17
  const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
@@ -21,7 +22,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('cancellation: in-flight :cancel reaches termin
21
22
  workflowId: WORKFLOW_ID,
22
23
  inputs: { delayMs: 10_000 },
23
24
  });
24
- expect(create.status, driver.describe(
25
+ expect(create.status, req('openwop.it.cancellation.post-v1-runs-runid-cancel-returns-200-and-run-terminates-as-cancelled',
25
26
  'rest-endpoints.md',
26
27
  'POST /v1/runs MUST return 201 on accepted run',
27
28
  )).toBe(201);
@@ -35,7 +36,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('cancellation: in-flight :cancel reaches termin
35
36
  `/v1/runs/${encodeURIComponent(runId)}/cancel`,
36
37
  { reason: 'conformance-cancellation-test' },
37
38
  );
38
- expect(cancel.status, driver.describe(
39
+ expect(cancel.status, req('openwop.it.cancellation.post-v1-runs-runid-cancel-returns-200-and-run-terminates-as-cancelled',
39
40
  'rest-endpoints.md POST /v1/runs/{runId}/cancel',
40
41
  'cancel MUST return 200 on accepted cancellation',
41
42
  )).toBe(200);
@@ -43,14 +44,14 @@ describe.skipIf(SKIP_NO_FIXTURE)('cancellation: in-flight :cancel reaches termin
43
44
  const cancelBody = cancel.json as { status?: string };
44
45
  expect(
45
46
  ['cancelled', 'cancelling'].includes(cancelBody.status ?? ''),
46
- driver.describe(
47
+ req('openwop.it.cancellation.post-v1-runs-runid-cancel-returns-200-and-run-terminates-as-cancelled',
47
48
  'rest-endpoints.md POST /v1/runs/{runId}/cancel',
48
49
  'cancel response status MUST be one of `cancelled` or `cancelling`',
49
50
  ),
50
51
  ).toBe(true);
51
52
 
52
53
  const terminal = await pollUntilStatus(runId, 'cancelled', { timeoutMs: 5_000 });
53
- expect(terminal.status, driver.describe(
54
+ expect(terminal.status, req('openwop.it.cancellation.post-v1-runs-runid-cancel-returns-200-and-run-terminates-as-cancelled',
54
55
  'fixtures.md conformance-cancellable §Terminal status',
55
56
  'fixture MUST reach terminal `cancelled` within 5s of cancel',
56
57
  )).toBe('cancelled');
@@ -62,7 +63,7 @@ describe('cancellation: cancelling an unknown run returns 404', () => {
62
63
  const res = await driver.post('/v1/runs/openwop-conformance-no-such-run/cancel', {});
63
64
  expect(
64
65
  [403, 404].includes(res.status),
65
- driver.describe('rest-endpoints.md', 'cancel on unknown run MUST return 404 or 403'),
66
+ req('openwop.it.cancellation.post-v1-runs-nonexistentid-cancel-returns-404', 'rest-endpoints.md', 'cancel on unknown run MUST return 404 or 403'),
66
67
  ).toBe(true);
67
68
  });
68
69
  });