@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
@@ -30,8 +30,7 @@ import {
30
30
  ProducedVarProducerUnknownError,
31
31
  type WorkflowChain,
32
32
  } from '../lib/workflow-chain-expansion.js';
33
-
34
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
33
+ import { req } from '../lib/requirement-ids.js';
35
34
  const SPEC = 'workflow-chain-packs.md §"Produced (run-scoped) variables (RFC 0133)"';
36
35
 
37
36
  /** `generate` writes `plan`; `decompose` reads it via a variable binding. */
@@ -56,19 +55,19 @@ const PLAN_GEN: WorkflowChain = {
56
55
  describe('chain-produced-var-roundtrip: run-scoped variables (RFC 0133 §2, server-free)', () => {
57
56
  it('emits declared producedVariables into variables[] (name + type, NO value)', () => {
58
57
  const vars = emitProducedVariables(PLAN_GEN);
59
- expect(vars, why(SPEC, '§2.3 — one run-scoped variable emitted')).toEqual([{ name: 'plan', type: 'object' }]);
58
+ expect(vars, req('openwop.it.chain-produced-var-roundtrip.emits-declared-producedvariables-into-variables-name-type-no-value', SPEC, '§2.3 — one run-scoped variable emitted')).toEqual([{ name: 'plan', type: 'object' }]);
60
59
  // Run-scoped: NO author-time value rides the emitted entry.
61
- expect('value' in (vars[0] as object), why(SPEC, '§2.3 — no author-time value (distinct from parameters)')).toBe(
60
+ expect('value' in (vars[0] as object), req('openwop.it.chain-produced-var-roundtrip.emits-declared-producedvariables-into-variables-name-type-no-value', SPEC, '§2.3 — no author-time value (distinct from parameters)')).toBe(
62
61
  false,
63
62
  );
64
63
  expect(
65
64
  'defaultValue' in (vars[0] as object),
66
- why(SPEC, '§2.3 — no default value (a produced var is written during the run)'),
65
+ req('openwop.it.chain-produced-var-roundtrip.emits-declared-producedvariables-into-variables-name-type-no-value', SPEC, '§2.3 — no default value (a produced var is written during the run)'),
67
66
  ).toBe(false);
68
67
  });
69
68
 
70
69
  it('validates a variable read of a DECLARED producedVariables name', () => {
71
- expect(() => validateVariableReads(PLAN_GEN), why(SPEC, '§2.2 — declared read is closed-world valid')).not.toThrow();
70
+ expect(() => validateVariableReads(PLAN_GEN), req('openwop.it.chain-produced-var-roundtrip.validates-a-variable-read-of-a-declared-producedvariables-name', SPEC, '§2.2 — declared read is closed-world valid')).not.toThrow();
72
71
  });
73
72
 
74
73
  it('rejects a variable read of an UNDECLARED name (variable_undeclared)', () => {
@@ -86,14 +85,14 @@ describe('chain-produced-var-roundtrip: run-scoped variables (RFC 0133 §2, serv
86
85
  ],
87
86
  },
88
87
  };
89
- expect(() => validateVariableReads(undeclared), why(SPEC, '§2.2 — undeclared read MUST reject')).toThrow(
88
+ expect(() => validateVariableReads(undeclared), req('openwop.it.chain-produced-var-roundtrip.rejects-a-variable-read-of-an-undeclared-name-variable-undeclared', SPEC, '§2.2 — undeclared read MUST reject')).toThrow(
90
89
  VariableUndeclaredError,
91
90
  );
92
91
  try {
93
92
  validateVariableReads(undeclared);
94
93
  } catch (e) {
95
- expect((e as VariableUndeclaredError).code, why(SPEC, 'wire code variable_undeclared')).toBe('variable_undeclared');
96
- expect((e as VariableUndeclaredError).variableName, why(SPEC, 'names the offending variable')).toBe('plan');
94
+ expect((e as VariableUndeclaredError).code, req('openwop.it.chain-produced-var-roundtrip.rejects-a-variable-read-of-an-undeclared-name-variable-undeclared', SPEC, 'wire code variable_undeclared')).toBe('variable_undeclared');
95
+ expect((e as VariableUndeclaredError).variableName, req('openwop.it.chain-produced-var-roundtrip.rejects-a-variable-read-of-an-undeclared-name-variable-undeclared', SPEC, 'names the offending variable')).toBe('plan');
97
96
  }
98
97
  });
99
98
 
@@ -104,12 +103,12 @@ describe('chain-produced-var-roundtrip: run-scoped variables (RFC 0133 §2, serv
104
103
  };
105
104
  expect(
106
105
  () => validateVariableReads(badProducer),
107
- why(SPEC, '§2.2 — producedBy MUST be a real fragment node'),
106
+ req('openwop.it.chain-produced-var-roundtrip.rejects-a-producedvariables-whose-producedby-names-a-non-existent-node-produced', SPEC, '§2.2 — producedBy MUST be a real fragment node'),
108
107
  ).toThrow(ProducedVarProducerUnknownError);
109
108
  try {
110
109
  validateVariableReads(badProducer);
111
110
  } catch (e) {
112
- expect((e as ProducedVarProducerUnknownError).code, why(SPEC, 'distinct wire code')).toBe(
111
+ expect((e as ProducedVarProducerUnknownError).code, req('openwop.it.chain-produced-var-roundtrip.rejects-a-producedvariables-whose-producedby-names-a-non-existent-node-produced', SPEC, 'distinct wire code')).toBe(
113
112
  'produced_var_producer_unknown',
114
113
  );
115
114
  }
@@ -123,7 +122,7 @@ describe('chain-produced-var-roundtrip: run-scoped variables (RFC 0133 §2, serv
123
122
  };
124
123
  expect(
125
124
  () => validateVariableReads(collide),
126
- why(SPEC, '§2.2 — a produced var colliding with a parameter name MUST reject'),
125
+ req('openwop.it.chain-produced-var-roundtrip.rejects-a-producedvariables-name-that-collides-with-a-parameter-channels-must-be', SPEC, '§2.2 — a produced var colliding with a parameter name MUST reject'),
127
126
  ).toThrow(VariableUndeclaredError);
128
127
  });
129
128
 
@@ -141,12 +140,12 @@ describe('chain-produced-var-roundtrip: run-scoped variables (RFC 0133 §2, serv
141
140
  };
142
141
  expect(
143
142
  () => validateVariableReads(paramRead, new Set(['seed'])),
144
- why(SPEC, '§2.2 — a materialized-parameter read validates'),
143
+ req('openwop.it.chain-produced-var-roundtrip.validates-a-read-of-a-materialized-parameter-name-params-produced-vars-compose', SPEC, '§2.2 — a materialized-parameter read validates'),
145
144
  ).not.toThrow();
146
145
  // …but still rejects when the name is neither a produced var nor a param.
147
146
  expect(
148
147
  () => validateVariableReads(paramRead, new Set()),
149
- why(SPEC, '§2.2 — same read with no matching param still rejects'),
148
+ req('openwop.it.chain-produced-var-roundtrip.validates-a-read-of-a-materialized-parameter-name-params-produced-vars-compose', SPEC, '§2.2 — same read with no matching param still rejects'),
150
149
  ).toThrow(VariableUndeclaredError);
151
150
  });
