@openwop/openwop-conformance 1.163.0 → 2.0.0-rc.1

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 (611) hide show
  1. package/README.md +11 -2
  2. package/dist/cli.js +262 -14
  3. package/dist/lib/certification-bundle-v3.js +142 -0
  4. package/dist/lib/paths.js +25 -3
  5. package/dist/lib/requirement-ids.js +57 -4
  6. package/dist/lib/requirement-ledger.js +1 -0
  7. package/dist/lib/scenario-disposition.js +6 -1
  8. package/dist/lib/spec-coherence.js +13 -32
  9. package/dist/spec-artifacts.lock.json +5 -0
  10. package/package.json +11 -33
  11. package/requirements.json +22892 -11701
  12. package/scenario-majors.json +1493 -0
  13. package/schemas/CORPUS-STAMP.json +137 -5
  14. package/src/cli.ts +236 -19
  15. package/src/global-setup.ts +3 -2
  16. package/src/lib/certification-bundle-v3.ts +175 -0
  17. package/src/lib/corpus-stamp.ts +29 -1
  18. package/src/lib/driver.ts +9 -1
  19. package/src/lib/era2-seed.ts +197 -0
  20. package/src/lib/paths.ts +25 -3
  21. package/src/lib/requirement-ids.ts +54 -4
  22. package/src/lib/requirement-ledger.ts +7 -1
  23. package/src/lib/scenario-disposition.ts +6 -1
  24. package/src/lib/seams.ts +45 -0
  25. package/src/lib/spec-coherence.ts +15 -32
  26. package/src/lib/v2.ts +62 -0
  27. package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
  28. package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
  29. package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
  30. package/src/scenarios/a2a-peer-authority.test.ts +7 -6
  31. package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
  32. package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
  33. package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
  34. package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
  35. package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
  36. package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
  37. package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
  38. package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
  39. package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
  40. package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
  41. package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
  42. package/src/scenarios/agent-deployment-shape.test.ts +22 -24
  43. package/src/scenarios/agent-eval-run.test.ts +19 -18
  44. package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
  45. package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
  46. package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
  47. package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
  48. package/src/scenarios/agent-live-structured-output.test.ts +7 -6
  49. package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
  50. package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
  51. package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
  52. package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
  53. package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
  54. package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
  55. package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
  56. package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
  57. package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
  58. package/src/scenarios/agent-platform-profile.test.ts +18 -19
  59. package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
  60. package/src/scenarios/agent-roster-attribution.test.ts +18 -17
  61. package/src/scenarios/agent-roster-shape.test.ts +17 -19
  62. package/src/scenarios/agent-verifier-shape.test.ts +11 -11
  63. package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
  64. package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
  65. package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
  66. package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
  67. package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
  68. package/src/scenarios/agentMessageReducer.test.ts +2 -1
  69. package/src/scenarios/agentMetadata.test.ts +2 -1
  70. package/src/scenarios/agentPackCatalog.test.ts +23 -21
  71. package/src/scenarios/agentPackExport.test.ts +4 -2
  72. package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
  73. package/src/scenarios/agentPackInstall.test.ts +4 -2
  74. package/src/scenarios/agentPackProvenance.test.ts +2 -1
  75. package/src/scenarios/agentReasoningEvents.test.ts +3 -2
  76. package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
  77. package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
  78. package/src/scenarios/ai-envelope-shape.test.ts +31 -29
  79. package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
  80. package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
  81. package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
  82. package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
  83. package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
  84. package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
  85. package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
  86. package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
  87. package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
  88. package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
  89. package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
  90. package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
  91. package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
  92. package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
  93. package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
  94. package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
  95. package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
  96. package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
  97. package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
  98. package/src/scenarios/append-ordering.test.ts +7 -5
  99. package/src/scenarios/approval-gate-events.test.ts +4 -3
  100. package/src/scenarios/approval-gate-flow.test.ts +4 -3
  101. package/src/scenarios/approval-payload.test.ts +5 -4
  102. package/src/scenarios/artifact-auth.test.ts +7 -6
  103. package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
  104. package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
  105. package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
  106. package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
  107. package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
  108. package/src/scenarios/audit-log-integrity.test.ts +8 -6
  109. package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
  110. package/src/scenarios/auth-mtls.test.ts +22 -20
  111. package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
  112. package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
  113. package/src/scenarios/auth-saml-profile.test.ts +14 -12
  114. package/src/scenarios/auth-scim-profile.test.ts +3 -2
  115. package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
  116. package/src/scenarios/auth-subject-link.test.ts +11 -10
  117. package/src/scenarios/auth.test.ts +5 -4
  118. package/src/scenarios/authorization-fail-closed.test.ts +3 -2
  119. package/src/scenarios/authorization-roles-shape.test.ts +9 -7
  120. package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
  121. package/src/scenarios/blob-presign-expiry.test.ts +12 -10
  122. package/src/scenarios/blob-roundtrip.test.ts +0 -0
  123. package/src/scenarios/budget-enforcement.test.ts +15 -14
  124. package/src/scenarios/budget-policy-shape.test.ts +18 -19
  125. package/src/scenarios/bulk-cancel.test.ts +9 -8
  126. package/src/scenarios/byok-auth-modes.test.ts +13 -14
  127. package/src/scenarios/byok-roundtrip.test.ts +12 -10
  128. package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
  129. package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
  130. package/src/scenarios/callai-multimodal.test.ts +5 -3
  131. package/src/scenarios/cancellation.test.ts +6 -5
  132. package/src/scenarios/cap-breach.test.ts +15 -14
  133. package/src/scenarios/capability-arm-witness.test.ts +5 -3
  134. package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
  135. package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
  136. package/src/scenarios/certification-bundle-v2.test.ts +11 -10
  137. package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
  138. package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
  139. package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
  140. package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
  141. package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
  142. package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
  143. package/src/scenarios/channel-presence-shape.test.ts +11 -12
  144. package/src/scenarios/channel-ttl.test.ts +6 -5
  145. package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
  146. package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
  147. package/src/scenarios/commitment-fired.test.ts +6 -5
  148. package/src/scenarios/compensation-behavior.test.ts +24 -23
  149. package/src/scenarios/compensation-recovery.test.ts +28 -27
  150. package/src/scenarios/configurable-schema.test.ts +8 -6
  151. package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
  152. package/src/scenarios/conformance-execution-witness.test.ts +9 -8
  153. package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
  154. package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
  155. package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
  156. package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
  157. package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
  158. package/src/scenarios/connection-provider-resolution.test.ts +18 -16
  159. package/src/scenarios/connector-manifest-validity.test.ts +8 -7
  160. package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
  161. package/src/scenarios/context-summarization-replay.test.ts +14 -12
  162. package/src/scenarios/contract-provenance.test.ts +18 -18
  163. package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
  164. package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
  165. package/src/scenarios/conversationLifecycle.test.ts +2 -1
  166. package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
  167. package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
  168. package/src/scenarios/core-standard-profile.test.ts +8 -9
  169. package/src/scenarios/cost-attribution.test.ts +23 -21
  170. package/src/scenarios/credential-payload-redaction.test.ts +4 -3
  171. package/src/scenarios/credentials-capability-shape.test.ts +5 -4
  172. package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
  173. package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
  174. package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
  175. package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
  176. package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
  177. package/src/scenarios/data-residency-admission.test.ts +15 -14
  178. package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
  179. package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
  180. package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
  181. package/src/scenarios/debugBundle.test.ts +25 -23
  182. package/src/scenarios/discovery-families-view.test.ts +5 -4
  183. package/src/scenarios/discovery.test.ts +30 -29
  184. package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
  185. package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
  186. package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
  187. package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
  188. package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
  189. package/src/scenarios/dispatchLoop.test.ts +3 -2
  190. package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
  191. package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
  192. package/src/scenarios/distillation-shape.test.ts +4 -4
  193. package/src/scenarios/distillation-stable-archive.test.ts +6 -6
  194. package/src/scenarios/distillation-token-budget.test.ts +5 -5
  195. package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
  196. package/src/scenarios/egress-audience-binding.test.ts +11 -10
  197. package/src/scenarios/egress-decision-content-free.test.ts +6 -5
  198. package/src/scenarios/egress-provenance-shape.test.ts +17 -18
  199. package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
  200. package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
  201. package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
  202. package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
  203. package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
  204. package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
  205. package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
  206. package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
  207. package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
  208. package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
  209. package/src/scenarios/envelope-truncated.test.ts +19 -17
  210. package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
  211. package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
  212. package/src/scenarios/errors.test.ts +20 -19
  213. package/src/scenarios/eventOrdering.test.ts +16 -14
  214. package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
  215. package/src/scenarios/experimental-tier-shape.test.ts +17 -15
  216. package/src/scenarios/export-bundle-portability.test.ts +17 -17
  217. package/src/scenarios/failure-path.test.ts +7 -6
  218. package/src/scenarios/feedback-capability-shape.test.ts +4 -3
  219. package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
  220. package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
  221. package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
  222. package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
  223. package/src/scenarios/feedback-record-and-list.test.ts +2 -1
  224. package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
  225. package/src/scenarios/fixtures-gating.test.ts +29 -28
  226. package/src/scenarios/fixtures-valid.test.ts +16 -15
  227. package/src/scenarios/form-content-instantiation.test.ts +15 -14
  228. package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
  229. package/src/scenarios/fs-path-traversal.test.ts +14 -12
  230. package/src/scenarios/goal-standing-continuation.test.ts +21 -21
  231. package/src/scenarios/grpc-transport.test.ts +9 -7
  232. package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
  233. package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
  234. package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
  235. package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
  236. package/src/scenarios/highConcurrency.test.ts +14 -13
  237. package/src/scenarios/host-callback-declaration.test.ts +8 -7
  238. package/src/scenarios/http-client-ssrf.test.ts +7 -5
  239. package/src/scenarios/i18n-negotiation.test.ts +14 -12
  240. package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
  241. package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
  242. package/src/scenarios/idempotency.test.ts +8 -7
  243. package/src/scenarios/idempotencyRetry.test.ts +13 -11
  244. package/src/scenarios/identity-owner-shape.test.ts +6 -5
  245. package/src/scenarios/identity-passthrough.test.ts +4 -3
  246. package/src/scenarios/interrupt-approval.test.ts +6 -5
  247. package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
  248. package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
  249. package/src/scenarios/interrupt-clarification.test.ts +4 -3
  250. package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
  251. package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
  252. package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
  253. package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
  254. package/src/scenarios/interruptRace.test.ts +12 -10
  255. package/src/scenarios/kv-atomic-increment.test.ts +11 -9
  256. package/src/scenarios/kv-cas.test.ts +14 -12
  257. package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
  258. package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
  259. package/src/scenarios/localized-content-delivery.test.ts +24 -26
  260. package/src/scenarios/maliciousManifest.test.ts +10 -8
  261. package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
  262. package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
  263. package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
  264. package/src/scenarios/mcp-discoverability.test.ts +9 -7
  265. package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
  266. package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
  267. package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
  268. package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
  269. package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
  270. package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
  271. package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
  272. package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
  273. package/src/scenarios/mcp-stateless-request.test.ts +11 -10
  274. package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
  275. package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
  276. package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
  277. package/src/scenarios/media-url-inline-cap.test.ts +21 -19
  278. package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
  279. package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
  280. package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
  281. package/src/scenarios/memory-attribution-shape.test.ts +4 -3
  282. package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
  283. package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
  284. package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
  285. package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
  286. package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
  287. package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
  288. package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
  289. package/src/scenarios/memory-degraded-projection.test.ts +10 -9
  290. package/src/scenarios/memory-injection-budget.test.ts +15 -14
  291. package/src/scenarios/metric-emission.test.ts +4 -3
  292. package/src/scenarios/model-capability-insufficient.test.ts +19 -17
  293. package/src/scenarios/model-capability-substituted.test.ts +20 -18
  294. package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
  295. package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
  296. package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
  297. package/src/scenarios/multi-node-ordering.test.ts +4 -3
  298. package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
  299. package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
  300. package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
  301. package/src/scenarios/multi-region-idempotency.test.ts +6 -5
  302. package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
  303. package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
  304. package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
  305. package/src/scenarios/oauth-capability-shape.test.ts +5 -4
  306. package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
  307. package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
  308. package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
  309. package/src/scenarios/orchestratorDispatch.test.ts +2 -1
  310. package/src/scenarios/orchestratorTermination.test.ts +2 -1
  311. package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
  312. package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
  313. package/src/scenarios/otel-emission-grpc.test.ts +3 -2
  314. package/src/scenarios/otel-emission.test.ts +6 -5
  315. package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
  316. package/src/scenarios/otel-trace-propagation.test.ts +2 -1
  317. package/src/scenarios/owner-subject-echo.test.ts +13 -12
  318. package/src/scenarios/owner-subject-shape.test.ts +11 -10
  319. package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
  320. package/src/scenarios/pack-registry-isolation.test.ts +4 -3
  321. package/src/scenarios/pack-registry-publish.test.ts +65 -63
  322. package/src/scenarios/pack-registry.test.ts +38 -36
  323. package/src/scenarios/pause-resume.test.ts +18 -16
  324. package/src/scenarios/policies.test.ts +20 -18
  325. package/src/scenarios/production-backpressure.test.ts +18 -16
  326. package/src/scenarios/production-retention-expiry.test.ts +8 -6
  327. package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
  328. package/src/scenarios/profileDerivation.test.ts +34 -33
  329. package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
  330. package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
  331. package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
  332. package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
  333. package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
  334. package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
  335. package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
  336. package/src/scenarios/prompt-pack-install.test.ts +14 -12
  337. package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
  338. package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
  339. package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
  340. package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
  341. package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
  342. package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
  343. package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
  344. package/src/scenarios/prompt-template-shape.test.ts +30 -28
  345. package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
  346. package/src/scenarios/protocol-versions-array.test.ts +10 -9
  347. package/src/scenarios/provider-usage.test.ts +17 -15
  348. package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
  349. package/src/scenarios/purpose-propagation.test.ts +23 -21
  350. package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
  351. package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
  352. package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
  353. package/src/scenarios/rate-limit-envelope.test.ts +6 -5
  354. package/src/scenarios/redaction.test.ts +13 -11
  355. package/src/scenarios/redactionAdversarial.test.ts +11 -9
  356. package/src/scenarios/registry-public.test.ts +12 -11
  357. package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
  358. package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
  359. package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
  360. package/src/scenarios/replay-fork.test.ts +20 -19
  361. package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
  362. package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
  363. package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
  364. package/src/scenarios/replay-retention-expiry.test.ts +11 -9
  365. package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
  366. package/src/scenarios/replayDeterminism.test.ts +13 -12
  367. package/src/scenarios/requirement-ledger.test.ts +15 -14
  368. package/src/scenarios/restart-during-run.test.ts +3 -2
  369. package/src/scenarios/route-coverage.test.ts +20 -19
  370. package/src/scenarios/run-diff.test.ts +22 -20
  371. package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
  372. package/src/scenarios/run-transport-economy.test.ts +13 -11
  373. package/src/scenarios/runner-ledger.test.ts +17 -16
  374. package/src/scenarios/runs-lifecycle.test.ts +7 -6
  375. package/src/scenarios/runtime-capabilities.test.ts +12 -10
  376. package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
  377. package/src/scenarios/runtime-requires-shape.test.ts +7 -6
  378. package/src/scenarios/safefetch-behavior.test.ts +22 -21
  379. package/src/scenarios/safefetch-live-audit.test.ts +14 -13
  380. package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
  381. package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
  382. package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
  383. package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
  384. package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
  385. package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
  386. package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
  387. package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
  388. package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
  389. package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
  390. package/src/scenarios/self-hosted-runner.test.ts +26 -24
  391. package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
  392. package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
  393. package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
  394. package/src/scenarios/sql-injection-rejection.test.ts +8 -6
  395. package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
  396. package/src/scenarios/staleClaim.test.ts +5 -4
  397. package/src/scenarios/stream-modes-buffer.test.ts +8 -7
  398. package/src/scenarios/stream-modes-mixed.test.ts +10 -9
  399. package/src/scenarios/stream-modes.test.ts +12 -11
  400. package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
  401. package/src/scenarios/stream-text-fixture.test.ts +14 -13
  402. package/src/scenarios/streamReconnect.test.ts +13 -11
  403. package/src/scenarios/strict-behavior-gate.test.ts +9 -8
  404. package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
  405. package/src/scenarios/subrun-approval-gate.test.ts +3 -3
  406. package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
  407. package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
  408. package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
  409. package/src/scenarios/subworkflow.test.ts +10 -9
  410. package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
  411. package/src/scenarios/table-cursor-pagination.test.ts +8 -6
  412. package/src/scenarios/table-schema-enforcement.test.ts +7 -5
  413. package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
  414. package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
  415. package/src/scenarios/tool-catalog-projection.test.ts +11 -9
  416. package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
  417. package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
  418. package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
  419. package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
  420. package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
  421. package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
  422. package/src/scenarios/tool-hooks-shape.test.ts +3 -3
  423. package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
  424. package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
  425. package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
  426. package/src/scenarios/trigger-ingestion.test.ts +19 -17
  427. package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
  428. package/src/scenarios/v2-approver-enforced.test.ts +97 -0
  429. package/src/scenarios/v2-assurance-downgrade-audited.test.ts +75 -0
  430. package/src/scenarios/v2-bundle-v3-signed.test.ts +96 -0
  431. package/src/scenarios/v2-capabilities-root-closed.test.ts +63 -0
  432. package/src/scenarios/v2-capability-record-shape.test.ts +104 -0
  433. package/src/scenarios/v2-chain-pin-exact.test.ts +118 -0
  434. package/src/scenarios/v2-coherence-not-in-bundle.test.ts +98 -0
  435. package/src/scenarios/v2-compensation-read-projection.test.ts +85 -0
  436. package/src/scenarios/v2-configurable-closed.test.ts +67 -0
  437. package/src/scenarios/v2-dual-stack-negotiation.test.ts +118 -0
  438. package/src/scenarios/v2-effect-identity-business-key.test.ts +132 -0
  439. package/src/scenarios/v2-effect-seam-manifest.test.ts +163 -0
  440. package/src/scenarios/v2-enum-growth-rule.test.ts +69 -0
  441. package/src/scenarios/v2-era-key.test.ts +86 -0
  442. package/src/scenarios/v2-error-registry.test.ts +89 -0
  443. package/src/scenarios/v2-event-type-closed.test.ts +97 -0
  444. package/src/scenarios/v2-fork-a-v1-run.test.ts +109 -0
  445. package/src/scenarios/v2-form-when-reuses-edge-conditions.test.ts +70 -0
  446. package/src/scenarios/v2-header-scheme.test.ts +67 -0
  447. package/src/scenarios/v2-id-grammar.test.ts +77 -0
  448. package/src/scenarios/v2-idempotency-key-grammar.test.ts +65 -0
  449. package/src/scenarios/v2-interrupt-token-scheme.test.ts +55 -0
  450. package/src/scenarios/v2-lane-issuer-advertised.test.ts +62 -0
  451. package/src/scenarios/v2-legacy-profiles-absent.test.ts +78 -0
  452. package/src/scenarios/v2-manifest-ceiling-refused.test.ts +130 -0
  453. package/src/scenarios/v2-manifest-hatch-carried.test.ts +120 -0
  454. package/src/scenarios/v2-min-client-version.test.ts +48 -0
  455. package/src/scenarios/v2-minimum-version-refused.test.ts +141 -0
  456. package/src/scenarios/v2-mrtr-rounds-ceiling.test.ts +95 -0
  457. package/src/scenarios/v2-negotiation-authenticated.test.ts +125 -0
  458. package/src/scenarios/v2-negotiation-decided-emitted.test.ts +149 -0
  459. package/src/scenarios/v2-no-transport-advertisement.test.ts +57 -0
  460. package/src/scenarios/v2-owner-subject-required.test.ts +72 -0
  461. package/src/scenarios/v2-pack-isolation.test.ts +147 -0
  462. package/src/scenarios/v2-payload-registry-closed.test.ts +110 -0
  463. package/src/scenarios/v2-peer-dependency-declared.test.ts +132 -0
  464. package/src/scenarios/v2-pinned-run-disposition.test.ts +124 -0
  465. package/src/scenarios/v2-poll-cursor-v2.test.ts +114 -0
  466. package/src/scenarios/v2-preferred-version-default.test.ts +83 -0
  467. package/src/scenarios/v2-profiles-derived-only.test.ts +70 -0
  468. package/src/scenarios/v2-provider-conflict.test.ts +115 -0
  469. package/src/scenarios/v2-refresh-sla.test.ts +78 -0
  470. package/src/scenarios/v2-relaxation-recorded.test.ts +134 -0
  471. package/src/scenarios/v2-revocation-honored.test.ts +66 -0
  472. package/src/scenarios/v2-subject-link-record.test.ts +102 -0
  473. package/src/scenarios/v2-unmapped-type-refused.test.ts +95 -0
  474. package/src/scenarios/v2-v1-events-translated.test.ts +105 -0
  475. package/src/scenarios/v2-v1-signed-webhook-accepted.test.ts +109 -0
  476. package/src/scenarios/v2-webhook-durable-delivery.test.ts +238 -0
  477. package/src/scenarios/v2-well-known-one-resource.test.ts +129 -0
  478. package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
  479. package/src/scenarios/verifier-gating.test.ts +8 -6
  480. package/src/scenarios/version-fold.test.ts +9 -8
  481. package/src/scenarios/version-negotiation.test.ts +12 -11
  482. package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
  483. package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
  484. package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
  485. package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
  486. package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
  487. package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
  488. package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
  489. package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
  490. package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
  491. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
  492. package/src/scenarios/wasm-pack-load.test.ts +4 -3
  493. package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
  494. package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
  495. package/src/scenarios/webhook-negative.test.ts +11 -9
  496. package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
  497. package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
  498. package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
  499. package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
  500. package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
  501. package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
  502. package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
  503. package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
  504. package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
  505. package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
  506. package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
  507. package/src/scenarios/workflow-variable-format.test.ts +24 -24
  508. package/src/scenarios/workload-identity-behavior.test.ts +15 -13
  509. package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
  510. package/src/scenarios/workspace-behavior.test.ts +19 -18
  511. package/src/scenarios/workspace-capability-shape.test.ts +3 -2
  512. package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
  513. package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
  514. package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
  515. package/src/setup.ts +44 -6
  516. package/vitest.config.ts +5 -1
  517. package/api/.redocly.lint-ignore.yaml +0 -22
  518. package/api/asyncapi.yaml +0 -834
  519. package/api/grpc/openwop.proto +0 -251
  520. package/api/openapi.yaml +0 -2693
  521. package/api/redocly.yaml +0 -23
  522. package/schemas/README.md +0 -144
  523. package/schemas/a2a-task-state.schema.json +0 -78
  524. package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
  525. package/schemas/agent-deployment-transition.schema.json +0 -49
  526. package/schemas/agent-deployment.schema.json +0 -54
  527. package/schemas/agent-eval-suite.schema.json +0 -140
  528. package/schemas/agent-inventory-response.schema.json +0 -115
  529. package/schemas/agent-manifest.schema.json +0 -156
  530. package/schemas/agent-org-chart.schema.json +0 -82
  531. package/schemas/agent-ref.schema.json +0 -63
  532. package/schemas/agent-roster-entry.schema.json +0 -81
  533. package/schemas/agent-roster-response.schema.json +0 -21
  534. package/schemas/ai-envelope.schema.json +0 -134
  535. package/schemas/annotation-create.schema.json +0 -37
  536. package/schemas/annotation.schema.json +0 -56
  537. package/schemas/artifact-type-pack-manifest.schema.json +0 -244
  538. package/schemas/audit-verify-result.schema.json +0 -90
  539. package/schemas/budget-policy.schema.json +0 -18
  540. package/schemas/capabilities.schema.json +0 -4160
  541. package/schemas/certification-bundle-v2.schema.json +0 -118
  542. package/schemas/channel-presence-payload.schema.json +0 -41
  543. package/schemas/channel-written-payload.schema.json +0 -55
  544. package/schemas/chat-card-pack-manifest.schema.json +0 -253
  545. package/schemas/compact-tool-descriptor.schema.json +0 -51
  546. package/schemas/compensation-policy.schema.json +0 -64
  547. package/schemas/conformance-certification-bundle.schema.json +0 -86
  548. package/schemas/connection-pack-manifest.schema.json +0 -353
  549. package/schemas/conversation-event.schema.json +0 -168
  550. package/schemas/conversation-turn.schema.json +0 -117
  551. package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
  552. package/schemas/credential-provenance.schema.json +0 -18
  553. package/schemas/credential-reference.schema.json +0 -21
  554. package/schemas/debug-bundle.schema.json +0 -196
  555. package/schemas/dispatch-config.schema.json +0 -112
  556. package/schemas/envelopes/clarification.request.schema.json +0 -52
  557. package/schemas/envelopes/error.schema.json +0 -30
  558. package/schemas/envelopes/media.audio.schema.json +0 -38
  559. package/schemas/envelopes/media.file.schema.json +0 -37
  560. package/schemas/envelopes/media.image.schema.json +0 -33
  561. package/schemas/envelopes/schema.request.schema.json +0 -26
  562. package/schemas/envelopes/schema.response.schema.json +0 -22
  563. package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
  564. package/schemas/error-envelope.schema.json +0 -25
  565. package/schemas/eval-summary.schema.json +0 -92
  566. package/schemas/export-bundle.schema.json +0 -66
  567. package/schemas/form-content-pack-manifest.schema.json +0 -243
  568. package/schemas/frontend-plugin-manifest.schema.json +0 -109
  569. package/schemas/goal.schema.json +0 -104
  570. package/schemas/heartbeat-evaluated.schema.json +0 -14
  571. package/schemas/heartbeat-state-changed.schema.json +0 -14
  572. package/schemas/localized-content-language-settings.schema.json +0 -26
  573. package/schemas/localized-content-page-response.schema.json +0 -60
  574. package/schemas/localized-content-page.schema.json +0 -62
  575. package/schemas/localized-content-section.schema.json +0 -51
  576. package/schemas/memory-entry.schema.json +0 -36
  577. package/schemas/memory-list-options.schema.json +0 -37
  578. package/schemas/node-pack-manifest.schema.json +0 -654
  579. package/schemas/orchestrator-decision.schema.json +0 -90
  580. package/schemas/org-chart-responsibility-view.schema.json +0 -26
  581. package/schemas/pack-lockfile.schema.json +0 -108
  582. package/schemas/prompt-kind.schema.json +0 -8
  583. package/schemas/prompt-pack-manifest.schema.json +0 -117
  584. package/schemas/prompt-ref.schema.json +0 -40
  585. package/schemas/prompt-template.schema.json +0 -149
  586. package/schemas/proposal.schema.json +0 -84
  587. package/schemas/registry-version-manifest.schema.json +0 -208
  588. package/schemas/residency.schema.json +0 -16
  589. package/schemas/run-ancestry-response.schema.json +0 -54
  590. package/schemas/run-diff-response.schema.json +0 -64
  591. package/schemas/run-event-payloads.schema.json +0 -4452
  592. package/schemas/run-event.schema.json +0 -211
  593. package/schemas/run-options.schema.json +0 -80
  594. package/schemas/run-orchestrator-decided-event.schema.json +0 -20
  595. package/schemas/run-snapshot.schema.json +0 -148
  596. package/schemas/security-advisory.schema.json +0 -109
  597. package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
  598. package/schemas/self-hosted-runner-registration.schema.json +0 -53
  599. package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
  600. package/schemas/subject.schema.json +0 -56
  601. package/schemas/suspend-request.schema.json +0 -207
  602. package/schemas/tool-descriptor.schema.json +0 -63
  603. package/schemas/trigger-event.schema.json +0 -222
  604. package/schemas/trigger-subscription-registration.schema.json +0 -67
  605. package/schemas/trigger-subscription.schema.json +0 -26
  606. package/schemas/ui-plugin-message.schema.json +0 -90
  607. package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
  608. package/schemas/workflow-definition.schema.json +0 -850
  609. package/schemas/workload-identity.schema.json +0 -79
  610. package/schemas/workspace-file-create.schema.json +0 -20
  611. package/schemas/workspace-file.schema.json +0 -39
