@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,6 +30,7 @@ import { describe, it, expect } from 'vitest';
30
30
  import { softSkip } from '../lib/soft-skip.js';
31
31
  import { driver } from '../lib/driver.js';
32
32
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
33
+ import { req } from '../lib/requirement-ids.js';
33
34
 
34
35
  const MEMORY_REF = 'mem_tenant:default_agent:conformance-rfc0012-sr1_longTerm';
35
36
 
@@ -77,13 +78,13 @@ describe('memory-compaction-sr1-carry-forward: derived content passes the BYOK r
77
78
  { id: `sr1-src-${Date.now()}-3`, content: 'Customer asked about pricing tiers.' },
78
79
  ],
79
80
  });
80
- expect(seed.status, 'seed endpoint MUST return 201 when reachable').toBe(201);
81
+ expect(seed.status, req('openwop.it.memory-compaction-sr1-carry-forward.compacted-memoryentry-content-must-not-carry-source-side-form-leak-signatures', 'RFC 0012 §D', 'seed endpoint MUST return 201 when reachable')).toBe(201);
81
82
 
82
83
  // 2. Drive compaction synchronously.
83
84
  const compactRes = await driver.post('/v1/test/memory/compact', {
84
85
  memoryRef: MEMORY_REF,
85
86
  });
86
- expect(compactRes.status, 'compact MUST return 200 with ≥2 source entries').toBe(200);
87
+ expect(compactRes.status, req('openwop.it.memory-compaction-sr1-carry-forward.compacted-memoryentry-content-must-not-carry-source-side-form-leak-signatures', 'RFC 0012 §D', 'compact MUST return 200 with ≥2 source entries')).toBe(200);
87
88
 