152
151
  });
@@ -30,8 +30,7 @@ import {
30
30
  DEFAULT_MAX_SUB_CHAIN_DEPTH,
31
31
  type WorkflowChain,
32
32
  } from '../lib/workflow-chain-expansion.js';
33
-
34
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
33
+ import { req } from '../lib/requirement-ids.js';
35
34
  const SPEC = 'workflow-chain-packs.md §"Sub-chain composition (RFC 0133)"';
36
35
 
37
36
  /** A chain node that dispatches a named sub-chain ref. */
@@ -88,14 +87,14 @@ const ctxFor = (siblings: Map<string, WorkflowChain>, maxDepth?: number) => ({
88
87
  describe('chain-subchain-cycle-rejected: bounded recursion (RFC 0133, server-free)', () => {
89
88
  it('rejects a chain that transitively composes itself (sub_chain_cycle)', () => {
90
89
  const siblings = new Map([[selfRef.chainId, selfRef]]);
91
- expect(() => expandChainTree(selfRef, ctxFor(siblings)), why(SPEC, 'self-composition MUST reject')).toThrow(
90
+ expect(() => expandChainTree(selfRef, ctxFor(siblings)), req('openwop.it.chain-subchain-cycle-rejected.rejects-a-chain-that-transitively-composes-itself-sub-chain-cycle', SPEC, 'self-composition MUST reject')).toThrow(
92
91
  SubChainCycleError,
93
92
  );
94
93
  try {
95
94
  expandChainTree(selfRef, ctxFor(siblings));
96
95
  } catch (e) {
97
- expect((e as SubChainCycleError).code, why(SPEC, 'wire code sub_chain_cycle')).toBe('sub_chain_cycle');
98
- expect((e as SubChainCycleError).httpStatus, why(SPEC, 'HTTP 400')).toBe(400);
96
+ expect((e as SubChainCycleError).code, req('openwop.it.chain-subchain-cycle-rejected.rejects-a-chain-that-transitively-composes-itself-sub-chain-cycle', SPEC, 'wire code sub_chain_cycle')).toBe('sub_chain_cycle');
97
+ expect((e as SubChainCycleError).httpStatus, req('openwop.it.chain-subchain-cycle-rejected.rejects-a-chain-that-transitively-composes-itself-sub-chain-cycle', SPEC, 'HTTP 400')).toBe(400);
99
98
  }
100
99
  });
101
100
 
@@ -105,13 +104,13 @@ describe('chain-subchain-cycle-rejected: bounded recursion (RFC 0133, server-fre
105
104
  const { root, siblings } = linearChain(5);
106
105
  expect(
107
106
  () => expandChainTree(root, ctxFor(siblings, 2)),
108
- why(SPEC, 'depth breach MUST reject (bounded recursion)'),
107
+ req('openwop.it.chain-subchain-cycle-rejected.rejects-nesting-past-maxsubchaindepth-with-a-distinct-sub-chain-max-depth-exceed', SPEC, 'depth breach MUST reject (bounded recursion)'),
109
108
  ).toThrow(SubChainDepthExceededError);
110
109
  try {
111
110
  expandChainTree(root, ctxFor(siblings, 2));
112
111
  } catch (e) {
113
- expect((e as SubChainDepthExceededError).code, why(SPEC, 'distinct wire code')).toBe('sub_chain_max_depth_exceeded');
114
- expect(e instanceof SubChainCycleError, why(SPEC, 'a depth breach is NOT a cycle')).toBe(false);
112
+ expect((e as SubChainDepthExceededError).code, req('openwop.it.chain-subchain-cycle-rejected.rejects-nesting-past-maxsubchaindepth-with-a-distinct-sub-chain-max-depth-exceed', SPEC, 'distinct wire code')).toBe('sub_chain_max_depth_exceeded');
113
+ expect(e instanceof SubChainCycleError, req('openwop.it.chain-subchain-cycle-rejected.rejects-nesting-past-maxsubchaindepth-with-a-distinct-sub-chain-max-depth-exceed', SPEC, 'a depth breach is NOT a cycle')).toBe(false);
115
114
  }
116
115
  });
117
116
 
@@ -119,7 +118,7 @@ describe('chain-subchain-cycle-rejected: bounded recursion (RFC 0133, server-fre
119
118
  const { root, siblings } = linearChain(3);
120
119
  const { children } = expandChainTree(root, ctxFor(siblings, DEFAULT_MAX_SUB_CHAIN_DEPTH));
121
120
  // 3 composing links (link.0..link.2 each compose their successor) ⇒ 3 co-registered children.
122
- expect(children.length, why(SPEC, 'benign acyclic tree within the bound expands')).toBe(3);
121
+ expect(children.length, req('openwop.it.chain-subchain-cycle-rejected.expands-an-acyclic-tree-within-the-bound-cleanly-guard-rejects-bombs-not-benign', SPEC, 'benign acyclic tree within the bound expands')).toBe(3);
123
122
  });
124
123
 
125
124
  it('rejects a subChainRef that resolves to no sibling chain (sub_chain_unresolved)', () => {
@@ -135,7 +134,7 @@ describe('chain-subchain-cycle-rejected: bounded recursion (RFC 0133, server-fre
135
134
  const siblings = new Map([[orphan.chainId, orphan]]);
136
135
  expect(
137
136
  () => expandChainTree(orphan, ctxFor(siblings)),
138
- why(SPEC, '§1.1 — unresolvable ref rejects distinctly'),
137
+ req('openwop.it.chain-subchain-cycle-rejected.rejects-a-subchainref-that-resolves-to-no-sibling-chain-sub-chain-unresolved', SPEC, '§1.1 — unresolvable ref rejects distinctly'),
139
138
  ).toThrow(SubChainUnresolvedError);
140
139
  });
141
140
  });
@@ -28,8 +28,7 @@ import addFormats from 'ajv-formats';
28
28
  import { SCHEMAS_DIR } from '../lib/paths.js';
29
29
  import { behaviorGate } from '../lib/behavior-gate.js';
30
30
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
31
-
32
- const cite = (section: string, requirement: string): string => `${section} — ${requirement}`;
31
+ import { req } from '../lib/requirement-ids.js';
33
32
  const CAPS = join(SCHEMAS_DIR, 'capabilities.schema.json');
34
33
  const MANIFEST = join(SCHEMAS_DIR, 'workflow-chain-pack-manifest.schema.json');
35
34
 
@@ -40,20 +39,20 @@ function loadSchema(path: string): Record<string, unknown> {
40
39
  describe('chain-subchain-fanout §A: capability + manifest shape (RFC 0133, always-on)', () => {
41
40
  it('capabilities.schema.json §workflowChainPacks.subChains requires supported:boolean + maxDepth default 8', () => {
42
41
  const raw = readFileSync(CAPS, 'utf8');
43
- expect(raw.includes('"subChains"'), cite('capabilities §workflowChainPacks', 'the subChains block MUST exist')).toBe(
42
+ expect(raw.includes('"subChains"'), req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §workflowChainPacks', 'the subChains block MUST exist')).toBe(
44
43
  true,
45
44
  );
46
45
  const schema = loadSchema(CAPS);
47
46
  // The subChains sub-block MUST be present somewhere in the workflowChainPacks family.
48
47
  expect(
49
48
  JSON.stringify(schema).includes('"subChains"'),
50
- cite('capabilities §subChains', 'declared in the capabilities schema'),
49
+ req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §subChains', 'declared in the capabilities schema'),
51
50
  ).toBe(true);
52
51
  expect(
53
52
  raw.includes('sub_chain_unsupported'),
54
- cite('capabilities §subChains', 'the description MUST cite the sub_chain_unsupported refusal'),
53
+ req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §subChains', 'the description MUST cite the sub_chain_unsupported refusal'),
55
54
  ).toBe(true);
56
- expect(raw.includes('"default": 8'), cite('capabilities §subChains.maxDepth', 'RECOMMENDED default 8')).toBe(true);
55
+ expect(raw.includes('"default": 8'), req('openwop.it.chain-subchain-fanout.capabilities-schema-json-workflowchainpacks-subchains-requires-supported-boolean', 'capabilities §subChains.maxDepth', 'RECOMMENDED default 8')).toBe(true);
57
56
  });
58
57
 
59
58
  it('manifest schema accepts a core.dispatch fan-out over a subChainRef worker', () => {
@@ -93,7 +92,7 @@ describe('chain-subchain-fanout §A: capability + manifest shape (RFC 0133, alwa
93
92
  },
94
93
  ],
95
94
  };
96
- expect(validate(pack), cite('manifest §subChains', `a subChainRef fan-out validates: ${ajv.errorsText(validate.errors)}`)).toBe(
95
+ expect(validate(pack), req('openwop.it.chain-subchain-fanout.manifest-schema-accepts-a-core-dispatch-fan-out-over-a-subchainref-worker', 'manifest §subChains', `a subChainRef fan-out validates: ${ajv.errorsText(validate.errors)}`)).toBe(
97
96
  true,
98
97
  );
99
98
  });
@@ -120,7 +119,7 @@ describe('chain-subchain-fanout §A: capability + manifest shape (RFC 0133, alwa
120
119
  };
121
120
  expect(
122
121
  validate(pack),
123
- cite('manifest §config not-guard', 'a chain MUST NOT pin a concrete config.workflowId'),
122
+ req('openwop.it.chain-subchain-fanout.manifest-schema-rejects-a-concrete-config-workflowid-inside-a-fragment-the-1-2-n', 'manifest §config not-guard', 'a chain MUST NOT pin a concrete config.workflowId'),
124
123
  ).toBe(false);
125
124
  });
126
125
  });
@@ -134,6 +133,6 @@ describe('chain-subchain-fanout §B: host child fan-out (RFC 0133, capability-ga
134
133
  // invariant `sub-chain-child-tenant-scoped` (child owned by parent's tenant).
135
134
  // The from-chain response MUST carry the §1.3 contract: { workflowId,
136
135
  // subChainWorkflowIds[] (tenant-scoped, deduped), nodeCount }.
137
- expect(wcp?.subChains?.supported, 'host advertising subChains.supported implements child fan-out').toBe(true);
136
+ expect(wcp?.subChains?.supported, req('openwop.it.chain-subchain-fanout.fans-out-n-child-runs-over-a-subchainref-worker-returns-the-from-chain-contract', 'RFC 0133 §1.2', 'host advertising subChains.supported implements child fan-out')).toBe(true);
138
137
  });
