@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
@@ -52,6 +52,7 @@ import { driver } from '../lib/driver.js';
52
52
  import { isFixtureAdvertised } from '../lib/fixtures.js';
53
53
  import { pollUntil } from '../lib/polling.js';
54
54
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
55
+ import { req } from '../lib/requirement-ids.js';
55
56
 
56
57
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
57
58
  const FIXTURE = 'conformance-multi-agent-confidence-escalation';
@@ -92,7 +93,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-confidence-escalation: capability shape
92
93
  if (floor === undefined) return softSkip('blocked', 'precondition not met — `floor === undefined` returned early (seam, prior step, or fixture unavailable)');
93
94
  expect(
94
95
  typeof floor === 'number' && Number.isFinite(floor) && floor >= 0.5 && floor <= 1.0,
95
- driver.describe(
96
+ req('openwop.it.multi-agent-confidence-escalation.confidenceescalationfloor-when-advertised-must-be-in-0-5-1-0',
96
97
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §A',
97
98
  'confidenceEscalationFloor MUST be number in [0.5, 1.0]; values below the spec floor are non-conformant',
98
99
  ),
@@ -140,7 +141,7 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-confidence-escalation: behavioral
140
141
  const expectedStatus = advertisedKind === 'clarification' ? 'waiting-clarification' : 'waiting-approval';
141
142
  expect(
142
143
  terminal.status,
143
- driver.describe(
144
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte',
144
145
  'RFCS/0044-confidence-escalation-interrupt-kind-advertisement.md §B',
145
146
  `host advertising confidenceEscalationInterruptKind: "${advertisedKind}" MUST surface the run as "${expectedStatus}" per spec/v1/interrupt.md §"Interrupt kinds"`,
146
147
  ),
@@ -149,7 +150,7 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-confidence-escalation: behavioral
149
150
  const status = terminal.status as string;
150
151
  expect(
151
152
  typeof status === 'string' && status.startsWith('waiting-'),
152
- driver.describe(
153
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte',
153
154
  'RFCS/0044-confidence-escalation-interrupt-kind-advertisement.md §B',
154
155
  `host advertising vendor confidenceEscalationInterruptKind ("${advertisedKind}") MUST surface the run as a waiting-* status; the suffix is determined by the host's interrupt.md mapping (see the host's vendor-extensions doc per RFC 0044 §C)`,
155
156
  ),
@@ -159,7 +160,7 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-confidence-escalation: behavioral
159
160
  const acceptedStatuses = ['waiting-clarification', 'waiting-approval'];
160
161
  expect(
161
162
  acceptedStatuses.includes(terminal.status as string),
162
- driver.describe(
163
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte',
163
164
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §A + spec/v1/interrupt.md',
164
165
  'a host below the confidence floor MUST surface the run as `waiting-clarification` (clarify-kind escalation) OR `waiting-approval` (escalate-kind escalation) per RFC 0039 §A; the low-confidence decision MUST NOT reach `completed` because no dispatch fired',
165
166
  ),
@@ -171,21 +172,21 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-confidence-escalation: behavioral
171
172
  const events = ((eventsRes.json as { events?: RunEvent[] } | undefined)?.events ?? []);
172
173
 
173
174
  const escalated = events.filter((e) => e.type === 'core.workflowChain.confidence-escalated');
174
- expect(escalated.length, driver.describe(
175
+ expect(escalated.length, req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte',
175
176
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §A',
176
177
  'low-confidence decision MUST emit exactly one core.workflowChain.confidence-escalated event',
177
178
  )).toBe(1);
178
179
 
179
180
  const ev = escalated[0]!;
180
181
  const payload = (ev.payload ?? {}) as { confidence?: number; floor?: number; escalationKind?: string; workerId?: string };
181
- expect(payload.confidence, 'payload.confidence echoes the decision').toBe(0.3);
182
+ expect(payload.confidence, req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte', 'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §A', 'payload.confidence echoes the decision')).toBe(0.3);
182
183
  expect(
183
184
  typeof payload.floor === 'number' && payload.floor >= 0.5 && payload.floor <= 1.0,
184
- 'payload.floor is the host-advertised floor (in [0.5, 1.0])',
185
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte', 'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §A', 'payload.floor is the host-advertised floor (in [0.5, 1.0])'),
185
186
  ).toBe(true);
186
187
  expect(
187
188
  payload.escalationKind === 'clarify' || payload.escalationKind === 'escalate',
188
- 'payload.escalationKind ∈ {clarify, escalate}',
189
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte', 'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §A', 'payload.escalationKind ∈ {clarify, escalate}'),
189
190
  ).toBe(true);
190
191
 
191
192
  // Causation (S32, 2026-08-17): this leg used to REQUIRE `causationId` → a
@@ -202,7 +203,7 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-confidence-escalation: behavioral
202
203
  const cause = events.find((e) => e.eventId === ev.causationId);
203
204
  expect(
204
205
  cause !== undefined,
205
- driver.describe(
206
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte',
206
207
  'spec/v1/multi-agent-execution.md §"Confidence escalation"',
207
208
  `confidence-escalated causationId (${ev.causationId}) MUST resolve to an event on this run's log when present`,
208
209
  ),
@@ -211,14 +212,14 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-confidence-escalation: behavioral
211
212
  const original = (ev.payload as { originalDecision?: unknown } | undefined)?.originalDecision;
212
213
  expect(
213
214
  original !== null && typeof original === 'object',
214
- driver.describe('run-event-payloads.schema.json §confidence-escalated', 'payload.originalDecision carries the escalated OrchestratorDecision verbatim — the decision is on the log HERE, not on a prior decided event'),
215
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte', 'run-event-payloads.schema.json §confidence-escalated', 'payload.originalDecision carries the escalated OrchestratorDecision verbatim — the decision is on the log HERE, not on a prior decided event'),
215
216
  ).toBe(true);
216
217
 
217
218
  // Load-bearing: NO dispatch event fired. RFC 0039 gates BEFORE the loop.
218
219
  const chainEvents = events.filter((e) => e.type === 'core.workflowChain.event');
219
220
  expect(
220
221
  chainEvents.length,
221
- driver.describe(
222
+ req('openwop.it.multi-agent-confidence-escalation.happy-path-low-confidence-decision-confidence-escalated-event-clarification-inte',
222
223
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §A',
223
224
  'low-confidence decision MUST NOT produce any core.workflowChain.event records — the escalation fires before any dispatch.began per the spec ordering',
224
225
  ),
@@ -37,6 +37,7 @@ import { executionModelVersionMax } from '../lib/execution-model-version.js';
37
37
  import { isFixtureAdvertised } from '../lib/fixtures.js';
38
38
  import { pollUntilTerminal } from '../lib/polling.js';
39
39
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
40
+ import { req } from '../lib/requirement-ids.js';
40
41
 
41
42
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
42
43
 
@@ -69,14 +70,14 @@ describe.skipIf(HTTP_SKIP)('multi-agent-handoff-state-machine: advertisement sha
69
70
  if (executionModel === undefined) return softSkip('inapplicable', 'host doesn\'t advertise — soft-skip');
70
71
  expect(
71
72
  typeof executionModel.supported,
72
- driver.describe(
73
+ req('openwop.it.multi-agent-handoff-state-machine.capabilities-multiagent-executionmodel-when-present-conforms-to-rfc-0037-c',
73
74
  'RFCS/0037-multi-agent-execution-model.md §C',
74
75
  'capabilities.multiAgent.executionModel.supported MUST be boolean when present',
75
76
  ),
76
77
  ).toBe('boolean');
77
78
  expect(
78
79
  typeof executionModel.version,
79
- driver.describe(
80
+ req('openwop.it.multi-agent-handoff-state-machine.capabilities-multiagent-executionmodel-when-present-conforms-to-rfc-0037-c',
80
81
  'RFCS/0037-multi-agent-execution-model.md §C',
81
82
  'capabilities.multiAgent.executionModel.version MUST be integer when present',
82
83
  ),
@@ -87,7 +88,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-handoff-state-machine: advertisement sha
87
88
  const max = executionModelVersionMax();
88
89
  expect(
89
90
  Number.isInteger(v) && v >= 1 && v <= max,
90
- driver.describe(
91
+ req('openwop.it.multi-agent-handoff-state-machine.capabilities-multiagent-executionmodel-when-present-conforms-to-rfc-0037-c',
91
92
  'RFCS/0037-multi-agent-execution-model.md §C',
92
93
  `version MUST be an integer in [1, ${max}] (1 = Phase 1 only; later phases lift the ceiling additively — 5 = RFC 0061 stateful agent-loop lifecycle, 6 = RFC 0090 verifier; the ceiling is \`capabilities.schema.json\` §multiAgent.executionModel.version maximum)`,
93
94
  ),
@@ -118,7 +119,7 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-handoff-state-machine: behavioral
118
119
  const runId = (create.json as { runId: string }).runId;
119
120
 
120
121
  const terminal = await pollUntilTerminal(runId);
121
- expect(terminal.status, driver.describe(
122
+ expect(terminal.status, req('openwop.it.multi-agent-handoff-state-machine.happy-path-dispatch-began-dispatch-succeeded-child-completed-output-harvested-fi',
122
123
  'spec/v1/multi-agent-execution.md §"Execution loop"',
123
124
  'parent run with supervisor → next-worker → terminate MUST reach terminal `completed`',
124
125
  )).toBe('completed');
@@ -128,13 +129,13 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-handoff-state-machine: behavioral
128
129
  const events = ((eventsRes.json as { events?: RunEvent[] } | undefined)?.events ?? []);
129
130
  const chainEvents = events.filter((e) => e.type === 'core.workflowChain.event');
130
131
 
131
- expect(chainEvents.length, driver.describe(
132
+ expect(chainEvents.length, req('openwop.it.multi-agent-handoff-state-machine.happy-path-dispatch-began-dispatch-succeeded-child-completed-output-harvested-fi',
132
133
  'RFCS/0037-multi-agent-execution-model.md §"Conformance"',
133
134
  'happy-path fixture MUST produce 4 core.workflowChain.event records (dispatch.began, dispatch.succeeded, child.completed, output.harvested)',
134
135
  )).toBe(4);
135
136
 
136
137
  const phases = chainEvents.map((e) => (e.payload as { phase?: string } | undefined)?.phase);
137
- expect(phases, driver.describe(
138
+ expect(phases, req('openwop.it.multi-agent-handoff-state-machine.happy-path-dispatch-began-dispatch-succeeded-child-completed-output-harvested-fi',
138
139
  'spec/v1/multi-agent-execution.md §"Transition events"',
139
140
  'phase order MUST be dispatch.began → dispatch.succeeded → child.completed → output.harvested',
140
141
  )).toEqual(['dispatch.began', 'dispatch.succeeded', 'child.completed', 'output.harvested']);
@@ -144,7 +145,7 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-handoff-state-machine: behavioral
144
145
  for (let i = 1; i < chainEvents.length; i++) {
145
146
  const prior = chainEvents[i - 1];
146
147
  const cur = chainEvents[i];
147
- expect(cur?.causationId, driver.describe(
148
+ expect(cur?.causationId, req('openwop.it.multi-agent-handoff-state-machine.happy-path-dispatch-began-dispatch-succeeded-child-completed-output-harvested-fi',
148
149
  'spec/v1/multi-agent-execution.md §"Transition events"',
149
150
  `core.workflowChain.event #${i} (${phases[i]}) MUST have causationId === prior event's eventId`,
150
151
  )).toBe(prior?.eventId);
@@ -154,14 +155,14 @@ describe.skipIf(BEHAVIORAL_SKIP)('multi-agent-handoff-state-machine: behavioral
154
155
  const dispatchBegan = chainEvents[0];
155
156
  expect(dispatchBegan?.causationId).toBeDefined();
156
157
  const decidedEvent = events.find((e) => e.eventId === dispatchBegan?.causationId);
157
- expect(decidedEvent?.type, driver.describe(
158
+ expect(decidedEvent?.type, req('openwop.it.multi-agent-handoff-state-machine.happy-path-dispatch-began-dispatch-succeeded-child-completed-output-harvested-fi',
158
159
  'spec/v1/multi-agent-execution.md §"Transition events"',
159
160
  'dispatch.began causationId MUST point at the runOrchestrator.decided event that named this worker',
160
161
  )).toBe('runOrchestrator.decided');
161
162
 
162
163
  // output.harvested.harvestedKeys MUST list the outputMapping keys harvested.
163
164
  const harvested = chainEvents[3]?.payload as { harvestedKeys?: string[] } | undefined;
164
- expect(harvested?.harvestedKeys, driver.describe(
165
+ expect(harvested?.harvestedKeys, req('openwop.it.multi-agent-handoff-state-machine.happy-path-dispatch-began-dispatch-succeeded-child-completed-output-harvested-fi',
165
166
  'spec/v1/multi-agent-execution.md §"Transition events"',
166
167
  'output.harvested payload MUST list harvested parent-variable keys (the fixture\'s outputMapping is { parentResult: \'childOutcome\' })',
167
168
  )).toEqual(['parentResult']);
@@ -50,6 +50,7 @@ import { describe, it, expect } from 'vitest';
50
50
  import { softSkip } from '../lib/soft-skip.js';
51
51
  import { driver } from '../lib/driver.js';
52
52
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
53
+ import { req } from '../lib/requirement-ids.js';
53
54
 
54
55
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
55
56
 
@@ -82,17 +83,17 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: advertisement shape (R
82
83
  if (d === null) {
83
84
  softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
84
85
  ctx.skip();
85
- return;
86
+ return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
86
87
  }
87
88
  const ccmc = capabilityFamily<{ executionModel?: { [k: string]: unknown; crossHostCausation?: Record<string, unknown>; replayDeterminism?: Record<string, unknown> } }>(d, 'multiAgent')?.executionModel?.crossChildMemoryConcurrency;
88
89
  if (ccmc === undefined) {
89
90
  softSkip('inapplicable', 'optional advertisement — `multiAgent.executionModel.crossChildMemoryConcurrency` not advertised by this host');
90
91
  ctx.skip(); // optional advertisement — host hasn't opted in
91
- return;
92
+ return softSkip('blocked', 'precondition not met — `ccmc === undefined` returned early (seam, prior step, or fixture unavailable)');
92
93
  }
93
94
  expect(
94
95
  ccmc === 'strict' || ccmc === 'advisory',
95
- driver.describe(
96
+ req('openwop.it.multi-agent-memory-lifecycle.crosschildmemoryconcurrency-when-advertised-must-be-one-of-strict-advisory',
96
97
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §B',
97
98
  'crossChildMemoryConcurrency MUST be one of {strict, advisory} when present; values outside the closed enum are non-conformant',
98
99
  ),
@@ -138,7 +139,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: behavioral (RFC 0039
138
139
  if (d === null) {
139
140
  softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
140
141
  ctx.skip();
141
- return;
142
+ return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
142
143
  }
143
144
  const v = capabilityFamily<{ executionModel?: { [k: string]: unknown; crossHostCausation?: Record<string, unknown>; replayDeterminism?: Record<string, unknown> } }>(d, 'multiAgent')?.executionModel?.version;
144
145
  const memorySupported = capabilityFamily<{ supported?: unknown }>(d, 'memory')?.supported;
@@ -147,7 +148,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: behavioral (RFC 0039
147
148
  if (!phase2OrLater || memorySupported !== true || !expiredRunId) {
148
149
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!phase2OrLater || memorySupported !== true || !expiredRunId` returned early');
149
150
  ctx.skip();
150
- return;
151
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!phase2OrLater || memorySupported !== true || !expiredRunId` returned early');
151
152
  }
152
153
 
153
154
  const fromSeq = 0;
@@ -158,7 +159,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: behavioral (RFC 0039
158
159
 
159
160
  expect(
160
161
  res.status,
161
- driver.describe(
162
+ req('openwop.it.multi-agent-memory-lifecycle.mae-3-replay-snapshot-refusal-fork-mode-replay-against-a-past-retention-runid-mu',
162
163
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §B MAE-3',
163
164
  'fork mode:replay against a past-retention runId MUST refuse with 422; silent substitution of current memory is non-conformant',
164
165
  ),
@@ -171,7 +172,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: behavioral (RFC 0039
171
172
 
172
173
  expect(
173
174
  body?.error,
174
- driver.describe(
175
+ req('openwop.it.multi-agent-memory-lifecycle.mae-3-replay-snapshot-refusal-fork-mode-replay-against-a-past-retention-runid-mu',
175
176
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §B MAE-3',
176
177
  'refusal envelope error code MUST be "replay_memory_snapshot_unavailable" (distinct from the pre-flight invalid_from_seq gate)',
177
178
  ),
@@ -179,7 +180,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: behavioral (RFC 0039
179
180
 
180
181
  expect(
181
182
  body?.details?.fromSeq,
182
- driver.describe(
183
+ req('openwop.it.multi-agent-memory-lifecycle.mae-3-replay-snapshot-refusal-fork-mode-replay-against-a-past-retention-runid-mu',
183
184
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §B MAE-3',
184
185
  'refusal envelope details.fromSeq MUST echo the requested fromSeq',
185
186
  ),
@@ -187,7 +188,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: behavioral (RFC 0039
187
188
 
188
189
  expect(
189
190
  body?.details?.sourceRunId,
190
- driver.describe(
191
+ req('openwop.it.multi-agent-memory-lifecycle.mae-3-replay-snapshot-refusal-fork-mode-replay-against-a-past-retention-runid-mu',
191
192
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §B MAE-3',
192
193
  'refusal envelope details.sourceRunId MUST echo the runId from the URL',
193
194
  ),
@@ -196,7 +197,7 @@ describe.skipIf(HTTP_SKIP)('multi-agent-memory-lifecycle: behavioral (RFC 0039
196
197
  const reason = body?.details?.reason;
197
198
  expect(
198
199
  reason === 'retention_expired' || reason === 'event_log_unavailable',
199
- driver.describe(
200
+ req('openwop.it.multi-agent-memory-lifecycle.mae-3-replay-snapshot-refusal-fork-mode-replay-against-a-past-retention-runid-mu',
200
201
  'RFCS/0039-multi-agent-confidence-and-memory-lifecycle.md §B MAE-3',
201
202
  'refusal envelope details.reason MUST be one of {"retention_expired", "event_log_unavailable"}',
202
203
  ),
@@ -14,6 +14,7 @@ import { describe, it, expect } from 'vitest';
14
14
  import { driver } from '../lib/driver.js';
15
15
  import { pollUntilTerminal } from '../lib/polling.js';
16
16
  import { isFixtureAdvertised } from '../lib/fixtures.js';
17
+ import { req } from '../lib/requirement-ids.js';
17
18
 
18
19
  const WORKFLOW_ID = 'conformance-multi-node';
19
20
  const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
@@ -33,7 +34,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('multi-node: conformance-multi-node fixture emi
33
34
  const runId = (create.json as { runId: string }).runId;
34
35
 
35
36
  const terminal = await pollUntilTerminal(runId);
36
- expect(terminal.status, driver.describe(
37
+ expect(terminal.status, req('openwop.it.multi-node-ordering.a-b-c-node-completed-events-arrive-in-dag-order-by-sequence',
37
38
  'fixtures.md conformance-multi-node §Terminal status',
38
39
  'fixture MUST reach terminal `completed`',
39
40
  )).toBe('completed');
@@ -41,7 +42,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('multi-node: conformance-multi-node fixture emi
41
42
  const eventsRes = await driver.get(
42
43
  `/v1/runs/${encodeURIComponent(runId)}/events/poll?lastSequence=0&timeout=1`,
43
44
  );
44
- expect(eventsRes.status, driver.describe(
45
+ expect(eventsRes.status, req('openwop.it.multi-node-ordering.a-b-c-node-completed-events-arrive-in-dag-order-by-sequence',
45
46
  'rest-endpoints.md GET /v1/runs/{runId}/events/poll',
46
47
  'event-poll MUST return 200 for known runs',
47
48
  )).toBe(200);
@@ -52,7 +53,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('multi-node: conformance-multi-node fixture emi
52
53
  .sort((x, y) => x.sequence - y.sequence)
53
54
  .map((e) => e.nodeId);
54
55
 
55
- expect(nodeCompletions, driver.describe(
56
+ expect(nodeCompletions, req('openwop.it.multi-node-ordering.a-b-c-node-completed-events-arrive-in-dag-order-by-sequence',
56
57
  'fixtures.md conformance-multi-node §Topology',
57
58
  'all three node.completed events (a, b, c) MUST be present',
58
59
  )).toEqual(['a', 'b', 'c']);
@@ -39,7 +39,6 @@
39
39
 
40
40
  import { describe, it, expect } from 'vitest';
41
41
  import { seamAbsent } from '../lib/soft-skip.js';
42
- import { driver } from '../lib/driver.js';
43
42
  import { behaviorGate } from '../lib/behavior-gate.js';
44
43
  import { isMultiPartyConversationSupported } from '../lib/multi-agent-capabilities.js';
45
44
  import {
@@ -50,6 +49,7 @@ import {
50
49
  type SeamAgentRef,
51
50
  type SeamTurn,
52
51
  } from '../lib/multiPartyConversation.js';
52
+ import { req } from '../lib/requirement-ids.js';
53
53
 
54
54
  const PROFILE = 'openwop-multi-party-conversation';
55
55
 
@@ -84,7 +84,7 @@ describe('multi-party-conversation-behavioral (RFC 0101 §Conformance)', () => {
84
84
  if (opened.unwired) return seamAbsent('host advertises multiPartyConversation but the open-conversation seam is not wired');
85
85
  expect(
86
86
  opened.status === 200,
87
- driver.describe('RFC 0101 §Spec', 'a conforming 3-agent council MUST open (≤ maxParticipants)'),
87
+ req('openwop.it.multi-party-conversation-behavioral.opens-a-council-accepts-an-attributed-turn-and-rejects-missing-non-participant-o', 'RFC 0101 §Spec', 'a conforming 3-agent council MUST open (≤ maxParticipants)'),
88
88
  ).toBe(true);
89
89
 
90
90
  // ---- MUST 1: POSITIVE — a roster-valid attributed turn is accepted ----
@@ -92,7 +92,7 @@ describe('multi-party-conversation-behavioral (RFC 0101 §Conformance)', () => {
92
92
  if (ok.unwired) return seamAbsent('host advertises multiPartyConversation but the conversation seam is not wired');
93
93
  expect(
94
94
  ok.status === 200,
95
- driver.describe('RFC 0101 §Spec', "a role:'agent' turn with an in-roster speakerId MUST be accepted"),
95
+ req('openwop.it.multi-party-conversation-behavioral.opens-a-council-accepts-an-attributed-turn-and-rejects-missing-non-participant-o', 'RFC 0101 §Spec', "a role:'agent' turn with an in-roster speakerId MUST be accepted"),
96
96
  ).toBe(true);
97
97
 
98
98
  // ---- MUST 2: ATTRIBUTION — agent turn missing speakerId is rejected ---
@@ -102,7 +102,7 @@ describe('multi-party-conversation-behavioral (RFC 0101 §Conformance)', () => {
102
102
  if (!missingRes.unwired) {
103
103
  expect(
104
104
  isValidationErrorRejection(missingRes),
105
- driver.describe('RFC 0101 §Spec (attribution MUST)', "a role:'agent' turn missing speakerId MUST be rejected with validation_error"),
105
+ req('openwop.it.multi-party-conversation-behavioral.opens-a-council-accepts-an-attributed-turn-and-rejects-missing-non-participant-o', 'RFC 0101 §Spec (attribution MUST)', "a role:'agent' turn missing speakerId MUST be rejected with validation_error"),
106
106
  ).toBe(true);
107
107
  }
108
108
 
@@ -112,7 +112,7 @@ describe('multi-party-conversation-behavioral (RFC 0101 §Conformance)', () => {
112
112
  if (!intruderRes.unwired) {
113
113
  expect(
114
114
  isValidationErrorRejection(intruderRes),
115
- driver.describe('RFC 0101 §Spec (membership MUST) / RFC 0005 §E', 'a turn whose speakerId is not in the roster MUST be rejected with validation_error'),
115
+ req('openwop.it.multi-party-conversation-behavioral.opens-a-council-accepts-an-attributed-turn-and-rejects-missing-non-participant-o', 'RFC 0101 §Spec (membership MUST) / RFC 0005 §E', 'a turn whose speakerId is not in the roster MUST be rejected with validation_error'),
116
116
  ).toBe(true);
117
117
  }
118
118
 
@@ -130,7 +130,7 @@ describe('multi-party-conversation-behavioral (RFC 0101 §Conformance)', () => {
130
130
  if (!overRes.unwired) {
131
131
  expect(
132
132
  isValidationErrorRejection(overRes),
133
- driver.describe('RFC 0101 §Spec (maxParticipants MUST)', 'an open whose roster exceeds the advertised maxParticipants MUST be rejected with validation_error'),
133
+ req('openwop.it.multi-party-conversation-behavioral.opens-a-council-accepts-an-attributed-turn-and-rejects-missing-non-participant-o', 'RFC 0101 §Spec (maxParticipants MUST)', 'an open whose roster exceeds the advertised maxParticipants MUST be rejected with validation_error'),
134
134
  ).toBe(true);
135
135
  }
136
136
  }
@@ -44,9 +44,7 @@ import { join } from 'node:path';
44
44
  import Ajv2020 from 'ajv/dist/2020.js';
45
45
  import addFormats from 'ajv-formats';
46
46
  import { SCHEMAS_DIR } from '../lib/paths.js';
47
-
48
- /** Server-free assertion-message helper. */
49
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
47
+ import { req } from '../lib/requirement-ids.js';
50
48
 
51
49
  function loadSchema(name: string): Record<string, unknown> {
52
50
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -59,7 +57,7 @@ describe('multi-party-conversation-shape: participant roster on conversation.ope
59
57
  const opened = ajv.getSchema('conversation-event#/$defs/ConversationOpenedPayload');
60
58
 
61
59
  it('the ConversationOpenedPayload $def exists and declares participants: AgentRef[]', () => {
62
- expect(opened, 'the ConversationOpenedPayload $def MUST exist').toBeTruthy();
60
+ expect(opened, req('openwop.it.multi-party-conversation-shape.the-conversationopenedpayload-def-exists-and-declares-participants-agentref', 'RFC 0101', 'the ConversationOpenedPayload $def MUST exist')).toBeTruthy();
63
61
  });
64
62
 
65
63
  it('a conforming 3-agent council transcript (participant roster + user opening turn) validates', () => {
@@ -80,7 +78,7 @@ describe('multi-party-conversation-shape: participant roster on conversation.ope
80
78
  turnIndex: 0,
81
79
  },
82
80
  };
83
- expect(opened!(good), why('RFC 0101 §Schema', 'a conversation.opened with a participant roster MUST validate')).toBe(true);
81
+ expect(opened!(good), req('openwop.it.multi-party-conversation-shape.a-conforming-3-agent-council-transcript-participant-roster-user-opening-turn-val', 'RFC 0101 §Schema', 'a conversation.opened with a participant roster MUST validate')).toBe(true);
84
82
  });
85
83
 
86
84
  it('a participant entry that is not a valid AgentRef (no agentId) is rejected', () => {
@@ -96,7 +94,7 @@ describe('multi-party-conversation-shape: participant roster on conversation.ope
96
94
  turnIndex: 0,
97
95
  },
98
96
  };
99
- expect(opened!(bad), why('RFC 0101 §Schema', 'a participants[] item without agentId MUST be rejected')).toBe(false);
97
+ expect(opened!(bad), req('openwop.it.multi-party-conversation-shape.a-participant-entry-that-is-not-a-valid-agentref-no-agentid-is-rejected', 'RFC 0101 §Schema', 'a participants[] item without agentId MUST be rejected')).toBe(false);
100
98
  });
101
99
 
102
100
  it('participants is OPTIONAL — a single-agent conversation.opened (no roster) still validates (back-compat)', () => {
@@ -112,7 +110,7 @@ describe('multi-party-conversation-shape: participant roster on conversation.ope
112
110
  turnIndex: 0,
113
111
  },
114
112
  };
115
- expect(opened!(noRoster), why('RFC 0101 §Compatibility', 'participants is additive — a roster-less conversation MUST still validate')).toBe(true);
113
+ expect(opened!(noRoster), req('openwop.it.multi-party-conversation-shape.participants-is-optional-a-single-agent-conversation-opened-no-roster-still-vali', 'RFC 0101 §Compatibility', 'participants is additive — a roster-less conversation MUST still validate')).toBe(true);
116
114
  });
117
115
  });
118
116
 
@@ -133,25 +131,25 @@ describe('multi-party-conversation-shape: per-turn speaker attribution (RFC 0101
133
131
  it('an agent turn WITH a roster-instance speakerId validates', () => {
134
132
  expect(
135
133
  turn({ ...agentBase, speakerId: 'host:advisor-cfo' }),
136
- why('RFC 0101 §Schema', "a role:'agent' turn carrying speakerId MUST validate"),
134
+ req('openwop.it.multi-party-conversation-shape.an-agent-turn-with-a-roster-instance-speakerid-validates', 'RFC 0101 §Schema', "a role:'agent' turn carrying speakerId MUST validate"),
137
135
  ).toBe(true);
138
136
  });
139
137
 
140
138
  it("a role:'agent' turn MISSING speakerId MUST fail schema validation (the attribution MUST)", () => {
141
139
  expect(
142
140
  turn(agentBase),
143
- why('RFC 0101 §Schema', "a role:'agent' turn that omits speakerId MUST be rejected (the conditional required)"),
141
+ req('openwop.it.multi-party-conversation-shape.a-role-agent-turn-missing-speakerid-must-fail-schema-validation-the-attribution', 'RFC 0101 §Schema', "a role:'agent' turn that omits speakerId MUST be rejected (the conditional required)"),
144
142
  ).toBe(false);
145
143
  });
146
144
 
147
145
  it("speakerId is OPTIONAL for role:'user' / role:'system' turns (additive — pre-RFC-0101 producers)", () => {
148
146
  expect(
149
147
  turn({ messageId: 'council-q1:0:user', from: 'user', content: 'Q3 or Q4?', ts: 1, role: 'user', turnIndex: 0 }),
150
- why('RFC 0101 §Compatibility', "a role:'user' turn without speakerId MUST still validate"),
148
+ req('openwop.it.multi-party-conversation-shape.speakerid-is-optional-for-role-user-role-system-turns-additive-pre-rfc-0101-prod', 'RFC 0101 §Compatibility', "a role:'user' turn without speakerId MUST still validate"),
151
149
  ).toBe(true);
152
150
  expect(
153
151
  turn({ messageId: 'council-q1:9:system', from: 'system', content: 'conversation timed out', ts: 1, role: 'system', turnIndex: 9 }),
154
- why('RFC 0101 §Compatibility', "a role:'system' turn without speakerId MUST still validate"),
152
+ req('openwop.it.multi-party-conversation-shape.speakerid-is-optional-for-role-user-role-system-turns-additive-pre-rfc-0101-prod', 'RFC 0101 §Compatibility', "a role:'system' turn without speakerId MUST still validate"),
155
153
  ).toBe(true);
156
154
  });
157
155
  });
@@ -166,13 +164,13 @@ describe('multi-party-conversation-shape: non-participant turn detection (RFC 01
166
164
  const roster = new Set(['host:advisor-cfo', 'host:advisor-cmo', 'host:advisor-cto']);
167
165
 
168
166
  it('a turn whose speakerId IS a participant is admissible', () => {
169
- expect(roster.has('host:advisor-cmo'), why('RFC 0101 §Spec', 'an agent in the roster MAY speak')).toBe(true);
167
+ expect(roster.has('host:advisor-cmo'), req('openwop.it.multi-party-conversation-shape.a-turn-whose-speakerid-is-a-participant-is-admissible', 'RFC 0101 §Spec', 'an agent in the roster MAY speak')).toBe(true);
170
168
  });
171
169
 
172
170
  it('a turn whose speakerId is NOT a participant MUST be rejected by the host (roster membership)', () => {
173
171
  expect(
174
172
  roster.has('host:advisor-intruder'),
175
- why('RFC 0101 §Spec', 'a turn from a non-participant agent MUST be rejected'),
173
+ req('openwop.it.multi-party-conversation-shape.a-turn-whose-speakerid-is-not-a-participant-must-be-rejected-by-the-host-roster', 'RFC 0101 §Spec', 'a turn from a non-participant agent MUST be rejected'),
176
174
  ).toBe(false);
177
175
  });
178
176
  });
@@ -184,11 +182,11 @@ describe('multi-party-conversation-shape: capability advertisement (RFC 0101 §S
184
182
  const mpc = props.multiPartyConversation as
185
183
  | { properties?: Record<string, unknown>; required?: string[]; additionalProperties?: boolean }
186
184
  | undefined;
187
- expect(mpc, why('RFC 0101 §Schema', 'capabilities.multiPartyConversation MUST be declared')).toBeDefined();
188
- expect(mpc?.properties?.supported, why('RFC 0101 §Schema', 'multiPartyConversation.supported MUST be declared')).toBeDefined();
189
- expect(mpc?.properties?.maxParticipants, why('RFC 0101 §Schema', 'multiPartyConversation.maxParticipants MUST be declared (optional)')).toBeDefined();
190
- expect(mpc?.required, why('RFC 0101 §Schema', 'supported MUST be required on the block')).toContain('supported');
191
- expect(mpc?.additionalProperties, why('RFC 0101 §Schema', 'the multiPartyConversation block MUST be closed')).toBe(false);
185
+ expect(mpc, req('openwop.it.multi-party-conversation-shape.capabilities-schema-json-declares-multipartyconversation-with-supported-optional', 'RFC 0101 §Schema', 'capabilities.multiPartyConversation MUST be declared')).toBeDefined();
186
+ expect(mpc?.properties?.supported, req('openwop.it.multi-party-conversation-shape.capabilities-schema-json-declares-multipartyconversation-with-supported-optional', 'RFC 0101 §Schema', 'multiPartyConversation.supported MUST be declared')).toBeDefined();
187
+ expect(mpc?.properties?.maxParticipants, req('openwop.it.multi-party-conversation-shape.capabilities-schema-json-declares-multipartyconversation-with-supported-optional', 'RFC 0101 §Schema', 'multiPartyConversation.maxParticipants MUST be declared (optional)')).toBeDefined();
188
+ expect(mpc?.required, req('openwop.it.multi-party-conversation-shape.capabilities-schema-json-declares-multipartyconversation-with-supported-optional', 'RFC 0101 §Schema', 'supported MUST be required on the block')).toContain('supported');
189
+ expect(mpc?.additionalProperties, req('openwop.it.multi-party-conversation-shape.capabilities-schema-json-declares-multipartyconversation-with-supported-optional', 'RFC 0101 §Schema', 'the multiPartyConversation block MUST be closed')).toBe(false);
192
190
  });
193
191
 
194
192
  it('the multiPartyConversation block validates a conforming advertisement and rejects extras', () => {
@@ -197,10 +195,10 @@ describe('multi-party-conversation-shape: capability advertisement (RFC 0101 §S
197
195
  const ajv = new Ajv2020({ strict: false, allErrors: true });
198
196
  addFormats(ajv);
199
197
  const validate = ajv.compile(mpc);
200
- expect(validate({ supported: true, maxParticipants: 8 }), why('RFC 0101 §Schema', 'a conforming advertisement MUST validate')).toBe(true);
201
- expect(validate({ supported: true }), why('RFC 0101 §Schema', 'maxParticipants is optional')).toBe(true);
202
- expect(validate({ maxParticipants: 8 }), why('RFC 0101 §Schema', 'supported is required')).toBe(false);
203
- expect(validate({ supported: true, unexpected: 1 }), why('RFC 0101 §Schema', 'an extra key MUST be rejected (closed block)')).toBe(false);
204
- expect(validate({ supported: true, maxParticipants: 1 }), why('RFC 0101 §Schema', 'maxParticipants minimum is 2 (a council has ≥2)')).toBe(false);
198
+ expect(validate({ supported: true, maxParticipants: 8 }), req('openwop.it.multi-party-conversation-shape.the-multipartyconversation-block-validates-a-conforming-advertisement-and-reject', 'RFC 0101 §Schema', 'a conforming advertisement MUST validate')).toBe(true);
199
+ expect(validate({ supported: true }), req('openwop.it.multi-party-conversation-shape.the-multipartyconversation-block-validates-a-conforming-advertisement-and-reject', 'RFC 0101 §Schema', 'maxParticipants is optional')).toBe(true);
200
+ expect(validate({ maxParticipants: 8 }), req('openwop.it.multi-party-conversation-shape.the-multipartyconversation-block-validates-a-conforming-advertisement-and-reject', 'RFC 0101 §Schema', 'supported is required')).toBe(false);
201
+ expect(validate({ supported: true, unexpected: 1 }), req('openwop.it.multi-party-conversation-shape.the-multipartyconversation-block-validates-a-conforming-advertisement-and-reject', 'RFC 0101 §Schema', 'an extra key MUST be rejected (closed block)')).toBe(false);
202
+ expect(validate({ supported: true, maxParticipants: 1 }), req('openwop.it.multi-party-conversation-shape.the-multipartyconversation-block-validates-a-conforming-advertisement-and-reject', 'RFC 0101 §Schema', 'maxParticipants minimum is 2 (a council has ≥2)')).toBe(false);
205
203
  });
206
204
  });
@@ -34,6 +34,7 @@ import { describe, it, expect } from 'vitest';
34
34
  import { softSkip, seamAbsent } from '../lib/soft-skip.js';
35
35
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
36
36
  import { driver } from '../lib/driver.js';
37
+ import { req } from '../lib/requirement-ids.js';
37
38
 
38
39
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
39
40
 
@@ -81,18 +82,18 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
81
82
  if (probe.status === 404) {
82
83
  await noteSimulatorAbsent();
83
84
  ctx.skip(); // host doesn't expose the simulator seam
84
- return;
85
+ return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam, prior step, or fixture unavailable)');
85
86
  }
86
87
  expect(
87
88
  probe.status,
88
- driver.describe(
89
+ req('openwop.it.multi-region-idempotency-behavior.two-region-conflict-resolves-to-the-lex-min-runid-per-annex-convergence-rule',
89
90
  'idempotency.md §"Multi-region idempotency annex"',
90
91
  'simulate-partition seam MUST return 200 when ≥2 conflicting claims are submitted',
91
92
  ),
92
93
  ).toBe(200);
93
94
  expect(
94
95
  probe.body.winner?.runId,
95
- driver.describe(
96
+ req('openwop.it.multi-region-idempotency-behavior.two-region-conflict-resolves-to-the-lex-min-runid-per-annex-convergence-rule',
96
97
  'idempotency.md §"Convergence rule"',
97
98
  'winner MUST be the lex-min runId (run-a-west < run-b-east)',
98
99
  ),
@@ -108,19 +109,19 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
108
109
  if (probe.status === 404) {
109
110
  await noteSimulatorAbsent();
110
111
  ctx.skip();
111
- return;
112
+ return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam, prior step, or fixture unavailable)');
112
113
  }
113
114
  expect(probe.status).toBe(200);
114
115
  expect(
115
116
  probe.body.winner?.runId,
116
- driver.describe(
117
+ req('openwop.it.multi-region-idempotency-behavior.three-region-partition-resolves-to-a-single-winner',
117
118
  'idempotency.md §"Convergence rule"',
118
119
  'winner MUST be the lex-min runId across all conflicting claims',
119
120
  ),
120
121
  ).toBe('aaa-1');
121
122
  expect(
122
123
  probe.body.losers?.length,
123
- driver.describe(
124
+ req('openwop.it.multi-region-idempotency-behavior.three-region-partition-resolves-to-a-single-winner',
124
125
  'idempotency.md §"Convergence rule"',
125
126
  'losers array MUST contain N-1 entries when N claims conflict',
126
127
  ),
@@ -135,13 +136,13 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
135
136
  if (probe.status === 404) {
136
137
  await noteSimulatorAbsent();
137
138
  ctx.skip();
138
- return;
139
+ return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam, prior step, or fixture unavailable)');
139
140
  }
140
141
  expect(probe.status).toBe(200);
141
142
  const redirects = probe.body.cacheRedirects ?? [];
142
143
  expect(
143
144
  redirects.length,
144
- driver.describe(
145
+ req('openwop.it.multi-region-idempotency-behavior.every-region-gets-a-cache-redirect-entry-pointing-at-the-winner',
145
146
  'idempotency.md §"Convergence rule"',
146
147
  'cacheRedirects MUST contain one entry per claim (including the winner)',
147
148
  ),
@@ -149,7 +150,7 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
149
150
  for (const redirect of redirects) {
150
151
  expect(
151
152
  redirect.redirectToRunId,
152
- driver.describe(
153
+ req('openwop.it.multi-region-idempotency-behavior.every-region-gets-a-cache-redirect-entry-pointing-at-the-winner',
153
154
  'idempotency.md §"Convergence rule"',
154
155
  'every cache redirect MUST point at the winner runId',
155
156
  ),
@@ -165,12 +166,12 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
165
166
  if (probe.status === 404) {
166
167
  await noteSimulatorAbsent();
167
168
  ctx.skip();
168
- return;
169
+ return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam, prior step, or fixture unavailable)');
169
170
  }
170
171
  expect(probe.status).toBe(200);
171
172
  expect(
172
173
  probe.body.loserCancelReason,
173
- driver.describe(
174
+ req('openwop.it.multi-region-idempotency-behavior.loser-cancel-reason-must-be-the-canonical-cross-region-dedup-loss-string',
174
175
  'idempotency.md §"Convergence rule"',
175
176
  'loserCancelReason MUST be the canonical `cross_region_dedup_loss` string',
176
177
  ),
@@ -187,7 +188,7 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
187
188
  if (p1.status === 404) {
188
189
  await noteSimulatorAbsent();
189
190
  ctx.skip();
190
- return;
191
+ return softSkip('blocked', 'precondition not met — `p1.status === 404` returned early (seam, prior step, or fixture unavailable)');
191
192
  }
192
193
  expect(p1.status).toBe(200);
193
194
  const p2 = await simulatePartition([claims[2]!, claims[0]!, claims[1]!]);
@@ -196,7 +197,7 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
196
197
  expect(p3.status).toBe(200);
197
198
  expect(
198
199
  p1.body.winner?.runId,
199
- driver.describe(
200
+ req('openwop.it.multi-region-idempotency-behavior.resolver-is-order-invariant-shuffled-inputs-produce-the-same-winner',
200
201
  'idempotency.md §"Convergence rule" — determinism',
201
202
  'resolver MUST be order-invariant; all permutations MUST produce the same lex-min winner',
202
203
  ),
@@ -213,11 +214,11 @@ describe.skipIf(HTTP_SKIP)('multi-region-idempotency-behavior: convergence rule
213
214
  if (probe.status === 404) {
214
215
  await noteSimulatorAbsent();
215
216
  ctx.skip();
216
- return;
217
+ return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam, prior step, or fixture unavailable)');
217
218
  }
218
219
  expect(
219
220
  probe.status,
220
- driver.describe(
221
+ req('openwop.it.multi-region-idempotency-behavior.mismatched-tuple-rejects-with-400-validation-error',
221
222
  'idempotency.md §"Convergence rule"',
222
223
  'claims with non-matching (tenantId, endpoint, key) MUST be rejected — it would be a programming error in the caller',
223
224
  ),