88
89
  const event = compactRes.json as {
89
90
  type?: string;
@@ -95,7 +96,7 @@ describe('memory-compaction-sr1-carry-forward: derived content passes the BYOK r
95
96
  // trivially without it.
96
97
  outputContent?: string;
97
98
  };
98
- expect(event.type, 'event payload MUST be type=memory.compacted').toBe('memory.compacted');
99
+ expect(event.type, req('openwop.it.memory-compaction-sr1-carry-forward.compacted-memoryentry-content-must-not-carry-source-side-form-leak-signatures', 'RFC 0012 §D', 'event payload MUST be type=memory.compacted')).toBe('memory.compacted');
99
100
 
100
101
  if (typeof event.outputContent !== 'string') {
101
102
  // eslint-disable-next-line no-console
@@ -107,11 +108,11 @@ describe('memory-compaction-sr1-carry-forward: derived content passes the BYOK r
107
108
  // future MemoryAdapter.get / list consumers would see) MUST NOT
108
109
  // carry source-side form-leak signatures. A host that skips its
109
110
  // BYOK redaction pass on derived content fails here.
110
- expect(event.outputContent.includes('[BYOK:hk_live_canary_42]'), driver.describe(
111
+ expect(event.outputContent.includes('[BYOK:hk_live_canary_42]'), req('openwop.it.memory-compaction-sr1-carry-forward.compacted-memoryentry-content-must-not-carry-source-side-form-leak-signatures',
111
112
  'RFC 0012 §D',
112
113
  'derived MemoryEntry.content MUST NOT carry source-side [BYOK:...] form-leak signatures (SR-1 carry-forward)',
113
114
  )).toBe(false);
114
- expect(event.outputContent.includes('<REDACTED:db-prod-creds>'), driver.describe(
115
+ expect(event.outputContent.includes('<REDACTED:db-prod-creds>'), req('openwop.it.memory-compaction-sr1-carry-forward.compacted-memoryentry-content-must-not-carry-source-side-form-leak-signatures',
115
116
  'RFC 0012 §D',
116
117
  'derived MemoryEntry.content MUST NOT echo non-canonical <REDACTED:...> markers from sources',
117
118
  )).toBe(false);
@@ -121,7 +122,7 @@ describe('memory-compaction-sr1-carry-forward: derived content passes the BYOK r
121
122
  // leak. Pinning this prevents a host from "passing" by simply
122
123
  // stripping source content rather than redacting it (which would
123
124
  // also lose audit signal).
124
- expect(event.outputContent, driver.describe(
125
+ expect(event.outputContent, req('openwop.it.memory-compaction-sr1-carry-forward.compacted-memoryentry-content-must-not-carry-source-side-form-leak-signatures',
125
126
  'RFC 0012 §D',
126
127
  'derived MemoryEntry.content MUST carry canonical [REDACTED:...] placeholders where source-side leaks were re-substituted',
127
128
  )).toMatch(/\[REDACTED:[^\]]+\]/);
@@ -24,6 +24,7 @@
24
24
  import { describe, it, expect } from 'vitest';
25
25
  import { softSkip } from '../lib/soft-skip.js';
26
26
  import { driver } from '../lib/driver.js';
27
+ import { req } from '../lib/requirement-ids.js';
27
28
 
28
29
  interface ConsolidationCaps {
29
30
  agents?: { memoryConsolidation?: { supported?: boolean } };
@@ -50,11 +51,11 @@ describe('memory-consolidation-idempotent: pass contract (RFC 0068 §D, capabili
50
51
  });
51
52
  if (first.status === 404 || first.status === 501) return softSkip('blocked', 'seam not wired — soft-skip');
52
53
 
53
- expect(first.status, driver.describe('RFC 0068 §D', 'an advertised consolidation seam MUST succeed')).toBe(200);
54
+ expect(first.status, req('openwop.it.memory-consolidation-idempotent.a-consolidation-pass-reduces-or-holds-entry-count-and-is-idempotent-on-a-stable', 'RFC 0068 §D', 'an advertised consolidation seam MUST succeed')).toBe(200);
54
55
  const r1 = first.json as ConsolidateResult;
55
56
  const in1 = r1.event?.inputCount ?? 0;
56
57
  const out1 = r1.event?.outputCount ?? 0;
57
- expect(out1, driver.describe('RFC 0068 §D.1', 'outputCount MUST be <= inputCount for a merge/dedup pass')).toBeLessThanOrEqual(in1);
58
+ expect(out1, req('openwop.it.memory-consolidation-idempotent.a-consolidation-pass-reduces-or-holds-entry-count-and-is-idempotent-on-a-stable', 'RFC 0068 §D.1', 'outputCount MUST be <= inputCount for a merge/dedup pass')).toBeLessThanOrEqual(in1);
58
59
 
59
60
  // §D.2 — a second pass over the unchanged corpus is a no-op.
60
61
  const second = await driver.post('/v1/host/sample/memory/consolidate', {
@@ -64,14 +65,14 @@ describe('memory-consolidation-idempotent: pass contract (RFC 0068 §D, capabili
64
65
  const r2 = second.json as ConsolidateResult;
65
66
  expect(
66
67
  r2.event?.inputCount,
67
- driver.describe('RFC 0068 §D.2', 'a second pass over an unchanged corpus MUST be a no-op (inputCount == outputCount)'),
68
+ req('openwop.it.memory-consolidation-idempotent.a-consolidation-pass-reduces-or-holds-entry-count-and-is-idempotent-on-a-stable', 'RFC 0068 §D.2', 'a second pass over an unchanged corpus MUST be a no-op (inputCount == outputCount)'),
68
69
  ).toBe(r2.event?.outputCount);
69
70
 
70
71
  // §D.3 — SR-1 carry-forward: a redacted secret stays redacted in the consolidated entry.
71
72
  if (typeof r1.secretLeaked === 'boolean') {
72
73
  expect(
73
74
  r1.secretLeaked,
74
- driver.describe('RFC 0068 §D.3 / agent-memory.md §SR-1', 'a redacted secret MUST NOT re-appear in a consolidated entry'),
75
+ req('openwop.it.memory-consolidation-idempotent.a-consolidation-pass-reduces-or-holds-entry-count-and-is-idempotent-on-a-stable', 'RFC 0068 §D.3 / agent-memory.md §SR-1', 'a redacted secret MUST NOT re-appear in a consolidated entry'),
75
76
  ).toBe(false);
76
77
  }
77
78
  });
@@ -26,9 +26,7 @@ import { join } from 'node:path';
26
26
  import Ajv2020 from 'ajv/dist/2020.js';
27
27
  import addFormats from 'ajv-formats';
28
28
  import { SCHEMAS_DIR } from '../lib/paths.js';
29
-
30
- /** Server-free assertion-message helper (mirrors driver.describe's "spec — requirement" shape without requiring OPENWOP_BASE_URL). */
31
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
29
+ import { req } from '../lib/requirement-ids.js';
32
30
 
33
31
  function loadSchema(name: string): Record<string, unknown> {
34
32
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -40,11 +38,11 @@ describe('memory-consolidation-shape: capability advertisement (RFC 0068, server
40
38
  const agents = (caps.properties as Record<string, { properties?: Record<string, unknown> }>).agents;
41
39
  expect(
42
40
  agents?.properties?.memoryConsolidation,
43
- why('capabilities.md §agents', 'agents.memoryConsolidation MUST be declared'),
41
+ req('openwop.it.memory-consolidation-shape.the-capabilities-schema-declares-agents-memoryconsolidation-agents-commitments', 'capabilities.md §agents', 'agents.memoryConsolidation MUST be declared'),
44
42
  ).toBeDefined();
45
43
  expect(
46
44
  agents?.properties?.commitments,
47
- why('capabilities.md §agents', 'agents.commitments MUST be declared'),
45
+ req('openwop.it.memory-consolidation-shape.the-capabilities-schema-declares-agents-memoryconsolidation-agents-commitments', 'capabilities.md §agents', 'agents.commitments MUST be declared'),
48
46
  ).toBeDefined();
49
47
  });
50
48
  });
@@ -59,32 +57,32 @@ describe('memory-consolidation-shape: event payloads (RFC 0068, server-free)', (
59
57
  const fired = ajv.getSchema('payloads#/$defs/commitmentFired');
60
58
 
61
59
  it('agent.memory.consolidated validates a content-free pass summary', () => {
62
- expect(consolidated, 'the agentMemoryConsolidated $def MUST exist').toBeTruthy();
60
+ expect(consolidated, req('openwop.it.memory-consolidation-shape.agent-memory-consolidated-validates-a-content-free-pass-summary', 'RFC 0068', 'the agentMemoryConsolidated $def MUST exist')).toBeTruthy();
63
61
  expect(
64
62
  consolidated!({ memoryRef: 'mem://a/agent-1', inputCount: 240, outputCount: 201, trigger: 'host-managed' }),
65
- why('RFC 0068 §B', 'a conforming agent.memory.consolidated payload MUST validate'),
63
+ req('openwop.it.memory-consolidation-shape.agent-memory-consolidated-validates-a-content-free-pass-summary', 'RFC 0068 §B', 'a conforming agent.memory.consolidated payload MUST validate'),
66
64
  ).toBe(true);
67
65
  // Negative: outputCount as string fails the integer type.
68
66
  expect(consolidated!({ memoryRef: 'mem://a/agent-1', inputCount: 1, outputCount: 'x' })).toBe(false);
69
67
  });
70
68
 
71
69
  it('commitment.fired validates a content-free fire record and requires memoryRef', () => {
72
- expect(fired, 'the commitmentFired $def MUST exist').toBeTruthy();
70
+ expect(fired, req('openwop.it.memory-consolidation-shape.commitment-fired-validates-a-content-free-fire-record-and-requires-memoryref', 'RFC 0068', 'the commitmentFired $def MUST exist')).toBeTruthy();
73
71
  expect(
74
72
  fired!({ commitmentId: 'cmt-1', memoryRef: 'mem://a/agent-1', condition: 'predicate', enqueuedRunId: 'run-1' }),
75
- why('RFC 0068 §C', 'a conforming commitment.fired payload MUST validate'),
73
+ req('openwop.it.memory-consolidation-shape.commitment-fired-validates-a-content-free-fire-record-and-requires-memoryref', 'RFC 0068 §C', 'a conforming commitment.fired payload MUST validate'),
76
74
  ).toBe(true);
77
75
  // Negative: missing memoryRef — a commitment with no provenance breaks CTI-1 binding.
78
76
  expect(
79
77
  fired!({ commitmentId: 'cmt-1', condition: 'time' }),
80
- why('RFC 0068 §C', 'commitment.fired without memoryRef MUST be rejected'),
78
+ req('openwop.it.memory-consolidation-shape.commitment-fired-validates-a-content-free-fire-record-and-requires-memoryref', 'RFC 0068 §C', 'commitment.fired without memoryRef MUST be rejected'),
81
79
  ).toBe(false);
82
80
  });
83
81
 
84
82
  it('both event names appear in the RunEventType enum', () => {
85
83
  const runEvent = loadSchema('run-event.schema.json');
86
84
  const enumVals = (runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum ?? [];
87
- expect(enumVals).toContain('agent.memory.consolidated');
85
+ expect(enumVals, req('openwop.it.memory-consolidation-shape.both-event-names-appear-in-the-runeventtype-enum', 'RFC 0068', 'both event names appear in the RunEventType enum')).toContain('agent.memory.consolidated');
88
86
  expect(enumVals).toContain('commitment.fired');
89
87
  });
90
88
  });
@@ -29,10 +29,11 @@
29
29
  */
30
30
 
31
31
  import { describe, it, expect } from 'vitest';
32
- import { driver } from '../lib/driver.js';
33
32
  import { behaviorGate } from '../lib/behavior-gate.js';
34
33
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
35
34
  import { readManifestRuntimeCap, listManifestAgents } from '../lib/agentRuntime.js';
35
+ import { req } from '../lib/requirement-ids.js';
36
+ import { softSkip } from '../lib/soft-skip.js';
36
37
 
37
38
  /** The CLOSED RFC 0080 §A dimension vocabulary (agent-inventory-response.schema.json
38
39
  * `degradedMemoryDimensions` enum). NOT the `memoryShape` keys. */
@@ -62,13 +63,13 @@ describe('memory-degraded-projection (RFC 0080 §C)', () => {
62
63
  if (!behaviorGate('openwop-memory-degraded', advertised)) return;
63
64
 
64
65
  const inv = await listManifestAgents();
65
- if (inv === null) return; // host advertises the cap but doesn't serve /v1/agents — soft-skip
66
+ if (inv === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `inv === null` returned early (host advertises the cap but doesn\'t serve /v1/agents — soft-skip)'); // host advertises the cap but doesn't serve /v1/agents — soft-skip
66
67
  const agents = (inv.agents ?? []) as InventoryEntry[];
67
68
 
68
69
  // Non-vacuity: an advertising + serving host MUST expose its inventory.
69
70
  expect(
70
71
  agents.length >= 1,
71
- driver.describe('agent-memory.md §"Memory capability model"', 'GET /v1/agents MUST return the installed manifest agents'),
72
+ req('openwop.it.memory-degraded-projection.stamps-memorydegraded-a-closed-enum-degradedmemorydimensions-on-degraded-agents', 'agent-memory.md §"Memory capability model"', 'GET /v1/agents MUST return the installed manifest agents'),
72
73
  ).toBe(true);
73
74
 
74
75
  // §C iff-contract on EVERY entry.
@@ -79,25 +80,25 @@ describe('memory-degraded-projection (RFC 0080 §C)', () => {
79
80
  if (degraded) {
80
81
  expect(
81
82
  Array.isArray(dims) && dims.length >= 1,
82
- driver.describe('RFC 0080 §C', `memoryDegraded:true MUST carry a non-empty degradedMemoryDimensions (agent ${a.agentId})`),
83
+ req('openwop.it.memory-degraded-projection.stamps-memorydegraded-a-closed-enum-degradedmemorydimensions-on-degraded-agents', 'RFC 0080 §C', `memoryDegraded:true MUST carry a non-empty degradedMemoryDimensions (agent ${a.agentId})`),
83
84
  ).toBe(true);
84
85
  if (Array.isArray(dims)) {
85
86
  for (const d of dims) {
86
87
  expect(
87
88
  typeof d === 'string' && DIMENSIONS.includes(d),
88
- driver.describe('agent-inventory-response.schema.json', `degradedMemoryDimensions members MUST be RFC 0080 §A dimension names (got ${String(d)})`),
89
+ req('openwop.it.memory-degraded-projection.stamps-memorydegraded-a-closed-enum-degradedmemorydimensions-on-degraded-agents', 'agent-inventory-response.schema.json', `degradedMemoryDimensions members MUST be RFC 0080 §A dimension names (got ${String(d)})`),
89
90
  ).toBe(true);
90
91
  }
91
92
  expect(
92
93
  new Set(dims as string[]).size === dims.length,
93
- driver.describe('RFC 0080 §C', 'degradedMemoryDimensions MUST be unique'),
94
+ req('openwop.it.memory-degraded-projection.stamps-memorydegraded-a-closed-enum-degradedmemorydimensions-on-degraded-agents', 'RFC 0080 §C', 'degradedMemoryDimensions MUST be unique'),
94
95
  ).toBe(true);
95
96
  }
96
97
  } else {
97
98
  // Not degraded ⇒ no non-empty dimension list (absent or empty both pass).
98
99
  expect(
99
100
  dims === undefined || (Array.isArray(dims) && dims.length === 0),
100
- driver.describe('RFC 0080 §C', `a non-degraded entry MUST NOT carry a non-empty degradedMemoryDimensions (agent ${a.agentId})`),
101
+ req('openwop.it.memory-degraded-projection.stamps-memorydegraded-a-closed-enum-degradedmemorydimensions-on-degraded-agents', 'RFC 0080 §C', `a non-degraded entry MUST NOT carry a non-empty degradedMemoryDimensions (agent ${a.agentId})`),
101
102
  ).toBe(true);
102
103
  }
103
104
  }
@@ -108,12 +109,12 @@ describe('memory-degraded-projection (RFC 0080 §C)', () => {
108
109
  const target = agents.find((a) => a.agentId === degradedId);
109
110
  expect(
110
111
  target !== undefined,
111
- driver.describe('RFC 0080 §C', `OPENWOP_DEGRADED_AGENT_ID=${degradedId} MUST appear in the inventory`),
112
+ req('openwop.it.memory-degraded-projection.stamps-memorydegraded-a-closed-enum-degradedmemorydimensions-on-degraded-agents', 'RFC 0080 §C', `OPENWOP_DEGRADED_AGENT_ID=${degradedId} MUST appear in the inventory`),
112
113
  ).toBe(true);
113
114
  if (target) {
114
115
  expect(
115
116
  target.memoryDegraded === true && Array.isArray(target.degradedMemoryDimensions) && target.degradedMemoryDimensions.length >= 1,
116
- driver.describe('RFC 0080 §C', 'the named degraded agent MUST project memoryDegraded:true + a non-empty degradedMemoryDimensions'),
117
+ req('openwop.it.memory-degraded-projection.stamps-memorydegraded-a-closed-enum-degradedmemorydimensions-on-degraded-agents', 'RFC 0080 §C', 'the named degraded agent MUST project memoryDegraded:true + a non-empty degradedMemoryDimensions'),
117
118
  ).toBe(true);
118
119
  }
119
120
  }
@@ -34,6 +34,7 @@ import { pollUntilTerminal } from '../lib/polling.js';
34
34
  import { behaviorGate } from '../lib/behavior-gate.js';
35
35
  import { isFixtureAdvertised } from '../lib/fixtures.js';
36
36
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
37
+ import { req } from '../lib/requirement-ids.js';
37
38
 
38
39
  const FIXTURE = 'conformance-agent-memory-injection-budget';
39
40
  const PROFILE = 'openwop-memory-injection-budget';
@@ -114,14 +115,14 @@ describe('memory-injection-budget (RFC 0113)', () => {
114
115
  if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', `host does not advertise the ${FIXTURE} conformance fixture`);
115
116
 
116
117
  const v = await driveFixtureVariables();
117
- expect(v, 'fixture MUST surface run variables').toBeDefined();
118
- if (v === undefined) return;
118
+ expect(v, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'fixture MUST surface run variables')).toBeDefined();
119
+ if (v === undefined) return softSkip('blocked', 'precondition not met — `v === undefined` returned early (seam, prior step, or fixture unavailable)');
119
120
 
120
121
  // ── tokenBudget bound (the new lever) ──────────────────────────────
121
122
  const tokenBudget = numberOf(v['tokenBudget']);
122
123
  const total = numberOf(v['budgetedTokenTotal']);
123
- expect(tokenBudget, 'fixture MUST echo the requested tokenBudget').toBeDefined();
124
- expect(total, 'fixture MUST surface the budgeted cumulative token total').toBeDefined();
124
+ expect(tokenBudget, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'fixture MUST echo the requested tokenBudget')).toBeDefined();
125
+ expect(total, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'fixture MUST surface the budgeted cumulative token total')).toBeDefined();
125
126
  // Cumulative tokens across the returned prefix MUST NOT exceed the budget.
126
127
  if (tokenBudget !== undefined && total !== undefined) {
127
128
  expect(total).toBeLessThanOrEqual(tokenBudget);
@@ -130,21 +131,21 @@ describe('memory-injection-budget (RFC 0113)', () => {
130
131
  // ── over-budget single entry omitted (not truncated) ───────────────
131
132
  expect(
132
133
  booleanOf(v['overBudgetEntryOmitted']),
133
- 'an entry larger than the whole budget MUST be omitted, not truncated mid-entry',
134
+ req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'an entry larger than the whole budget MUST be omitted, not truncated mid-entry'),
134
135
  ).toBe(true);
135
136
  const entries = recordArrayOf(v['budgetedEntries']);
136
- expect(entries, 'fixture MUST surface the budgeted entry slice').toBeDefined();
137
+ expect(entries, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'fixture MUST surface the budgeted entry slice')).toBeDefined();
137
138
  const overId = stringOf(v['overBudgetEntryId']);
138
139
  if (entries !== undefined && overId !== undefined) {
139
140
  const ids = entries.map((e) => stringOf(e['id']));
140
- expect(ids, 'the over-budget entry MUST NOT appear in the returned slice').not.toContain(overId);
141
+ expect(ids, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'the over-budget entry MUST NOT appear in the returned slice')).not.toContain(overId);
141
142
  }
142
143
 
143
144
  // ── SR-1 re-assertion on the budgeted path ─────────────────────────
144
145
  // A budgeted/ranked read ranks over already-redacted content; the read
145
146
  // surface MUST carry the redaction marker, never the plaintext.
146
147
  const redacted = stringOf(v['redactedContentSample']);
147
- expect(redacted, 'budgeted read MUST surface a redacted-content sample').toBeDefined();
148
+ expect(redacted, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'budgeted read MUST surface a redacted-content sample')).toBeDefined();
148
149
  if (redacted !== undefined) {
149
150
  expect(redacted).toMatch(/\[REDACTED:[^\]]+\]/);
150
151
  }
@@ -154,9 +155,9 @@ describe('memory-injection-budget (RFC 0113)', () => {
154
155
  // the cross-tenant probe under the budgeted path MUST return empty.
155
156
  const probe = v['crossTenantBudgetedProbe'];
156
157
  if (Array.isArray(probe)) {
157
- expect(probe.length, 'cross-tenant probe on the budgeted path MUST return []').toBe(0);
158
+ expect(probe.length, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'cross-tenant probe on the budgeted path MUST return []')).toBe(0);
158
159
  } else {
159
- expect(probe, 'cross-tenant probe on the budgeted path MUST return [] / null').toBeFalsy();
160
+ expect(probe, req('openwop.it.memory-injection-budget.token-bounds-the-injection-read-omits-the-over-budget-entry-and-preserves-sr-1-c', 'RFC 0113', 'cross-tenant probe on the budgeted path MUST return [] / null')).toBeFalsy();
160
161
  }
161
162
  });
162
163
 
@@ -175,13 +176,13 @@ describe('memory-injection-budget (RFC 0113)', () => {
175
176
  if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', `host does not advertise the ${FIXTURE} conformance fixture`);
176
177
 
177
178
  const v = await driveFixtureVariables();
178
- expect(v, 'fixture MUST surface run variables').toBeDefined();
179
- if (v === undefined) return;
179
+ expect(v, req('openwop.it.memory-injection-budget.rank-relevance-reorders-vs-recency-only-when-memory-search-semantic-is-also-adve', 'RFC 0113', 'fixture MUST surface run variables')).toBeDefined();
180
+ if (v === undefined) return softSkip('blocked', 'precondition not met — `v === undefined` returned early (seam, prior step, or fixture unavailable)');
180
181
 
181
182
  const recencyOrder = stringArrayOf(v['recencyOrder']);
182
183
  const relevanceOrder = stringArrayOf(v['relevanceOrder']);
183
- expect(recencyOrder, 'fixture MUST surface the recency ordering').toBeDefined();
184
- expect(relevanceOrder, 'fixture MUST surface the relevance ordering').toBeDefined();
184
+ expect(recencyOrder, req('openwop.it.memory-injection-budget.rank-relevance-reorders-vs-recency-only-when-memory-search-semantic-is-also-adve', 'RFC 0113', 'fixture MUST surface the recency ordering')).toBeDefined();
185
+ expect(relevanceOrder, req('openwop.it.memory-injection-budget.rank-relevance-reorders-vs-recency-only-when-memory-search-semantic-is-also-adve', 'RFC 0113', 'fixture MUST surface the relevance ordering')).toBeDefined();
185
186
  // The crafted fixture pins a query whose semantic top-k differs from the
186
187
  // most-recent-first order — relevance MUST reorder (not echo recency).
187
188
  expect(relevanceOrder).not.toEqual(recencyOrder);
@@ -25,6 +25,7 @@ import { discoveryFamilies } from '../lib/discovery-capabilities.js';
25
25
  import { pollUntilTerminal } from '../lib/polling.js';
26
26
  import { isFixtureAdvertised } from '../lib/fixtures.js';
27
27
  import { getCollector } from '../lib/otel-collector.js';
28
+ import { req } from '../lib/requirement-ids.js';
28
29
 
29
30
  /**
30
31
  * Callback-shaped: the host exports OTLP metrics to the suite's collector.
@@ -96,19 +97,19 @@ describe('metric-emission: canonical openwop.* metrics arrive at the collector',
96
97
 
97
98
  // Wait for the host's metric-emit tick to land at the collector.
98
99
  const sawBacklog = await waitForMetric('openwop.run.backlog', 5_000);
99
- expect(sawBacklog, driver.describe(
100
+ expect(sawBacklog, req('openwop.it.metric-emission.host-emits-openwop-run-backlog-openwop-queue-depth-and-openwop-run-duration',
100
101
  'observability.md §"Metrics"',
101
102
  'host claiming metrics MUST emit openwop.run.backlog',
102
103
  )).toBe(true);
103
104
 
104
105
  const sawQueueDepth = await waitForMetric('openwop.queue.depth', 5_000);
105
- expect(sawQueueDepth, driver.describe(
106
+ expect(sawQueueDepth, req('openwop.it.metric-emission.host-emits-openwop-run-backlog-openwop-queue-depth-and-openwop-run-duration',
106
107
  'observability.md §"Metrics"',
107
108
  'host claiming metrics MUST emit openwop.queue.depth',
108
109
  )).toBe(true);
109
110
 
110
111
  const sawDuration = await waitForMetric('openwop.run.duration', 5_000);
111
- expect(sawDuration, driver.describe(
112
+ expect(sawDuration, req('openwop.it.metric-emission.host-emits-openwop-run-backlog-openwop-queue-depth-and-openwop-run-duration',
112
113
  'observability.md §"Metrics"',
113
114
  'host claiming metrics MUST emit openwop.run.duration after a completed run',
114
115
  )).toBe(true);
@@ -39,24 +39,24 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: dispatch refusal (RFC
39
39
  supportedProviders: ['unknown-vendor'],
40
40
  nodeId: 'editor-node',
41
41
  });
42
- if (r.status === 404) return;
42
+ if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
43
43
  expect(
44
44
  r.body.outcome?.route,
45
- driver.describe(
45
+ req('openwop.it.model-capability-insufficient.unmet-no-fallbackmodel-declared-refuse-with-fallbackattempted-false',
46
46
  'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 4',
47
47
  'unmet capability + no fallbackModel declared → host MUST refuse',
48
48
  ),
49
49
  ).toBe('refuse');
50
50
  expect(
51
51
  r.body.outcome?.fallbackAttempted,
52
- driver.describe(
52
+ req('openwop.it.model-capability-insufficient.unmet-no-fallbackmodel-declared-refuse-with-fallbackattempted-false',
53
53
  'schemas/run-event-payloads.schema.json §modelCapabilityInsufficient',
54
54
  'fallbackAttempted MUST be false when no fallbackModel was declared on the NodeModule',
55
55
  ),
56
56
  ).toBe(false);
57
57
  expect(
58
58
  r.body.event?.type,
59
- driver.describe(
59
+ req('openwop.it.model-capability-insufficient.unmet-no-fallbackmodel-declared-refuse-with-fallbackattempted-false',
60
60
  'RFCS/0031-envelope-variants-and-model-capabilities.md §D',
61
61
  'refuse path MUST emit `model.capability.insufficient` BEFORE the node failure',
62
62
  ),
@@ -81,11 +81,11 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: dispatch refusal (RFC
81
81
  // authenticate per RFC 0031 §B step 3 final clause.
82
82
  supportedProviders: ['anthropic', 'unknown-vendor'],
83
83
  });
84
- if (r.status === 404) return;
84
+ if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
85
85
  expect(r.body.outcome?.route).toBe('refuse');
86
86
  expect(
87
87
  r.body.outcome?.fallbackAttempted,
88
- driver.describe(
88
+ req('openwop.it.model-capability-insufficient.unmet-fallback-declared-but-provider-not-in-supportedproviders-refuse-with-fallb',
89
89
  'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 3',
90
90
  'fallback provider NOT in capabilities.aiProviders.supported[] → host cannot authenticate → fallbackAttempted MUST be true (the attempt failed at credential resolution)',
91
91
  ),
@@ -104,11 +104,11 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: dispatch refusal (RFC
104
104
  substitutionSupported: false,
105
105
  supportedProviders: ['anthropic', 'unknown-vendor'],
106
106
  });
107
- if (r.status === 404) return;
107
+ if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
108
108
  expect(r.body.outcome?.route).toBe('refuse');
109
109
  expect(
110
110
  r.body.outcome?.fallbackAttempted,
111
- driver.describe(
111
+ req('openwop.it.model-capability-insufficient.unmet-substitutionsupported-false-host-posture-refuse-with-fallbackattempted-fal',
112
112
  'RFCS/0031-envelope-variants-and-model-capabilities.md §E',
113
113
  'capabilities.modelCapabilities.substitutionSupported: false → host MUST NOT attempt fallback even when NodeModule.fallbackModel is declared → fallbackAttempted MUST be false (no attempt was made)',
114
114
  ),
@@ -130,11 +130,11 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: dispatch refusal (RFC
130
130
  substitutionSupported: true,
131
131
  supportedProviders: ['unknown-vendor', 'unknown-vendor-2'],
132
132
  });
133
- if (r.status === 404) return;
133
+ if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
134
134
  expect(r.body.outcome?.route).toBe('refuse');
135
135
  expect(
136
136
  r.body.outcome?.fallbackAttempted,
137
- driver.describe(
137
+ req('openwop.it.model-capability-insufficient.recursive-fallback-not-permitted-fallback-that-itself-fails-capability-check-ref',
138
138
  'RFCS/0031-envelope-variants-and-model-capabilities.md §"Unresolved questions" #3',
139
139
  'recursive fallback NOT permitted — when the declared fallback model itself fails the capability check, host MUST refuse with fallbackAttempted: true (NOT chain to another fallback)',
140
140
  ),
@@ -152,12 +152,14 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: dispatch refusal (RFC
152
152
 
153
153
  import { pollUntilTerminal } from '../lib/polling.js';
154
154
  import { isFixtureAdvertised } from '../lib/fixtures.js';
155
+ import { req } from '../lib/requirement-ids.js';
156
+ import { softSkip } from '../lib/soft-skip.js';
155
157
 
156
158
  const E2E_FIXTURE = 'conformance-model-capability-insufficient';
157
159
 
158
160
  describe.skipIf(HTTP_SKIP)('model-capability-insufficient: end-to-end refusal through executor', () => {
159
161
  it('workflow with a node declaring requiredModelCapabilities the active provider does not satisfy fails with RunSnapshot.error.code = "capability_not_provided" AND emits model.capability.insufficient into the run event log BEFORE node.failed', async () => {
160
- if (!isFixtureAdvertised(E2E_FIXTURE)) return; // fixture not seeded — soft-skip
162
+ if (!isFixtureAdvertised(E2E_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(E2E_FIXTURE)` returned early (fixture not seeded — soft-skip)'); // fixture not seeded — soft-skip
161
163
 
162
164
  const create = await driver.post('/v1/runs', { workflowId: E2E_FIXTURE });
163
165
  expect(create.status).toBe(201);
@@ -167,7 +169,7 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: end-to-end refusal th
167
169
  expect(terminal.status).toBe('failed');
168
170
  expect(
169
171
  (terminal as { error?: { code?: string } }).error?.code,
170
- driver.describe(
172
+ req('openwop.it.model-capability-insufficient.workflow-with-a-node-declaring-requiredmodelcapabilities-the-active-provider-doe',
171
173
  'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 4',
172
174
  'unmet capability without viable fallback MUST fail with error.code = "capability_not_provided"',
173
175
  ),
@@ -178,11 +180,11 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: end-to-end refusal th
178
180
  const events = ((eventsRes.json as { events?: Array<{ type: string }> } | undefined)?.events ?? []);
179
181
  const insufficientIdx = events.findIndex((e) => e.type === 'model.capability.insufficient');
180
182
  const nodeFailedIdx = events.findIndex((e) => e.type === 'node.failed');
181
- expect(insufficientIdx, 'model.capability.insufficient MUST appear in the event log').toBeGreaterThanOrEqual(0);
182
- expect(nodeFailedIdx, 'node.failed MUST appear in the event log').toBeGreaterThanOrEqual(0);
183
+ expect(insufficientIdx, req('openwop.it.model-capability-insufficient.workflow-with-a-node-declaring-requiredmodelcapabilities-the-active-provider-doe', 'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 4', 'model.capability.insufficient MUST appear in the event log')).toBeGreaterThanOrEqual(0);
184
+ expect(nodeFailedIdx, req('openwop.it.model-capability-insufficient.workflow-with-a-node-declaring-requiredmodelcapabilities-the-active-provider-doe', 'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 4', 'node.failed MUST appear in the event log')).toBeGreaterThanOrEqual(0);
183
185
  expect(
184
186
  insufficientIdx < nodeFailedIdx,
185
- driver.describe(
187
+ req('openwop.it.model-capability-insufficient.workflow-with-a-node-declaring-requiredmodelcapabilities-the-active-provider-doe',
186
188
  'RFCS/0031-envelope-variants-and-model-capabilities.md §D',
187
189
  'model.capability.insufficient MUST be emitted BEFORE node.failed (cause precedes effect)',
188
190
  ),
@@ -190,7 +192,7 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: end-to-end refusal th
190
192
  });
191
193
 
192
194
  it('NO envelope emission occurs after the refusal (no node.completed, provider.usage, or envelope-reliability events)', async () => {
193
- if (!isFixtureAdvertised(E2E_FIXTURE)) return; // fixture not seeded — soft-skip
195
+ if (!isFixtureAdvertised(E2E_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(E2E_FIXTURE)` returned early (fixture not seeded — soft-skip)'); // fixture not seeded — soft-skip
194
196
 
195
197
  const create = await driver.post('/v1/runs', { workflowId: E2E_FIXTURE });
196
198
  expect(create.status).toBe(201);
@@ -212,7 +214,7 @@ describe.skipIf(HTTP_SKIP)('model-capability-insufficient: end-to-end refusal th
212
214
  const leaked = events.filter((e) => forbidden.includes(e.type)).map((e) => e.type);
213
215
  expect(
214
216
  leaked,
215
- driver.describe(
217
+ req('openwop.it.model-capability-insufficient.no-envelope-emission-occurs-after-the-refusal-no-node-completed-provider-usage-o',
216
218
  'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 4',
217
219
  'a refused dispatch MUST NOT emit any downstream envelope-emission events — the node never ran',
218
220
  ),
@@ -18,6 +18,8 @@
18
18
  import { describe, it, expect } from 'vitest';
19
19
  import { driver } from '../lib/driver.js';
20
20
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
21
+ import { req } from '../lib/requirement-ids.js';
22
+ import { softSkip } from '../lib/soft-skip.js';
21
23
 
22
24
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
23
25
 
@@ -64,12 +66,12 @@ async function evaluateGate(input: Record<string, unknown>): Promise<{ status: n
64
66
  describe.skipIf(HTTP_SKIP)('model-capability-substituted: advertisement shape (RFC 0031 §E)', () => {
65
67
  it('capabilities.modelCapabilities (when present) conforms to RFC 0031 §E', async () => {
66
68
  const d = await readDiscovery();
67
- if (d === null) return;
69
+ if (d === null) return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
68
70
  const mc = capabilityFamily(d, 'modelCapabilities');
69
- if (mc === undefined) return;
71
+ if (mc === undefined) return softSkip('blocked', 'precondition not met — `mc === undefined` returned early (seam, prior step, or fixture unavailable)');
70
72
  expect(
71
73
  typeof mc.supported,
72
- driver.describe(
74
+ req('openwop.it.model-capability-substituted.capabilities-modelcapabilities-when-present-conforms-to-rfc-0031-e',
73
75
  'schemas/capabilities.schema.json §modelCapabilities',
74
76
  'capabilities.modelCapabilities.supported MUST be boolean when the block is advertised',
75
77
  ),
@@ -77,7 +79,7 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: advertisement shape (R
77
79
  if (mc.advertised !== undefined) {
78
80
  expect(
79
81
  Array.isArray(mc.advertised),
80
- driver.describe('RFCS/0031-envelope-variants-and-model-capabilities.md §E', 'modelCapabilities.advertised MUST be an array of capability identifiers'),
82
+ req('openwop.it.model-capability-substituted.capabilities-modelcapabilities-when-present-conforms-to-rfc-0031-e', 'RFCS/0031-envelope-variants-and-model-capabilities.md §E', 'modelCapabilities.advertised MUST be an array of capability identifiers'),
81
83
  ).toBe(true);
82
84
  // RFC 0031 §C's five, PLUS the four modality identifiers RFC 0055 §A
83
85
  // promoted into the formal vocabulary (Accepted 2026-05-26; registered in
@@ -89,13 +91,13 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: advertisement shape (R
89
91
  'vision-input', 'audio-input', 'audio-output', 'image-output',
90
92
  ];
91
93
  for (const id of mc.advertised as unknown[]) {
92
- expect(typeof id, 'each advertised identifier MUST be a string').toBe('string');
94
+ expect(typeof id, req('openwop.it.model-capability-substituted.capabilities-modelcapabilities-when-present-conforms-to-rfc-0031-e', 'RFCS/0031-envelope-variants-and-model-capabilities.md §E', 'each advertised identifier MUST be a string')).toBe('string');
93
95
  const idStr = String(id);
94
96
  const isReserved = SPEC_RESERVED.includes(idStr);
95
97
  const isHostExt = /^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$/.test(idStr);
96
98
  expect(
97
99
  isReserved || isHostExt,
98
- driver.describe(
100
+ req('openwop.it.model-capability-substituted.capabilities-modelcapabilities-when-present-conforms-to-rfc-0031-e',
99
101
  'RFCS/0031-envelope-variants-and-model-capabilities.md §C',
100
102
  `advertised identifier "${idStr}" MUST be spec-reserved (RFC 0031: structured-output, discriminator-enum, long-context, reasoning, function-calling; RFC 0055: vision-input, audio-input, audio-output, image-output) or match the x-host-<host>-<key> extension pattern`,
101
103
  ),
@@ -103,7 +105,7 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: advertisement shape (R
103
105
  }
104
106
  }
105
107
  if (mc.substitutionSupported !== undefined) {
106
- expect(typeof mc.substitutionSupported, 'substitutionSupported MUST be boolean').toBe('boolean');
108
+ expect(typeof mc.substitutionSupported, req('openwop.it.model-capability-substituted.capabilities-modelcapabilities-when-present-conforms-to-rfc-0031-e', 'RFCS/0031-envelope-variants-and-model-capabilities.md §C', 'substitutionSupported MUST be boolean')).toBe('boolean');
107
109
  }
108
110
  });
109
111
  });
@@ -117,15 +119,15 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: dispatch behavior (RFC
117
119
  substitutionSupported: true,
118
120
  supportedProviders: ['anthropic', 'openai'],
119
121
  });
120
- if (r.status === 404) return; // host doesn't expose the seam
122
+ if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (host doesn\'t expose the seam) (seam, prior step, or fixture unavailable)'); // host doesn't expose the seam
121
123
  expect(
122
124
  r.body.outcome?.route,
123
- driver.describe(
125
+ req('openwop.it.model-capability-substituted.all-required-capabilities-met-outcome-dispatch-no-event-emitted',
124
126
  'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 2',
125
127
  'all required model capabilities met → route MUST be "dispatch" (gate is a no-op)',
126
128
  ),
127
129
  ).toBe('dispatch');
128
- expect(r.body.event, 'no event emitted when gate is a no-op').toBeNull();
130
+ expect(r.body.event, req('openwop.it.model-capability-substituted.all-required-capabilities-met-outcome-dispatch-no-event-emitted', 'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 2', 'no event emitted when gate is a no-op')).toBeNull();
129
131
  });
130
132
 
131
133
  it('unmet + fallback declared + authenticatable → outcome: substitute + event with originalProvider/originalModel/fallbackProvider/fallbackModel/missingCapabilities', async () => {
@@ -148,23 +150,23 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: dispatch behavior (RFC
148
150
  supportedProviders: ['anthropic', 'openai', 'unknown-vendor'],
149
151
  nodeId: 'writer-node',
150
152
  });
151
- if (r.status === 404) return;
153
+ if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
152
154
  expect(
153
155
  r.body.outcome?.route,
154
- driver.describe(
156
+ req('openwop.it.model-capability-substituted.unmet-fallback-declared-authenticatable-outcome-substitute-event-with-originalpr',
155
157
  'RFCS/0031-envelope-variants-and-model-capabilities.md §B step 3',
156
158
  'unmet capability + declared fallback + fallback provider authenticatable → route MUST be "substitute"',
157
159
  ),
158
160
  ).toBe('substitute');
159
161
  expect(
160
162
  r.body.event?.type,
161
- driver.describe(
163
+ req('openwop.it.model-capability-substituted.unmet-fallback-declared-authenticatable-outcome-substitute-event-with-originalpr',
162
164
  'RFCS/0031-envelope-variants-and-model-capabilities.md §D',
163
165
  'substitute path MUST emit `model.capability.substituted`',
164
166
  ),
165
167
  ).toBe('model.capability.substituted');
166
168
  const payload = (r.body.event?.payload ?? {}) as Record<string, unknown>;
167
- expect(payload.nodeId, 'payload.nodeId MUST mirror the request').toBe('writer-node');
169
+ expect(payload.nodeId, req('openwop.it.model-capability-substituted.unmet-fallback-declared-authenticatable-outcome-substitute-event-with-originalpr', 'RFCS/0031-envelope-variants-and-model-capabilities.md §D', 'payload.nodeId MUST mirror the request')).toBe('writer-node');
168
170
  expect(payload.originalProvider).toBe('unknown-vendor');
169
171
  expect(payload.originalModel).toBe('unknown-model');
170
172
  expect(payload.fallbackProvider).toBe('anthropic');
@@ -172,7 +174,7 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: dispatch behavior (RFC
172
174
  expect(
173
175
  Array.isArray(payload.missingCapabilities) &&
174
176
  (payload.missingCapabilities as string[]).includes('structured-output'),
175
- driver.describe(
177
+ req('openwop.it.model-capability-substituted.unmet-fallback-declared-authenticatable-outcome-substitute-event-with-originalpr',
176
178
  'schemas/run-event-payloads.schema.json §modelCapabilitySubstituted',
177
179
  'missingCapabilities[] MUST include the subset of required capabilities the active model did not satisfy',
178
180
  ),
@@ -192,10 +194,10 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: dispatch behavior (RFC
192
194
  substitutionSupported: false,
193
195
  supportedProviders: ['anthropic', 'unknown-vendor'],
194
196
  });
195
- if (r.status === 404) return;
197
+ if (r.status === 404) return softSkip('blocked', 'precondition not met — `r.status === 404` returned early (seam, prior step, or fixture unavailable)');
196
198
  expect(
197
199
  r.body.outcome?.route,
198
- driver.describe(
200
+ req('openwop.it.model-capability-substituted.unmet-substitutionsupported-false-outcome-refuse-with-fallbackattempted-false-ho',
199
201
  'RFCS/0031-envelope-variants-and-model-capabilities.md §E',
200
202
  'capabilities.modelCapabilities.substitutionSupported: false → host MUST refuse on any unmet capability even when NodeModule.fallbackModel is declared',
201
203
  ),
@@ -203,7 +205,7 @@ describe.skipIf(HTTP_SKIP)('model-capability-substituted: dispatch behavior (RFC
203
205
  expect(r.body.event?.type).toBe('model.capability.insufficient');
204
206
  expect(
205
207
  (r.body.event?.payload as { fallbackAttempted?: boolean }).fallbackAttempted,
206
- driver.describe(
208
+ req('openwop.it.model-capability-substituted.unmet-substitutionsupported-false-outcome-refuse-with-fallbackattempted-false-ho',
207
209
  'schemas/run-event-payloads.schema.json §modelCapabilityInsufficient',
208
210
  'fallbackAttempted MUST be false when the refusal is driven by substitutionSupported: false (host posture, not fallback failure)',
209
211
  ),