139
138
  });
@@ -30,9 +30,7 @@ import {
30
30
  mintChildWorkflowId,
31
31
  type WorkflowChain,
32
32
  } from '../lib/workflow-chain-expansion.js';
33
-
34
- /** Server-free assertion-message helper (mirrors driver.describe without OPENWOP_BASE_URL). */
35
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
33
+ import { req } from '../lib/requirement-ids.js';
36
34
  const SPEC = 'workflow-chain-packs.md §"Sub-chain composition (RFC 0133)"';
37
35
 
38
36
  /** A leaf child chain — one plain node, no further composition. */
@@ -83,53 +81,53 @@ const ctx = (tenantId = 'tenant-a') => ({
83
81
  describe('chain-subchain-sibling: co-registration (RFC 0133 §1, server-free)', () => {
84
82
  it('co-registers the referenced sibling as its own workflow', () => {
85
83
  const { children } = expandChainTree(PARENT, ctx());
86
- expect(children.length, why(SPEC, '§1.3 step 2 — one distinct sibling ref ⇒ one co-registered child')).toBe(1);
87
- expect(children[0]?.chainId, why(SPEC, 'child carries the composed chainId')).toBe('lesson-batch');
84
+ expect(children.length, req('openwop.it.chain-subchain-sibling.co-registers-the-referenced-sibling-as-its-own-workflow', SPEC, '§1.3 step 2 — one distinct sibling ref ⇒ one co-registered child')).toBe(1);
85
+ expect(children[0]?.chainId, req('openwop.it.chain-subchain-sibling.co-registers-the-referenced-sibling-as-its-own-workflow', SPEC, 'child carries the composed chainId')).toBe('lesson-batch');
88
86
  expect(
89
87
  children[0]?.fragment.nodes.length,
90
- why(SPEC, 'child is a fully expanded fragment (its own registered workflow)'),
88
+ req('openwop.it.chain-subchain-sibling.co-registers-the-referenced-sibling-as-its-own-workflow', SPEC, 'child is a fully expanded fragment (its own registered workflow)'),
91
89
  ).toBe(1);
92
90
  });
93
91
 
94
92
  it('mints a DETERMINISTIC, TENANT-SCOPED, version-pinned child id', () => {
95
93
  const { children } = expandChainTree(PARENT, ctx());
96
94
  const expected = mintChildWorkflowId('tenant-a', 'lesson-batch', '1.0.0');
97
- expect(children[0]?.childWorkflowId, why(SPEC, '§1.3 step 2 — deterministic (tenantId, childChainId, version) id')).toBe(
95
+ expect(children[0]?.childWorkflowId, req('openwop.it.chain-subchain-sibling.mints-a-deterministic-tenant-scoped-version-pinned-child-id', SPEC, '§1.3 step 2 — deterministic (tenantId, childChainId, version) id')).toBe(
98
96
  expected,
99
97
  );
100
98
  // Re-instantiating in the same tenant converges on the same id.
101
99
  const again = expandChainTree(PARENT, ctx());
102
- expect(again.children[0]?.childWorkflowId, why(SPEC, 'repeat instantiation in-tenant converges')).toBe(expected);
100
+ expect(again.children[0]?.childWorkflowId, req('openwop.it.chain-subchain-sibling.mints-a-deterministic-tenant-scoped-version-pinned-child-id', SPEC, 'repeat instantiation in-tenant converges')).toBe(expected);
103
101
  });
104
102
 
105
103
  it('scopes the child id per TENANT — two tenants NEVER collide on the global registry (isolation)', () => {
106
104
  const a = expandChainTree(PARENT, ctx('tenant-a')).children[0]?.childWorkflowId;
107
105
  const b = expandChainTree(PARENT, ctx('tenant-b')).children[0]?.childWorkflowId;
108
- expect(a, why(SPEC, 'tenant-a mints an id')).toBeTruthy();
106
+ expect(a, req('openwop.it.chain-subchain-sibling.scopes-the-child-id-per-tenant-two-tenants-never-collide-on-the-global-registry', SPEC, 'tenant-a mints an id')).toBeTruthy();
109
107
  expect(
110
108
  a !== b,
111
- why(SPEC, '§1.3 SECURITY sub-chain-child-tenant-scoped — distinct tenants ⇒ distinct child ids, no cross-tenant collision'),
109
+ req('openwop.it.chain-subchain-sibling.scopes-the-child-id-per-tenant-two-tenants-never-collide-on-the-global-registry', SPEC, '§1.3 SECURITY sub-chain-child-tenant-scoped — distinct tenants ⇒ distinct child ids, no cross-tenant collision'),
112
110
  ).toBe(true);
113
111
  });
114
112
 
115
113
  it('registers a child referenced twice exactly ONCE (dedup by deterministic id)', () => {
116
114
  const { children } = expandChainTree(PARENT, ctx());
117
115
  const ids = children.map((c) => c.childWorkflowId);
118
- expect(new Set(ids).size, why(SPEC, '§1.3 step 2 — a shared child registers once')).toBe(ids.length);
119
- expect(ids.length, why(SPEC, 'both build-0 + build-1 collapse to one child')).toBe(1);
116
+ expect(new Set(ids).size, req('openwop.it.chain-subchain-sibling.registers-a-child-referenced-twice-exactly-once-dedup-by-deterministic-id', SPEC, '§1.3 step 2 — a shared child registers once')).toBe(ids.length);
117
+ expect(ids.length, req('openwop.it.chain-subchain-sibling.registers-a-child-referenced-twice-exactly-once-dedup-by-deterministic-id', SPEC, 'both build-0 + build-1 collapse to one child')).toBe(1);
120
118
  });
121
119
 
122
120
  it('rewrites config.subChainRef → the minted child config.workflowId', () => {
123
121
  const { parent } = expandChainTree(PARENT, ctx());
124
122
  const expected = mintChildWorkflowId('tenant-a', 'lesson-batch', '1.0.0');
125
123
  const dispatchNodes = parent.nodes.filter((n) => n.typeId === 'core.subWorkflow');
126
- expect(dispatchNodes.length, why(SPEC, 'both dispatch nodes present')).toBe(2);
124
+ expect(dispatchNodes.length, req('openwop.it.chain-subchain-sibling.rewrites-config-subchainref-the-minted-child-config-workflowid', SPEC, 'both dispatch nodes present')).toBe(2);
127
125
  for (const n of dispatchNodes) {
128
126
  const config = n.config as Record<string, unknown>;
129
- expect(config['workflowId'], why(SPEC, '§1.3 step 3 — subChainRef rewritten to minted child id')).toBe(expected);
127
+ expect(config['workflowId'], req('openwop.it.chain-subchain-sibling.rewrites-config-subchainref-the-minted-child-config-workflowid', SPEC, '§1.3 step 3 — subChainRef rewritten to minted child id')).toBe(expected);
130
128
  expect(
131
129
  'subChainRef' in config,
132
- why(SPEC, '§1.3 step 3 — transient subChainRef key dropped from the runtime config'),
130
+ req('openwop.it.chain-subchain-sibling.rewrites-config-subchainref-the-minted-child-config-workflowid', SPEC, '§1.3 step 3 — transient subChainRef key dropped from the runtime config'),
133
131
  ).toBe(false);
134
132
  }
135
133
  });
@@ -140,7 +138,7 @@ describe('chain-subchain-sibling: co-registration (RFC 0133 §1, server-free)',
140
138
  const referenced = parent.nodes
141
139
  .filter((n) => n.typeId === 'core.subWorkflow')
142
140
  .map((n) => (n.config as Record<string, unknown>)['workflowId']);
143
- expect(referenced.every((id) => id === childId), why(SPEC, 'parent HOLDS the co-registered child at runtime')).toBe(
141
+ expect(referenced.every((id) => id === childId), req('openwop.it.chain-subchain-sibling.preserves-the-child-reference-at-runtime-concrete-workflowid-unlike-inline-mode', SPEC, 'parent HOLDS the co-registered child at runtime')).toBe(
144
142
  true,
145
143
  );
146
144
  });
@@ -33,6 +33,8 @@ import { describe, it, expect } from 'vitest';
33
33
  import { driver } from '../lib/driver.js';
34
34
  import { behaviorGate } from '../lib/behavior-gate.js';
35
35
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
36
+ import { req } from '../lib/requirement-ids.js';
37
+ import { softSkip } from '../lib/soft-skip.js';
36
38
 
37
39
  const PROFILE = 'openwop-channel-presence';
38
40
  const SUBJECT_REF = /^(user|agent):.+/;
@@ -47,37 +49,37 @@ describe('channel-presence-behavioral (RFC 0110 §Conformance)', () => {
47
49
 
48
50
  const conversationId = 'conf:channel-presence:c1';
49
51
  const res = await driver.post('/v1/host/sample/channel-presence/snapshot', { conversationId, member: 'user:conformance-runner' });
50
- if (res.status === 404 || res.status === 405) return; // seam unwired — host witnesses via its own route test (dual-staging)
52
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired — host witnesses via its own route test (dual-staging)) (seam, prior step, or fixture unavailable)'); // seam unwired — host witnesses via its own route test (dual-staging)
51
53
 
52
54
  expect(
53
55
  res.status === 200,
54
- driver.describe('RFC 0110 §Proposal', 'the presence snapshot seam MUST return 200 for a member'),
56
+ req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'the presence snapshot seam MUST return 200 for a member'),
55
57
  ).toBe(true);
56
58
  const snap = res.json as PresenceSnapshot;
57
59
 
58
60
  // MUST 1 — CLOSED shape: exactly conversationId / present / typing (no PII field rides).
59
61
  expect(
60
62
  Object.keys(snap).sort().join(','),
61
- driver.describe('RFC 0110 §Proposal', 'channel.presence carries ONLY conversationId/present/typing (no PII)'),
63
+ req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'channel.presence carries ONLY conversationId/present/typing (no PII)'),
62
64
  ).toBe('conversationId,present,typing');
63
- expect(snap.conversationId, driver.describe('RFC 0110 §Proposal', 'the snapshot echoes the conversationId')).toBe(conversationId);
65
+ expect(snap.conversationId, req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'the snapshot echoes the conversationId')).toBe(conversationId);
64
66
 
65
67
  // MUST 2 — every ref is an opaque RFC 0041 subject ref (no PII).
66
68
  for (const ref of [...snap.present, ...snap.typing]) {
67
69
  expect(
68
70
  SUBJECT_REF.test(ref),
69
- driver.describe('RFC 0110 §Proposal / RFC 0041', `present/typing ref "${ref}" MUST be an opaque user:/agent: subject ref`),
71
+ req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal / RFC 0041', `present/typing ref "${ref}" MUST be an opaque user:/agent: subject ref`),
70
72
  ).toBe(true);
71
73
  }
72
74
  // typing is a subset of present.
73
75
  for (const ref of snap.typing) {
74
- expect(snap.present.includes(ref), driver.describe('RFC 0110 §Proposal', 'every typing ref MUST also be present')).toBe(true);
76
+ expect(snap.present.includes(ref), req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'every typing ref MUST also be present')).toBe(true);
75
77
  }
76
78
 
77
79
  // MUST 3 — NON-VACUOUS: the snapshotting member is present.
78
80
  expect(
79
81
  snap.present.includes('user:conformance-runner'),
80
- driver.describe('RFC 0110 §Proposal', 'the snapshotting member MUST appear in present (members-only, real)'),
82
+ req('openwop.it.channel-presence-behavioral.a-presence-snapshot-is-the-closed-members-only-non-vacuous-channel-presence-shap', 'RFC 0110 §Proposal', 'the snapshotting member MUST appear in present (members-only, real)'),
81
83
  ).toBe(true);
82
84
  });
