@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
@@ -20,6 +20,7 @@
20
20
  import { describe, it, expect } from 'vitest';
21
21
  import { softSkip } from '../lib/soft-skip.js';
22
22
  import { driver } from '../lib/driver.js';
23
+ import { req } from '../lib/requirement-ids.js';
23
24
 
24
25
  interface CommitmentCaps {
25
26
  agents?: { commitments?: { supported?: boolean } };
@@ -54,14 +55,14 @@ describe('commitment-fired: fire contract (RFC 0068 §C, capability-gated)', ()
54
55
  });
55
56
  if (res.status === 404 || res.status === 501) return softSkip('blocked', 'seam not wired — soft-skip');
56
57
 
57
- expect(res.status, driver.describe('RFC 0068 §C', 'an advertised commitment seam MUST succeed')).toBe(200);
58
+ expect(res.status, req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C', 'an advertised commitment seam MUST succeed')).toBe(200);
58
59
  const r = res.json as FireResult;
59
60
 
60
61
  // §C — required identifiers.
61
- expect(r.event?.commitmentId, driver.describe('RFC 0068 §C', 'commitment.fired MUST carry commitmentId')).toBeTruthy();
62
+ expect(r.event?.commitmentId, req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C', 'commitment.fired MUST carry commitmentId')).toBeTruthy();
62
63
  expect(
63
64
  r.event?.memoryRef,
64
- driver.describe('RFC 0068 §C.1', 'commitment.fired MUST carry the source memoryRef (CTI-1 provenance)'),
65
+ req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C.1', 'commitment.fired MUST carry the source memoryRef (CTI-1 provenance)'),
65
66
  ).toBeTruthy();
66
67
 
67
68
  // §C.3 — content-free: the inferred intention text MUST NOT appear on the event.
@@ -69,7 +70,7 @@ describe('commitment-fired: fire contract (RFC 0068 §C, capability-gated)', ()
69
70
  const serialized = JSON.stringify(r.event ?? {});
70
71
  expect(
71
72
  serialized.includes(r.intentionCanary),
72
- driver.describe('RFC 0068 §C.3', 'the inferred intention text MUST NOT appear on the commitment.fired payload'),
73
+ req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C.3', 'the inferred intention text MUST NOT appear on the commitment.fired payload'),
73
74
  ).toBe(false);
74
75
  }
75
76
 
@@ -77,7 +78,7 @@ describe('commitment-fired: fire contract (RFC 0068 §C, capability-gated)', ()
77
78
  if (typeof r.fireCount === 'number') {
78
79
  expect(
79
80
  r.fireCount,
80
- driver.describe('RFC 0068 §C.2', 'a commitment MUST fire at most once per satisfied condition'),
81
+ req('openwop.it.commitment-fired.a-fired-commitment-emits-a-content-free-event-with-memory-provenance-exactly-onc', 'RFC 0068 §C.2', 'a commitment MUST fire at most once per satisfied condition'),
81
82
  ).toBeLessThanOrEqual(1);
82
83
  }
83
84
  });
@@ -44,6 +44,7 @@ import { softSkip } from '../lib/soft-skip.js';
44
44
  import { driver } from '../lib/driver.js';
45
45
  import { behaviorGate } from '../lib/behavior-gate.js';
46
46
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
47
+ import { req } from '../lib/requirement-ids.js';
47
48
 
48
49
  const PROFILE = 'openwop-compensation';
49
50
 
@@ -76,7 +77,7 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
76
77
  const caps = capabilityFamily<CompensationCaps>(disco.json, 'compensation');
77
78
  expect(
78
79
  caps?.orderingModels ?? [],
79
- driver.describe(
80
+ req('openwop.it.compensation-behavior.a-host-advertising-compensation-implements-reverse-completion',
80
81
  'RFCS/0151-compensation-and-partial-failure-profile.md §A',
81
82
  'an advertising host MUST implement `reverse-completion`; `dependency-graph` is optional',
82
83
  ),
@@ -93,23 +94,23 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
93
94
  if (seam.status === 404) {
94
95
  expect(
95
96
  seam.status,
96
- driver.describe(
97
+ req('openwop.it.compensation-behavior.the-plan-is-persisted-before-the-first-inverse-action',
97
98
  'RFCS/0151 §C',
98
99
  'a host advertising `compensation` MUST expose the unwind sample seam so plan-before-effect ' +
99
100
  'ordering can be witnessed; without it the requirement is unobservable and the profile ' +
100
101
  'cannot be certified (RFC 0148 §A: unobservable resolves to `blocked`, not to a pass)',
101
102
  ),
102
103
  ).not.toBe(404);
103
- return;
104
+ return softSkip('blocked', 'precondition not met — `seam.status === 404` returned early (seam, prior step, or fixture unavailable)');
104
105
  }
105
106
  const events = (seam.json as { events?: { type: string }[] }).events ?? [];
106
107
  const requestedAt = events.findIndex((e) => e.type === 'compensation.requested');
107
108
  const startedAt = events.findIndex((e) => e.type === 'compensation.started');
108
- expect(requestedAt, driver.describe('RFCS/0151 §D', '`compensation.requested` MUST be emitted')).toBeGreaterThanOrEqual(0);
109
- expect(startedAt, driver.describe('RFCS/0151 §D', '`compensation.started` MUST be emitted')).toBeGreaterThanOrEqual(0);
109
+ expect(requestedAt, req('openwop.it.compensation-behavior.the-plan-is-persisted-before-the-first-inverse-action', 'RFCS/0151 §D', '`compensation.requested` MUST be emitted')).toBeGreaterThanOrEqual(0);
110
+ expect(startedAt, req('openwop.it.compensation-behavior.the-plan-is-persisted-before-the-first-inverse-action', 'RFCS/0151 §D', '`compensation.started` MUST be emitted')).toBeGreaterThanOrEqual(0);
110
111
  expect(
111
112
  requestedAt,
112
- driver.describe(
113
+ req('openwop.it.compensation-behavior.the-plan-is-persisted-before-the-first-inverse-action',
113
114
  'RFCS/0151 §C',
114
115
  'the plan MUST be persisted BEFORE the first inverse action executes',
115
116
  ),
@@ -119,12 +120,12 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
119
120
  it('inverse actions run in descending forward-completion order', async () => {
120
121
  if (!behaviorGate(PROFILE, await advertised())) return;
121
122
  const seam = await driver.post('/v1/host/sample/test/compensation/unwind', { nodes: 3 });
122
- if (seam.status === 404) return; // covered by the seam assertion above
123
+ if (seam.status === 404) return softSkip('blocked', 'precondition not met — `seam.status === 404` returned early (covered by the seam assertion above) (seam, prior step, or fixture unavailable)'); // covered by the seam assertion above
123
124
  const order = (seam.json as { compensatedOrder?: number[] }).compensatedOrder ?? [];
124
125
  const descending = [...order].sort((a, b) => b - a);
125
126
  expect(
126
127
  order,
127
- driver.describe(
128
+ req('openwop.it.compensation-behavior.inverse-actions-run-in-descending-forward-completion-order',
128
129
  'RFCS/0151 §C',
129
130
  '`reverse-completion` orders compensations by DESCENDING durable forward-completion ' +
130
131
  'sequence. Compensating forward can release a resource a later inverse action still needs.',
@@ -135,10 +136,10 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
135
136
  it('replay does not re-fire inverse effects', async () => {
136
137
  if (!behaviorGate(PROFILE, await advertised())) return;
137
138
  const seam = await driver.post('/v1/host/sample/test/compensation/replay', {});
138
- if (seam.status === 404) return;
139
+ if (seam.status === 404) return softSkip('blocked', 'precondition not met — `seam.status === 404` returned early (seam, prior step, or fixture unavailable)');
139
140
  expect(
140
141
  (seam.json as { refiredEffects?: number }).refiredEffects ?? 0,
141
- driver.describe(
142
+ req('openwop.it.compensation-behavior.replay-does-not-re-fire-inverse-effects',
142
143
  'RFCS/0151 §F',
143
144
  'replay defaults MUST use recorded compensation outcomes and MUST NOT re-fire inverse ' +
144
145
  'effects — a replay that re-executes them turns a recovery into a second outage',
@@ -149,22 +150,22 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
149
150
  it('the run snapshot carries the §D rollup, and it agrees with the events', async () => {
150
151
  if (!behaviorGate(PROFILE, await advertised())) return;
151
152
  const seam = await driver.post('/v1/host/sample/test/compensation/unwind', {});
152
- if (seam.status === 404) return; // covered by the seam assertion above
153
+ if (seam.status === 404) return softSkip('blocked', 'precondition not met — `seam.status === 404` returned early (covered by the seam assertion above) (seam, prior step, or fixture unavailable)'); // covered by the seam assertion above
153
154
  const body = seam.json as { runId?: string; events?: { type: string }[] };
154
155
  expect(
155
156
  typeof body.runId === 'string' && body.runId.length > 0,
156
- driver.describe(
157
+ req('openwop.it.compensation-behavior.the-run-snapshot-carries-the-d-rollup-and-it-agrees-with-the-events',
157
158
  'host-sample-test-seams.md §21',
158
159
  'the unwind seam MUST return the `runId` it created — without it the §D rollup has no ' +
159
160
  'black-box path to a witness and lands as another shape-only claim',
160
161
  ),
161
162
  ).toBe(true);
162
163
  const snap = await driver.get(`/v1/runs/${encodeURIComponent(body.runId ?? '')}`);
163
- expect(snap.status, driver.describe('rest-endpoints.md', 'GET /v1/runs/{runId} for the seam run')).toBe(200);
164
+ expect(snap.status, req('openwop.it.compensation-behavior.the-run-snapshot-carries-the-d-rollup-and-it-agrees-with-the-events', 'rest-endpoints.md', 'GET /v1/runs/{runId} for the seam run')).toBe(200);
164
165
  const status = (snap.json as { compensationStatus?: unknown }).compensationStatus;
165
166
  expect(
166
167
  status,
167
- driver.describe(
168
+ req('openwop.it.compensation-behavior.the-run-snapshot-carries-the-d-rollup-and-it-agrees-with-the-events',
168
169
  'compensation.md §"Run rollup: compensationStatus"',
169
170
  'a host that advertises `compensation` MUST include `compensationStatus` on every snapshot ' +
170
171
  '(`none` when idle) — presence is the wire witness of the advert',
@@ -187,17 +188,17 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
187
188
  if (expected === null) {
188
189
  expect(
189
190
  ['running', 'partial', 'failed'].includes(String(status)),
190
- driver.describe(
191
+ req('openwop.it.compensation-behavior.the-run-snapshot-carries-the-d-rollup-and-it-agrees-with-the-events',
191
192
  'compensation.md §"Run rollup: compensationStatus"',
192
193
  'an unwind that started and did not complete MUST report `running`, `partial`, or `failed` ' +
193
194
  `— got ${String(status)}`,
194
195
  ),
195
196
  ).toBe(true);
196
- return;
197
+ return softSkip('blocked', 'precondition not met — `expected === null` returned early (seam, prior step, or fixture unavailable)');
197
198
  }
198
199
  expect(
199
200
  status,
200
- driver.describe(
201
+ req('openwop.it.compensation-behavior.the-run-snapshot-carries-the-d-rollup-and-it-agrees-with-the-events',
201
202
  'compensation.md §"Run rollup: compensationStatus"',
202
203
  `the rollup MUST be the deterministic fold of the compensation.* events — events ${JSON.stringify(types)} fold to \`${expected}\``,
203
204
  ),
@@ -207,7 +208,7 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
207
208
  it('compensation events carry no provider bodies or credentials', async () => {
208
209
  if (!behaviorGate(PROFILE, await advertised())) return;
209
210
  const seam = await driver.post('/v1/host/sample/test/compensation/unwind', {});
210
- if (seam.status === 404) return;
211
+ if (seam.status === 404) return softSkip('blocked', 'precondition not met — `seam.status === 404` returned early (seam, prior step, or fixture unavailable)');
211
212
  const events = (seam.json as { events?: Record<string, unknown>[] }).events ?? [];
212
213
  for (const e of events) {
213
214
  if (!COMPENSATION_EVENTS.includes(e['type'] as (typeof COMPENSATION_EVENTS)[number])) continue;
@@ -215,7 +216,7 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
215
216
  for (const forbidden of ['-----BEGIN', 'Bearer ', 'sk-', 'authorization', 'providerResponse']) {
216
217
  expect(
217
218
  serialized.toLowerCase().includes(forbidden.toLowerCase()),
218
- driver.describe(
219
+ req('openwop.it.compensation-behavior.compensation-events-carry-no-provider-bodies-or-credentials',
219
220
  'RFCS/0151 §D + §G',
220
221
  'compensation event payloads carry opaque IDs and closed reason codes — never provider ' +
221
222
  'bodies or credentials. These land in the DURABLE log, which is the least revocable ' +
@@ -257,7 +258,7 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
257
258
  const body = seam.json as { runId?: string; events?: { type: string }[] };
258
259
  expect(
259
260
  typeof body.runId === 'string' && body.runId.length > 0,
260
- driver.describe('host-sample-test-seams.md §21', '`fail: false` MUST still return the runId it created'),
261
+ req('openwop.it.compensation-behavior.a-healthy-run-that-declares-a-compensator-reports-compensationstatus-none-sp-11a', 'host-sample-test-seams.md §21', '`fail: false` MUST still return the runId it created'),
261
262
  ).toBe(true);
262
263
 
263
264
  // Positive control: the seam really did run a healthy compensator-declaring
@@ -274,12 +275,12 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
274
275
  }
275
276
 
276
277
  const snap = await driver.get(`/v1/runs/${encodeURIComponent(body.runId ?? '')}`);
277
- expect(snap.status, driver.describe('rest-endpoints.md', 'GET /v1/runs/{runId} for the healthy seam run')).toBe(200);
278
+ expect(snap.status, req('openwop.it.compensation-behavior.a-healthy-run-that-declares-a-compensator-reports-compensationstatus-none-sp-11a', 'rest-endpoints.md', 'GET /v1/runs/{runId} for the healthy seam run')).toBe(200);
278
279
  const snapshot = snap.json as { status?: unknown; compensationStatus?: unknown };
279
280
 
280
281
  expect(
281
282
  snapshot.compensationStatus,
282
- driver.describe(
283
+ req('openwop.it.compensation-behavior.a-healthy-run-that-declares-a-compensator-reports-compensationstatus-none-sp-11a',
283
284
  'compensation.md §"Run rollup: compensationStatus"',
284
285
  'a host advertising `compensation` MUST carry the field on EVERY snapshot — presence is the wire witness of the advert',
285
286
  ),
@@ -287,7 +288,7 @@ describe('RFC 0151 §C — compensation lifecycle (capability-gated behavior)',
287
288
 
288
289
  expect(
289
290
  snapshot.compensationStatus,
290
- driver.describe(
291
+ req('openwop.it.compensation-behavior.a-healthy-run-that-declares-a-compensator-reports-compensationstatus-none-sp-11a',
291
292
  'compensation.md §"Run rollup: compensationStatus"',
292
293
  'a run that completed while declaring compensable nodes has nothing to unwind: no `compensation.requested` ' +
293
294
  'was recorded, so the fold is `none`. `pending` here means the rollup was derived from obligation ROWS ' +
@@ -55,6 +55,7 @@ import { behaviorGate } from '../lib/behavior-gate.js';
55
55
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
56
56
  import { seamAbsent, softSkip } from '../lib/soft-skip.js';
57
57
  import { readErrorCode, readRetriable } from '../lib/error-envelope.js';
58
+ import { req } from '../lib/requirement-ids.js';
58
59
 
59
60
  const PROFILE = 'openwop-compensation';
60
61
  const UNWIND = '/v1/host/sample/test/compensation/unwind';
@@ -112,29 +113,29 @@ describe('RFC 0151 §C — inverse-action identity is retry-stable (capability-g
112
113
  it('a transient inverse failure retries under the SAME identity and the same downstream key', async () => {
113
114
  if (!behaviorGate(PROFILE, await advertised())) return;
114
115
  const r = await post(UNWIND, { nodes: 2, failFirstInverseAttempts: 2 });
115
- if (r === null) return;
116
- expect(r.status, driver.describe('spec/v1/host-sample-test-seams.md §21', 'unwind seam answers 200')).toBe(200);
116
+ if (r === null) return softSkip('blocked', 'precondition not met — `r === null` returned early (seam, prior step, or fixture unavailable)');
117
+ expect(r.status, req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr', 'spec/v1/host-sample-test-seams.md §21', 'unwind seam answers 200')).toBe(200);
117
118
  const body = r.json as UnwindResponse;
118
119
  if (!Array.isArray(body.inverseActions)) return extensionAbsent('`unwind` did not return `inverseActions[]`');
119
120
  // Under reverse-completion the first inverse to run is the highest forward ordinal (2).
120
121
  const first = body.inverseActions.find((a) => a.ordinal === 2) ?? body.inverseActions[0];
121
- expect(first, driver.describe('spec/v1/host-sample-test-seams.md §21', 'one entry per plan entry')).toBeDefined();
122
+ expect(first, req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr', 'spec/v1/host-sample-test-seams.md §21', 'one entry per plan entry')).toBeDefined();
122
123
  const a = first as InverseAction;
123
- expect(a.attempts, driver.describe('RFCS/0151 §C', 'two transient failures then success is THREE attempts of one obligation')).toBe(3);
124
- expect(a.outcome, driver.describe('RFCS/0151 §C', 'a transient failure MUST be retryable — the action completes')).toBe('completed');
125
- expect(Array.isArray(a.downstreamKeys) ? a.downstreamKeys.length : -1, driver.describe('spec/v1/host-sample-test-seams.md §21', '`downstreamKeys` has one entry per attempt')).toBe(3);
124
+ expect(a.attempts, req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr', 'RFCS/0151 §C', 'two transient failures then success is THREE attempts of one obligation')).toBe(3);
125
+ expect(a.outcome, req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr', 'RFCS/0151 §C', 'a transient failure MUST be retryable — the action completes')).toBe('completed');
126
+ expect(Array.isArray(a.downstreamKeys) ? a.downstreamKeys.length : -1, req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr', 'spec/v1/host-sample-test-seams.md §21', '`downstreamKeys` has one entry per attempt')).toBe(3);
126
127
  const distinct = new Set(a.downstreamKeys ?? []);
127
128
  expect(
128
129
  distinct.size,
129
- driver.describe(
130
+ req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr',
130
131
  'RFCS/0151 §C + RFC 0150 §B',
131
132
  'a retry re-presents the SAME inverse-action identity as its idempotency key — a second key at the downstream is a second obligation (two refunds). `attempt` is outside the identity for exactly this reason.',
132
133
  ),
133
134
  ).toBe(1);
134
135
  // One obligation per ordinal: no duplicate plan entries.
135
136
  const ordinals = body.inverseActions.map((x) => x.ordinal);
136
- expect(new Set(ordinals).size, driver.describe('RFCS/0151 §C', 'exactly one plan entry per forward ordinal')).toBe(ordinals.length);
137
- expect(typeof a.effectId === 'string' && a.effectId.length > 0, driver.describe('RFCS/0151 §D', 'the identity is carried as an opaque `effectId`')).toBe(true);
137
+ expect(new Set(ordinals).size, req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr', 'RFCS/0151 §C', 'exactly one plan entry per forward ordinal')).toBe(ordinals.length);
138
+ expect(typeof a.effectId === 'string' && a.effectId.length > 0, req('openwop.it.compensation-recovery.a-transient-inverse-failure-retries-under-the-same-identity-and-the-same-downstr', 'RFCS/0151 §D', 'the identity is carried as an opaque `effectId`')).toBe(true);
138
139
  });
139
140
  });
140
141
 
@@ -142,7 +143,7 @@ describe('RFC 0151 §E — operator authority is bound to the plan\'s tenant (ca
142
143
  it('cross-tenant is neutralized (404), same-tenant non-operator is refused and audited (403), the operator acts (200)', async () => {
143
144
  if (!behaviorGate(PROFILE, await advertised())) return;
144
145
  const held = await post(UNWIND, { nodes: 2, hold: true });
145
- if (held === null) return;
146
+ if (held === null) return softSkip('blocked', 'precondition not met — `held === null` returned early (seam, prior step, or fixture unavailable)');
146
147
  const body = held.json as UnwindResponse;
147
148
  const runId = body.runId;
148
149
  if (typeof runId !== 'string') return extensionAbsent('`unwind` did not return a `runId`');
@@ -151,8 +152,8 @@ describe('RFC 0151 §E — operator authority is bound to the plan\'s tenant (ca
151
152
  if (heldEntry === undefined && !manual) return extensionAbsent('`unwind` with `hold: true` produced neither a held plan entry nor `compensation.manual_intervention_required`');
152
153
  // Snapshot must read `manual` while held (§D fold).
153
154
  const snap = await driver.get(`/v1/runs/${encodeURIComponent(runId)}`);
154
- expect(snap.status, driver.describe('rest-endpoints.md', 'GET /v1/runs/{runId} for the held run')).toBe(200);
155
- expect((snap.json as { compensationStatus?: string }).compensationStatus, driver.describe('spec/v1/compensation.md §D', 'a held plan reads `manual`')).toBe('manual');
155
+ expect(snap.status, req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'rest-endpoints.md', 'GET /v1/runs/{runId} for the held run')).toBe(200);
156
+ expect((snap.json as { compensationStatus?: string }).compensationStatus, req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'spec/v1/compensation.md §D', 'a held plan reads `manual`')).toBe('manual');
156
157
 
157
158
  const op = async (actor: Record<string, unknown>) =>
158
159
  driver.post(OPERATOR, { runId, action: 'retry', actor });
@@ -161,28 +162,28 @@ describe('RFC 0151 §E — operator authority is bound to the plan\'s tenant (ca
161
162
  if (cross.status === 404 && readErrorCode(cross.json) === undefined && (cross.json === null || cross.json === undefined || Object.keys(cross.json as object).length === 0)) {
162
163
  return extensionAbsent(`${OPERATOR} answered a bodiless 404 — the operator seam is absent (an absent seam and a neutralized cross-tenant plan must be told apart by the envelope: RFC 0132 §A.2 answers \`not_found\` in the canonical envelope)`);
163
164
  }
164
- expect(cross.status, driver.describe('RFCS/0151 §E + RFC 0132 §A.2', 'an actor from another tenant MUST NOT learn the plan exists — 404, not 403')).toBe(404);
165
- expect(readErrorCode(cross.json), driver.describe('rest-endpoints.md §Error codes', '`not_found` — do not leak existence')).toBe('not_found');
165
+ expect(cross.status, req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'RFCS/0151 §E + RFC 0132 §A.2', 'an actor from another tenant MUST NOT learn the plan exists — 404, not 403')).toBe(404);
166
+ expect(readErrorCode(cross.json), req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'rest-endpoints.md §Error codes', '`not_found` — do not leak existence')).toBe('not_found');
166
167
  // 2. Same tenant, no operator authority: refused AND audited.
167
168
  const plain = await op({ tenantId: 'default', principalId: 'conformance-bystander', operator: false });
168
- expect(plain.status, driver.describe('RFCS/0151 §E', 'a principal without operator authority in the plan\'s tenant is refused')).toBe(403);
169
- expect(readErrorCode(plain.json), driver.describe('rest-endpoints.md §Error codes', '`forbidden`')).toBe('forbidden');
170
- expect(readRetriable(plain.json), driver.describe('spec/v1/host-sample-test-seams.md §21', 'a refused override is not retriable')).toBe(false);
169
+ expect(plain.status, req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'RFCS/0151 §E', 'a principal without operator authority in the plan\'s tenant is refused')).toBe(403);
170
+ expect(readErrorCode(plain.json), req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'rest-endpoints.md §Error codes', '`forbidden`')).toBe('forbidden');
171
+ expect(readRetriable(plain.json), req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'spec/v1/host-sample-test-seams.md §21', 'a refused override is not retriable')).toBe(false);
171
172
  // 3. The operator: acts, audited, rollup moves off `manual`.
172
173
  const ok = await op({ tenantId: 'default', principalId: 'conformance-operator', operator: true });
173
- expect(ok.status, driver.describe('RFCS/0151 §E', 'an authorized operator MAY retry a held inverse action')).toBe(200);
174
+ expect(ok.status, req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'RFCS/0151 §E', 'an authorized operator MAY retry a held inverse action')).toBe(200);
174
175
  const res = ok.json as { compensationStatus?: string; audited?: boolean; planVersion?: unknown };
175
- expect(res.audited, driver.describe('RFCS/0151 §E', 'every override MUST be audited (`authorization.decided`)')).toBe(true);
176
+ expect(res.audited, req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'RFCS/0151 §E', 'every override MUST be audited (`authorization.decided`)')).toBe(true);
176
177
  expect(
177
178
  ['completed', 'partial', 'failed', 'running'],
178
- driver.describe('spec/v1/compensation.md §D', 'after the operator retries, the rollup is whatever the recorded outcomes yield — never still `manual` for a resolved hold'),
179
+ req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'spec/v1/compensation.md §D', 'after the operator retries, the rollup is whatever the recorded outcomes yield — never still `manual` for a resolved hold'),
179
180
  ).toContain(res.compensationStatus);
180
181
  // The refusal in step 2 was audited too: the plan's events carry a reason.
181
182
  const after = await driver.get(`/v1/runs/${encodeURIComponent(runId)}/events`);
182
183
  if (after.status === 200) {
183
184
  const evs = (after.json as { events?: Array<{ type?: string; payload?: Record<string, unknown> }> }).events ?? [];
184
185
  const decided = evs.filter((e) => e.type === 'authorization.decided');
185
- expect(decided.length, driver.describe('RFCS/0151 §E + RFC 0049', 'both the refusal and the override are `authorization.decided` records')).toBeGreaterThanOrEqual(2);
186
+ expect(decided.length, req('openwop.it.compensation-recovery.cross-tenant-is-neutralized-404-same-tenant-non-operator-is-refused-and-audited', 'RFCS/0151 §E + RFC 0049', 'both the refusal and the override are `authorization.decided` records')).toBeGreaterThanOrEqual(2);
186
187
  }
187
188
  });
188
189
  });
@@ -191,23 +192,23 @@ describe('RFC 0151 §B/§F — inverse inputs are recorded facts, not re-derived
191
192
  it('a replay executes the same inverse actions with the same inputs, and re-fires nothing', async () => {
192
193
  if (!behaviorGate(PROFILE, await advertised())) return;
193
194
  const r = await post(REPLAY, {});
194
- if (r === null) return;
195
- expect(r.status, driver.describe('spec/v1/host-sample-test-seams.md §21', 'replay seam answers 200')).toBe(200);
195
+ if (r === null) return softSkip('blocked', 'precondition not met — `r === null` returned early (seam, prior step, or fixture unavailable)');
196
+ expect(r.status, req('openwop.it.compensation-recovery.a-replay-executes-the-same-inverse-actions-with-the-same-inputs-and-re-fires-not', 'spec/v1/host-sample-test-seams.md §21', 'replay seam answers 200')).toBe(200);
196
197
  const body = r.json as ReplayResponse;
197
198
  if (!Array.isArray(body.source) || !Array.isArray(body.replayed)) return extensionAbsent('`replay` did not return `source[]` / `replayed[]`');
198
- expect(body.refiredEffects, driver.describe('RFCS/0151 §F', 'replay MUST NOT re-fire inverse effects')).toBe(0);
199
- expect(body.source.length, driver.describe('spec/v1/host-sample-test-seams.md §21', 'the source run had inverse actions to compare')).toBeGreaterThan(0);
199
+ expect(body.refiredEffects, req('openwop.it.compensation-recovery.a-replay-executes-the-same-inverse-actions-with-the-same-inputs-and-re-fires-not', 'RFCS/0151 §F', 'replay MUST NOT re-fire inverse effects')).toBe(0);
200
+ expect(body.source.length, req('openwop.it.compensation-recovery.a-replay-executes-the-same-inverse-actions-with-the-same-inputs-and-re-fires-not', 'spec/v1/host-sample-test-seams.md §21', 'the source run had inverse actions to compare')).toBeGreaterThan(0);
200
201
  const norm = (xs: readonly InverseAction[]) =>
201
202
  [...xs].sort((a, b) => (a.ordinal ?? 0) - (b.ordinal ?? 0)).map((x) => ({ ordinal: x.ordinal, effectId: x.effectId, input: x.input }));
202
203
  expect(
203
204
  norm(body.replayed),
204
- driver.describe(
205
+ req('openwop.it.compensation-recovery.a-replay-executes-the-same-inverse-actions-with-the-same-inputs-and-re-fires-not',
205
206
  'RFCS/0151 §B + §F',
206
207
  'a replay uses the RECORDED inverse inputs and identities — an inverse built from a re-derived (prompt / model / live) value is not the inverse of what was actually done',
207
208
  ),
208
209
  ).toEqual(norm(body.source));
209
210
  for (const x of body.source) {
210
- expect(x.input, driver.describe('RFCS/0151 §B', 'each inverse action executed with a recorded input')).toBeDefined();
211
+ expect(x.input, req('openwop.it.compensation-recovery.a-replay-executes-the-same-inverse-actions-with-the-same-inputs-and-re-fires-not', 'RFCS/0151 §B', 'each inverse action executed with a recorded input')).toBeDefined();
211
212
  }
212
213
  });
213
214
  });
@@ -18,6 +18,8 @@
18
18
  import { describe, it, expect } from 'vitest';
19
19
  import { driver } from '../lib/driver.js';
20
20
  import { isFixtureAdvertised } from '../lib/fixtures.js';
21
+ import { req } from '../lib/requirement-ids.js';
22
+ import { softSkip } from '../lib/soft-skip.js';
21
23
 
22
24
  // Re-use `conformance-identity` if it advertises a configurableSchema;
23
25
  // otherwise the scenario soft-skips. Hosts adopting v1.1 SHOULD seed a
@@ -44,13 +46,13 @@ describe('configurable-schema: per-workflow schema enforced', () => {
44
46
  console.warn(
45
47
  '[configurable-schema] no advertised fixture declares configurableSchema; skipping',
46
48
  );
47
- return;
49
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!fixture` returned early ([configurable-schema] no advertised fixture declares configurableSchema; skipping)');
48
50
  }
49
51
 
50
52
  const manifest = await driver.get(`/v1/workflows/${encodeURIComponent(fixture)}`);
51
53
  const schema = (manifest.json as { configurableSchema?: Record<string, unknown> })
52
54
  .configurableSchema;
53
- expect(schema, driver.describe(
55
+ expect(schema, req('openwop.it.configurable-schema.manifest-surfaces-configurableschema-mismatched-configurable-is-rejected',
54
56
  'run-options.md §"Per-workflow configurableSchema"',
55
57
  'GET /v1/workflows/{workflowId} MUST surface configurableSchema when the workflow declares one',
56
58
  )).toBeDefined();
@@ -64,7 +66,7 @@ describe('configurable-schema: per-workflow schema enforced', () => {
64
66
  });
65
67
  expect(
66
68
  [400, 422].includes(create.status),
67
- driver.describe(
69
+ req('openwop.it.configurable-schema.manifest-surfaces-configurableschema-mismatched-configurable-is-rejected',
68
70
  'run-options.md §"Per-workflow configurableSchema"',
69
71
  'configurable that violates the workflow schema MUST be rejected with 400/422',
70
72
  ),
@@ -76,12 +78,12 @@ describe('configurable-schema: per-workflow schema enforced', () => {
76
78
 
77
79
  it('configurable overlay matching configurableSchema is accepted', async () => {
78
80
  const fixture = await pickFixture();
79
- if (!fixture) return; // covered by skip warning above
81
+ if (!fixture) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!fixture` returned early (covered by skip warning above)'); // covered by skip warning above
80
82
 
81
83
  const manifest = await driver.get(`/v1/workflows/${encodeURIComponent(fixture)}`);
82
84
  const schema = (manifest.json as { configurableSchema?: Record<string, unknown> })
83
85
  .configurableSchema;
84
- if (!schema) return;
86
+ if (!schema) return softSkip('blocked', 'precondition not met — `!schema` returned early (seam, prior step, or fixture unavailable)');
85
87
 
86
88
  // Build a minimal valid overlay derived from the schema's first
87
89
  // `properties.*` entry. This stays generic across fixtures: we pick
@@ -106,7 +108,7 @@ describe('configurable-schema: per-workflow schema enforced', () => {
106
108
  workflowId: fixture,
107
109
  configurable: overlay,
108
110
  });
109
- expect(create.status, driver.describe(
111
+ expect(create.status, req('openwop.it.configurable-schema.configurable-overlay-matching-configurableschema-is-accepted',
110
112
  'run-options.md §"Per-workflow configurableSchema"',
111
113
  'configurable matching the declared schema MUST be accepted (201)',
112
114
  )).toBe(201);
@@ -27,6 +27,7 @@ import { behaviorGate, behaviorGatePresent } from '../lib/behavior-gate.js';
27
27
  import { seamAbsent, softSkipDisposition, resetSoftSkips } from '../lib/soft-skip.js';
28
28
  import { dispositionOf, resetLedger, suspendSinkForFixtures } from '../lib/requirement-ledger.js';
29
29
  import { __resetEnvCacheForTests } from '../lib/env.js';
30
+ import { req } from '../lib/requirement-ids.js';
30
31
 
31
32
  export const HOST_CALLBACK_NOT_REQUIRED = 'server-free: toggles OPENWOP_REQUIRE_BEHAVIOR in-process and pins the advertised-missing-seam rule';
32
33
 
@@ -71,7 +72,7 @@ describe('RFC 0148 §B — conformance-advertised-seam-required', () => {
71
72
  delete process.env['OPENWOP_REQUIRE_BEHAVIOR'];
72
73
  __resetEnvCacheForTests();
73
74
  delete process.env['OPENWOP_OPTED_OUT_PROFILES'];
74
- expect(behaviorGate(PROFILE, false)).toBe(false);
75
+ expect(behaviorGate(PROFILE, false), req('openwop.it.conformance-advertised-seam-required.default-mode-an-unadvertised-profile-records-inapplicable-and-gates-false-never', 'RFC 0148 §B', 'default mode: an unadvertised profile records inapplicable and gates false — never a pass')).toBe(false);
75
76
  expect(dispositionOf(`openwop.profile.${PROFILE}`)).toBe('inapplicable');
76
77
  });
77
78
 
@@ -79,14 +80,14 @@ describe('RFC 0148 §B — conformance-advertised-seam-required', () => {
79
80
  process.env['OPENWOP_REQUIRE_BEHAVIOR'] = 'true';
80
81
  __resetEnvCacheForTests();
81
82
  delete process.env['OPENWOP_OPTED_OUT_PROFILES'];
82
- expect(() => behaviorGate(PROFILE, false)).toThrow(/OPENWOP_REQUIRE_BEHAVIOR=true/);
83
+ expect(() => behaviorGate(PROFILE, false), req('openwop.it.conformance-advertised-seam-required.strict-mode-an-unadvertised-un-opted-out-profile-fails-advertise-or-opt-out-expl', 'RFC 0148 §B', 'strict mode: an unadvertised, un-opted-out profile FAILS (advertise or opt out explicitly)')).toThrow(/OPENWOP_REQUIRE_BEHAVIOR=true/);
83
84
  });
84
85
 
85
86
  it('strict mode: an advertised capability whose seam helper returned nothing FAILS (behaviorGatePresent)', () => {
86
87
  process.env['OPENWOP_REQUIRE_BEHAVIOR'] = 'true';
87
88
  __resetEnvCacheForTests();
88
89
  delete process.env['OPENWOP_OPTED_OUT_PROFILES'];
89
- expect(() => behaviorGatePresent(PROFILE, null)).toThrow();
90
+ expect(() => behaviorGatePresent(PROFILE, null), req('openwop.it.conformance-advertised-seam-required.strict-mode-an-advertised-capability-whose-seam-helper-returned-nothing-fails-be', 'RFC 0148 §B', 'strict mode: an advertised capability whose seam helper returned nothing FAILS (behaviorGatePresent)')).toThrow();
90
91
  // and with a value present it narrows and passes through
91
92
  delete process.env['OPENWOP_REQUIRE_BEHAVIOR'];
92
93
  __resetEnvCacheForTests();
@@ -96,7 +97,7 @@ describe('RFC 0148 §B — conformance-advertised-seam-required', () => {
96
97
  it('strict mode: seamAbsent (advertised, seam answered 404/403 mid-scenario) FAILS; default mode notes blocked with the reason', () => {
97
98
  process.env['OPENWOP_REQUIRE_BEHAVIOR'] = 'true';
98
99
  __resetEnvCacheForTests();
99
- expect(() => seamAbsent('host advertises X but /v1/host/sample/x answered 404')).toThrow(/RFC 0148 §B/);
100
+ expect(() => seamAbsent('host advertises X but /v1/host/sample/x answered 404'), req('openwop.it.conformance-advertised-seam-required.strict-mode-seamabsent-advertised-seam-answered-404-403-mid-scenario-fails-defau', 'RFC 0148 §B', 'strict mode: seamAbsent (advertised, seam answered 404/403 mid-scenario) FAILS; default mode notes blocked with the reason')).toThrow(/RFC 0148 §B/);
100
101
  delete process.env['OPENWOP_REQUIRE_BEHAVIOR'];
101
102
  __resetEnvCacheForTests();
102
103
  resetSoftSkips();
@@ -111,7 +112,7 @@ describe('RFC 0148 §B — conformance-advertised-seam-required', () => {
111
112
  __resetEnvCacheForTests();
112
113
  process.env['OPENWOP_OPTED_OUT_PROFILES'] = PROFILE;
113
114
  __resetEnvCacheForTests();
114
- expect(behaviorGate(PROFILE, false)).toBe(false);
115
+ expect(behaviorGate(PROFILE, false), req('openwop.it.conformance-advertised-seam-required.the-sanctioned-escape-is-an-explicit-opt-out-which-records-skipped-with-the-reas', 'RFC 0148 §B', 'the sanctioned escape is an explicit opt-out, which records skipped with the reason — still never a pass')).toBe(false);
115
116
  expect(dispositionOf(`openwop.profile.${PROFILE}`)).toBe('skipped');
116
117
  });
117
118
  });
@@ -27,6 +27,7 @@ import { UNCLASSIFIED_RETURN_DETAIL } from '../lib/soft-skip.js';
27
27
  import { PROFILE_FLOOR_SCENARIOS } from '../lib/profiles.js';
28
28
  import { requirementIdForScenario, requirementsFor } from '../lib/requirement-registry.js';
29
29
  import { verifyBundleV2, type BundleV2Requirement } from '../lib/certification-bundle-verify.js';
30
+ import { req } from '../lib/requirement-ids.js';
30
31
 
31
32
  export const HOST_CALLBACK_NOT_REQUIRED = 'server-free: pins the runner/emitter/verifier rule that an early return is never a pass';
32
33
 
@@ -34,19 +35,19 @@ const HEX = 'c'.repeat(64);
34
35
 
35
36
  describe('RFC 0148 §A — conformance-execution-witness: the runner record', () => {
36
37
  it('a witnessed pass is executed-pass; a failed test is executed-fail regardless of count', () => {
37
- expect(resolveFileRecord(['pass', 'pass'], undefined, 7, null).disposition).toBe('executed-pass');
38
+ expect(resolveFileRecord(['pass', 'pass'], undefined, 7, null).disposition, req('openwop.it.conformance-execution-witness.a-witnessed-pass-is-executed-pass-a-failed-test-is-executed-fail-regardless-of-c', 'RFC 0148 §A', 'a witnessed pass is executed-pass; a failed test is executed-fail regardless of count')).toBe('executed-pass');
38
39
  expect(resolveFileRecord(['pass', 'fail'], undefined, 7, null).disposition).toBe('executed-fail');
39
40
  expect(resolveFileRecord(['fail'], undefined, 0, null).disposition).toBe('executed-fail');
40
41
  });
41
42
 
42
43
  it('a zero-assertion pass with NO reason is BLOCKED with the marker — never a pass', () => {
43
44
  const r = resolveFileRecord(['pass', 'pass'], undefined, 0, null);
44
- expect(r.disposition).toBe('blocked');
45
+ expect(r.disposition, req('openwop.it.conformance-execution-witness.a-zero-assertion-pass-with-no-reason-is-blocked-with-the-marker-never-a-pass', 'RFC 0148 §A', 'a zero-assertion pass with NO reason is BLOCKED with the marker — never a pass')).toBe('blocked');
45
46
  expect(r.detail).toBe(UNCLASSIFIED_RETURN_DETAIL);
46
47
  });
47
48
 
48
49
  it('a zero-assertion pass takes the noted reason (softSkip / seamAbsent) — inapplicable, skipped, or blocked with the text', () => {
49
- expect(resolveFileRecord(['pass'], undefined, 0, { kind: 'inapplicable', reason: 'host does not advertise X' })).toEqual({ disposition: 'inapplicable', detail: 'host does not advertise X' });
50
+ expect(resolveFileRecord(['pass'], undefined, 0, { kind: 'inapplicable', reason: 'host does not advertise X' }), req('openwop.it.conformance-execution-witness.a-zero-assertion-pass-takes-the-noted-reason-softskip-seamabsent-inapplicable-sk', 'RFC 0148 §A', 'a zero-assertion pass takes the noted reason (softSkip / seamAbsent) — inapplicable, skipped, or blocked with the text')).toEqual({ disposition: 'inapplicable', detail: 'host does not advertise X' });
50
51
  expect(resolveFileRecord(['pass'], undefined, 0, { kind: 'blocked', reason: 'seam answered 404' })).toEqual({ disposition: 'blocked', detail: 'seam answered 404' });
51
52
  expect(resolveFileRecord(['pass'], undefined, 0, { kind: 'skipped', reason: 'operator opt-out' })).toEqual({ disposition: 'skipped', detail: 'operator opt-out' });
52
53
  });
@@ -59,7 +60,7 @@ describe('RFC 0148 §A — conformance-execution-witness: the runner record', ()
59
60
  // from a positive control or a setup precondition. Measured on this exact
60
61
  // function by a tier-1 host writing a scenario whose first leg is a control.
61
62
  const one = resolveFileRecord(['pass'], undefined, 1, { kind: 'blocked', reason: 'fork returned 501' });
62
- expect(one.disposition).toBe('executed-pass');
63
+ expect(one.disposition, req('openwop.it.conformance-execution-witness.gap-g8-a-file-that-asserted-then-soft-skipped-keeps-the-note-as-a-partial-witnes', 'RFC 0148 §A', 'gap G8 — a file that asserted then soft-skipped keeps the note as a partial-witness detail, and its disposition does NOT move')).toBe('executed-pass');
63
64
  expect(one.detail).toBe('partial-witness: blocked: fork returned 501');
64
65
 
65
66
  const many = resolveFileRecord(['pass', 'pass'], undefined, 4, { kind: 'inapplicable', reason: 'fork unsupported' });
@@ -83,7 +84,7 @@ describe('RFC 0148 §A — conformance-execution-witness: the runner record', ()
83
84
  it('every test ctx.skip()ped takes the noted reason when one was written before the skip, else stays the blocked marker', () => {
84
85
  // `ctx.skip()` throws — a `softSkip(...)` AFTER it is dead code. Seven files
85
86
  // carried exactly that dead note and reported as unclassified for a suite minor.
86
- expect(resolveFileRecord(['skip', 'skip'], undefined, 0, { kind: 'inapplicable', reason: 'sandbox not advertised' })).toEqual({ disposition: 'inapplicable', detail: 'sandbox not advertised' });
87
+ expect(resolveFileRecord(['skip', 'skip'], undefined, 0, { kind: 'inapplicable', reason: 'sandbox not advertised' }), req('openwop.it.conformance-execution-witness.every-test-ctx-skip-ped-takes-the-noted-reason-when-one-was-written-before-the-s', 'RFC 0148 §A', 'every test ctx.skip()ped takes the noted reason when one was written before the skip, else stays the blocked marker')).toEqual({ disposition: 'inapplicable', detail: 'sandbox not advertised' });
87
88
  expect(resolveFileRecord(['skip'], undefined, 0, { kind: 'blocked', reason: 'simulator seam 404' })).toEqual({ disposition: 'blocked', detail: 'simulator seam 404' });
88
89
  const bare = resolveFileRecord(['skip', 'skip'], undefined, 0, null);
89
90
  expect(bare.disposition).toBe('blocked');
@@ -93,7 +94,7 @@ describe('RFC 0148 §A — conformance-execution-witness: the runner record', ()
93
94
  });
94
95
 
95
96
  it('a behaviorGate reason resolves a zero-assertion pass to inapplicable/skipped; a note outranks nothing but never a witnessed pass', () => {
96
- expect(resolveFileRecord(['pass'], 'inapplicable', 0, null).disposition).toBe('inapplicable');
97
+ expect(resolveFileRecord(['pass'], 'inapplicable', 0, null).disposition, req('openwop.it.conformance-execution-witness.a-behaviorgate-reason-resolves-a-zero-assertion-pass-to-inapplicable-skipped-a-n', 'RFC 0148 §A', 'a behaviorGate reason resolves a zero-assertion pass to inapplicable/skipped; a note outranks nothing but never a witnessed pass')).toBe('inapplicable');
97
98
  expect(resolveFileRecord(['pass'], 'skipped', 0, null).disposition).toBe('skipped');
98
99
  // real assertions ran: the note is irrelevant, the file passed
99
100
  expect(resolveFileRecord(['pass'], undefined, 3, { kind: 'blocked', reason: 'irrelevant' }).disposition).toBe('executed-pass');
@@ -115,7 +116,7 @@ describe('RFC 0148 §A — conformance-execution-witness: emitter and verifier r
115
116
  rep.set('interrupt-alpha.test.ts', 'passed');
116
117
  const d = deriveRequirementDispositions(rep, ledger, [profile], {});
117
118
  const v = d.verdicts.find((x) => x.profile === profile)!;
118
- expect(v.unclassified).toEqual([requirementIdForScenario(files[0]!)]);
119
+ expect(v.unclassified, req('openwop.it.conformance-execution-witness.the-emitter-derivation-marks-a-marker-blocked-floor-row-unclassified-and-rejects', 'RFC 0148 §A', 'the emitter derivation marks a marker-blocked floor row unclassified and rejects the claim')).toEqual([requirementIdForScenario(files[0]!)]);
119
120
  expect(d.rejectUnclassified).toBe(true);
120
121
  // and the same file with a witnessed pass certifies
121
122
  ledger[0] = { requirementId: requirementIdForScenario(files[0]!), disposition: 'executed-pass' as const, assertionCount: 3 };
@@ -134,7 +135,7 @@ describe('RFC 0148 §A — conformance-execution-witness: emitter and verifier r
134
135
  results: { totals: { executedPass: rs.filter((r) => r.disposition === 'executed-pass').length, executedFail: 0, skipped: 0, inapplicable: 0, blocked: rs.filter((r) => r.disposition === 'blocked').length }, requirements: rs },
135
136
  scenarioManifestSha256: HEX, targetConfigurationSha256: HEX,
136
137
  });
137
- expect(verifyBundleV2(bundle(rows)).certified).toBe(true);
138
+ expect(verifyBundleV2(bundle(rows)).certified, req('openwop.it.conformance-execution-witness.the-consumer-verifier-rejects-a-bundle-whose-required-row-is-a-vacuous-pass-or-t', 'RFC 0148 §A', 'the consumer verifier rejects a bundle whose required row is a vacuous pass or the runner marker, and accepts the witnessed twin')).toBe(true);
138
139
  const vacuous = rows.map((r, i) => (i === 0 ? { ...r, assertionCount: 0 } : r));
139
140
  expect(verifyBundleV2(bundle(vacuous)).evidenceValid).toBe(false);
140
141
  const marker = rows.map((r, i) => (i === 0 ? { requirementId: r.requirementId, scenarioId: r.scenarioId, disposition: 'blocked', detail: UNCLASSIFIED_RETURN_DETAIL, assertionCount: 0 } : r));