@@ -24,13 +24,14 @@
24
24
 
25
25
  import { describe, it, expect } from 'vitest';
26
26
  import { behaviorGate } from '../lib/behavior-gate.js';
27
- import { driver } from '../lib/driver.js';
28
27
  import {
29
28
  isAnonymousActorAdvertised,
30
29
  anonDispatch,
31
30
  anonToolCatalog,
32
31
  readAnonymousActorCap,
33
32
  } from '../lib/anonymousActor.js';
33
+ import { req } from '../lib/requirement-ids.js';
34
+ import { softSkip } from '../lib/soft-skip.js';
34
35
 
35
36
  const PROFILE = 'openwop-anonymous-actor';
36
37
 
@@ -41,36 +42,36 @@ describe('anonymous-actor-default-deny (RFC 0132 §C.1)', () => {
41
42
  it('the anon tool catalog returns only the explicit surface grant — never a default baseline', async () => {
42
43
  if (!behaviorGate(PROFILE, await isAnonymousActorAdvertised())) return;
43
44
  const cat = await anonToolCatalog();
44
- if (cat.status === 404 || cat.status === 405) return; // seam unwired — soft-skip
45
+ if (cat.status === 404 || cat.status === 405) return softSkip('blocked', 'precondition not met — `cat.status === 404 || cat.status === 405` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
45
46
  expect(
46
47
  cat.status,
47
- driver.describe('RFC 0132 §C.1', 'the anon tool-catalog read MUST resolve (scoped to the anon principal)'),
48
+ req('openwop.it.anonymous-actor-default-deny.the-anon-tool-catalog-returns-only-the-explicit-surface-grant-never-a-default-ba', 'RFC 0132 §C.1', 'the anon tool-catalog read MUST resolve (scoped to the anon principal)'),
48
49
  ).toBe(200);
49
50
  // Default-deny: the ungranted baseline tool MUST NOT appear in the anon catalog.
50
51
  const names = cat.tools.map((t) => t.name);
51
52
  expect(
52
53
  names,
53
- driver.describe('RFC 0132 §C.1', 'a default-on baseline tool MUST NOT appear in the anon grant'),
54
+ req('openwop.it.anonymous-actor-default-deny.the-anon-tool-catalog-returns-only-the-explicit-surface-grant-never-a-default-ba', 'RFC 0132 §C.1', 'a default-on baseline tool MUST NOT appear in the anon grant'),
54
55
  ).not.toContain(UNGRANTED_TOOL);
55
56
  });
56
57
 
57
58
  it('calling a non-granted tool denies with reason "anon-not-granted" and does not dispatch', async () => {
58
59
  if (!behaviorGate(PROFILE, await isAnonymousActorAdvertised())) return;
59
60
  const res = await anonDispatch({ tool: UNGRANTED_TOOL });
60
- if (res.status === 404 || res.status === 405) return; // seam unwired — soft-skip
61
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
61
62
  const decided = res.json?.authorizationDecided?.payload;
62
63
  expect(
63
64
  decided?.allowed,
64
- driver.describe('RFC 0132 §C.1', 'a non-granted anon tool MUST be denied (allowed:false), never default-allowed'),
65
+ req('openwop.it.anonymous-actor-default-deny.calling-a-non-granted-tool-denies-with-reason-anon-not-granted-and-does-not-disp', 'RFC 0132 §C.1', 'a non-granted anon tool MUST be denied (allowed:false), never default-allowed'),
65
66
  ).toBe(false);
66
67
  expect(
67
68
  decided?.reason,
68
- driver.describe('RFC 0132 §C.1', 'a default-deny denial carries the machine reason "anon-not-granted"'),
69
+ req('openwop.it.anonymous-actor-default-deny.calling-a-non-granted-tool-denies-with-reason-anon-not-granted-and-does-not-disp', 'RFC 0132 §C.1', 'a default-deny denial carries the machine reason "anon-not-granted"'),
69
70
  ).toBe('anon-not-granted');
70
71
  // No dispatch — the seam MUST NOT return a tool result for a denied call.
71
72
  expect(
72
73
  res.json?.result,
73
- driver.describe('RFC 0132 §C.1', 'a denied anon tool MUST NOT dispatch (no result)'),
74
+ req('openwop.it.anonymous-actor-default-deny.calling-a-non-granted-tool-denies-with-reason-anon-not-granted-and-does-not-disp', 'RFC 0132 §C.1', 'a denied anon tool MUST NOT dispatch (no result)'),
74
75
  ).toBeUndefined();
75
76
  });
76
77
 
@@ -80,7 +81,7 @@ describe('anonymous-actor-default-deny (RFC 0132 §C.1)', () => {
80
81
  if ((cap?.tiers ?? []).includes('bounded-write-egress')) {
81
82
  expect(
82
83
  (cap?.writeEgressControls ?? []).length,
83
- driver.describe('RFC 0132 §B.2', 'bounded-write-egress MUST advertise ≥1 writeEgressControl'),
84
+ req('openwop.it.anonymous-actor-default-deny.a-host-that-advertises-bounded-write-egress-also-advertises-a-mandatory-control', 'RFC 0132 §B.2', 'bounded-write-egress MUST advertise ≥1 writeEgressControl'),
84
85
  ).toBeGreaterThan(0);
85
86
  }
86
87
  });
@@ -21,8 +21,9 @@
21
21
 
22
22
  import { describe, it, expect } from 'vitest';
23
23
  import { behaviorGate } from '../lib/behavior-gate.js';
24
- import { driver } from '../lib/driver.js';
25
24
  import { readAnonymousActorCap, anonDispatch } from '../lib/anonymousActor.js';
25
+ import { req } from '../lib/requirement-ids.js';
26
+ import { softSkip } from '../lib/soft-skip.js';
26
27
 
27
28
  const PROFILE = 'openwop-anonymous-actor';
28
29
 
@@ -36,19 +37,19 @@ describe('anonymous-actor-egress-guarded (RFC 0132 §C.3)', () => {
36
37
  tool: 'http.fetch',
37
38
  destination: 'https://attacker.example/exfil',
38
39
  });
39
- if (res.status === 404 || res.status === 405) return; // seam unwired — soft-skip
40
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
40
41
  const egress = res.json?.egressDecided;
41
42
  expect(
42
43
  egress,
43
- driver.describe('RFC 0132 §C.3', 'an anon egress MUST ride the RFC 0079 egress-decision path'),
44
+ req('openwop.it.anonymous-actor-egress-guarded.an-out-of-audience-anon-egress-is-denied-downgraded-and-attaches-no-credential', 'RFC 0132 §C.3', 'an anon egress MUST ride the RFC 0079 egress-decision path'),
44
45
  ).toBeDefined();
45
46
  expect(
46
47
  ['denied', 'downgraded'],
47
- driver.describe('RFC 0132 §C.3', 'an out-of-audience anon egress MUST be denied or downgraded — never allowed-with-credential'),
48
+ req('openwop.it.anonymous-actor-egress-guarded.an-out-of-audience-anon-egress-is-denied-downgraded-and-attaches-no-credential', 'RFC 0132 §C.3', 'an out-of-audience anon egress MUST be denied or downgraded — never allowed-with-credential'),
48
49
  ).toContain(egress?.decision);
49
50
  expect(
50
51
  egress?.credentialAttached === true,
51
- driver.describe('SECURITY anon-actor-egress-ssrf-guarded', 'no tenant/host credential MUST attach out-of-audience'),
52
+ req('openwop.it.anonymous-actor-egress-guarded.an-out-of-audience-anon-egress-is-denied-downgraded-and-attaches-no-credential', 'SECURITY anon-actor-egress-ssrf-guarded', 'no tenant/host credential MUST attach out-of-audience'),
52
53
  ).toBe(false);
53
54
  });
54
55
  });