83
85
  });
@@ -34,8 +34,7 @@ import { join } from 'node:path';
34
34
  import Ajv2020 from 'ajv/dist/2020.js';
35
35
  import addFormats from 'ajv-formats';
36
36
  import { SCHEMAS_DIR } from '../lib/paths.js';
37
-
38
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
37
+ import { req } from '../lib/requirement-ids.js';
39
38
 
40
39
  function loadSchema(name: string): Record<string, unknown> {
41
40
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -49,26 +48,26 @@ describe('channel-presence-shape: the channel.presence payload (RFC 0110 §Propo
49
48
  it('a conforming presence snapshot (present + typing) validates', () => {
50
49
  expect(
51
50
  presence({ conversationId: 'chan-eng', present: ['user:alice', 'agent:iris'], typing: ['user:alice'] }),
52
- why('RFC 0110 §Proposal', 'a conforming channel.presence payload MUST validate'),
51
+ req('openwop.it.channel-presence-shape.a-conforming-presence-snapshot-present-typing-validates', 'RFC 0110 §Proposal', 'a conforming channel.presence payload MUST validate'),
53
52
  ).toBe(true);
54
53
  });
55
54
 
56
55
  it('typing is OPTIONAL — a snapshot with nobody typing validates', () => {
57
56
  expect(
58
57
  presence({ conversationId: 'chan-eng', present: ['user:alice'] }),
59
- why('RFC 0110 §Proposal', 'typing is optional'),
58
+ req('openwop.it.channel-presence-shape.typing-is-optional-a-snapshot-with-nobody-typing-validates', 'RFC 0110 §Proposal', 'typing is optional'),
60
59
  ).toBe(true);
61
60
  });
62
61
 
63
62
  it('conversationId and present are REQUIRED', () => {
64
- expect(presence({ present: ['user:a'] }), why('RFC 0110 §Proposal', 'conversationId is required')).toBe(false);
65
- expect(presence({ conversationId: 'c' }), why('RFC 0110 §Proposal', 'present is required')).toBe(false);
63
+ expect(presence({ present: ['user:a'] }), req('openwop.it.channel-presence-shape.conversationid-and-present-are-required', 'RFC 0110 §Proposal', 'conversationId is required')).toBe(false);
64
+ expect(presence({ conversationId: 'c' }), req('openwop.it.channel-presence-shape.conversationid-and-present-are-required', 'RFC 0110 §Proposal', 'present is required')).toBe(false);
66
65
  });
67
66
 
68
67
  it('the payload is CLOSED — a non-subject-ref field (ip/location) MUST be rejected (the no-PII guard)', () => {
69
68
  expect(
70
69
  presence({ conversationId: 'c', present: ['user:a'], ip: '10.0.0.1' }),
71
- why('RFC 0110 §Proposal', 'channel.presence MUST forbid extra keys — no PII rides the payload'),
70
+ req('openwop.it.channel-presence-shape.the-payload-is-closed-a-non-subject-ref-field-ip-location-must-be-rejected-the-n', 'RFC 0110 §Proposal', 'channel.presence MUST forbid extra keys — no PII rides the payload'),
72
71
  ).toBe(false);
73
72
  });
74
73
  });
