@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
@@ -41,6 +41,8 @@ import { loadEnv } from '../lib/env.js';
41
41
  import { behaviorGate } from '../lib/behavior-gate.js';
42
42
  import { isFixtureAdvertised } from '../lib/fixtures.js';
43
43
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
44
+ import { req } from '../lib/requirement-ids.js';
45
+ import { softSkip } from '../lib/soft-skip.js';
44
46
 
45
47
  interface BackpressureCaps {
46
48
  supported?: boolean;
@@ -72,12 +74,12 @@ describe('production-backpressure: capability shape', () => {
72
74
  return;
73
75
  }
74
76
 
75
- expect(prod?.supported, driver.describe(
77
+ expect(prod?.supported, req('openwop.it.production-backpressure.host-that-claims-openwop-production-with-backpressure-advertises-required-fields',
76
78
  'production-profile.md §Compatibility baseline',
77
79
  'capabilities.production.supported MUST be true when claiming the openwop-production profile',
78
80
  )).toBe(true);
79
81
 
80
- expect(prod?.backpressure?.supported, driver.describe(
82
+ expect(prod?.backpressure?.supported, req('openwop.it.production-backpressure.host-that-claims-openwop-production-with-backpressure-advertises-required-fields',
81
83
  'production-profile.md §Backpressure',
82
84
  'capabilities.production.backpressure.supported MUST be true for production-profile claimants',
83
85
  )).toBe(true);
@@ -86,7 +88,7 @@ describe('production-backpressure: capability shape', () => {
86
88
  expect(
87
89
  Number.isInteger(prod.backpressure.inflightCap) &&
88
90
  prod.backpressure.inflightCap >= 1,
89
- driver.describe(
91
+ req('openwop.it.production-backpressure.host-that-claims-openwop-production-with-backpressure-advertises-required-fields',
90
92
  'capabilities.schema.json production.backpressure.inflightCap',
91
93
  'inflightCap MUST be an integer ≥ 1 when advertised',
92
94
  ),
@@ -97,7 +99,7 @@ describe('production-backpressure: capability shape', () => {
97
99
  expect(
98
100
  Number.isInteger(prod.backpressure.retryAfterSeconds) &&
99
101
  prod.backpressure.retryAfterSeconds >= 0,
100
- driver.describe(
102
+ req('openwop.it.production-backpressure.host-that-claims-openwop-production-with-backpressure-advertises-required-fields',
101
103
  'capabilities.schema.json production.backpressure.retryAfterSeconds',
102
104
  'retryAfterSeconds MUST be a non-negative integer when advertised',
103
105
  ),
@@ -120,7 +122,7 @@ describe('production-backpressure: 503 envelope under saturation', () => {
120
122
  console.warn(
121
123
  '[production-backpressure] host does not advertise inflightCap; skipping saturation assertion',
122
124
  );
123
- return;
125
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === undefined` returned early ([production-backpressure] host does not advertise inflightCap; skipping saturation assertion)');
124
126
  }
125
127
 
126
128
  // Use the conformance-delay fixture to hold inflight slots via
@@ -132,7 +134,7 @@ describe('production-backpressure: 503 envelope under saturation', () => {
132
134
  console.warn(
133
135
  `[production-backpressure] ${FIXTURE} not advertised; skipping saturation (host doesn't seed the long-running fixture)`,
134
136
  );
135
- return;
137
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early ([production-backpressure] … not advertised; skipping saturation (host doesn\'t seed the long-running fixture))');
136
138
  }
137
139
 
138
140
  // Create `cap` long-running runs and open SSE streams against each
@@ -210,7 +212,7 @@ describe('production-backpressure: 503 envelope under saturation', () => {
210
212
  }
211
213
  }
212
214
  await Promise.allSettled(slotPromises);
213
- return;
215
+ return softSkip('blocked', 'precondition not met — `saturationEarlyExit` returned early (seam, prior step, or fixture unavailable)');
214
216
  }
215
217
 
216
218
  // Let SSE connections register.
@@ -231,11 +233,11 @@ describe('production-backpressure: 503 envelope under saturation', () => {
231
233
  console.warn(
232
234
  `[production-backpressure] expected 503 at cap+1=${cap + 1}, got ${blocked.status}; saturation may need tuning`,
233
235
  );
234
- return;
236
+ return softSkip('blocked', 'precondition not met — `blocked.status !== 503` returned early ([production-backpressure] expected 503 at cap+1=…, got …; saturation may need tuning) (seam, prior step, or fixture unavailable)');
235
237
  }
236
238
 
237
239
  const retryAfterHeader = blocked.headers.get('retry-after');
238
- expect(retryAfterHeader, driver.describe(
240
+ expect(retryAfterHeader, req('openwop.it.production-backpressure.saturating-advertised-inflightcap-returns-503-retry-after-canonical-envelope',
239
241
  'production-profile.md §Backpressure',
240
242
  '503 response MUST include a Retry-After header',
241
243
  )).toBeTruthy();
@@ -247,7 +249,7 @@ describe('production-backpressure: 503 envelope under saturation', () => {
247
249
  details?: { retryAfter?: number };
248
250
  };
249
251
 
250
- expect(body.error, driver.describe(
252
+ expect(body.error, req('openwop.it.production-backpressure.saturating-advertised-inflightcap-returns-503-retry-after-canonical-envelope',
251
253
  'production-profile.md §Backpressure',
252
254
  '503 envelope MUST have error: "service_unavailable"',
253
255
  )).toBe('service_unavailable');
@@ -255,14 +257,14 @@ describe('production-backpressure: 503 envelope under saturation', () => {
255
257
  expect(typeof body.message).toBe('string');
256
258
  expect((body.message ?? '').length).toBeGreaterThan(0);
257
259
 
258
- expect(typeof body.details?.retryAfter, driver.describe(
260
+ expect(typeof body.details?.retryAfter, req('openwop.it.production-backpressure.saturating-advertised-inflightcap-returns-503-retry-after-canonical-envelope',
259
261
  'production-profile.md §Backpressure',
260
262
  'details.retryAfter MUST be present and numeric',
261
263
  )).toBe('number');
262
264
 
263
265
  // details.retryAfter MUST equal the Retry-After header in seconds.
264
266
  const headerSeconds = Number.parseInt(retryAfterHeader ?? '', 10);
265
- expect(body.details?.retryAfter, driver.describe(
267
+ expect(body.details?.retryAfter, req('openwop.it.production-backpressure.saturating-advertised-inflightcap-returns-503-retry-after-canonical-envelope',
266
268
  'production-profile.md §Backpressure',
267
269
  'details.retryAfter MUST equal Retry-After header in seconds',
268
270
  )).toBe(headerSeconds);
@@ -270,7 +272,7 @@ describe('production-backpressure: 503 envelope under saturation', () => {
270
272
  // If retryAfterSeconds is advertised, both equal it.
271
273
  const advertised = prod?.backpressure?.retryAfterSeconds;
272
274
  if (advertised !== undefined) {
273
- expect(headerSeconds, driver.describe(
275
+ expect(headerSeconds, req('openwop.it.production-backpressure.saturating-advertised-inflightcap-returns-503-retry-after-canonical-envelope',
274
276
  'capabilities.schema.json production.backpressure.retryAfterSeconds',
275
277
  'Retry-After MUST equal advertised retryAfterSeconds when both are present',
276
278
  )).toBe(advertised);
@@ -319,11 +321,11 @@ describe('production-backpressure: discovery exempt from cap', () => {
319
321
  // Without advertised cap we can't saturate deterministically;
320
322
  // fall back to a single discovery probe.
321
323
  const probe = await driver.get('/.well-known/openwop');
322
- expect(probe.status, driver.describe(
324
+ expect(probe.status, req('openwop.it.production-backpressure.get-well-known-openwop-returns-200-even-when-inflight-is-saturated',
323
325
  'production-profile.md §Backpressure',
324
326
  'discovery MUST answer regardless of load',
325
327
  )).toBe(200);
326
- return;
328
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === undefined` returned early');
327
329
  }
328
330
 
329
331
  // Issue many concurrent discovery probes; all MUST succeed.
@@ -333,7 +335,7 @@ describe('production-backpressure: discovery exempt from cap', () => {
333
335
  ),
334
336
  );
335
337
  for (const probe of probes) {
336
- expect(probe.status, driver.describe(
338
+ expect(probe.status, req('openwop.it.production-backpressure.get-well-known-openwop-returns-200-even-when-inflight-is-saturated',
337
339
  'production-profile.md §Backpressure',
338
340
  'discovery MUST bypass the inflight cap (health probes always answer)',
339
341
  )).toBe(200);
@@ -32,6 +32,8 @@ import { describe, it, expect } from 'vitest';
32
32
  import { driver } from '../lib/driver.js';
33
33
  import { behaviorGate } from '../lib/behavior-gate.js';
34
34
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
35
+ import { req } from '../lib/requirement-ids.js';
36
+ import { softSkip } from '../lib/soft-skip.js';
35
37
 
36
38
  interface RetentionCaps {
37
39
  supported?: boolean;
@@ -63,12 +65,12 @@ describe('production-retention-expiry: capability shape', () => {
63
65
  return;
64
66
  }
65
67
 
66
- expect(prod?.retention?.supported, driver.describe(
68
+ expect(prod?.retention?.supported, req('openwop.it.production-retention-expiry.host-claiming-openwop-production-with-retention-advertises-required-fields',
67
69
  'production-profile.md §"Event retention"',
68
70
  'capabilities.production.retention.supported MUST be true for production-profile claimants',
69
71
  )).toBe(true);
70
72
 
71
- expect(prod?.retention?.minWindowSeconds, driver.describe(
73
+ expect(prod?.retention?.minWindowSeconds, req('openwop.it.production-retention-expiry.host-claiming-openwop-production-with-retention-advertises-required-fields',
72
74
  'production-profile.md §"Event retention"',
73
75
  'capabilities.production.retention.minWindowSeconds MUST be advertised when retention.supported is true',
74
76
  )).toBeDefined();
@@ -76,7 +78,7 @@ describe('production-retention-expiry: capability shape', () => {
76
78
  expect(
77
79
  Number.isInteger(prod?.retention?.minWindowSeconds) &&
78
80
  (prod?.retention?.minWindowSeconds ?? 0) >= SEVEN_DAYS_SECONDS,
79
- driver.describe(
81
+ req('openwop.it.production-retention-expiry.host-claiming-openwop-production-with-retention-advertises-required-fields',
80
82
  'production-profile.md §"Event retention"',
81
83
  'minWindowSeconds MUST be an integer ≥ 604800 (7 days) for public production-profile claimants',
82
84
  ),
@@ -126,14 +128,14 @@ describe('production-retention-expiry: 410/404 envelope on expired run', () => {
126
128
  console.warn(
127
129
  '[production-retention-expiry] no expired runId available (set OPENWOP_TEST_EXPIRED_RUN_ID or advertise testForceExpire + provide OPENWOP_TEST_FORCE_EXPIRE_URL); skipping envelope assertion',
128
130
  );
129
- return;
131
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `expiredRunId === undefined` returned early ([production-retention-expiry] no expired runId available (set OPENWOP_TEST_EXPIRED_RUN_ID or advertise testForceExp…');
130
132
  }
131
133
 
132
134
  const res = await driver.get(`/v1/runs/${encodeURIComponent(expiredRunId)}`);
133
135
 
134
136
  expect(
135
137
  res.status === 410 || res.status === 404,
136
- driver.describe(
138
+ req('openwop.it.production-retention-expiry.get-v1-runs-expiredrunid-returns-410-or-404-with-canonical-envelope',
137
139
  'production-profile.md §"Event retention"',
138
140
  'expired run MUST return 410 Gone (preferred) or 404 Not Found',
139
141
  ),
@@ -145,7 +147,7 @@ describe('production-retention-expiry: 410/404 envelope on expired run', () => {
145
147
  details?: { expiredAt?: string };
146
148
  };
147
149
 
148
- expect(typeof body.error, driver.describe(
150
+ expect(typeof body.error, req('openwop.it.production-retention-expiry.get-v1-runs-expiredrunid-returns-410-or-404-with-canonical-envelope',
149
151
  'production-profile.md §"Event retention"',
150
152
  'expired-run response MUST use the canonical error envelope ({error, message, details?})',
151
153
  )).toBe('string');
@@ -30,6 +30,8 @@ import { join } from 'node:path';
30
30
  import { driver } from '../lib/driver.js';
31
31
  import { PROFILE_NAMES, deriveProfiles, hasProfile, type DiscoveryPayload } from '../lib/profiles.js';
32
32
  import { V1_DIR } from '../lib/paths.js';
33
+ import { req } from '../lib/requirement-ids.js';
34
+ import { softSkip } from '../lib/soft-skip.js';
33
35
 
34
36
  const CANONICAL = 'openwop-discovery-core';
35
37
  const ALIAS = 'openwop-core';
@@ -59,7 +61,7 @@ describe('RFC 0155 §A — openwop-discovery-core is canonical, openwop-core is
59
61
  expect(PROFILE_NAMES).toContain(ALIAS);
60
62
  expect(
61
63
  PROFILE_NAMES.indexOf(CANONICAL),
62
- 'the canonical name precedes its alias so derived sets read canonical-first',
64
+ req('openwop.it.profile-discovery-core-alias.both-names-are-in-the-closed-catalog-canonical-first', 'RFC 0155 §A', 'the canonical name precedes its alias so derived sets read canonical-first'),
63
65
  ).toBeLessThan(PROFILE_NAMES.indexOf(ALIAS));
64
66
  });
65
67
 
@@ -69,26 +71,26 @@ describe('RFC 0155 §A — openwop-discovery-core is canonical, openwop-core is
69
71
  for (const [label, c] of PAYLOADS) {
70
72
  const canonical = hasProfile(c, CANONICAL);
71
73
  const alias = hasProfile(c, ALIAS);
72
- expect(alias, `${label}: hasProfile(alias) MUST equal hasProfile(canonical)`).toBe(canonical);
74
+ expect(alias, req('openwop.it.profile-discovery-core-alias.the-alias-derives-exactly-when-the-canonical-name-derives-for-payloads-on-both-s', 'RFC 0155 §A', `${label}: hasProfile(alias) MUST equal hasProfile(canonical)`)).toBe(canonical);
73
75
  const derived = deriveProfiles(c);
74
76
  expect(
75
77
  derived.includes(ALIAS),
76
- `${label}: deriveProfiles MUST emit the alias iff it emits the canonical name (never the alias alone)`,
78
+ req('openwop.it.profile-discovery-core-alias.the-alias-derives-exactly-when-the-canonical-name-derives-for-payloads-on-both-s', 'RFC 0155 §A', `${label}: deriveProfiles MUST emit the alias iff it emits the canonical name (never the alias alone)`),
77
79
  ).toBe(derived.includes(CANONICAL));
78
80
  if (canonical) trueCount++;
79
81
  else falseCount++;
80
82
  }
81
83
  // Non-vacuity: an equivalence over payloads that all derive (or none do)
82
84
  // proves nothing about the other side.
83
- expect(trueCount, 'at least one payload MUST derive the predicate').toBeGreaterThan(0);
84
- expect(falseCount, 'at least one payload MUST fail the predicate').toBeGreaterThan(0);
85
+ expect(trueCount, req('openwop.it.profile-discovery-core-alias.the-alias-derives-exactly-when-the-canonical-name-derives-for-payloads-on-both-s', 'RFC 0155 §A', 'at least one payload MUST derive the predicate')).toBeGreaterThan(0);
86
+ expect(falseCount, req('openwop.it.profile-discovery-core-alias.the-alias-derives-exactly-when-the-canonical-name-derives-for-payloads-on-both-s', 'RFC 0155 §A', 'at least one payload MUST fail the predicate')).toBeGreaterThan(0);
85
87
  });
86
88
 
87
89
  it('a derived set that carries the alias carries the canonical name immediately before it', () => {
88
90
  const derived = deriveProfiles(CORE);
89
91
  const i = derived.indexOf(CANONICAL);
90
92
  expect(i).toBeGreaterThanOrEqual(0);
91
- expect(derived[i + 1], 'alias rides directly beside its canonical name').toBe(ALIAS);
93
+ expect(derived[i + 1], req('openwop.it.profile-discovery-core-alias.a-derived-set-that-carries-the-alias-carries-the-canonical-name-immediately-befo', 'RFC 0155 §A', 'alias rides directly beside its canonical name')).toBe(ALIAS);
92
94
  });
93
95
  });
94
96
 
@@ -99,7 +101,7 @@ describe.skipIf(V1_DIR === null)('RFC 0155 §A — profiles.md states the rename
99
101
  const md = doc();
100
102
  expect(md).toMatch(/###\s+`openwop-discovery-core`\s+\(canonical\)/);
101
103
  expect(md).toMatch(/alias `openwop-core` \(deprecated\)/);
102
- expect(md, 'the alias MUST be defined as deriving exactly when the canonical name derives').toMatch(
104
+ expect(md, req('openwop.it.profile-discovery-core-alias.names-the-canonical-profile-and-marks-openwop-core-as-a-deprecated-alias', 'RFC 0155 §A', 'the alias MUST be defined as deriving exactly when the canonical name derives')).toMatch(
103
105
  /derives \*\*exactly when\*\* `openwop-discovery-core` derives/,
104
106
  );
105
107
  });
@@ -107,7 +109,7 @@ describe.skipIf(V1_DIR === null)('RFC 0155 §A — profiles.md states the rename
107
109
  it('states that an unqualified conformance claim means openwop-core-standard', () => {
108
110
  const md = doc();
109
111
  expect(md).toMatch(/unqualified\*\* "OpenWOP conformant".*\*\*MUST\*\* mean \*\*`openwop-core-standard`\*\*/s);
110
- expect(md, 'discovery-only claims MUST say openwop-discovery-core').toMatch(
112
+ expect(md, req('openwop.it.profile-discovery-core-alias.states-that-an-unqualified-conformance-claim-means-openwop-core-standard', 'RFC 0155 §A', 'discovery-only claims MUST say openwop-discovery-core')).toMatch(
111
113
  /discovery-only\*\* claim \*\*MUST\*\* say \*\*`openwop-discovery-core`\*\*/,
112
114
  );
113
115
  });
@@ -116,7 +118,7 @@ describe.skipIf(V1_DIR === null)('RFC 0155 §A — profiles.md states the rename
116
118
  const md = doc();
117
119
  const canonicalLine = md.indexOf("'openwop-discovery-core' if openwop-discovery-core(c)");
118
120
  const aliasLine = md.indexOf("'openwop-core' if openwop-discovery-core(c)");
119
- expect(canonicalLine).toBeGreaterThan(0);
121
+ expect(canonicalLine, req('openwop.it.profile-discovery-core-alias.the-reference-derivation-lists-the-alias-beside-the-canonical-name-never-alone', 'RFC 0155 §A', 'the reference derivation lists the alias beside the canonical name, never alone')).toBeGreaterThan(0);
120
122
  expect(aliasLine).toBeGreaterThan(canonicalLine);
121
123
  });
122
124
  });
@@ -124,11 +126,11 @@ describe.skipIf(V1_DIR === null)('RFC 0155 §A — profiles.md states the rename
124
126
  describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0155 §A — a live host derives both names or neither', () => {
125
127
  it('the discovery payload derives the alias iff it derives the canonical name', async () => {
126
128
  const res = await driver.get('/.well-known/openwop');
127
- if (res.status !== 200) return; // discovery is witnessed elsewhere; this leg is about the alias rule
129
+ if (res.status !== 200) return softSkip('blocked', 'precondition not met — `res.status !== 200` returned early (discovery is witnessed elsewhere; this leg is about the alias rule) (seam, prior step, or fixture unavailable)'); // discovery is witnessed elsewhere; this leg is about the alias rule
128
130
  const derived = deriveProfiles(res.json as DiscoveryPayload);
129
131
  expect(
130
132
  derived.includes(ALIAS),
131
- driver.describe(
133
+ req('openwop.it.profile-discovery-core-alias.the-discovery-payload-derives-the-alias-iff-it-derives-the-canonical-name',
132
134
  'profiles.md §"openwop-discovery-core"',
133
135
  'the deprecated alias MUST derive exactly when the canonical name derives — a host is never `openwop-core` without being `openwop-discovery-core`',
134
136
  ),
@@ -25,6 +25,7 @@ import {
25
25
  type DiscoveryPayload,
26
26
  type ProfileName,
27
27
  } from '../lib/profiles.js';
28
+ import { req } from '../lib/requirement-ids.js';
28
29
 
29
30
  /**
30
31
  * Minimum payload that satisfies `openwop-core`. Other fixtures extend this.
@@ -42,16 +43,16 @@ const CORE_PAYLOAD: DiscoveryPayload = {
42
43
 
43
44
  describe('profiles: openwop-core predicate per spec/v1/profiles.md §`openwop-core`', () => {
44
45
  it('accepts the minimum-conforming payload', () => {
45
- expect(isCore(CORE_PAYLOAD)).toBe(true);
46
+ expect(isCore(CORE_PAYLOAD), req('openwop.it.profileDerivation.accepts-the-minimum-conforming-payload', 'spec/v1/profiles.md', 'accepts the minimum-conforming payload')).toBe(true);
46
47
  });
47
48
 
48
49
  it('rejects payload without protocolVersion', () => {
49
50
  const { protocolVersion: _omit, ...rest } = CORE_PAYLOAD;
50
- expect(isCore(rest as DiscoveryPayload)).toBe(false);
51
+ expect(isCore(rest as DiscoveryPayload), req('openwop.it.profileDerivation.rejects-payload-without-protocolversion', 'spec/v1/profiles.md', 'rejects payload without protocolVersion')).toBe(false);
51
52
  });
52
53
 
53
54
  it('rejects v2.x protocolVersion', () => {
54
- expect(isCore({ ...CORE_PAYLOAD, protocolVersion: '2.0.0' })).toBe(false);
55
+ expect(isCore({ ...CORE_PAYLOAD, protocolVersion: '2.0.0' }), req('openwop.it.profileDerivation.rejects-v2-x-protocolversion', 'spec/v1/profiles.md', 'rejects v2.x protocolVersion')).toBe(false);
55
56
  });
56
57
 
57
58
  it('rejects negative limits (RFC 2119 MUST: non-negative integers)', () => {
@@ -59,7 +60,7 @@ describe('profiles: openwop-core predicate per spec/v1/profiles.md §`openwop-co
59
60
  isCore({
60
61
  ...CORE_PAYLOAD,
61
62
  limits: { ...CORE_PAYLOAD.limits!, clarificationRounds: -1 },
62
- }),
63
+ }), req('openwop.it.profileDerivation.rejects-negative-limits-rfc-2119-must-non-negative-integers', 'RFC 2119', 'rejects negative limits (RFC 2119 MUST: non-negative integers)'),
63
64
  ).toBe(false);
64
65
  });
65
66
 
@@ -68,17 +69,17 @@ describe('profiles: openwop-core predicate per spec/v1/profiles.md §`openwop-co
68
69
  isCore({
69
70
  ...CORE_PAYLOAD,
70
71
  limits: { ...CORE_PAYLOAD.limits!, schemaRounds: 1.5 },
71
- }),
72
+ }), req('openwop.it.profileDerivation.rejects-fractional-limits', 'spec/v1/profiles.md', 'rejects fractional limits'),
72
73
  ).toBe(false);
73
74
  });
74
75
 
75
76
  it('accepts empty supportedEnvelopes array (engine-only host)', () => {
76
- expect(isCore({ ...CORE_PAYLOAD, supportedEnvelopes: [] })).toBe(true);
77
+ expect(isCore({ ...CORE_PAYLOAD, supportedEnvelopes: [] }), req('openwop.it.profileDerivation.accepts-empty-supportedenvelopes-array-engine-only-host', 'spec/v1/profiles.md', 'accepts empty supportedEnvelopes array (engine-only host)')).toBe(true);
77
78
  });
78
79
 
79
80
  it('rejects non-array supportedEnvelopes', () => {
80
81
  expect(
81
- isCore({ ...CORE_PAYLOAD, supportedEnvelopes: 'prd.create' as unknown as string[] }),
82
+ isCore({ ...CORE_PAYLOAD, supportedEnvelopes: 'prd.create' as unknown as string[] }), req('openwop.it.profileDerivation.rejects-non-array-supportedenvelopes', 'spec/v1/profiles.md', 'rejects non-array supportedEnvelopes'),
82
83
  ).toBe(false);
83
84
  });
84
85
  });
@@ -89,12 +90,12 @@ describe('profiles: openwop-interrupts predicate per spec/v1/profiles.md §`open
89
90
  isInterrupts({
90
91
  ...CORE_PAYLOAD,
91
92
  supportedEnvelopes: ['prd.create', 'clarification.request'],
92
- }),
93
+ }), req('openwop.it.profileDerivation.passes-when-clarification-request-is-in-supportedenvelopes', 'spec/v1/profiles.md', 'passes when clarification.request is in supportedEnvelopes'),
93
94
  ).toBe(true);
94
95
  });
95
96
 
96
97
  it('fails when clarification.request is absent (fire-and-forget host)', () => {
97
- expect(isInterrupts(CORE_PAYLOAD)).toBe(false);
98
+ expect(isInterrupts(CORE_PAYLOAD), req('openwop.it.profileDerivation.fails-when-clarification-request-is-absent-fire-and-forget-host', 'spec/v1/profiles.md', 'fails when clarification.request is absent (fire-and-forget host)')).toBe(false);
98
99
  });
99
100
 
100
101
  it('implies openwop-core', () => {
@@ -103,7 +104,7 @@ describe('profiles: openwop-interrupts predicate per spec/v1/profiles.md §`open
103
104
  protocolVersion: '2.0.0',
104
105
  supportedEnvelopes: ['clarification.request'],
105
106
  };
106
- expect(isInterrupts(broken)).toBe(false);
107
+ expect(isInterrupts(broken), req('openwop.it.profileDerivation.implies-openwop-core', 'spec/v1/profiles.md', 'implies openwop-core')).toBe(false);
107
108
  });
108
109
  });
109
110
 
@@ -113,7 +114,7 @@ describe('profiles: openwop-secrets predicate per spec/v1/profiles.md §`openwop
113
114
  isSecrets({
114
115
  ...CORE_PAYLOAD,
115
116
  secrets: { supported: true, scopes: ['user'] },
116
- }),
117
+ }), req('openwop.it.profileDerivation.passes-when-secrets-supported-true-and-scopes-includes-user', 'spec/v1/profiles.md', 'passes when secrets.supported=true and scopes includes user'),
117
118
  ).toBe(true);
118
119
  });
119
120
 
@@ -122,7 +123,7 @@ describe('profiles: openwop-secrets predicate per spec/v1/profiles.md §`openwop
122
123
  isSecrets({
123
124
  ...CORE_PAYLOAD,
124
125
  secrets: { supported: true, scopes: ['user', 'tenant'] },
125
- }),
126
+ }), req('openwop.it.profileDerivation.passes-with-multiple-scopes', 'spec/v1/profiles.md', 'passes with multiple scopes'),
126
127
  ).toBe(true);
127
128
  });
128
129
 
@@ -131,7 +132,7 @@ describe('profiles: openwop-secrets predicate per spec/v1/profiles.md §`openwop
131
132
  isSecrets({
132
133
  ...CORE_PAYLOAD,
133
134
  secrets: { supported: true, scopes: ['tenant'] },
134
- }),
135
+ }), req('openwop.it.profileDerivation.fails-when-scopes-omits-user', 'spec/v1/profiles.md', 'fails when scopes omits user'),
135
136
  ).toBe(false);
136
137
  });
137
138
 
@@ -140,12 +141,12 @@ describe('profiles: openwop-secrets predicate per spec/v1/profiles.md §`openwop
140
141
  isSecrets({
141
142
  ...CORE_PAYLOAD,
142
143
  secrets: { supported: false, scopes: ['user'] },
143
- }),
144
+ }), req('openwop.it.profileDerivation.fails-when-secrets-supported-false', 'spec/v1/profiles.md', 'fails when secrets.supported=false'),
144
145
  ).toBe(false);
145
146
  });
146
147
 
147
148
  it('fails when secrets field is absent', () => {
148
- expect(isSecrets(CORE_PAYLOAD)).toBe(false);
149
+ expect(isSecrets(CORE_PAYLOAD), req('openwop.it.profileDerivation.fails-when-secrets-field-is-absent', 'spec/v1/profiles.md', 'fails when secrets field is absent')).toBe(false);
149
150
  });
150
151
  });
151
152
 
@@ -158,7 +159,7 @@ describe('profiles: openwop-provider-policy predicate per spec/v1/profiles.md §
158
159
  supported: ['anthropic'],
159
160
  policies: { modes: ['optional', 'required'] },
160
161
  },
161
- }),
162
+ }), req('openwop.it.profileDerivation.passes-when-policies-modes-contains-optional', 'spec/v1/profiles.md', 'passes when policies.modes contains optional'),
162
163
  ).toBe(true);