@@ -19,8 +19,9 @@
19
19
 
20
20
  import { describe, it, expect } from 'vitest';
21
21
  import { behaviorGate } from '../lib/behavior-gate.js';
22
- import { driver } from '../lib/driver.js';
23
22
  import { isAnonymousActorAdvertised, anonDispatch } from '../lib/anonymousActor.js';
23
+ import { req } from '../lib/requirement-ids.js';
24
+ import { softSkip } from '../lib/soft-skip.js';
24
25
 
25
26
  const PROFILE = 'openwop-anonymous-actor';
26
27
 
@@ -32,11 +33,11 @@ describe('anonymous-actor-no-secret-reach (RFC 0132 §C.2/§C.3)', () => {
32
33
  it('a read-tier anon tool call never surfaces a planted BYOK canary', async () => {
33
34
  if (!behaviorGate(PROFILE, await isAnonymousActorAdvertised())) return;
34
35
  const res = await anonDispatch({ tool: 'catalog.read', args: { probeSecrets: true } });
35
- if (res.status === 404 || res.status === 405) return; // seam unwired — soft-skip
36
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
36
37
  const serialized = JSON.stringify(res.json ?? {});
37
38
  expect(
38
39
  serialized.includes(BYOK_CANARY),
39
- driver.describe('SECURITY anon-actor-no-secret-reach', 'an anon tool call MUST NOT surface secret/BYOK material'),
40
+ req('openwop.it.anonymous-actor-no-secret-reach.a-read-tier-anon-tool-call-never-surfaces-a-planted-byok-canary', 'SECURITY anon-actor-no-secret-reach', 'an anon tool call MUST NOT surface secret/BYOK material'),
40
41
  ).toBe(false);
41
42
  });
42
43
 
@@ -50,7 +51,7 @@ describe('anonymous-actor-no-secret-reach (RFC 0132 §C.2/§C.3)', () => {
50
51
  // one non-conformant behavior is resolving/returning the caller's tenant.
51
52
  const CROSS = 'other-tenant';
52
53
  const res = await anonDispatch({ tool: 'catalog.read', args: { tenant: CROSS } });
53
- if (res.status === 404 || res.status === 405) return; // seam unwired — soft-skip
54
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
54
55
  const decided = res.json?.authorizationDecided?.payload;
55
56
  const deniedByDecision = decided?.allowed === false;
56
57
  const deniedByStatus = res.status === 403 || res.status === 404;
@@ -61,7 +62,7 @@ describe('anonymous-actor-no-secret-reach (RFC 0132 §C.2/§C.3)', () => {
61
62
  typeof resolvedTenant === 'string' && resolvedTenant.length > 0 && resolvedTenant !== CROSS;
62
63
  expect(
63
64
  deniedByDecision || deniedByStatus || neutralizedToSurface,
64
- driver.describe(
65
+ req('openwop.it.anonymous-actor-no-secret-reach.a-cross-tenant-read-fails-closed-the-caller-supplied-tenant-is-never-resolved',
65
66
  'SECURITY anon-actor-no-secret-reach (CTI-1 / RFC 0132 §A.2)',
66
67
  'a cross-tenant anon read MUST fail closed — denied, or the caller-supplied tenant ignored (never resolved to the caller’s tenant)',
67
68
  ),
@@ -71,7 +72,7 @@ describe('anonymous-actor-no-secret-reach (RFC 0132 §C.2/§C.3)', () => {
71
72
  if (deniedByDecision || deniedByStatus) {
72
73
  expect(
73
74
  res.json?.result,
74
- driver.describe('SECURITY anon-actor-no-secret-reach (CTI-1)', 'a denied cross-tenant anon read MUST NOT return data'),
75
+ req('openwop.it.anonymous-actor-no-secret-reach.a-cross-tenant-read-fails-closed-the-caller-supplied-tenant-is-never-resolved', 'SECURITY anon-actor-no-secret-reach (CTI-1)', 'a denied cross-tenant anon read MUST NOT return data'),
75
76
  ).toBeUndefined();
76
77
  }
77
78
  });
@@ -34,9 +34,7 @@ import { join } from 'node:path';
34
34
  import Ajv2020 from 'ajv/dist/2020.js';
35
35
  import addFormats from 'ajv-formats';
36
36
  import { SCHEMAS_DIR } from '../lib/paths.js';
37
-
38
- /** Server-free assertion-message helper (mirrors driver.describe without OPENWOP_BASE_URL). */
39
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
37
+ import { req } from '../lib/requirement-ids.js';
40
38
 
41
39
  function loadSchema(name: string): Record<string, unknown> {
42
40
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -50,12 +48,12 @@ describe('anonymous-actor-shape: capability advertisement (RFC 0132 §B, server-
50
48
  it('the capabilities schema declares anonymousActor with its sub-flags', () => {
51
49
  expect(
52
50
  anon,
53
- why('capabilities.md §anonymousActor', 'capabilities.anonymousActor MUST be declared'),
51
+ req('openwop.it.anonymous-actor-shape.the-capabilities-schema-declares-anonymousactor-with-its-sub-flags', 'capabilities.md §anonymousActor', 'capabilities.anonymousActor MUST be declared'),
54
52
  ).toBeDefined();
55
53
  for (const flag of ['supported', 'tiers', 'writeEgressControls', 'failClosed']) {
56
54
  expect(
57
55
  anon?.properties?.[flag],
58
- why('capabilities.md §anonymousActor', `anonymousActor.${flag} MUST be declared`),
56
+ req('openwop.it.anonymous-actor-shape.the-capabilities-schema-declares-anonymousactor-with-its-sub-flags', 'capabilities.md §anonymousActor', `anonymousActor.${flag} MUST be declared`),
59
57
  ).toBeDefined();
60
58
  }
61
59
  });
@@ -68,7 +66,7 @@ describe('anonymous-actor-shape: capability advertisement (RFC 0132 §B, server-
68
66
  // Positive — read-only tier.
69
67
  expect(
70
68
  validate({ supported: true, tiers: ['read'], failClosed: true }),
71
- why('RFC 0132 §B', 'a conforming read-tier advert MUST validate'),
69
+ req('openwop.it.anonymous-actor-shape.validates-conforming-read-bounded-write-egress-adverts-and-rejects-the-negatives', 'RFC 0132 §B', 'a conforming read-tier advert MUST validate'),
72
70
  ).toBe(true);
73
71
  // Positive — bounded-write-egress tier with a mandatory control.
74
72
  expect(
@@ -78,33 +76,33 @@ describe('anonymous-actor-shape: capability advertisement (RFC 0132 §B, server-
78
76
  writeEgressControls: ['hitl'],
79
77
  failClosed: true,
80
78
  }),
81
- why('RFC 0132 §B', 'a bounded-write-egress advert with a control MUST validate'),
79
+ req('openwop.it.anonymous-actor-shape.validates-conforming-read-bounded-write-egress-adverts-and-rejects-the-negatives', 'RFC 0132 §B', 'a bounded-write-egress advert with a control MUST validate'),
82
80
  ).toBe(true);
83
81
 
84
82
  // Negative — empty tiers (minItems: 1).
85
83
  expect(
86
84
  validate({ supported: true, tiers: [] }),
87
- why('RFC 0132 §B', 'tiers: [] MUST be rejected (minItems)'),
85
+ req('openwop.it.anonymous-actor-shape.validates-conforming-read-bounded-write-egress-adverts-and-rejects-the-negatives', 'RFC 0132 §B', 'tiers: [] MUST be rejected (minItems)'),
88
86
  ).toBe(false);
89
87
  // Negative — write tier without a control (the §B.2 conditional-MUST).
90
88
  expect(
91
89
  validate({ supported: true, tiers: ['bounded-write-egress'] }),
92
- why('RFC 0132 §B.2', 'bounded-write-egress without writeEgressControls MUST be rejected'),
90
+ req('openwop.it.anonymous-actor-shape.validates-conforming-read-bounded-write-egress-adverts-and-rejects-the-negatives', 'RFC 0132 §B.2', 'bounded-write-egress without writeEgressControls MUST be rejected'),
93
91
  ).toBe(false);
94
92
  // Negative — controls advertised without the write tier (§B.2 else branch).
95
93
  expect(
96
94
  validate({ supported: true, tiers: ['read'], writeEgressControls: ['hitl'] }),
97
- why('RFC 0132 §B.2', 'writeEgressControls without the write tier MUST be rejected'),
95
+ req('openwop.it.anonymous-actor-shape.validates-conforming-read-bounded-write-egress-adverts-and-rejects-the-negatives', 'RFC 0132 §B.2', 'writeEgressControls without the write tier MUST be rejected'),
98
96
  ).toBe(false);
99
97
  // Negative — supported: false (the block is omitted when unsupported, const: true).
100
98
  expect(
101
99
  validate({ supported: false, tiers: ['read'] }),
102
- why('RFC 0132 §B', 'supported: false MUST be rejected (const: true — omit the block instead)'),
100
+ req('openwop.it.anonymous-actor-shape.validates-conforming-read-bounded-write-egress-adverts-and-rejects-the-negatives', 'RFC 0132 §B', 'supported: false MUST be rejected (const: true — omit the block instead)'),
103
101
  ).toBe(false);
104
102
  // Negative — unknown property (additionalProperties: false).
105
103
  expect(
106
104
  validate({ supported: true, tiers: ['read'], surface: 'wgt_abc' }),
107
- why('RFC 0132 §B', 'an unknown property MUST be rejected (additionalProperties: false)'),
105
+ req('openwop.it.anonymous-actor-shape.validates-conforming-read-bounded-write-egress-adverts-and-rejects-the-negatives', 'RFC 0132 §B', 'an unknown property MUST be rejected (additionalProperties: false)'),
108
106
  ).toBe(false);
109
107
  });
110
108
  });
@@ -122,16 +120,16 @@ describe('anonymous-actor-shape: owner.principalKind (RFC 0132 §A, server-free)
122
120
  const validate = ajv.compile(owner);
123
121
  expect(
124
122
  validate({ tenant: 'acme', principal: 'anon:sess-3f9c', principalKind: 'anonymous' }),
125
- why('RFC 0132 §A', 'owner.principalKind "anonymous" MUST validate'),
123
+ req('openwop.it.anonymous-actor-shape.run-snapshot-owner-accepts-principalkind-anonymous-and-rejects-guest', 'RFC 0132 §A', 'owner.principalKind "anonymous" MUST validate'),
126
124
  ).toBe(true);
127
125
  // Absent principalKind is today's RFC 0048 behavior — still valid.
128
126
  expect(
129
127
  validate({ tenant: 'acme', principal: 'u_42' }),
130
- why('RFC 0048', 'owner without principalKind MUST still validate'),
128
+ req('openwop.it.anonymous-actor-shape.run-snapshot-owner-accepts-principalkind-anonymous-and-rejects-guest', 'RFC 0048', 'owner without principalKind MUST still validate'),
131
129
  ).toBe(true);
132
130
  expect(
133
131
  validate({ tenant: 'acme', principalKind: 'guest' }),
134
- why('RFC 0132 §A', 'owner.principalKind "guest" MUST be rejected (enum)'),
132
+ req('openwop.it.anonymous-actor-shape.run-snapshot-owner-accepts-principalkind-anonymous-and-rejects-guest', 'RFC 0132 §A', 'owner.principalKind "guest" MUST be rejected (enum)'),
135
133
  ).toBe(false);
136
134
  });
137
135
  });
@@ -145,7 +143,7 @@ describe('anonymous-actor-shape: audit reuses authorization.decided (RFC 0132 §
145
143
  const decided = ajv.getSchema('payloads#/$defs/authorizationDecided');
146
144
 
147
145
  it('a content-free anon grant + deny record validates against the existing $def', () => {
148
- expect(decided, 'the authorizationDecided $def MUST exist (no new event minted)').toBeTruthy();
146
+ expect(decided, req('openwop.it.anonymous-actor-shape.a-content-free-anon-grant-deny-record-validates-against-the-existing-def', 'RFC 0132', 'the authorizationDecided $def MUST exist (no new event minted)')).toBeTruthy();
149
147
  // Grant — the §G positive example.
150
148
  expect(
151
149
  decided!({
@@ -155,7 +153,7 @@ describe('anonymous-actor-shape: audit reuses authorization.decided (RFC 0132 §
155
153
  allowed: true,
156
154
  reason: 'anon-granted',
157
155
  }),
158
- why('RFC 0132 §D', 'a conforming anon grant record MUST validate'),
156
+ req('openwop.it.anonymous-actor-shape.a-content-free-anon-grant-deny-record-validates-against-the-existing-def', 'RFC 0132 §D', 'a conforming anon grant record MUST validate'),
159
157
  ).toBe(true);
160
158
  // Deny — a not-granted tool.
161
159
  expect(
@@ -166,13 +164,13 @@ describe('anonymous-actor-shape: audit reuses authorization.decided (RFC 0132 §
166
164
  allowed: false,
167
165
  reason: 'anon-not-granted',
168
166
  }),
169
- why('RFC 0132 §D', 'a conforming anon deny record MUST validate'),
167
+ req('openwop.it.anonymous-actor-shape.a-content-free-anon-grant-deny-record-validates-against-the-existing-def', 'RFC 0132 §D', 'a conforming anon deny record MUST validate'),
170
168
  ).toBe(true);
171
169
  });
172
170
 
173
171
  it('authorization.decided is in the RunEventType enum (the reused audit event)', () => {
174
172
  const runEvent = loadSchema('run-event.schema.json');
175
173
  const enumVals = (runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum ?? [];
176
- expect(enumVals).toContain('authorization.decided');
174
+ expect(enumVals, req('openwop.it.anonymous-actor-shape.authorization-decided-is-in-the-runeventtype-enum-the-reused-audit-event', 'RFC 0132', 'authorization.decided is in the RunEventType enum (the reused audit event)')).toContain('authorization.decided');
177
175
  });
178
176
  });
@@ -22,8 +22,9 @@
22
22
 
23
23
  import { describe, it, expect } from 'vitest';
24
24
  import { behaviorGate } from '../lib/behavior-gate.js';
25
- import { driver } from '../lib/driver.js';
26
25
  import { readAnonymousActorCap, anonDispatch } from '../lib/anonymousActor.js';
26
+ import { req } from '../lib/requirement-ids.js';
27
+ import { softSkip } from '../lib/soft-skip.js';
27
28
 
28
29
  const PROFILE = 'openwop-anonymous-actor';
29
30
 
@@ -34,7 +35,7 @@ describe('anonymous-actor-write-gated (RFC 0132 §C.3)', () => {
34
35
  if (!behaviorGate(PROFILE, cap?.supported === true && supportsWrite)) return;
35
36
 
36
37
  const res = await anonDispatch({ tool: 'lead.capture', args: { email: 'visitor@example.com' } });
37
- if (res.status === 404 || res.status === 405) return; // seam unwired — soft-skip
38
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
38
39
 
39
40
  const controls = cap?.writeEgressControls ?? [];
40
41
  const decided = res.json?.authorizationDecided?.payload;
@@ -44,11 +45,11 @@ describe('anonymous-actor-write-gated (RFC 0132 §C.3)', () => {
44
45
  // With a HITL control the write MUST suspend on an approval interrupt before durable write.
45
46
  expect(
46
47
  suspended,
47
- driver.describe('RFC 0132 §C.3 (hitl)', 'an anon bounded-write MUST suspend on an approval interrupt before the write'),
48
+ req('openwop.it.anonymous-actor-write-gated.an-anon-bounded-write-tool-is-gated-denied-when-ungated-or-suspends-on-an-approv', 'RFC 0132 §C.3 (hitl)', 'an anon bounded-write MUST suspend on an approval interrupt before the write'),
48
49
  ).toBe(true);
49
50
  expect(
50
51
  res.json?.result,
51
- driver.describe('RFC 0132 §C.3 (hitl)', 'no durable write result before the approval resolves'),
52
+ req('openwop.it.anonymous-actor-write-gated.an-anon-bounded-write-tool-is-gated-denied-when-ungated-or-suspends-on-an-approv', 'RFC 0132 §C.3 (hitl)', 'no durable write result before the approval resolves'),
52
53
  ).toBeUndefined();
53
54
  } else {
54
55
  // With only a rate-limit/session-cap control, the seam surfaces a gate; an
@@ -56,7 +57,7 @@ describe('anonymous-actor-write-gated (RFC 0132 §C.3)', () => {
56
57
  const gatedOrDenied = suspended || decided?.allowed === false || res.status === 429;
57
58
  expect(
58
59
  gatedOrDenied,
59
- driver.describe('SECURITY anon-actor-write-egress-gated', 'an anon bounded-write MUST be gated — an ungated write MUST be denied'),
60
+ req('openwop.it.anonymous-actor-write-gated.an-anon-bounded-write-tool-is-gated-denied-when-ungated-or-suspends-on-an-approv', 'SECURITY anon-actor-write-egress-gated', 'an anon bounded-write MUST be gated — an ungated write MUST be denied'),
60
61
  ).toBe(true);
61
62
  }
62
63
  });
@@ -67,16 +68,16 @@ describe('anonymous-actor-write-gated (RFC 0132 §C.3)', () => {
67
68
  if (!behaviorGate(PROFILE, cap?.supported === true && supportsWrite)) return;
68
69
  // Probe a surface deliberately configured with a write grant but no control.
69
70
  const res = await anonDispatch({ tool: 'lead.capture', surface: 'sample-uncontrolled-surface' });
70
- if (res.status === 404 || res.status === 405) return; // seam unwired / surface absent — soft-skip
71
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam unwired / surface absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired / surface absent — soft-skip
71
72
  const decided = res.json?.authorizationDecided?.payload;
72
73
  expect(
73
74
  decided?.allowed === false || res.status === 403 || res.status === 429,
74
- driver.describe('SECURITY anon-actor-write-egress-gated', 'an anon write with no resolvable control MUST be denied'),
75
+ req('openwop.it.anonymous-actor-write-gated.an-anon-write-with-no-resolvable-control-is-denied-with-a-machine-reason', 'SECURITY anon-actor-write-egress-gated', 'an anon write with no resolvable control MUST be denied'),
75
76
  ).toBe(true);
76
77
  if (decided && decided.allowed === false) {
77
78
  expect(
78
79
  decided.reason,
79
- driver.describe('RFC 0132 §C.3', 'an ungated anon write denial carries a machine reason'),
80
+ req('openwop.it.anonymous-actor-write-gated.an-anon-write-with-no-resolvable-control-is-denied-with-a-machine-reason', 'RFC 0132 §C.3', 'an ungated anon write denial carries a machine reason'),
80
81
  ).toBe('anon-write-ungated');
81
82
  }
82
83
  });
@@ -18,6 +18,8 @@ import { describe, it, expect } from 'vitest';
18
18
  import { driver } from '../lib/driver.js';
19
19
  import { pollUntilTerminal } from '../lib/polling.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
  const CANDIDATES = ['conformance-append-ordering', 'conformance-multi-node'] as const;
23
25
  const FIXTURE = CANDIDATES.find((id) => isFixtureAdvertised(id)) ?? null;
@@ -71,13 +73,13 @@ describe.skipIf(SKIP)('append-ordering: folded channel reflects event sequence',
71
73
  console.warn(
72
74
  '[append-ordering] fixture emitted no channel.written events; skipping ordering assertions',
73
75
  );
74
- return;
76
+ return softSkip('blocked', 'precondition not met — `byChannel.size === 0` returned early ([append-ordering] fixture emitted no channel.written events; skipping ordering assertions) (seam, prior step, or fixture unavailable)');
75
77
  }
76
78
 
77
79
  // For each channel, sequence MUST be strictly increasing within the run.
78
80
  for (const [channel, writes] of byChannel) {
79
81
  for (let i = 1; i < writes.length; i++) {
80
- expect(writes[i].sequence, driver.describe(
82
+ expect(writes[i].sequence, req('openwop.it.append-ordering.append-reducer-channels-project-entries-in-event-sequence-order',
81
83
  'channels-and-reducers.md §"Append ordering"',
82
84
  `channel '${channel}': channel.written events MUST appear in sequence order in the event log`,
83
85
  )).toBeGreaterThan(writes[i - 1].sequence);
@@ -101,7 +103,7 @@ describe.skipIf(SKIP)('append-ordering: folded channel reflects event sequence',
101
103
  // Property: every cross-engine event carries BOTH sourceEngineId
102
104
  // AND sourceRunId (per channel-written-payload.schema.json).
103
105
  for (const e of crossEngineWrites) {
104
- expect(typeof e.payload?.sourceRunId, driver.describe(
106
+ expect(typeof e.payload?.sourceRunId, req('openwop.it.append-ordering.append-reducer-channels-project-entries-in-event-sequence-order',
105
107
  'channel-written-payload.schema.json',
106
108
  'cross-engine writes MUST carry sourceRunId alongside sourceEngineId',
107
109
  )).toBe('string');
@@ -110,7 +112,7 @@ describe.skipIf(SKIP)('append-ordering: folded channel reflects event sequence',
110
112
  const seen = new Set<string>();
111
113
  for (const e of allWrites) {
112
114
  const key = `${e.sequence}::${e.eventId ?? ''}`;
113
- expect(seen.has(key), driver.describe(
115
+ expect(seen.has(key), req('openwop.it.append-ordering.append-reducer-channels-project-entries-in-event-sequence-order',
114
116
  'channels-and-reducers.md §"Tie-breaking when sequences collide"',
115
117
  `(sequence, eventId) MUST be unique across the run — duplicate found: ${key}`,
116
118
  )).toBe(false);
@@ -125,7 +127,7 @@ describe.skipIf(SKIP)('append-ordering: folded channel reflects event sequence',
125
127
  for (const [channel, writes] of byChannel) {
126
128
  const projected = (channels as Record<string, unknown>)[channel];
127
129
  if (Array.isArray(projected)) {
128
- expect(projected.length, driver.describe(
130
+ expect(projected.length, req('openwop.it.append-ordering.append-reducer-channels-project-entries-in-event-sequence-order',
129
131
  'channels-and-reducers.md §"Append ordering"',
130
132
  `channel '${channel}': projected array length MUST equal #channel.written events`,
131
133
  )).toBe(writes.length);
@@ -22,6 +22,7 @@ import { readFileSync } from 'node:fs';
22
22
  import { join } from 'node:path';
23
23
  import Ajv2020 from 'ajv/dist/2020.js';
24
24
  import { SCHEMAS_DIR } from '../lib/paths.js';
25
+ import { req } from '../lib/requirement-ids.js';
25
26
 
26
27
  interface PayloadsSchema {
27
28
  $schema: string;
@@ -41,7 +42,7 @@ describe('category: approval-gate governance events (RFC 0051 §B)', () => {
41
42
  it('approval.granted requires gateId + principal; quorumProgress optional', () => {
42
43
  const v = compile('approvalGranted');
43
44
  expect(v({ gateId: 'g1', principal: 'user_1' }), JSON.stringify(v.errors)).toBe(true);
44
- expect(v({ gateId: 'g1', principal: 'user_1', quorumProgress: { granted: 1, required: 2 } })).toBe(true);
45
+ expect(v({ gateId: 'g1', principal: 'user_1', quorumProgress: { granted: 1, required: 2 } }), req('openwop.it.approval-gate-events.approval-granted-requires-gateid-principal-quorumprogress-optional', 'RFC 0051 §B', 'approval.granted requires gateId + principal; quorumProgress optional')).toBe(true);
45
46
  expect(v({ gateId: 'g1' })).toBe(false); // missing principal
46
47
  expect(v({ gateId: 'g1', principal: 'user_1', role: 'admin' })).toBe(false); // unknown prop
47
48
  });
@@ -49,13 +50,13 @@ describe('category: approval-gate governance events (RFC 0051 §B)', () => {
49
50
  it('approval.rejected requires gateId + principal; reason optional', () => {
50
51
  const v = compile('approvalRejected');
51
52
  expect(v({ gateId: 'g1', principal: 'user_1' }), JSON.stringify(v.errors)).toBe(true);
52
- expect(v({ gateId: 'g1', principal: 'user_1', reason: 'incomplete' })).toBe(true);
53
+ expect(v({ gateId: 'g1', principal: 'user_1', reason: 'incomplete' }), req('openwop.it.approval-gate-events.approval-rejected-requires-gateid-principal-reason-optional', 'RFC 0051 §B', 'approval.rejected requires gateId + principal; reason optional')).toBe(true);
53
54
  expect(v({ principal: 'user_1' })).toBe(false); // missing gateId
54
55
  });
55
56
 
56
57
  it('approval.overridden requires gateId + principal + reason (audit breadcrumb)', () => {
57
58
  const v = compile('approvalOverridden');
58
59
  expect(v({ gateId: 'g1', principal: 'owner_1', reason: 'emergency publish' }), JSON.stringify(v.errors)).toBe(true);
59
- expect(v({ gateId: 'g1', principal: 'owner_1' })).toBe(false); // reason MUST be present
60
+ expect(v({ gateId: 'g1', principal: 'owner_1' }), req('openwop.it.approval-gate-events.approval-overridden-requires-gateid-principal-reason-audit-breadcrumb', 'RFC 0051 §B', 'approval.overridden requires gateId + principal + reason (audit breadcrumb)')).toBe(false); // reason MUST be present
60
61
  });
61
62
  });
@@ -24,6 +24,7 @@ import { describe, it, expect } from 'vitest';
24
24
  import { softSkip } from '../lib/soft-skip.js';
25
25
  import { driver } from '../lib/driver.js';
26
26
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
27
+ import { req } from '../lib/requirement-ids.js';
27
28
 
28
29
  async function authorizationSupported(): Promise<boolean> {
29
30
  // Root-first per RFC 0073 (`capabilities.authorization` is the deprecated wrapper shape).
@@ -42,7 +43,7 @@ describe('approval-gate-flow: role-gated, audited approval (RFC 0051 §A)', () =
42
43
  const body = res.json as { released?: boolean } | undefined;
43
44
  expect(
44
45
  body?.released,
45
- driver.describe('RFC 0051 §A', 'an unauthorized principal MUST NOT release the gate (fail-closed)'),
46
+ req('openwop.it.approval-gate-flow.an-unauthorized-principal-does-not-release-the-gate-fail-closed', 'RFC 0051 §A', 'an unauthorized principal MUST NOT release the gate (fail-closed)'),
46
47
  ).toBe(false);
47
48
  });
48
49
 
@@ -57,11 +58,11 @@ describe('approval-gate-flow: role-gated, audited approval (RFC 0051 §A)', () =
57
58
  const body = res.json as { event?: { type?: string; payload?: { reason?: string } } } | undefined;
58
59
  expect(
59
60
  body?.event?.type,
60
- driver.describe('RFC 0051 §B', 'taking the override path MUST emit approval.overridden'),
61
+ req('openwop.it.approval-gate-flow.the-override-path-emits-an-audited-approval-overridden-with-a-reason', 'RFC 0051 §B', 'taking the override path MUST emit approval.overridden'),
61
62
  ).toBe('approval.overridden');
62
63
  expect(
63
64
  typeof body?.event?.payload?.reason === 'string' && body.event.payload.reason.length > 0,
64
- driver.describe('RFC 0051 §B', 'approval.overridden MUST carry a non-empty reason (the audit breadcrumb)'),
65
+ req('openwop.it.approval-gate-flow.the-override-path-emits-an-audited-approval-overridden-with-a-reason', 'RFC 0051 §B', 'approval.overridden MUST carry a non-empty reason (the audit breadcrumb)'),
65
66
  ).toBe(true);
66
67
  });
67
68
  });
@@ -43,6 +43,7 @@
43
43
 
44
44
  import { describe, it, expect } from 'vitest';
45
45
  import { driver } from '../lib/driver.js';
46
+ import { req } from '../lib/requirement-ids.js';
46
47
 
47
48
  const CANONICAL_ACTIONS = ['accept', 'reject', 'refine', 'edit-accept', 'ask'] as const;
48
49
  const CANONICAL_EVENT_ACTIONS = ['accept', 'reject', 'refine', 'edit-accept', 'timeout'] as const;
@@ -73,7 +74,7 @@ describe('approval-payload: vocabulary discovery contract', () => {
73
74
  // is distinguishable from the canonical form.
74
75
  const legacyHits = text.match(/"edit"/g) ?? [];
75
76
 
76
- expect(legacyHits.length, driver.describe(
77
+ expect(legacyHits.length, req('openwop.it.approval-payload.host-capability-declaration-does-not-regress-on-the-legacy-edit-form-7-drift-pin',
77
78
  'interrupt.md §"`ApprovalResume`"',
78
79
  'capability declaration MUST NOT contain the legacy `"edit"` action token (use `"edit-accept"` per spec)',
79
80
  )).toBe(0);
@@ -84,7 +85,7 @@ describe('approval-payload: vocabulary discovery contract', () => {
84
85
  // accept/reject/refine/edit-accept/ask. Per-host advertisement is
85
86
  // optional; this test pins the vocabulary itself for future
86
87
  // scenarios that gate on it.
87
- expect(CANONICAL_ACTIONS).toHaveLength(5);
88
+ expect(CANONICAL_ACTIONS, req('openwop.it.approval-payload.canonical-action-vocabulary-is-documented-in-spec-assertion-free-reference', 'capabilities.md', 'canonical action vocabulary is documented in spec (assertion-free reference)')).toHaveLength(5);
88
89
  expect(new Set(CANONICAL_ACTIONS)).toEqual(
89
90
  new Set(['accept', 'reject', 'refine', 'edit-accept', 'ask']),
90
91
  );
@@ -98,7 +99,7 @@ describe('approval-payload: vocabulary discovery contract', () => {
98
99
  // but isn't a resume action (clients can't submit a timeout).
99
100
  //
100
101
  // Pin this asymmetry so it doesn't drift.
101
- expect(CANONICAL_EVENT_ACTIONS).toHaveLength(5);
102
+ expect(CANONICAL_EVENT_ACTIONS, req('openwop.it.approval-payload.canonical-event-action-vocabulary-differs-from-resume-timeout-instead-of-ask', 'capabilities.md', 'canonical event action vocabulary differs from resume (timeout instead of ask)')).toHaveLength(5);
102
103
  expect(new Set(CANONICAL_EVENT_ACTIONS)).toEqual(
103
104
  new Set(['accept', 'reject', 'refine', 'edit-accept', 'timeout']),
104
105
  );
@@ -112,7 +113,7 @@ describe('approval-payload: vocabulary discovery contract', () => {
112
113
  // The 3 documented scopes `whole/section/items` MUST be a stable
113
114
  // set in v1.x. Adding a scope is additive (clients tolerating
114
115
  // unknown values) but semantic changes need a spec discussion.
115
- expect(CANONICAL_REFINE_SCOPES).toHaveLength(3);
116
+ expect(CANONICAL_REFINE_SCOPES, req('openwop.it.approval-payload.refinefeedback-scope-vocabulary-pin-7-audit-a-5-prereq', 'capabilities.md', 'refineFeedback scope vocabulary pin (§7 audit, A.5 prereq)')).toHaveLength(3);
116
117
  expect(new Set(CANONICAL_REFINE_SCOPES)).toEqual(
117
118
  new Set(['whole', 'section', 'items']),
118
119
  );
@@ -20,8 +20,9 @@
20
20
 
21
21
  import { describe, it, expect } from 'vitest';
22
22
 
23
- import { driver } from '../lib/driver.js';
24
23
  import { loadEnv } from '../lib/env.js';
24
+ import { req } from '../lib/requirement-ids.js';
25
+ import { softSkip } from '../lib/soft-skip.js';
25
26
 
26
27
  describe('artifact-auth: unauthenticated artifact requests are rejected', () => {
27
28
  it('GET /v1/runs/{runId}/artifacts/{artifactId} without Authorization returns 401', async () => {
@@ -31,12 +32,12 @@ describe('artifact-auth: unauthenticated artifact requests are rejected', () =>
31
32
  const res = await fetch(
32
33
  `${env.baseUrl}/v1/runs/openwop-conformance-noauth-run/artifacts/openwop-conformance-noauth-artifact`,
33
34
  );
34
- expect(res.status, driver.describe(
35
+ expect(res.status, req('openwop.it.artifact-auth.get-v1-runs-runid-artifacts-artifactid-without-authorization-returns-401',
35
36
  'rest-endpoints.md GET /v1/runs/{runId}/artifacts/{artifactId}',
36
37
  'artifact endpoint MUST reject unauthenticated requests with 401 (never 200, never redirect)',
37
38
  )).toBe(401);
38
- expect(res.status, 'redirect MUST NOT be used to handle missing auth on artifact endpoint').not.toBe(301);
39
- expect(res.status, 'redirect MUST NOT be used to handle missing auth on artifact endpoint').not.toBe(302);
39
+ expect(res.status, req('openwop.it.artifact-auth.get-v1-runs-runid-artifacts-artifactid-without-authorization-returns-401', 'rest-endpoints.md GET /v1/runs/{runId}/artifacts/{artifactId}', 'redirect MUST NOT be used to handle missing auth on artifact endpoint')).not.toBe(301);
40
+ expect(res.status, req('openwop.it.artifact-auth.get-v1-runs-runid-artifacts-artifactid-without-authorization-returns-401', 'rest-endpoints.md GET /v1/runs/{runId}/artifacts/{artifactId}', 'redirect MUST NOT be used to handle missing auth on artifact endpoint')).not.toBe(302);
40
41
  expect(res.status).not.toBe(200);
41
42
 
42
43
  // Canonical error envelope: error: 'unauthenticated', message: string.
@@ -46,10 +47,10 @@ describe('artifact-auth: unauthenticated artifact requests are rejected', () =>
46
47
  } catch {
47
48
  // Some hosts return a bare 401 with no body — acceptable. Skip the
48
49
  // envelope-shape assertion in that case.
49
- return;
50
+ return softSkip('blocked', 'precondition not met — an earlier step threw (Some hosts return a bare 401 with no body — acceptable. Skip the envelope-shape assertion in that case.) (seam, prior step, or fixture unavailable)');
50
51
  }
51
52
  if (typeof body.error === 'string') {
52
- expect(body.error, driver.describe(
53
+ expect(body.error, req('openwop.it.artifact-auth.get-v1-runs-runid-artifacts-artifactid-without-authorization-returns-401',
53
54
  'auth.md §"Error envelope"',
54
55
  '401 envelope SHOULD carry `error: "unauthenticated"` for missing-auth on artifact endpoint',
55
56
  )).toBe('unauthenticated');
@@ -26,7 +26,6 @@
26
26
  */
27
27
 
28
28
  import { describe, it, expect } from 'vitest';
29
- import { driver } from '../lib/driver.js';
30
29
  import { behaviorGate, behaviorGatePresent } from '../lib/behavior-gate.js';
31
30
 
32
31
  const PROFILE = 'openwop-artifact-type-packs';
@@ -37,6 +36,7 @@ import {
37
36
  produceArtifact,
38
37
  sampleArtifactTypePack,
39
38
  } from '../lib/artifactTypes.js';
39
+ import { req } from '../lib/requirement-ids.js';
40
40
 
41
41
  describe('artifact-type-pack-install: registered artifacts are schema-validated (RFC 0071)', () => {
42
42
  it('a conforming payload yields artifact.created { registered: true }', async () => {
@@ -47,24 +47,24 @@ describe('artifact-type-pack-install: registered artifacts are schema-validated
47
47
  if (!behaviorGatePresent(PROFILE, installed)) return; // seam absent: skip default, FAIL strict
48
48
  expect(
49
49
  installed.status >= 200 && installed.status < 300,
50
- driver.describe('artifact-type-packs.md §"Pack kind"', 'a valid artifact-type pack MUST install cleanly'),
50
+ req('openwop.it.artifact-type-pack-install.a-conforming-payload-yields-artifact-created-registered-true', 'artifact-type-packs.md §"Pack kind"', 'a valid artifact-type pack MUST install cleanly'),
51
51
  ).toBe(true);
52
52
 
53
53
  const produced = await produceArtifact(artifactTypeId, { title: 'Hello', body: 'World' });
54
54
  if (!behaviorGatePresent(PROFILE, produced)) return; // seam absent: skip default, FAIL strict
55
55
  expect(
56
56
  produced.json['registered'],
57
- driver.describe('artifact-type-packs.md §"Binding the existing artifact surfaces"', 'a payload matching a registered artifactTypeId MUST be marked registered'),
57
+ req('openwop.it.artifact-type-pack-install.a-conforming-payload-yields-artifact-created-registered-true', 'artifact-type-packs.md §"Binding the existing artifact surfaces"', 'a payload matching a registered artifactTypeId MUST be marked registered'),
58
58
  ).toBe(true);
59
59
  expect(
60
60
  produced.json['validated'],
61
- driver.describe('artifact-type-packs.md', 'the host MUST validate the payload against the pack schema before emitting artifact.created'),
61
+ req('openwop.it.artifact-type-pack-install.a-conforming-payload-yields-artifact-created-registered-true', 'artifact-type-packs.md', 'the host MUST validate the payload against the pack schema before emitting artifact.created'),
62
62
  ).toBe(true);
63
63
  const evt = produced.json['artifactCreated'] as { registered?: unknown } | undefined;
64
64
  if (evt && 'registered' in evt) {
65
65
  expect(
66
66
  evt.registered,
67
- driver.describe('run-event-payloads.schema.json §artifactCreated', 'artifact.created.registered MUST be true for a validated registered artifact'),
67
+ req('openwop.it.artifact-type-pack-install.a-conforming-payload-yields-artifact-created-registered-true', 'run-event-payloads.schema.json §artifactCreated', 'artifact.created.registered MUST be true for a validated registered artifact'),
68
68
  ).toBe(true);
69
69
  }
70
70
  });
@@ -83,7 +83,7 @@ describe('artifact-type-pack-install: registered artifacts are schema-validated
83
83
  produced.json['stored'] === false;
84
84
  expect(
85
85
  rejected,
86
- driver.describe('artifact-type-packs.md §"Binding the existing artifact surfaces"', 'a payload that fails the pack schema MUST NOT be emitted as a validated registered artifact'),
86
+ req('openwop.it.artifact-type-pack-install.a-schema-violating-payload-is-rejected-not-stored-as-a-validated-registered-arti', 'artifact-type-packs.md §"Binding the existing artifact surfaces"', 'a payload that fails the pack schema MUST NOT be emitted as a validated registered artifact'),
87
87
  ).toBe(true);
88
88
  });
89
89
  });