@@ -77,7 +76,7 @@ describe('channel-presence-shape: event type + capability advertisement (RFC 011
77
76
  it('run-event.schema.json enumerates `channel.presence` as a RunEvent type', () => {
78
77
  const re = loadSchema('run-event.schema.json');
79
78
  const enumVals = JSON.stringify(re);
80
- expect(enumVals.includes('"channel.presence"'), why('RFC 0110 §Proposal', 'channel.presence MUST be a declared RunEvent type')).toBe(true);
79
+ expect(enumVals.includes('"channel.presence"'), req('openwop.it.channel-presence-shape.run-event-schema-json-enumerates-channel-presence-as-a-runevent-type', 'RFC 0110 §Proposal', 'channel.presence MUST be a declared RunEvent type')).toBe(true);
81
80
  });
82
81
 
83
82
  it('capabilities.schema.json declares channelPresence with supported, closed', () => {
@@ -85,9 +84,9 @@ describe('channel-presence-shape: event type + capability advertisement (RFC 011
85
84
  const block = (caps.properties as Record<string, Record<string, unknown>>).channelPresence as
86
85
  | { properties?: Record<string, unknown>; required?: string[]; additionalProperties?: boolean }
87
86
  | undefined;
88
- expect(block, why('RFC 0110 §Conformance', 'capabilities.channelPresence MUST be declared')).toBeDefined();
89
- expect(block?.properties?.supported, why('RFC 0110 §Conformance', 'channelPresence.supported MUST be declared')).toBeDefined();
90
- expect(block?.required, why('RFC 0110 §Conformance', 'supported MUST be required on the block')).toContain('supported');
91
- expect(block?.additionalProperties, why('RFC 0110 §Conformance', 'the block MUST be closed')).toBe(false);
87
+ expect(block, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'capabilities.channelPresence MUST be declared')).toBeDefined();
88
+ expect(block?.properties?.supported, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'channelPresence.supported MUST be declared')).toBeDefined();
89
+ expect(block?.required, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'supported MUST be required on the block')).toContain('supported');
90
+ expect(block?.additionalProperties, req('openwop.it.channel-presence-shape.capabilities-schema-json-declares-channelpresence-with-supported-closed', 'RFC 0110 §Conformance', 'the block MUST be closed')).toBe(false);
92
91
  });