163
164
  });
164
165
 
@@ -170,7 +171,7 @@ describe('profiles: openwop-provider-policy predicate per spec/v1/profiles.md §
170
171
  supported: ['anthropic'],
171
172
  policies: { modes: [] },
172
173
  },
173
- }),
174
+ }), req('openwop.it.profileDerivation.fails-when-policies-modes-is-empty-per-spec-empty-not-a-valid-third-state', 'spec/v1/profiles.md', 'fails when policies.modes is empty (per spec: empty {} not a valid third state)'),
174
175
  ).toBe(false);
175
176
  });
176
177
 
@@ -182,7 +183,7 @@ describe('profiles: openwop-provider-policy predicate per spec/v1/profiles.md §
182
183
  supported: ['anthropic'],
183
184
  policies: { modes: ['required'] },
184
185
  },
185
- }),
186
+ }), req('openwop.it.profileDerivation.fails-when-policies-modes-omits-optional-cannot-satisfy-default-no-restriction-c', 'spec/v1/profiles.md', 'fails when policies.modes omits optional (cannot satisfy default-no-restriction case)'),
186
187
  ).toBe(false);
187
188
  });
188
189
 
@@ -191,23 +192,23 @@ describe('profiles: openwop-provider-policy predicate per spec/v1/profiles.md §
191
192
  isProviderPolicy({
192
193
  ...CORE_PAYLOAD,
193
194
  aiProviders: { supported: ['anthropic'] },
194
- }),
195
+ }), req('openwop.it.profileDerivation.fails-when-policies-field-is-absent', 'spec/v1/profiles.md', 'fails when policies field is absent'),
195
196
  ).toBe(false);
