@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
@@ -12,8 +12,8 @@
12
12
 
13
13
  import { describe, it, expect } from 'vitest';
14
14
  import { softSkip } from '../lib/soft-skip.js';
15
- import { driver } from '../lib/driver.js';
16
15
  import { readDistillationCap, invokeDistill } from '../lib/distillation.js';
16
+ import { req } from '../lib/requirement-ids.js';
17
17
 
18
18
  describe('distillation-token-budget (RFC 0062 §B)', () => {
19
19
  it('within budget tokensUsed ≤ tokenBudget; an un-meetable budget fails atomically', async () => {
@@ -24,11 +24,11 @@ describe('distillation-token-budget (RFC 0062 §B)', () => {
24
24
  const dist = ok.body.event?.distillation ?? {};
25
25
  expect(
26
26
  typeof dist.tokenBudget === 'number' && typeof dist.tokensUsed === 'number',
27
- driver.describe('RFC 0062 §B', 'memory.compacted MUST carry distillation.tokenBudget + tokensUsed on a budgeted run'),
27
+ req('openwop.it.distillation-token-budget.within-budget-tokensused-tokenbudget-an-un-meetable-budget-fails-atomically', 'RFC 0062 §B', 'memory.compacted MUST carry distillation.tokenBudget + tokensUsed on a budgeted run'),
28
28
  ).toBe(true);
29
29
  expect(
30
30
  (dist.tokensUsed as number) <= (dist.tokenBudget as number),
31
- driver.describe('RFC 0062 §B', 'a successful distillation MUST consume ≤ its tokenBudget'),
31
+ req('openwop.it.distillation-token-budget.within-budget-tokensused-tokenbudget-an-un-meetable-budget-fails-atomically', 'RFC 0062 §B', 'a successful distillation MUST consume ≤ its tokenBudget'),
32
32
  ).toBe(true);
33
33
 
34
34
  // A budget too small to distill the corpus MUST fail closed, no partial archive.
@@ -36,11 +36,11 @@ describe('distillation-token-budget (RFC 0062 §B)', () => {
36
36
  if (tooSmall === null) return softSkip('blocked', 'precondition not met — `tooSmall === null` returned early (seam, prior step, or fixture unavailable)');
37
37
  expect(
38
38
  tooSmall.status >= 400 && tooSmall.body.error === 'token_budget_exceeded',
39
- driver.describe('RFC 0062 §B', 'an un-meetable budget MUST fail with token_budget_exceeded'),
39
+ req('openwop.it.distillation-token-budget.within-budget-tokensused-tokenbudget-an-un-meetable-budget-fails-atomically', 'RFC 0062 §B', 'an un-meetable budget MUST fail with token_budget_exceeded'),
40
40
  ).toBe(true);
41
41
  expect(
42
42
  tooSmall.body.archiveChecksum,
43
- driver.describe('RFC 0062 §B', 'a token_budget_exceeded run MUST write no partial archive (atomic)'),
43
+ req('openwop.it.distillation-token-budget.within-budget-tokensused-tokenbudget-an-un-meetable-budget-fails-atomically', 'RFC 0062 §B', 'a token_budget_exceeded run MUST write no partial archive (atomic)'),
44
44
  ).toBeUndefined();
45
45
  });
46
46
  });
@@ -51,6 +51,7 @@ import { softSkip } from '../lib/soft-skip.js';
51
51
  import { queryTestEvents, requireEvents } from '../lib/event-log-query.js';
52
52
  import { recordRequirement } from '../lib/requirement-ledger.js';
53
53
  import { requirementIdForFile } from '../lib/scenario-disposition.js';
54
+ import { req } from '../lib/requirement-ids.js';
54
55
 
55
56
  const WORKFLOW_ID = 'conformance-failure';
56
57
  const FILE = 'durability-poison-exhaustion.test.ts';
@@ -90,7 +91,7 @@ if (SKIP_NO_FIXTURE) {
90
91
  describe.skipIf(SKIP_NO_FIXTURE)('RFC 0158 §C.8 — poison work terminates within a bounded number of attempts', () => {
91
92
  it('reaches terminal AND stops being retried, asserted on the log rather than on the status alone', async () => {
92
93
  const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
93
- expect(create.status, driver.describe(
94
+ expect(create.status, req('openwop.it.durability-poison-exhaustion.reaches-terminal-and-stops-being-retried-asserted-on-the-log-rather-than-on-the',
94
95
  'rest-endpoints.md',
95
96
  'POST /v1/runs MUST return 201 even for work that fails at runtime',
96
97
  )).toBe(201);
@@ -98,7 +99,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('RFC 0158 §C.8 — poison work terminates with
98
99
 
99
100
  // ── First clause: a terminal, OPERATOR-VISIBLE state ─────────────────────
100
101
  const terminal = await pollUntilTerminal(runId);
101
- expect(terminal.status, driver.describe(
102
+ expect(terminal.status, req('openwop.it.durability-poison-exhaustion.reaches-terminal-and-stops-being-retried-asserted-on-the-log-rather-than-on-the',
102
103
  'RFC 0158 §C.8',
103
104
  'deterministically failing work MUST reach a terminal, operator-visible state',
104
105
  )).toBe('failed');
@@ -118,13 +119,13 @@ describe.skipIf(SKIP_NO_FIXTURE)('RFC 0158 §C.8 — poison work terminates with
118
119
  // Non-vacuity: the failure must actually be ON the log. Without this, a host
119
120
  // returning an empty array would sail through every count comparison below,
120
121
  // since 0 === 0 after any wait.
121
- expect(events.some((e) => e.type === 'node.failed'), driver.describe(
122
+ expect(events.some((e) => e.type === 'node.failed'), req('openwop.it.durability-poison-exhaustion.reaches-terminal-and-stops-being-retried-asserted-on-the-log-rather-than-on-the',
122
123
  'RFC 0158 §C.8',
123
124
  'the run log MUST record the deterministic failure — an empty log makes every attempt count vacuous',
124
125
  )).toBe(true);
125
126
 
126
127
  const attemptsBefore = events.filter((e) => ATTEMPT_TYPES.has(e.type)).length;
127
- expect(attemptsBefore, driver.describe(
128
+ expect(attemptsBefore, req('openwop.it.durability-poison-exhaustion.reaches-terminal-and-stops-being-retried-asserted-on-the-log-rather-than-on-the',
128
129
  'RFC 0158 §C.8',
129
130
  'at least one attempt MUST be recorded — zero attempts means nothing was delivered',
130
131
  )).toBeGreaterThan(0);
@@ -135,7 +136,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('RFC 0158 §C.8 — poison work terminates with
135
136
  const after = requireEvents(second, 'RFC 0158 §C.8 attempt counting (post-terminal)');
136
137
  const attemptsAfter = after.filter((e) => ATTEMPT_TYPES.has(e.type)).length;
137
138
 
138
- expect(attemptsAfter, driver.describe(
139
+ expect(attemptsAfter, req('openwop.it.durability-poison-exhaustion.reaches-terminal-and-stops-being-retried-asserted-on-the-log-rather-than-on-the',
139
140
  'RFC 0158 §C.8',
140
141
  'attempts MUST NOT continue after the run reports terminal — a host still redelivering records more',
141
142
  )).toBe(attemptsBefore);
@@ -143,7 +144,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('RFC 0158 §C.8 — poison work terminates with
143
144
  // ── Optional ceiling, only when the operator supplies the declared bound ─
144
145
  const bound = declaredAttemptBound();
145
146
  if (bound !== null) {
146
- expect(attemptsAfter, driver.describe(
147
+ expect(attemptsAfter, req('openwop.it.durability-poison-exhaustion.reaches-terminal-and-stops-being-retried-asserted-on-the-log-rather-than-on-the',
147
148
  'RFC 0158 §C.8 + §B.5',
148
149
  'total attempts MUST NOT exceed the operator-declared attempt bound',
149
150
  )).toBeLessThanOrEqual(bound);
@@ -28,9 +28,10 @@
28
28
  */
29
29
 
30
30
  import { describe, it, expect } from 'vitest';
31
- import { driver } from '../lib/driver.js';
32
31
  import { behaviorGate } from '../lib/behavior-gate.js';
33
32
  import { readEgressPolicyCap, driveEgress, EGRESS_DECISIONS, EGRESS_REASONS } from '../lib/egressPolicy.js';
33
+ import { req } from '../lib/requirement-ids.js';
34
+ import { softSkip } from '../lib/soft-skip.js';
34
35
 
35
36
  describe('egress-audience-binding (RFC 0079 §C)', () => {
36
37
  it('denies/downgrades an out-of-audience egress without attaching the credential, and fails closed on unevaluable provenance', async () => {
@@ -39,22 +40,22 @@ describe('egress-audience-binding (RFC 0079 §C)', () => {
39
40
 
40
41
  // ---- Leg 1: out-of-audience — deny|downgrade + credential NOT attached --
41
42
  const oob = await driveEgress({ scenario: 'out-of-audience' });
42
- if (oob === null) return; // egress seam absent — soft-skip the whole behavior
43
+ if (oob === null) return softSkip('blocked', 'precondition not met — `oob === null` returned early (egress seam absent — soft-skip the whole behavior) (seam, prior step, or fixture unavailable)'); // egress seam absent — soft-skip the whole behavior
43
44
  expect(
44
45
  oob.decision === 'denied' || oob.decision === 'downgraded',
45
- driver.describe('host-capabilities.md §"Credential provenance + egress policy"', 'an out-of-audience egress MUST be denied or downgraded'),
46
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'host-capabilities.md §"Credential provenance + egress policy"', 'an out-of-audience egress MUST be denied or downgraded'),
46
47
  ).toBe(true);
47
48
  expect(
48
49
  typeof oob.decision === 'string' && EGRESS_DECISIONS.includes(oob.decision),
49
- driver.describe('run-event-payloads.schema.json#egressDecided', 'decision MUST be in the closed enum'),
50
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'run-event-payloads.schema.json#egressDecided', 'decision MUST be in the closed enum'),
50
51
  ).toBe(true);
51
52
  expect(
52
53
  oob.reason === 'out-of-audience',
53
- driver.describe('RFC 0079 §C', 'an out-of-audience denial MUST carry reason "out-of-audience"'),
54
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'RFC 0079 §C', 'an out-of-audience denial MUST carry reason "out-of-audience"'),
54
55
  ).toBe(true);
55
56
  expect(
56
57
  oob.credentialAttached !== true,
57
- driver.describe('SECURITY/invariants.yaml egress-credential-audience-bound', 'the host MUST NOT attach a credential whose audience excludes the destination (confused-deputy)'),
58
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'SECURITY/invariants.yaml egress-credential-audience-bound', 'the host MUST NOT attach a credential whose audience excludes the destination (confused-deputy)'),
58
59
  ).toBe(true);
59
60
 
60
61
  // ---- Leg 2: provenance-unevaluable — fail closed (deny) ----------------
@@ -62,19 +63,19 @@ describe('egress-audience-binding (RFC 0079 §C)', () => {
62
63
  if (uneval !== null) {
63
64
  expect(
64
65
  uneval.decision === 'denied',
65
- driver.describe('RFC 0079 §C', 'an egress with unevaluable provenance MUST fail closed (denied)'),
66
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'RFC 0079 §C', 'an egress with unevaluable provenance MUST fail closed (denied)'),
66
67
  ).toBe(true);
67
68
  expect(
68
69
  uneval.reason === 'provenance-unevaluable',
69
- driver.describe('RFC 0079 §C', 'a provenance-unevaluable denial MUST carry reason "provenance-unevaluable"'),
70
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'RFC 0079 §C', 'a provenance-unevaluable denial MUST carry reason "provenance-unevaluable"'),
70
71
  ).toBe(true);
71
72
  expect(
72
73
  typeof uneval.reason === 'string' && EGRESS_REASONS.includes(uneval.reason),
73
- driver.describe('run-event-payloads.schema.json#egressDecided', 'reason MUST be in the closed enum'),
74
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'run-event-payloads.schema.json#egressDecided', 'reason MUST be in the closed enum'),
74
75
  ).toBe(true);
75
76
  expect(
76
77
  uneval.credentialAttached !== true,
77
- driver.describe('SECURITY/invariants.yaml egress-credential-audience-bound', 'a fail-closed egress MUST NOT attach the credential'),
78
+ req('openwop.it.egress-audience-binding.denies-downgrades-an-out-of-audience-egress-without-attaching-the-credential-and', 'SECURITY/invariants.yaml egress-credential-audience-bound', 'a fail-closed egress MUST NOT attach the credential'),
78
79
  ).toBe(true);
79
80
  }
80
81
  });
@@ -20,9 +20,10 @@
20
20
  */
21
21
 
22
22
  import { describe, it, expect } from 'vitest';
23
- import { driver } from '../lib/driver.js';
24
23
  import { behaviorGate } from '../lib/behavior-gate.js';
25
24
  import { readEgressPolicyCap, driveEgress, EGRESS_REASONS, EGRESS_CONTENT_FORBIDDEN } from '../lib/egressPolicy.js';
25
+ import { req } from '../lib/requirement-ids.js';
26
+ import { softSkip } from '../lib/soft-skip.js';
26
27
 
27
28
  describe('egress-decision-content-free (RFC 0079 §F / SR-1)', () => {
28
29
  it('never leaks the credential value or the blocked destination into the egress.decided payload', async () => {
@@ -30,19 +31,19 @@ describe('egress-decision-content-free (RFC 0079 §F / SR-1)', () => {
30
31
  if (!behaviorGate('openwop-egress-decision-content-free', cap?.supported === true)) return;
31
32
 
32
33
  const res = await driveEgress({ scenario: 'canary' });
33
- if (res === null) return; // seam absent — soft-skip
34
+ if (res === null) return softSkip('blocked', 'precondition not met — `res === null` returned early (seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam absent — soft-skip
34
35
 
35
36
  // The canary sentinel MUST NOT appear anywhere observable.
36
37
  expect(
37
38
  res.canaryLeaked !== true,
38
- driver.describe('RFC 0079 §F (SR-1)', 'the credential value (canary) MUST NOT leak into any observable surface'),
39
+ req('openwop.it.egress-decision-content-free.never-leaks-the-credential-value-or-the-blocked-destination-into-the-egress-deci', 'RFC 0079 §F (SR-1)', 'the credential value (canary) MUST NOT leak into any observable surface'),
39
40
  ).toBe(true);
40
41
 
41
42
  // No forbidden content keys on the decision payload.
42
43
  for (const forbidden of EGRESS_CONTENT_FORBIDDEN) {
43
44
  expect(
44
45
  !(forbidden in res),
45
- driver.describe('RFC 0079 §F (SR-1)', `egress.decided MUST be content-free (no ${forbidden})`),
46
+ req('openwop.it.egress-decision-content-free.never-leaks-the-credential-value-or-the-blocked-destination-into-the-egress-deci', 'RFC 0079 §F (SR-1)', `egress.decided MUST be content-free (no ${forbidden})`),
46
47
  ).toBe(true);
47
48
  }
48
49
 
@@ -50,7 +51,7 @@ describe('egress-decision-content-free (RFC 0079 §F / SR-1)', () => {
50
51
  if (res.reason !== undefined) {
51
52
  expect(
52
53
  typeof res.reason === 'string' && EGRESS_REASONS.includes(res.reason),
53
- driver.describe('run-event-payloads.schema.json#egressDecided', 'reason MUST be in the closed enum (no free-form spill)'),
54
+ req('openwop.it.egress-decision-content-free.never-leaks-the-credential-value-or-the-blocked-destination-into-the-egress-deci', 'run-event-payloads.schema.json#egressDecided', 'reason MUST be in the closed enum (no free-form spill)'),
54
55
  ).toBe(true);
55
56
  }
56
57
  });
@@ -40,8 +40,7 @@ import { join } from 'node:path';
40
40
  import Ajv2020 from 'ajv/dist/2020.js';
41
41
  import addFormats from 'ajv-formats';
42
42
  import { SCHEMAS_DIR } from '../lib/paths.js';
43
-
44
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
43
+ import { req } from '../lib/requirement-ids.js';
45
44
 
46
45
  function loadSchema(name: string): Record<string, unknown> {
47
46
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -58,20 +57,20 @@ describe('egress-provenance-shape: CredentialProvenance (RFC 0079 §A, server-fr
58
57
  it('a conforming descriptor validates', () => {
59
58
  expect(
60
59
  validate({ credentialId: 'cred-stripe-1', issuer: 'host', audiences: ['api.stripe.com'], expiresAt: '2026-12-01T00:00:00Z', scopes: ['egress:stripe:charge'], redactionPolicy: 'always' }),
61
- why('host-capabilities.md §"Credential provenance + egress policy"', 'a conforming CredentialProvenance MUST validate'),
60
+ req('openwop.it.egress-provenance-shape.a-conforming-descriptor-validates', 'host-capabilities.md §"Credential provenance + egress policy"', 'a conforming CredentialProvenance MUST validate'),
62
61
  ).toBe(true);
63
62
  });
64
63
 
65
64
  it('audiences: [] is rejected (minItems:1 — a credential needs ≥1 audience to bind)', () => {
66
- expect(validate({ credentialId: 'c', issuer: 'host', audiences: [] }), why('RFC 0079 §A', 'audiences MUST have ≥1 entry')).toBe(false);
65
+ expect(validate({ credentialId: 'c', issuer: 'host', audiences: [] }), req('openwop.it.egress-provenance-shape.audiences-is-rejected-minitems-1-a-credential-needs-1-audience-to-bind', 'RFC 0079 §A', 'audiences MUST have ≥1 entry')).toBe(false);
67
66
  });
68
67
 
69
68
  it('a missing REQUIRED credentialId is rejected', () => {
70
- expect(validate({ issuer: 'host', audiences: ['a'] }), why('RFC 0079 §A', 'credentialId is REQUIRED')).toBe(false);
69
+ expect(validate({ issuer: 'host', audiences: ['a'] }), req('openwop.it.egress-provenance-shape.a-missing-required-credentialid-is-rejected', 'RFC 0079 §A', 'credentialId is REQUIRED')).toBe(false);
71
70
  });
72
71
 
73
72
  it('an unknown property is rejected (additionalProperties:false)', () => {
74
- expect(validate({ credentialId: 'c', issuer: 'host', audiences: ['a'], secretValue: 'sk-live-xxx' }), why('RFC 0079 §A', 'CredentialProvenance MUST be additionalProperties:false')).toBe(false);
73
+ expect(validate({ credentialId: 'c', issuer: 'host', audiences: ['a'], secretValue: 'sk-live-xxx' }), req('openwop.it.egress-provenance-shape.an-unknown-property-is-rejected-additionalproperties-false', 'RFC 0079 §A', 'CredentialProvenance MUST be additionalProperties:false')).toBe(false);
75
74
  });
76
75
 
77
76
  it('declares no secret-value property (egress-decision-no-secret-leak)', () => {
@@ -79,7 +78,7 @@ describe('egress-provenance-shape: CredentialProvenance (RFC 0079 §A, server-fr
79
78
  for (const p of props) {
80
79
  expect(
81
80
  SECRET_PROP_NAMES.includes(p.toLowerCase()),
82
- why('SECURITY invariant egress-decision-no-secret-leak', `CredentialProvenance MUST NOT declare a secret-bearing property (${p})`),
81
+ req('openwop.it.egress-provenance-shape.declares-no-secret-value-property-egress-decision-no-secret-leak', 'SECURITY invariant egress-decision-no-secret-leak', `CredentialProvenance MUST NOT declare a secret-bearing property (${p})`),
83
82
  ).toBe(false);
84
83
  }
85
84
  });
@@ -95,32 +94,32 @@ describe('egress-provenance-shape: egress.decided event (RFC 0079 §B, server-fr
95
94
  } as Record<string, unknown>);
96
95
 
97
96
  it('validates a content-free decision and enforces the decision enum + required fields', () => {
98
- expect(validate({ decision: 'allowed', destination: 'api.stripe.com', credentialId: 'cred-stripe-1', reason: 'ok' }), why('RFC 0079 §B', 'a conforming egress.decided MUST validate')).toBe(true);
99
- expect(validate({ decision: 'denied', destination: 'attacker.example', credentialId: 'cred-stripe-1', reason: 'out-of-audience' }), why('RFC 0079 §B', 'a denied decision MUST validate')).toBe(true);
100
- expect(validate({ decision: 'ok', destination: 'a' }), why('RFC 0079 §B', 'the canonical allow value is "allowed", not "ok"')).toBe(false);
101
- expect(validate({ destination: 'a' }), why('RFC 0079 §B', 'decision is REQUIRED')).toBe(false);
102
- expect(validate({ decision: 'allowed' }), why('RFC 0079 §B', 'destination is REQUIRED')).toBe(false);
97
+ expect(validate({ decision: 'allowed', destination: 'api.stripe.com', credentialId: 'cred-stripe-1', reason: 'ok' }), req('openwop.it.egress-provenance-shape.validates-a-content-free-decision-and-enforces-the-decision-enum-required-fields', 'RFC 0079 §B', 'a conforming egress.decided MUST validate')).toBe(true);
98
+ expect(validate({ decision: 'denied', destination: 'attacker.example', credentialId: 'cred-stripe-1', reason: 'out-of-audience' }), req('openwop.it.egress-provenance-shape.validates-a-content-free-decision-and-enforces-the-decision-enum-required-fields', 'RFC 0079 §B', 'a denied decision MUST validate')).toBe(true);
99
+ expect(validate({ decision: 'ok', destination: 'a' }), req('openwop.it.egress-provenance-shape.validates-a-content-free-decision-and-enforces-the-decision-enum-required-fields', 'RFC 0079 §B', 'the canonical allow value is "allowed", not "ok"')).toBe(false);
100
+ expect(validate({ destination: 'a' }), req('openwop.it.egress-provenance-shape.validates-a-content-free-decision-and-enforces-the-decision-enum-required-fields', 'RFC 0079 §B', 'decision is REQUIRED')).toBe(false);
101
+ expect(validate({ decision: 'allowed' }), req('openwop.it.egress-provenance-shape.validates-a-content-free-decision-and-enforces-the-decision-enum-required-fields', 'RFC 0079 §B', 'destination is REQUIRED')).toBe(false);
103
102
  });
104
103
 
105
104
  it('reason is a CLOSED enum — a free-form / URL-bearing reason is rejected (egress-decision-no-secret-leak)', () => {
106
- expect(validate({ decision: 'denied', destination: 'attacker.example', reason: 'out-of-audience' }), why('egress-decision-no-secret-leak', 'a conventional reason code MUST validate')).toBe(true);
105
+ expect(validate({ decision: 'denied', destination: 'attacker.example', reason: 'out-of-audience' }), req('openwop.it.egress-provenance-shape.reason-is-a-closed-enum-a-free-form-url-bearing-reason-is-rejected-egress-decisi', 'egress-decision-no-secret-leak', 'a conventional reason code MUST validate')).toBe(true);
107
106
  expect(
108
107
  validate({ decision: 'denied', destination: 'attacker.example', reason: 'https://attacker.example/leak?token=sk-live-xxx' }),
109
- why('egress-decision-no-secret-leak', 'a free-form / URL-bearing reason MUST be rejected (it would defeat the content-free guarantee)'),
108
+ req('openwop.it.egress-provenance-shape.reason-is-a-closed-enum-a-free-form-url-bearing-reason-is-rejected-egress-decisi', 'egress-decision-no-secret-leak', 'a free-form / URL-bearing reason MUST be rejected (it would defeat the content-free guarantee)'),
110
109
  ).toBe(false);
111
110
  });
112
111
 
113
112
  it('the egressDecided $def declares no secret-value property', () => {
114
113
  const def = ((payloads.$defs as Record<string, { properties?: Record<string, unknown> }>).egressDecided.properties) ?? {};
115
114
  for (const p of Object.keys(def)) {
116
- expect(SECRET_PROP_NAMES.includes(p.toLowerCase()), why('egress-decision-no-secret-leak', `egress.decided MUST NOT declare a secret-bearing property (${p})`)).toBe(false);
115
+ expect(SECRET_PROP_NAMES.includes(p.toLowerCase()), req('openwop.it.egress-provenance-shape.the-egressdecided-def-declares-no-secret-value-property', 'egress-decision-no-secret-leak', `egress.decided MUST NOT declare a secret-bearing property (${p})`)).toBe(false);
117
116
  }
118
117
  });
119
118
 
120
119
  it('egress.decided is in the RunEventType enum', () => {
121
120
  const runEvent = loadSchema('run-event.schema.json');
122
121
  const enumVals = ((runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum) ?? [];
123
- expect(enumVals.includes('egress.decided'), why('run-event.schema.json', 'egress.decided MUST be in the RunEventType enum')).toBe(true);
122
+ expect(enumVals.includes('egress.decided'), req('openwop.it.egress-provenance-shape.egress-decided-is-in-the-runeventtype-enum', 'run-event.schema.json', 'egress.decided MUST be in the RunEventType enum')).toBe(true);
124
123
  });
125
124
  });
126
125
 
@@ -129,9 +128,9 @@ describe('egress-provenance-shape: capability advertisement (RFC 0079 §D, serve
129
128
  const caps = loadSchema('capabilities.schema.json');
130
129
  const httpClient = (caps.properties as Record<string, { properties?: Record<string, { properties?: Record<string, unknown> }> }>).httpClient;
131
130
  const egressPolicy = httpClient?.properties?.egressPolicy;
132
- expect(egressPolicy, why('capabilities.md §httpClient', 'httpClient.egressPolicy MUST be declared')).toBeDefined();
131
+ expect(egressPolicy, req('openwop.it.egress-provenance-shape.capabilities-httpclient-egresspolicy-is-declared-with-its-sub-flags', 'capabilities.md §httpClient', 'httpClient.egressPolicy MUST be declared')).toBeDefined();
133
132
  for (const flag of ['supported', 'decisions']) {
134
- expect(egressPolicy?.properties?.[flag], why('host-capabilities.md §"Credential provenance + egress policy"', `egressPolicy.${flag} MUST be declared`)).toBeDefined();
133
+ expect(egressPolicy?.properties?.[flag], req('openwop.it.egress-provenance-shape.capabilities-httpclient-egresspolicy-is-declared-with-its-sub-flags', 'host-capabilities.md §"Credential provenance + egress policy"', `egressPolicy.${flag} MUST be declared`)).toBeDefined();
135
134
  }
136
135
  });
137
136
  });
@@ -32,6 +32,8 @@ import { driver } from '../lib/driver.js';
32
32
  import { pollUntilTerminal } from '../lib/polling.js';
33
33
  import { isFixtureAdvertised } from '../lib/fixtures.js';
34
34
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
35
+ import { req } from '../lib/requirement-ids.js';
36
+ import { softSkip } from '../lib/soft-skip.js';
35
37
 
36
38
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
37
39
  const NODE_ID = 'structured-call';
@@ -91,18 +93,18 @@ async function lastBudget(): Promise<number | null> {
91
93
  describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: advertisement shape (RFC 0033 §E)', () => {
92
94
  it('capabilities.envelopes.reliability.completion (when present) conforms to RFC 0033 §E', async () => {
93
95
  const d = await readDiscovery();
94
- if (d === null) return;
96
+ if (d === null) return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
95
97
  const completion = capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability?.completion;
96
- if (completion === undefined) return;
98
+ if (completion === undefined) return softSkip('blocked', 'precondition not met — `completion === undefined` returned early (seam, prior step, or fixture unavailable)');
97
99
  expect(
98
100
  typeof completion.distinguishesTruncation,
99
- driver.describe('RFCS/0033-envelope-completion-contract.md §E', 'completion.distinguishesTruncation MUST be boolean when block is advertised'),
101
+ req('openwop.it.envelope-completion-distinguishes-truncation.capabilities-envelopes-reliability-completion-when-present-conforms-to-rfc-0033', 'RFCS/0033-envelope-completion-contract.md §E', 'completion.distinguishesTruncation MUST be boolean when block is advertised'),
100
102
  ).toBe('boolean');
101
103
  if (completion.truncationBudgetMultiplier !== undefined) {
102
104
  const n = completion.truncationBudgetMultiplier as number;
103
105
  expect(
104
106
  typeof n === 'number' && n >= 1 && n <= 8,
105
- driver.describe('RFCS/0033-envelope-completion-contract.md §E', 'truncationBudgetMultiplier MUST be a number in [1, 8] (default 2)'),
107
+ req('openwop.it.envelope-completion-distinguishes-truncation.capabilities-envelopes-reliability-completion-when-present-conforms-to-rfc-0033', 'RFCS/0033-envelope-completion-contract.md §E', 'truncationBudgetMultiplier MUST be a number in [1, 8] (default 2)'),
106
108
  ).toBe(true);
107
109
  }
108
110
  });
@@ -113,24 +115,24 @@ const SCHEMA_VIOLATION_FIXTURE = 'conformance-envelope-retry-attempted';
113
115
 
114
116
  describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: truncation path (RFC 0033 §B)', () => {
115
117
  it('truncation: emits envelope.truncated + envelope.retry.attempted with reason: "truncation"', async () => {
116
- if (!isFixtureAdvertised(TRUNCATED_FIXTURE)) return;
118
+ if (!isFixtureAdvertised(TRUNCATED_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(TRUNCATED_FIXTURE)` returned early');
117
119
  const d = await readDiscovery();
118
- if (capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability?.completion?.distinguishesTruncation !== true) return;
120
+ if (capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability?.completion?.distinguishesTruncation !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<stri…');
119
121
  const seed = await programMock([
120
122
  { stopReason: 'max_tokens', content: '{"partial' },
121
123
  { stopReason: 'end_turn', content: '{"valid":true}' },
122
124
  ]);
123
- if (seed.status === 404) return;
125
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
124
126
 
125
127
  const result = await startRunAndRead(TRUNCATED_FIXTURE);
126
- if (result === null) return;
128
+ if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
127
129
  const truncated = result.events.find((e) => e.type === 'envelope.truncated');
128
- expect(truncated, 'envelope.truncated MUST fire on the truncation path').toBeDefined();
130
+ expect(truncated, req('openwop.it.envelope-completion-distinguishes-truncation.truncation-emits-envelope-truncated-envelope-retry-attempted-with-reason-truncat', 'RFCS/0033-envelope-completion-contract.md §B', 'envelope.truncated MUST fire on the truncation path')).toBeDefined();
129
131
  const retry = result.events.find((e) => e.type === 'envelope.retry.attempted');
130
- expect(retry, 'envelope.retry.attempted MUST fire between attempts').toBeDefined();
132
+ expect(retry, req('openwop.it.envelope-completion-distinguishes-truncation.truncation-emits-envelope-truncated-envelope-retry-attempted-with-reason-truncat', 'RFCS/0033-envelope-completion-contract.md §B', 'envelope.retry.attempted MUST fire between attempts')).toBeDefined();
131
133
  expect(
132
134
  retry!.payload?.reason,
133
- driver.describe(
135
+ req('openwop.it.envelope-completion-distinguishes-truncation.truncation-emits-envelope-truncated-envelope-retry-attempted-with-reason-truncat',
134
136
  'RFCS/0033-envelope-completion-contract.md §B',
135
137
  'truncation-routed retry MUST carry reason: "truncation" (distinct from schema-violation per RFC 0033 §A precedence rule)',
136
138
  ),
@@ -138,21 +140,21 @@ describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: trunca
138
140
  });
139
141
 
140
142
  it('truncation: retry budget strictly greater than initial (RFC 0033 §B truncationBudgetMultiplier)', async () => {
141
- if (!isFixtureAdvertised(TRUNCATED_FIXTURE)) return;
143
+ if (!isFixtureAdvertised(TRUNCATED_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(TRUNCATED_FIXTURE)` returned early');
142
144
  const d = await readDiscovery();
143
- if (capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability?.completion?.distinguishesTruncation !== true) return;
145
+ if (capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<string, unknown> }>(d, 'envelopes')?.reliability?.completion?.distinguishesTruncation !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `capabilityFamily<{ reasoning?: Record<string, unknown>; tierOneSubsetCompliance?: unknown; reliability?: { completion?: Record<string, unknown> } & Record<stri…');
144
146
  const seed = await programMock([
145
147
  { stopReason: 'max_tokens', content: '{"partial' },
146
148
  { stopReason: 'end_turn', content: '{"valid":true}' },
147
149
  ]);
148
- if (seed.status === 404) return;
150
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
149
151
 
150
152
  await startRunAndRead(TRUNCATED_FIXTURE);
151
153
  const budget = await lastBudget();
152
- if (budget === null) return;
154
+ if (budget === null) return softSkip('blocked', 'precondition not met — `budget === null` returned early (seam, prior step, or fixture unavailable)');
153
155
  expect(
154
156
  budget,
155
- driver.describe(
157
+ req('openwop.it.envelope-completion-distinguishes-truncation.truncation-retry-budget-strictly-greater-than-initial-rfc-0033-b-truncationbudge',
156
158
  'RFCS/0033-envelope-completion-contract.md §B',
157
159
  'truncation retry MUST multiply maxTokens by truncationBudgetMultiplier — final budget > initial 50 fixture value',
158
160
  ),
@@ -162,19 +164,19 @@ describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: trunca
162
164
 
163
165
  describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: schema-violation path (RFC 0033 §C)', () => {
164
166
  it('schema-violation: NO envelope.truncated; envelope.retry.attempted reason ∈ {schema-violation, parse-error}', async () => {
165
- if (!isFixtureAdvertised(SCHEMA_VIOLATION_FIXTURE)) return;
167
+ if (!isFixtureAdvertised(SCHEMA_VIOLATION_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(SCHEMA_VIOLATION_FIXTURE)` returned early');
166
168
  const seed = await programMock([
167
169
  { content: 'not valid json' },
168
170
  { content: '{"valid":true}' },
169
171
  ]);
170
- if (seed.status === 404) return;
172
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
171
173
 
172
174
  const result = await startRunAndRead(SCHEMA_VIOLATION_FIXTURE);
173
- if (result === null) return;
175
+ if (result === null) return softSkip('blocked', 'precondition not met — `result === null` returned early (seam, prior step, or fixture unavailable)');
174
176
  const truncated = result.events.find((e) => e.type === 'envelope.truncated');
175
177
  expect(
176
178
  truncated,
177
- driver.describe(
179
+ req('openwop.it.envelope-completion-distinguishes-truncation.schema-violation-no-envelope-truncated-envelope-retry-attempted-reason-schema-vi',
178
180
  'RFCS/0033-envelope-completion-contract.md §C',
179
181
  'schema-violation path MUST NOT emit envelope.truncated (truncation and schema-violation are distinct paths per RFC 0033 §A)',
180
182
  ),
@@ -184,7 +186,7 @@ describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: schema
184
186
  const reason = retry!.payload?.reason as string | undefined;
185
187
  expect(
186
188
  reason === 'schema-violation' || reason === 'parse-error',
187
- driver.describe(
189
+ req('openwop.it.envelope-completion-distinguishes-truncation.schema-violation-no-envelope-truncated-envelope-retry-attempted-reason-schema-vi',
188
190
  'RFCS/0033-envelope-completion-contract.md §C',
189
191
  'schema-violation-routed retry MUST carry reason ∈ {schema-violation, parse-error}; truncation reason is reserved for the budget-doubling path',
190
192
  ),
@@ -192,16 +194,16 @@ describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: schema
192
194
  });
193
195
 
194
196
  it('schema-violation: retry budget UNCHANGED from initial (no budget multiplication on this path)', async () => {
195
- if (!isFixtureAdvertised(SCHEMA_VIOLATION_FIXTURE)) return;
197
+ if (!isFixtureAdvertised(SCHEMA_VIOLATION_FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(SCHEMA_VIOLATION_FIXTURE)` returned early');
196
198
  const seed = await programMock([
197
199
  { content: 'not valid json' },
198
200
  { content: '{"valid":true}' },
199
201
  ]);
200
- if (seed.status === 404) return;
202
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
201
203
 
202
204
  await startRunAndRead(SCHEMA_VIOLATION_FIXTURE);
203
205
  const budget = await lastBudget();
204
- if (budget === null) return;
206
+ if (budget === null) return softSkip('blocked', 'precondition not met — `budget === null` returned early (seam, prior step, or fixture unavailable)');
205
207
  // The schema-violation fixture doesn't set maxTokens explicitly →
206
208
  // budget snapshots whatever the host's default is on each call.
207
209
  // The KEY invariant: the retry call's budget MUST NOT be multiplied
@@ -214,7 +216,7 @@ describe.skipIf(HTTP_SKIP)('envelope-completion-distinguishes-truncation: schema
214
216
  if (budget !== null) {
215
217
  expect(
216
218
  budget,
217
- driver.describe(
219
+ req('openwop.it.envelope-completion-distinguishes-truncation.schema-violation-retry-budget-unchanged-from-initial-no-budget-multiplication-on',
218
220
  'RFCS/0033-envelope-completion-contract.md §C',
219
221
  'schema-violation retry MUST NOT multiply maxTokens — budget stays at the original value (host default)',
220
222
  ),
@@ -28,6 +28,8 @@ import { describe, it, expect } from 'vitest';
28
28
  import { driver } from '../lib/driver.js';
29
29
  import { pollUntilTerminal } from '../lib/polling.js';
30
30
  import { isFixtureAdvertised } from '../lib/fixtures.js';
31
+ import { req } from '../lib/requirement-ids.js';
32
+ import { softSkip } from '../lib/soft-skip.js';
31
33
 
32
34
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
33
35
  const FIXTURE = 'conformance-envelope-nl-to-format-engaged';
@@ -69,17 +71,17 @@ const NL_THEN_COERCED_PROGRAM = [
69
71
 
70
72
  describe.skipIf(HTTP_SKIP)('envelope-nl-to-format-engaged: runtime behavior (RFC 0032 §B.5 MAY)', () => {
71
73
  it('when retry exhaustion triggers the NL-to-Format fallback, exactly one `envelope.nlToFormat.engaged` event fires', async () => {
72
- if (!isFixtureAdvertised(FIXTURE)) return;
74
+ if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
73
75
  const seed = await programMock(NL_THEN_COERCED_PROGRAM);
74
- if (seed.status === 404) return;
76
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
75
77
  expect(seed.status).toBe(200);
76
78
 
77
79
  const events = await runAndReadEvents();
78
- if (events === null) return;
80
+ if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
79
81
  const engagements = events.filter((e) => e.type === 'envelope.nlToFormat.engaged');
80
82
  expect(
81
83
  engagements.length,
82
- driver.describe(
84
+ req('openwop.it.envelope-nl-to-format-engaged.when-retry-exhaustion-triggers-the-nl-to-format-fallback-exactly-one-envelope-nl',
83
85
  'RFCS/0032-envelope-reliability-events.md §B.5',
84
86
  'exactly one envelope.nlToFormat.engaged event MUST fire when the host detects NL-shape responses after retry exhaustion',
85
87
  ),
@@ -87,17 +89,17 @@ describe.skipIf(HTTP_SKIP)('envelope-nl-to-format-engaged: runtime behavior (RFC
87
89
  });
88
90
 
89
91
  it('`originalEnvelopeType` carries the envelope kind the original attempt targeted', async () => {
90
- if (!isFixtureAdvertised(FIXTURE)) return;
92
+ if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
91
93
  const seed = await programMock(NL_THEN_COERCED_PROGRAM);
92
- if (seed.status === 404) return;
94
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
93
95
 
94
96
  const events = await runAndReadEvents();
95
- if (events === null) return;
97
+ if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
96
98
  const engagement = events.find((e) => e.type === 'envelope.nlToFormat.engaged');
97
99
  expect(engagement).toBeDefined();
98
100
  expect(
99
101
  typeof engagement!.payload?.originalEnvelopeType,
100
- driver.describe(
102
+ req('openwop.it.envelope-nl-to-format-engaged.originalenvelopetype-carries-the-envelope-kind-the-original-attempt-targeted',
101
103
  'RFCS/0032-envelope-reliability-events.md §B.5',
102
104
  'originalEnvelopeType MUST be present and string-typed — derived from the response-schema or wrapping metadata',
103
105
  ),
@@ -106,19 +108,19 @@ describe.skipIf(HTTP_SKIP)('envelope-nl-to-format-engaged: runtime behavior (RFC
106
108
  });
107
109
 
108
110
  it('`fallbackCalls >= 1` reports the number of secondary LLM calls used to reformat free-form output into the envelope schema', async () => {
109
- if (!isFixtureAdvertised(FIXTURE)) return;
111
+ if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
110
112
  const seed = await programMock(NL_THEN_COERCED_PROGRAM);
111
- if (seed.status === 404) return;
113
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
112
114
 
113
115
  const events = await runAndReadEvents();
114
- if (events === null) return;
116
+ if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
115
117
  const engagement = events.find((e) => e.type === 'envelope.nlToFormat.engaged');
116
118
  expect(engagement).toBeDefined();
117
119
  const fallbackCalls = engagement!.payload?.fallbackCalls;
118
120
  expect(typeof fallbackCalls).toBe('number');
119
121
  expect(
120
122
  fallbackCalls as number,
121
- driver.describe(
123
+ req('openwop.it.envelope-nl-to-format-engaged.fallbackcalls-1-reports-the-number-of-secondary-llm-calls-used-to-reformat-free',
122
124
  'RFCS/0032-envelope-reliability-events.md §B.5',
123
125
  'fallbackCalls MUST be >= 1 — the fallback fired at least one secondary call to reformat the free-form output',
124
126
  ),
@@ -126,16 +128,16 @@ describe.skipIf(HTTP_SKIP)('envelope-nl-to-format-engaged: runtime behavior (RFC
126
128
  });
127
129
 
128
130
  it('the eventual envelope acceptance (when fallback succeeds) records normally via downstream RunEventDoc', async () => {
129
- if (!isFixtureAdvertised(FIXTURE)) return;
131
+ if (!isFixtureAdvertised(FIXTURE)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early');
130
132
  const seed = await programMock(NL_THEN_COERCED_PROGRAM);
131
- if (seed.status === 404) return;
133
+ if (seed.status === 404) return softSkip('blocked', 'precondition not met — `seed.status === 404` returned early (seam, prior step, or fixture unavailable)');
132
134
 
133
135
  const events = await runAndReadEvents();
134
- if (events === null) return;
136
+ if (events === null) return softSkip('blocked', 'precondition not met — `events === null` returned early (seam, prior step, or fixture unavailable)');
135
137
  const nodeCompleted = events.find((e) => e.type === 'node.completed' && e.nodeId === NODE_ID);
136
138
  expect(
137
139
  nodeCompleted,
138
- driver.describe(
140
+ req('openwop.it.envelope-nl-to-format-engaged.the-eventual-envelope-acceptance-when-fallback-succeeds-records-normally-via-dow',
139
141
  'RFCS/0032-envelope-reliability-events.md §B.5',
140
142
  'NL-to-Format fallback success MUST reach node.completed — the coerced envelope flows downstream like any other accepted envelope',
141
143
  ),
@@ -143,7 +145,7 @@ describe.skipIf(HTTP_SKIP)('envelope-nl-to-format-engaged: runtime behavior (RFC
143
145
  const completedPayload = JSON.stringify(nodeCompleted?.payload ?? {});
144
146
  expect(
145
147
  completedPayload.includes('coerced-ok'),
146
- driver.describe(
148
+ req('openwop.it.envelope-nl-to-format-engaged.the-eventual-envelope-acceptance-when-fallback-succeeds-records-normally-via-dow',
147
149
  'RFCS/0032-envelope-reliability-events.md §B.5',
148
150
  'the coerced structured data from the secondary call MUST flow to the downstream RunEventDoc',
149
151
  ),