93
92
  });
@@ -22,6 +22,7 @@ import { describe, it, expect } from 'vitest';
22
22
  import { driver } from '../lib/driver.js';
23
23
  import { pollUntilTerminal } from '../lib/polling.js';
24
24
  import { isFixtureAdvertised } from '../lib/fixtures.js';
25
+ import { req } from '../lib/requirement-ids.js';
25
26
 
26
27
  const WORKFLOW_ID = 'conformance-channel-ttl';
27
28
  const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
@@ -38,7 +39,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('channel-ttl: conformance-channel-ttl drops ent
38
39
  const runId = (create.json as { runId: string }).runId;
39
40
 
40
41
  const terminal = await pollUntilTerminal(runId);
41
- expect(terminal.status, driver.describe(
42
+ expect(terminal.status, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
42
43
  'fixtures.md conformance-channel-ttl §Terminal status',
43
44
  'fixture MUST reach terminal `completed`',
44
45
  )).toBe('completed');
@@ -46,22 +47,22 @@ describe.skipIf(SKIP_NO_FIXTURE)('channel-ttl: conformance-channel-ttl drops ent
46
47
  const variables = terminal.variables ?? {};
47
48
  const events = variables.events as ChannelEntry[] | undefined;
48
49
 
49
- expect(Array.isArray(events), driver.describe(
50
+ expect(Array.isArray(events), req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
50
51
  'channels-and-reducers.md §append',
51
52
  'channel state MUST be stored as an array of {value, _ts} entries',
52
53
  )).toBe(true);
53
54
 
54
- expect(events!.length, driver.describe(
55
+ expect(events!.length, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
55
56
  'channels-and-reducers.md §TTL — write-time filter',
56
57
  'after the post-TTL write, exactly 1 entry MUST remain (the 3 priors aged out)',
57
58
  )).toBe(1);
58
59
 
59
- expect(events![0].value, driver.describe(
60
+ expect(events![0].value, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
60
61
  'fixtures.md conformance-channel-ttl §Topology',
61
62
  'the surviving entry MUST be the post-delay write (value "d")',
62
63
  )).toBe('d');
63
64
 
64
- expect(typeof events![0]._ts, driver.describe(
65
+ expect(typeof events![0]._ts, req('openwop.it.channel-ttl.after-the-post-ttl-write-the-channel-contains-exactly-one-entry-with-value-d',
65
66
  'channels-and-reducers.md §append entry shape',
66
67
  'each channel entry MUST carry a numeric `_ts` write timestamp',
67
68
  )).toBe('number');
@@ -27,9 +27,9 @@
27
27
  */
28
28
 
29
29
  import { describe, it, expect } from 'vitest';
30
- import { driver } from '../lib/driver.js';
31
30
  import { behaviorGate, behaviorGatePresent } from '../lib/behavior-gate.js';
32
31
  import { readCardPacksCap, cardPacksSupported, executeCard } from '../lib/cardPacks.js';
32
+ import { req } from '../lib/requirement-ids.js';
33
33
 
34
34
  const PROFILE = 'openwop-chat-card-packs';
35
35
 
@@ -40,13 +40,13 @@ describe('chat-card-pack-execution: prompt -> envelope -> typed artifact (RFC 00
40
40
  if (!behaviorGatePresent(PROFILE, res)) return; // seam absent: skip default, FAIL strict
41
41
  expect(
42
42
  res.json['validated'],
43
- driver.describe('chat-card-packs.md "Card execution"', 'the host MUST validate the LLM output against the linked outputArtifactType schema'),
43
+ req('openwop.it.chat-card-pack-execution.a-registered-card-produces-a-schema-validated-artifact', 'chat-card-packs.md "Card execution"', 'the host MUST validate the LLM output against the linked outputArtifactType schema'),
44
44
  ).toBe(true);
45
45
  const evt = res.json['artifactCreated'] as { registered?: unknown } | undefined;
46
46
  if (evt && 'registered' in evt) {
47
47
  expect(
48
48
  evt.registered,
49
- driver.describe('run-event-payloads.schema.json artifactCreated', 'a validated card output MUST emit artifact.created with registered:true'),
49
+ req('openwop.it.chat-card-pack-execution.a-registered-card-produces-a-schema-validated-artifact', 'run-event-payloads.schema.json artifactCreated', 'a validated card output MUST emit artifact.created with registered:true'),
50
50
  ).toBe(true);
51
51
  }
52
52
  });
@@ -62,7 +62,7 @@ describe('chat-card-pack-execution: prompt -> envelope -> typed artifact (RFC 00
62
62
  if (!behaviorGatePresent(PROFILE, res.json['contentTrust'])) return; // FAIL strict
63
63
  expect(
64
64
  res.json['contentTrust'],
65
- driver.describe('chat-card-packs.md "Trust boundary" (R2)', 'a prompt segment derived from a card input MUST carry contentTrust:"untrusted"'),
65
+ req('openwop.it.chat-card-pack-execution.card-input-derived-prompt-content-propagates-contenttrust-untrusted-r2', 'chat-card-packs.md "Trust boundary" (R2)', 'a prompt segment derived from a card input MUST carry contentTrust:"untrusted"'),
66
66
  ).toBe('untrusted');
67
67
  });
68
68
  });
@@ -30,6 +30,7 @@ import Ajv2020 from 'ajv/dist/2020.js';
30
30
  import addFormats from 'ajv-formats';
31
31
  import type { ErrorObject } from 'ajv';
32
32
  import { SCHEMAS_DIR } from '../lib/paths.js';
33
+ import { req } from '../lib/requirement-ids.js';
33
34
 
34
35
  const SCHEMA_PATH = join(SCHEMAS_DIR, 'chat-card-pack-manifest.schema.json');
35
36
 
@@ -68,7 +69,7 @@ describe('category: chat-card-pack manifest validation', () => {
68
69
  it('positive: a valid chat card pack manifest validates cleanly', () => {
69
70
  expect(
70
71
  validate(validManifest()),
71
- `chat-card-packs.md §"Manifest format": a well-formed kind:"card" manifest MUST validate. Errors: ${JSON.stringify(validate.errors)}`,
72
+ req('openwop.it.chat-card-pack-manifest-validation.positive-a-valid-chat-card-pack-manifest-validates-cleanly', 'chat-card-packs.md', `chat-card-packs.md §"Manifest format": a well-formed kind:"card" manifest MUST validate. Errors: ${JSON.stringify(validate.errors)}`),
72
73
  ).toBe(true);
73
74
  });
74
75
 
@@ -77,24 +78,24 @@ describe('category: chat-card-pack manifest validation', () => {
77
78
  const errs = failsWith(manifest, 'additionalProperties');
78
79
  expect(
79
80
  errs.some((e) => (e.params as { additionalProperty?: string }).additionalProperty === 'artifactTypes'),
80
- 'chat-card-packs.md §"Pack kind": one kind per pack (additionalProperties:false)',
81
+ req('openwop.it.chat-card-pack-manifest-validation.negative-a-manifest-mixing-cards-and-artifacttypes-is-rejected', 'chat-card-packs.md', 'chat-card-packs.md §"Pack kind": one kind per pack (additionalProperties:false)'),
81
82
  ).toBe(true);
82
83
  });
83
84
 
84
85
  it('negative: an empty cards[] is rejected', () => {
85
- expect(failsWith({ ...validManifest(), cards: [] }, 'minItems').length).toBeGreaterThan(0);
86
+ expect(failsWith({ ...validManifest(), cards: [] }, 'minItems').length, req('openwop.it.chat-card-pack-manifest-validation.negative-an-empty-cards-is-rejected', 'chat-card-packs.md', 'negative: an empty cards[] is rejected')).toBeGreaterThan(0);
86
87
  });
87
88
 
88
89
  it('negative: an uppercase-scope cardTypeId is rejected', () => {
89
90
  const m = validManifest();
90
91
  m.cards[0]!.cardTypeId = 'Vendor.Acme.Card';
91
- expect(failsWith(m, 'pattern').length).toBeGreaterThan(0);
92
+ expect(failsWith(m, 'pattern').length, req('openwop.it.chat-card-pack-manifest-validation.negative-an-uppercase-scope-cardtypeid-is-rejected', 'chat-card-packs.md', 'negative: an uppercase-scope cardTypeId is rejected')).toBeGreaterThan(0);
92
93
  });
93
94
 
94
95
  it('negative: a card missing prompt is rejected', () => {
95
96
  const m = validManifest();
96
97
  delete (m.cards[0] as { prompt?: unknown }).prompt;
97
- expect(failsWith(m, 'required').length).toBeGreaterThan(0);
98
+ expect(failsWith(m, 'required').length, req('openwop.it.chat-card-pack-manifest-validation.negative-a-card-missing-prompt-is-rejected', 'chat-card-packs.md', 'negative: a card missing prompt is rejected')).toBeGreaterThan(0);
98
99
  });
99
100
 
100
101
  it('negative: a non-portable inputs[].type (canvas-reference) is rejected', () => {
@@ -102,7 +103,7 @@ describe('category: chat-card-pack manifest validation', () => {
102
103
  m.cards[0]!.inputs[0]!.type = 'canvas-reference';
103
104
  expect(
104
105
  failsWith(m, 'pattern').length,
105
- 'chat-card-packs.md §"Input fields": type is the closed portable enum OR a vendor.*/x- extension',
106
+ req('openwop.it.chat-card-pack-manifest-validation.negative-a-non-portable-inputs-type-canvas-reference-is-rejected', 'chat-card-packs.md', 'chat-card-packs.md §"Input fields": type is the closed portable enum OR a vendor.*/x- extension'),
106
107
  ).toBeGreaterThan(0);
107
108
  });
108
109
 
@@ -111,7 +112,7 @@ describe('category: chat-card-pack manifest validation', () => {
111
112
  m.cards[0]!.inputs[0]!.type = 'vendor.myndhyve.canvas-ref';
112
113
  expect(
113
114
  validate(m),
114
- 'chat-card-packs.md §"Input fields": a vendor.<org>.<kind> input type extension MUST validate (other hosts ignore it)',
115
+ req('openwop.it.chat-card-pack-manifest-validation.positive-a-vendor-prefixed-inputs-type-extension-is-tolerated', 'chat-card-packs.md', 'chat-card-packs.md §"Input fields": a vendor.<org>.<kind> input type extension MUST validate (other hosts ignore it)'),
115
116
  ).toBe(true);
116
117
  });
117
118
 
@@ -121,7 +122,7 @@ describe('category: chat-card-pack manifest validation', () => {
121
122
  m.cards[0]!.inputs[0]!.type = t;
122
123
  expect(
123
124
  validate(m),
124
- `chat-card-packs.md §"Input fields": portable inputs[].type "${t}" MUST validate (G9 resolved 2026-05-27)`,
125
+ req('openwop.it.chat-card-pack-manifest-validation.positive-the-full-portable-inputs-type-subset-validates-g9-incl-multiselect-file', 'chat-card-packs.md', `chat-card-packs.md §"Input fields": portable inputs[].type "${t}" MUST validate (G9 resolved 2026-05-27)`),
125
126
  ).toBe(true);
126
127
  }
127
128
  });