196
197
  });
197
198
  });
198
199
 
199
200
  describe('profiles: openwop-fixtures predicate per spec/v1/profiles.md §`openwop-fixtures` (RFC 0003)', () => {
200
201
  it('rejects payloads missing `fixtures`', () => {
201
- expect(isFixtures(CORE_PAYLOAD)).toBe(false);
202
+ expect(isFixtures(CORE_PAYLOAD), req('openwop.it.profileDerivation.rejects-payloads-missing-fixtures', 'spec/v1/profiles.md', 'rejects payloads missing `fixtures`')).toBe(false);
202
203
  });
203
204
 
204
205
  it('rejects empty `fixtures` array', () => {
205
- expect(isFixtures({ ...CORE_PAYLOAD, fixtures: [] })).toBe(false);
206
+ expect(isFixtures({ ...CORE_PAYLOAD, fixtures: [] }), req('openwop.it.profileDerivation.rejects-empty-fixtures-array', 'spec/v1/profiles.md', 'rejects empty `fixtures` array')).toBe(false);
206
207
  });
207
208
 
208
209
  it('accepts non-empty string array', () => {
209
210
  expect(
210
- isFixtures({ ...CORE_PAYLOAD, fixtures: ['conformance-noop'] }),
211
+ isFixtures({ ...CORE_PAYLOAD, fixtures: ['conformance-noop'] }), req('openwop.it.profileDerivation.accepts-non-empty-string-array', 'spec/v1/profiles.md', 'accepts non-empty string array'),
211
212
  ).toBe(true);
212
213
  });
213
214
 
@@ -216,16 +217,16 @@ describe('profiles: openwop-fixtures predicate per spec/v1/profiles.md §`openwo
216
217
  isFixtures({
217
218
  ...CORE_PAYLOAD,
218
219
  fixtures: ['conformance-noop', 'openwop.smoke.byok'],
219
- }),
220
+ }), req('openwop.it.profileDerivation.accepts-vendor-prefixed-fixture-ids', 'spec/v1/profiles.md', 'accepts vendor-prefixed fixture ids'),
220
221
  ).toBe(true);
221
222
  });
222
223
 
223
224
  it('rejects array with empty-string entries', () => {
224
- expect(isFixtures({ ...CORE_PAYLOAD, fixtures: ['', 'conformance-noop'] })).toBe(false);
225
+ expect(isFixtures({ ...CORE_PAYLOAD, fixtures: ['', 'conformance-noop'] }), req('openwop.it.profileDerivation.rejects-array-with-empty-string-entries', 'spec/v1/profiles.md', 'rejects array with empty-string entries')).toBe(false);
225
226
  });
226
227
 
227
228
  it('rejects non-array `fixtures`', () => {
228
- expect(isFixtures({ ...CORE_PAYLOAD, fixtures: 'conformance-noop' })).toBe(false);
229
+ expect(isFixtures({ ...CORE_PAYLOAD, fixtures: 'conformance-noop' }), req('openwop.it.profileDerivation.rejects-non-array-fixtures', 'spec/v1/profiles.md', 'rejects non-array `fixtures`')).toBe(false);
229
230
  expect(
230
231
  isFixtures({ ...CORE_PAYLOAD, fixtures: { 'conformance-noop': true } }),
231
232
  ).toBe(false);
@@ -233,12 +234,12 @@ describe('profiles: openwop-fixtures predicate per spec/v1/profiles.md §`openwo
233
234
 
234
235
  it('rejects array with non-string entries', () => {
235
236
  expect(
236
- isFixtures({ ...CORE_PAYLOAD, fixtures: ['conformance-noop', 42] as unknown[] }),
237
+ isFixtures({ ...CORE_PAYLOAD, fixtures: ['conformance-noop', 42] as unknown[] }), req('openwop.it.profileDerivation.rejects-array-with-non-string-entries', 'spec/v1/profiles.md', 'rejects array with non-string entries'),
237
238
  ).toBe(false);
238
239
  });
239
240
 
240
241
  it('rejects when openwop-core fails (predicate is layered)', () => {
241
- expect(isFixtures({ fixtures: ['conformance-noop'] })).toBe(false);
242
+ expect(isFixtures({ fixtures: ['conformance-noop'] }), req('openwop.it.profileDerivation.rejects-when-openwop-core-fails-predicate-is-layered', 'spec/v1/profiles.md', 'rejects when openwop-core fails (predicate is layered)')).toBe(false);
242
243
  });
243
244
  });
244
245
 
@@ -249,7 +250,7 @@ describe('profiles: deriveProfiles produces the full set', () => {
249
250
  // (no supportedTransports set => permitted), openwop-node-packs (discovery-
250
251
  // only predicate is openwop-core).
251
252
  const result = deriveProfiles(CORE_PAYLOAD);
252
- expect(result).toContain('openwop-core');
253
+ expect(result, req('openwop.it.profileDerivation.returns-openwop-core-stream-node-packs-for-the-minimum-payload', 'spec/v1/profiles.md', 'returns openwop-core + stream-* + node-packs for the minimum payload')).toContain('openwop-core');
253
254
  expect(result).toContain('openwop-stream-sse');
254
255
  expect(result).toContain('openwop-stream-poll');
255
256
  expect(result).toContain('openwop-node-packs');
@@ -282,7 +283,7 @@ describe('profiles: deriveProfiles produces the full set', () => {
282
283
  'openwop-node-packs',
283
284
  'openwop-fixtures',
284
285
  ];
285
- expect(result).toEqual(expected);
286
+ expect(result, req('openwop.it.profileDerivation.returns-the-full-set-for-a-richly-advertised-host', 'spec/v1/profiles.md', 'returns the full set for a richly-advertised host')).toEqual(expected);
286
287
  });
287
288
 
288
289
  it('returns stable order matching PROFILE_NAMES', () => {
@@ -293,7 +294,7 @@ describe('profiles: deriveProfiles produces the full set', () => {
293
294
  };
294
295
  const first = deriveProfiles(rich);
295
296
  const second = deriveProfiles(rich);
296
- expect(first).toEqual(second);
297
+ expect(first, req('openwop.it.profileDerivation.returns-stable-order-matching-profile-names', 'spec/v1/profiles.md', 'returns stable order matching PROFILE_NAMES')).toEqual(second);
297
298
  // Specifically: openwop-interrupts before openwop-secrets even though openwop-secrets
298
299
  // was added to the payload "second."
299
300
  expect(first.indexOf('openwop-interrupts')).toBeLessThan(first.indexOf('openwop-secrets'));
@@ -301,13 +302,13 @@ describe('profiles: deriveProfiles produces the full set', () => {
301
302
 
302
303
  it('returns empty for a non-conforming payload', () => {
303
304
  const broken: DiscoveryPayload = { protocolVersion: '0.9.0' };
304
- expect(deriveProfiles(broken)).toEqual([]);
305
+ expect(deriveProfiles(broken), req('openwop.it.profileDerivation.returns-empty-for-a-non-conforming-payload', 'spec/v1/profiles.md', 'returns empty for a non-conforming payload')).toEqual([]);
305
306
  });
306
307
 
307
308
  it('is deterministic across calls (same input → same output)', () => {
308
309
  const calls = Array.from({ length: 10 }, () => deriveProfiles(CORE_PAYLOAD));
309
310
  for (let i = 1; i < calls.length; i++) {
310
- expect(calls[i]).toEqual(calls[0]);
311
+ expect(calls[i], req('openwop.it.profileDerivation.is-deterministic-across-calls-same-input-same-output', 'spec/v1/profiles.md', 'is deterministic across calls (same input → same output)')).toEqual(calls[0]);
311
312
  }
312
313
  });
313
314
  });
@@ -330,7 +331,7 @@ describe('profiles: hasProfile is consistent with deriveProfiles', () => {
330
331
  'openwop-node-packs',
331
332
  'openwop-fixtures',
332
333
  ] as const) {
333
- expect(hasProfile(rich, p)).toBe(derived.has(p));
334
+ expect(hasProfile(rich, p), req('openwop.it.profileDerivation.membership-matches-the-derived-set-for-every-profile', 'spec/v1/profiles.md', 'membership matches the derived set for every profile')).toBe(derived.has(p));
334
335
  }
335
336
  });
336
337
  });
@@ -35,6 +35,8 @@ import { pollUntilTerminal } from '../lib/polling.js';
35
35
  import { isFixtureAdvertised } from '../lib/fixtures.js';
36
36
  import { behaviorGate } from '../lib/behavior-gate.js';
37
37
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
38
+ import { req } from '../lib/requirement-ids.js';
39
+ import { softSkip } from '../lib/soft-skip.js';
38
40
 
39
41
  const WORKFLOW_ID = 'conformance-prompt-all-four-kinds';
40
42
  const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
@@ -85,7 +87,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-all-four-kinds-events: eac
85
87
  const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
86
88
  expect(
87
89
  create.status,
88
- driver.describe(
90
+ req('openwop.it.prompt-all-four-kinds-events.emits-agent-promptresolved-prompt-composed-for-system-user-schema-hint-and-few-s',
89
91
  'spec/v1/rest-endpoints.md',
90
92
  'POST /v1/runs MUST return 201 on accepted creation',
91
93
  ),
@@ -95,7 +97,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-all-four-kinds-events: eac
95
97
  const terminal = await pollUntilTerminal(runId);
96
98
  expect(
97
99
  terminal.status,
98
- driver.describe(
100
+ req('openwop.it.prompt-all-four-kinds-events.emits-agent-promptresolved-prompt-composed-for-system-user-schema-hint-and-few-s',
99
101
  'fixtures.md conformance-prompt-all-four-kinds §Terminal status',
100
102
  'fixture MUST reach terminal `completed`',
101
103
  ),
@@ -120,7 +122,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-all-four-kinds-events: eac
120
122
  for (const expectedKind of ['system', 'user', 'schema-hint', 'few-shot']) {
121
123
  expect(
122
124
  resolvedKinds.includes(expectedKind),
123
- driver.describe(
125
+ req('openwop.it.prompt-all-four-kinds-events.emits-agent-promptresolved-prompt-composed-for-system-user-schema-hint-and-few-s',
124
126
  'spec/v1/prompts.md §"PromptKind"',
125
127
  `host MUST emit \`agent.promptResolved\` with kind: "${expectedKind}" when the node carries the matching ref`,
126
128
  ),
@@ -144,14 +146,14 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-all-four-kinds-events: eac
144
146
  for (const expectedRef of expectedTemplates) {
145
147
  expect(
146
148
  resolvedRefs.includes(expectedRef),
147
- driver.describe(
149
+ req('openwop.it.prompt-all-four-kinds-events.emits-agent-promptresolved-prompt-composed-for-system-user-schema-hint-and-few-s',
148
150
  'spec/v1/prompts.md §"Resolution chain (normative)"',
149
151
  `\`agent.promptResolved.resolved\` MUST surface "${expectedRef}" — the fixture carries it on the node config and the resolver MUST return it (multi-entry few-shot[slotIndex] regression pin)`,
150
152
  ),
151
153
  ).toBe(true);
152
154
  expect(
153
155
  composedRefs.includes(expectedRef),
154
- driver.describe(
156
+ req('openwop.it.prompt-all-four-kinds-events.emits-agent-promptresolved-prompt-composed-for-system-user-schema-hint-and-few-s',
155
157
  'spec/v1/prompts.md §"Composition + observability"',
156
158
  `\`prompt.composed.refs[]\` MUST contain "${expectedRef}" — one composition per resolved ref`,
157
159
  ),
@@ -161,7 +163,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-all-four-kinds-events: eac
161
163
  // silently dropped non-zero few-shot indices would emit fewer.
162
164
  expect(
163
165
  composedRefs.length,
164
- driver.describe(
166
+ req('openwop.it.prompt-all-four-kinds-events.emits-agent-promptresolved-prompt-composed-for-system-user-schema-hint-and-few-s',
165
167
  'spec/v1/prompts.md §"Composition + observability"',
166
168
  'host MUST emit one `prompt.composed` event per composed body (5 refs → 5 events when all five resolve, including both few-shot entries)',
167
169
  ),
@@ -172,7 +174,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-all-four-kinds-events: eac
172
174
  const d = await readDiscovery();
173
175
  if (!behaviorGate('prompts-supported', promptsSupported(d))) return;
174
176
  const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
175
- if (create.status !== 201) return;
177
+ if (create.status !== 201) return softSkip('blocked', 'precondition not met — `create.status !== 201` returned early (seam, prior step, or fixture unavailable)');
176
178
  const { runId } = create.json as { runId: string };
177
179
  await pollUntilTerminal(runId);
178
180
  const events = await readAllEvents(runId);
@@ -186,11 +188,11 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-all-four-kinds-events: eac
186
188
  const firstComposedIdx = events.findIndex((e) => e.type === 'prompt.composed');
187
189
  expect(
188
190
  firstResolvedIdx >= 0 && firstComposedIdx >= 0,
189
- 'both event types MUST appear in the event log',
191
+ req('openwop.it.prompt-all-four-kinds-events.emits-the-first-agent-promptresolved-before-the-first-prompt-composed-resolution', 'spec/v1/prompts.md §"Composition + observability"', 'both event types MUST appear in the event log'),
190
192
  ).toBe(true);
191
193
  expect(
192
194
  firstResolvedIdx,
193
- driver.describe(
195
+ req('openwop.it.prompt-all-four-kinds-events.emits-the-first-agent-promptresolved-before-the-first-prompt-composed-resolution',
194
196
  'spec/v1/prompts.md §"Composition + observability"',
195
197
  'resolution events MUST precede the first composition event in the run log (composition cannot start before any resolution completes)',
196
198
  ),