@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
@@ -31,6 +31,7 @@ import Ajv2020 from 'ajv/dist/2020.js';
31
31
  import { readFileSync } from 'node:fs';
32
32
  import { join } from 'node:path';
33
33
  import { SCHEMAS_DIR } from '../lib/paths.js';
34
+ import { req } from '../lib/requirement-ids.js';
34
35
 
35
36
  const ajv = new Ajv2020({ strict: false, allErrors: true });
36
37
  const schema = JSON.parse(
@@ -70,7 +71,7 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
70
71
  it('ui.a2ui-surface.schema.json compiles under Ajv2020', () => {
71
72
  expect(
72
73
  validate,
73
- 'RFC 0102 §A: the core ui.a2ui-surface payload schema MUST compile',
74
+ req('openwop.it.a2ui-surface-shape.ui-a2ui-surface-schema-json-compiles-under-ajv2020', 'RFC 0102 §A', 'RFC 0102 §A: the core ui.a2ui-surface payload schema MUST compile'),
74
75
  ).toBeTypeOf('function');
75
76
  });
76
77
 
@@ -78,7 +79,7 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
78
79
  const ok = validate(positivePayload());
79
80
  expect(
80
81
  ok,
81
- `RFC 0102 §A: positive surface MUST validate; errors: ${JSON.stringify(validate.errors)}`,
82
+ req('openwop.it.a2ui-surface-shape.accepts-a-positive-surface-payload-closed-catalog-confined-action', 'RFC 0102 §A', `RFC 0102 §A: positive surface MUST validate; errors: ${JSON.stringify(validate.errors)}`),
82
83
  ).toBe(true);
83
84
  });
84
85
 
@@ -87,19 +88,19 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
87
88
  (p.surface as { components: Array<Record<string, unknown>> }).components = [
88
89
  { component: 'action.button', id: 'send', label: 'Send', action: { target: 'exchange' } },
89
90
  ];
90
- expect(validate(p)).toBe(true);
91
+ expect(validate(p), req('openwop.it.a2ui-surface-shape.accepts-an-exchange-targeted-action-the-other-confined-target', 'RFC 0102 §A', 'accepts an exchange-targeted action (the other confined target)')).toBe(true);
91
92
  });
92
93
 
93
94
  it('rejects a payload missing required `catalogVersion`', () => {
94
95
  const p = positivePayload();
95
96
  delete p.catalogVersion;
96
- expect(validate(p), 'RFC 0102 §A: `catalogVersion` is REQUIRED').toBe(false);
97
+ expect(validate(p), req('openwop.it.a2ui-surface-shape.rejects-a-payload-missing-required-catalogversion', 'RFC 0102 §A', 'RFC 0102 §A: `catalogVersion` is REQUIRED')).toBe(false);
97
98
  });
98
99
 
99
100
  it('rejects a payload missing required `surface`', () => {
100
101
  const p = positivePayload();
101
102
  delete p.surface;
102
- expect(validate(p), 'RFC 0102 §A: `surface` is REQUIRED').toBe(false);
103
+ expect(validate(p), req('openwop.it.a2ui-surface-shape.rejects-a-payload-missing-required-surface', 'RFC 0102 §A', 'RFC 0102 §A: `surface` is REQUIRED')).toBe(false);
103
104
  });
104
105
 
105
106
  it('rejects a `catalogVersion` the schema does not enumerate (unknown version)', () => {
@@ -107,7 +108,7 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
107
108
  p.catalogVersion = '9.9.9';
108
109
  expect(
109
110
  validate(p),
110
- 'RFC 0102 §A.3: an unadvertised catalogVersion MUST fail the enumerated set',
111
+ req('openwop.it.a2ui-surface-shape.rejects-a-catalogversion-the-schema-does-not-enumerate-unknown-version', 'RFC 0102 §A', 'RFC 0102 §A.3: an unadvertised catalogVersion MUST fail the enumerated set'),
111
112
  ).toBe(false);
112
113
  });
113
114
 
@@ -118,7 +119,7 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
118
119
  ];
119
120
  expect(
120
121
  validate(p),
121
- 'RFC 0102 §A.1: an out-of-catalog component MUST fail the closed anyOf',
122
+ req('openwop.it.a2ui-surface-shape.rejects-an-out-of-catalog-component-object-additionalproperties-false', 'RFC 0102 §A', 'RFC 0102 §A.1: an out-of-catalog component MUST fail the closed anyOf'),
122
123
  ).toBe(false);
123
124
  });
124
125
 
@@ -129,7 +130,7 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
129
130
  ];
130
131
  expect(
131
132
  validate(p),
132
- 'RFC 0102 §A.1: additionalProperties:false MUST reject a smuggled code field',
133
+ req('openwop.it.a2ui-surface-shape.rejects-a-known-component-carrying-an-extra-script-bearing-property', 'RFC 0102 §A', 'RFC 0102 §A.1: additionalProperties:false MUST reject a smuggled code field'),
133
134
  ).toBe(false);
134
135
  });
135
136
 
@@ -140,7 +141,7 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
140
141
  ];
141
142
  expect(
142
143
  validate(p),
143
- 'RFC 0102 §A.4 / SECURITY a2ui-action-confinement: an action target outside resume/exchange MUST be rejected',
144
+ req('openwop.it.a2ui-surface-shape.rejects-an-action-whose-target-is-outside-enum-resume-exchange-action-confinemen', 'RFC 0102 §A', 'RFC 0102 §A.4 / SECURITY a2ui-action-confinement: an action target outside resume/exchange MUST be rejected'),
144
145
  ).toBe(false);
145
146
  });
146
147
 
@@ -156,7 +157,7 @@ describe('a2ui-surface-shape: schema compile + round-trip (RFC 0102 §A)', () =>
156
157
  ];
157
158
  expect(
158
159
  validate(p),
159
- 'RFC 0102 §A.4: action additionalProperties:false MUST reject an arbitrary URL target',
160
+ req('openwop.it.a2ui-surface-shape.rejects-an-action-carrying-an-arbitrary-url-field-no-unconfined-egress-target', 'RFC 0102 §A', 'RFC 0102 §A.4: action additionalProperties:false MUST reject an arbitrary URL target'),
160
161
  ).toBe(false);
161
162
  });
162
163
  });
@@ -20,6 +20,8 @@ import { readFileSync } from 'node:fs';
20
20
  import { join } from 'node:path';
21
21
  import { driver } from '../lib/driver.js';
22
22
  import { SCHEMAS_DIR } from '../lib/paths.js';
23
+ import { req } from '../lib/requirement-ids.js';
24
+ import { softSkip } from '../lib/soft-skip.js';
23
25
 
24
26
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
25
27
  const schema = JSON.parse(
@@ -42,14 +44,14 @@ describe('a2ui-surface-version-refusal: enumerated catalogVersion (RFC 0102 §A.
42
44
  const ok = validate({ catalogVersion: '9.9.9', surface: { components: [] } });
43
45
  expect(
44
46
  ok,
45
- 'RFC 0102 §A.3: a catalogVersion outside the host-enumerated set MUST fail (→ unknown_schema_version at runtime)',
47
+ req('openwop.it.a2ui-surface-version-refusal.catalogversion-is-a-closed-enum-an-unadvertised-version-fails-validation', 'RFC 0102 §A.3', 'RFC 0102 §A.3: a catalogVersion outside the host-enumerated set MUST fail (→ unknown_schema_version at runtime)'),
46
48
  ).toBe(false);
47
49
  });
48
50
 
49
51
  it('surface payload is self-contained — no external $ref (replay determinism)', () => {
50
52
  expect(
51
53
  hasAbsoluteRef(schema),
52
- 'RFC 0102 §A.3: the surface MUST be self-contained, never a live external-catalog reference',
54
+ req('openwop.it.a2ui-surface-version-refusal.surface-payload-is-self-contained-no-external-ref-replay-determinism', 'RFC 0102 §A.3', 'RFC 0102 §A.3: the surface MUST be self-contained, never a live external-catalog reference'),
53
55
  ).toBe(false);
54
56
  });
55
57
  });
@@ -67,11 +69,11 @@ describe.skipIf(HTTP_SKIP)('a2ui-surface-version-refusal: live host refuses unad
67
69
  },
68
70
  hostSupportedEnvelopes: ['ui.a2ui-surface'],
69
71
  });
70
- if (res.status === 404) return; // seam absent — soft-skip
72
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam absent — soft-skip
71
73
  const body = res.json as { status?: string; reason?: string };
72
74
  expect(
73
75
  body.status === 'invalid' || body.status === 'refused',
74
- driver.describe('RFC 0102 §A.3', 'an unadvertised catalogVersion MUST be refused'),
76
+ req('openwop.it.a2ui-surface-version-refusal.ui-a2ui-surface-with-an-unadvertised-catalogversion-refused', 'RFC 0102 §A.3', 'an unadvertised catalogVersion MUST be refused'),
75
77
  ).toBe(true);
76
78
  });
77
79
  });
@@ -21,6 +21,8 @@
21
21
 
22
22
  import { describe, it, expect } from 'vitest';
23
23
  import { driver } from '../lib/driver.js';
24
+ import { req } from '../lib/requirement-ids.js';
25
+ import { softSkip } from '../lib/soft-skip.js';
24
26
 
25
27
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
26
28
  const UNIVERSAL_KINDS = ['clarification.request', 'schema.request', 'schema.response', 'error'];
@@ -29,7 +31,7 @@ describe('a2ui-untrusted-blocks-approval: trust machinery applies (RFC 0102 §A.
29
31
  it('ui.a2ui-surface is an advertised kind subject to meta.contentTrust gating (not universal/always-allowed)', () => {
30
32
  expect(
31
33
  UNIVERSAL_KINDS.includes('ui.a2ui-surface'),
32
- 'ai-envelope.md §"A2UI surfaces" / §"Trust boundary": a ui.a2ui-surface is trust-gated like any advertised envelope, so an untrusted surface is subject to untrusted_content_blocks_approval',
34
+ req('openwop.it.a2ui-untrusted-blocks-approval.ui-a2ui-surface-is-an-advertised-kind-subject-to-meta-contenttrust-gating-not-un', 'RFC 0102 §A.5', 'ai-envelope.md §"A2UI surfaces" / §"Trust boundary": a ui.a2ui-surface is trust-gated like any advertised envelope, so an untrusted surface is subject to untrusted_content_blocks_approval'),
33
35
  ).toBe(false);
34
36
  });
35
37
  });
@@ -55,11 +57,11 @@ describe.skipIf(HTTP_SKIP)('a2ui-untrusted-blocks-approval: untrusted surface ca
55
57
  hostSupportedEnvelopes: ['ui.a2ui-surface'],
56
58
  boundInterruptKind: 'approval',
57
59
  });
58
- if (res.status === 404) return; // seam absent — soft-skip
60
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam absent — soft-skip
59
61
  const body = res.json as { status?: string; reason?: string };
60
62
  expect(
61
63
  body.status === 'blocked' || (body.reason ?? '').includes('untrusted'),
62
- driver.describe(
64
+ req('openwop.it.a2ui-untrusted-blocks-approval.an-untrusted-marked-ui-a2ui-surface-bound-to-an-approval-interrupt-is-refused',
63
65
  'RFC 0102 §A.5',
64
66
  'an untrusted ui.a2ui-surface MUST NOT advance an approval interrupt (untrusted_content_blocks_approval)',
65
67
  ),
@@ -26,9 +26,10 @@
26
26
  */
27
27
 
28
28
  import { describe, it, expect } from 'vitest';
29
- import { driver } from '../lib/driver.js';
30
29
  import { behaviorGate } from '../lib/behavior-gate.js';
31
30
  import { readManifestRuntimeCap, listManifestAgents } from '../lib/agentRuntime.js';
31
+ import { req } from '../lib/requirement-ids.js';
32
+ import { softSkip } from '../lib/soft-skip.js';
32
33
 
33
34
  interface InventoryEntry {
34
35
  agentId?: string;
@@ -43,13 +44,13 @@ describe('agent-capability-degraded-projection (RFC 0092 §B)', () => {
43
44
  if (!behaviorGate('openwop-agent-capability-degraded', mr?.supported === true)) return;
44
45
 
45
46
  const inv = await listManifestAgents();
46
- if (inv === null) return; // cap advertised but /v1/agents unserved — soft-skip
47
+ if (inv === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `inv === null` returned early (cap advertised but /v1/agents unserved — soft-skip)'); // cap advertised but /v1/agents unserved — soft-skip
47
48
  const agents = (inv.agents ?? []) as InventoryEntry[];
48
49
 
49
50
  // Non-vacuity: an advertising + serving host MUST expose its inventory.
50
51
  expect(
51
52
  agents.length >= 1,
52
- driver.describe('RFC 0072 §A', 'GET /v1/agents MUST return the installed manifest agents'),
53
+ req('openwop.it.agent-capability-degraded-projection.surfaces-unmet-requirescapabilities-in-degraded-and-nothing-on-the-rest', 'RFC 0072 §A', 'GET /v1/agents MUST return the installed manifest agents'),
53
54
  ).toBe(true);
54
55
 
55
56
  // §B well-formedness on EVERY entry: degraded[], when present, is a unique
@@ -59,18 +60,18 @@ describe('agent-capability-degraded-projection (RFC 0092 §B)', () => {
59
60
  if (d !== undefined) {
60
61
  expect(
61
62
  Array.isArray(d),
62
- driver.describe('agent-inventory-response.schema.json', `degraded MUST be an array when present (agent ${a.agentId})`),
63
+ req('openwop.it.agent-capability-degraded-projection.surfaces-unmet-requirescapabilities-in-degraded-and-nothing-on-the-rest', 'agent-inventory-response.schema.json', `degraded MUST be an array when present (agent ${a.agentId})`),
63
64
  ).toBe(true);
64
65
  if (Array.isArray(d)) {
65
66
  for (const k of d) {
66
67
  expect(
67
68
  typeof k === 'string' && k.length > 0,
68
- driver.describe('RFC 0072 §C', `degraded[] members MUST be non-empty strings (agent ${a.agentId}, got ${String(k)})`),
69
+ req('openwop.it.agent-capability-degraded-projection.surfaces-unmet-requirescapabilities-in-degraded-and-nothing-on-the-rest', 'RFC 0072 §C', `degraded[] members MUST be non-empty strings (agent ${a.agentId}, got ${String(k)})`),
69
70
  ).toBe(true);
70
71
  }
71
72
  expect(
72
73
  new Set(d as string[]).size === d.length,
73
- driver.describe('RFC 0092 §B', `degraded[] MUST be unique (agent ${a.agentId})`),
74
+ req('openwop.it.agent-capability-degraded-projection.surfaces-unmet-requirescapabilities-in-degraded-and-nothing-on-the-rest', 'RFC 0092 §B', `degraded[] MUST be unique (agent ${a.agentId})`),
74
75
  ).toBe(true);
75
76
  }
76
77
  }
@@ -82,23 +83,23 @@ describe('agent-capability-degraded-projection (RFC 0092 §B)', () => {
82
83
  const target = agents.find((a) => a.agentId === degradedId);
83
84
  expect(
84
85
  target !== undefined,
85
- driver.describe('RFC 0092 §B', `OPENWOP_DEGRADED_CAPABILITY_AGENT_ID=${degradedId} MUST appear in the inventory`),
86
+ req('openwop.it.agent-capability-degraded-projection.surfaces-unmet-requirescapabilities-in-degraded-and-nothing-on-the-rest', 'RFC 0092 §B', `OPENWOP_DEGRADED_CAPABILITY_AGENT_ID=${degradedId} MUST appear in the inventory`),
86
87
  ).toBe(true);
87
88
  if (target) {
88
89
  const d = target.degraded;
89
90
  expect(
90
91
  Array.isArray(d) && d.length >= 1,
91
- driver.describe('RFC 0092 §B', 'the named capability-degraded agent MUST carry a non-empty degraded[]'),
92
+ req('openwop.it.agent-capability-degraded-projection.surfaces-unmet-requirescapabilities-in-degraded-and-nothing-on-the-rest', 'RFC 0092 §B', 'the named capability-degraded agent MUST carry a non-empty degraded[]'),
92
93
  ).toBe(true);
93
94
  // When the entry also exposes requiresCapabilities, every degraded key
94
95
  // MUST be one the agent actually requires (the projection is a subset of
95
96
  // requirements, never invented).
96
97
  if (Array.isArray(d) && Array.isArray(target.requiresCapabilities)) {
97
- const req = new Set(target.requiresCapabilities as unknown[]);
98
+ const required = new Set(target.requiresCapabilities as unknown[]);
98
99
  for (const k of d) {
99
100
  expect(
100
- req.has(k),
101
- driver.describe('RFC 0092 §B', `a degraded[] key MUST be one the agent requires (got ${String(k)})`),
101
+ required.has(k),
102
+ req('openwop.it.agent-capability-degraded-projection.surfaces-unmet-requirescapabilities-in-degraded-and-nothing-on-the-rest', 'RFC 0092 §B', `a degraded[] key MUST be one the agent requires (got ${String(k)})`),
102
103
  ).toBe(true);
103
104
  }
104
105
  }
@@ -43,6 +43,8 @@ import { pollUntilTerminal } from '../lib/polling.js';
43
43
  import { behaviorGate } from '../lib/behavior-gate.js';
44
44
  import { isFixtureAdvertised } from '../lib/fixtures.js';
45
45
  import { readDeploymentCap, driveDeploymentTransition } from '../lib/agentDeployment.js';
46
+ import { req } from '../lib/requirement-ids.js';
47
+ import { softSkip } from '../lib/soft-skip.js';
46
48
 
47
49
  const FIXTURE_ID = 'conformance-agent-channel-dispatch';
48
50
  const BOUND_CHANNEL = 'stable';
@@ -93,7 +95,7 @@ async function startChannelRun(): Promise<string> {
93
95
  const create = await driver.post('/v1/runs', { workflowId: FIXTURE_ID });
94
96
  expect(
95
97
  create.status,
96
- driver.describe(
98
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r',
97
99
  'agent-deployment.md §B',
98
100
  `a host advertising agents.deployment + the ${FIXTURE_ID} fixture MUST accept a channel-bound run (201)`,
99
101
  ),
@@ -111,12 +113,12 @@ describe.skipIf(HTTP_SKIP)('agent-channel-dispatch (RFC 0082 §B): production ru
111
113
  // Host advertises agents.deployment but hasn't seeded the channel-bound
112
114
  // fixture — a host-config precondition, not a conformance failure.
113
115
  ctx.skip();
114
- return;
116
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE_ID)` returned early');
115
117
  }
116
118
  const modes = await fetchReplayModes();
117
119
  if (!modes.includes('replay')) {
118
120
  ctx.skip();
119
- return;
121
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!modes.includes(\'replay\')` returned early');
120
122
  }
121
123
 
122
124
  // ---- Leg 1: production-path channel resolution + recorded pin (§B) ----
@@ -124,14 +126,14 @@ describe.skipIf(HTTP_SKIP)('agent-channel-dispatch (RFC 0082 §B): production ru
124
126
  const started = await firstInvocationStarted(sourceRunId);
125
127
  expect(
126
128
  started !== null,
127
- driver.describe(
129
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r',
128
130
  'agent-deployment.md §B',
129
131
  'a @channel-bound run MUST emit agent.invocation.started',
130
132
  ),
131
133
  ).toBe(true);
132
134
  expect(
133
135
  started!.payload.resolvedChannel,
134
- driver.describe(
136
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r',
135
137
  'agent-deployment.md §B',
136
138
  `agent.invocation.started MUST carry the bound channel as resolvedChannel ("${BOUND_CHANNEL}")`,
137
139
  ),
@@ -139,7 +141,7 @@ describe.skipIf(HTTP_SKIP)('agent-channel-dispatch (RFC 0082 §B): production ru
139
141
  const pinnedVersion = started!.payload.resolvedAgentVersion;
140
142
  expect(
141
143
  typeof pinnedVersion === 'string' && (pinnedVersion as string).length > 0,
142
- driver.describe(
144
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r',
143
145
  'agent-deployment.md §B',
144
146
  'a @channel-bound run MUST record a concrete resolvedAgentVersion (the recorded fact a replay re-reads, RFC 0077)',
145
147
  ),
@@ -152,22 +154,22 @@ describe.skipIf(HTTP_SKIP)('agent-channel-dispatch (RFC 0082 §B): production ru
152
154
  );
153
155
  if (forkDeclined(fork1.status, 'channel-dispatch replay fork 1')) {
154
156
  ctx.skip();
155
- return;
157
+ return softSkip('blocked', 'precondition not met — `forkDeclined(fork1.status, \'channel-dispatch replay fork 1\')` returned early (seam, prior step, or fixture unavailable)');
156
158
  }
157
159
  expect(
158
160
  fork1.status,
159
- driver.describe('rest-endpoints.md POST /v1/runs/{runId}:fork', 'replay fork MUST return 201'),
161
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r', 'rest-endpoints.md POST /v1/runs/{runId}:fork', 'replay fork MUST return 201'),
160
162
  ).toBe(201);
161
163
  const fork1RunId = (fork1.json as { runId: string }).runId;
162
164
  await pollUntilTerminal(fork1RunId, { timeoutMs: 15_000 });
163
165
  const fork1Started = await firstInvocationStarted(fork1RunId);
164
166
  expect(
165
167
  fork1Started !== null,
166
- driver.describe('agent-deployment.md §B', 'a replay fork MUST re-emit agent.invocation.started'),
168
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r', 'agent-deployment.md §B', 'a replay fork MUST re-emit agent.invocation.started'),
167
169
  ).toBe(true);
168
170
  expect(
169
171
  fork1Started!.payload.resolvedAgentVersion,
170
- driver.describe(
172
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r',
171
173
  'agent-deployment.md §B',
172
174
  'a replay MUST re-read the recorded resolvedAgentVersion (NOT re-resolve the channel)',
173
175
  ),
@@ -196,7 +198,7 @@ describe.skipIf(HTTP_SKIP)('agent-channel-dispatch (RFC 0082 §B): production ru
196
198
  // evidence; the cross-move proof needs the seam. Honest skip of Leg 3.
197
199
  // eslint-disable-next-line no-console
198
200
  console.warn('[agent-channel-dispatch] deployment seam absent — skipping the channel-move non-re-resolution leg (Leg 3)');
199
- return;
201
+ return softSkip('blocked', 'precondition not met — `moved === null` returned early ([agent-channel-dispatch] deployment seam absent — skipping the channel-move non-re-resolution leg (Leg 3)) (seam, prior step, or fixture unavailable)');
200
202
  }
201
203
  // Confirm the move is OBSERVABLE: a fresh channel-bound run must now resolve
202
204
  // to a DIFFERENT version. If it doesn't (canary split, no-op promote), we
@@ -207,7 +209,7 @@ describe.skipIf(HTTP_SKIP)('agent-channel-dispatch (RFC 0082 §B): production ru
207
209
  if (typeof movedVersion !== 'string' || movedVersion === pinnedVersion) {
208
210
  // eslint-disable-next-line no-console
209
211
  console.warn('[agent-channel-dispatch] channel did not observably move — skipping Leg 3 strict assertion');
210
- return;
212
+ return softSkip('blocked', 'precondition not met — `typeof movedVersion !== \'string\' || movedVersion === pinnedVersion` returned early ([agent-channel-dispatch] channel did not observably move — skipping Leg 3 strict assertion) (seam, prior step…');
211
213
  }
212
214
  const fork2 = await driver.post(
213
215
  `/v1/runs/${encodeURIComponent(sourceRunId)}:fork`,
@@ -215,25 +217,25 @@ describe.skipIf(HTTP_SKIP)('agent-channel-dispatch (RFC 0082 §B): production ru
215
217
  );
216
218
  if (forkDeclined(fork2.status, 'channel-dispatch replay fork 2')) {
217
219
  ctx.skip();
218
- return;
220
+ return softSkip('blocked', 'precondition not met — `forkDeclined(fork2.status, \'channel-dispatch replay fork 2\')` returned early (seam, prior step, or fixture unavailable)');
219
221
  }
220
222
  expect(
221
223
  fork2.status,
222
- driver.describe('rest-endpoints.md POST /v1/runs/{runId}:fork', 'replay fork MUST return 201'),
224
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r', 'rest-endpoints.md POST /v1/runs/{runId}:fork', 'replay fork MUST return 201'),
223
225
  ).toBe(201);
224
226
  const fork2RunId = (fork2.json as { runId: string }).runId;
225
227
  await pollUntilTerminal(fork2RunId, { timeoutMs: 15_000 });
226
228
  const fork2Started = await firstInvocationStarted(fork2RunId);
227
229
  expect(
228
230
  fork2Started?.payload.resolvedAgentVersion,
229
- driver.describe(
231
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r',
230
232
  'agent-deployment.md §B',
231
233
  'after the channel moves, a replay of the original run MUST still carry the ORIGINAL pin — never re-resolving the moved channel',
232
234
  ),
233
235
  ).toBe(pinnedVersion);
234
236
  expect(
235
237
  fork2Started?.payload.resolvedAgentVersion,
236
- driver.describe(
238
+ req('openwop.it.agent-channel-dispatch.resolves-records-the-channel-pin-on-a-real-run-and-re-reads-it-on-replay-never-r',
237
239
  'agent-deployment.md §B',
238
240
  'a replay MUST NOT resolve to the post-move version (proves the recorded fact is re-read, not re-resolved)',
239
241
  ),
@@ -33,7 +33,6 @@ import { readFileSync } from 'node:fs';
33
33
  import { join } from 'node:path';
34
34
  import Ajv2020 from 'ajv/dist/2020.js';
35
35
  import addFormats from 'ajv-formats';
36
- import { driver } from '../lib/driver.js';
37
36
  import { behaviorGate } from '../lib/behavior-gate.js';
38
37
  import { SCHEMAS_DIR } from '../lib/paths.js';
39
38
  import {
@@ -43,6 +42,8 @@ import {
43
42
  DEPLOYMENT_CONTENT_FORBIDDEN,
44
43
  } from '../lib/agentDeployment.js';
45
44
  import { queryTestEvents, requireEvents, isEventLogSeamAvailable, resetTestSeam } from '../lib/event-log-query.js';
45
+ import { req } from '../lib/requirement-ids.js';
46
+ import { softSkip } from '../lib/soft-skip.js';
46
47
 
47
48
  function loadSchema(name: string): Record<string, unknown> {
48
49
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -52,7 +53,7 @@ function expectContentFree(payload: Record<string, unknown>, where: string): voi
52
53
  for (const f of DEPLOYMENT_CONTENT_FORBIDDEN) {
53
54
  expect(
54
55
  !(f in payload),
55
- driver.describe('RFC 0082 §D (deployment-event-no-content-leak)', `${where} MUST be content-free (no ${f})`),
56
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'RFC 0082 §D (deployment-event-no-content-leak)', `${where} MUST be content-free (no ${f})`),
56
57
  ).toBe(true);
57
58
  }
58
59
  }
@@ -61,7 +62,7 @@ describe('agent-deployment-lifecycle (RFC 0082 §B/§E)', () => {
61
62
  it('promotes via the eval+RBAC+approval gate, fails closed without scope/eval, and pins the channel version', async () => {
62
63
  const cap = await readDeploymentCap();
63
64
  if (!behaviorGate('openwop-deployment-lifecycle', cap?.supported === true)) return;
64
- if (!(await isEventLogSeamAvailable())) return; // event-log seam absent — soft-skip
65
+ if (!(await isEventLogSeamAvailable())) return softSkip('blocked', 'precondition not met — `!(await isEventLogSeamAvailable())` returned early (event-log seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // event-log seam absent — soft-skip
65
66
 
66
67
  const ajv = new Ajv2020({ strict: false, allErrors: true });
67
68
  addFormats(ajv);
@@ -69,22 +70,22 @@ describe('agent-deployment-lifecycle (RFC 0082 §B/§E)', () => {
69
70
 
70
71
  // ---- Leg 1: eval+RBAC+approval-gated promotion (§E) ------------------
71
72
  const promote = await driveDeploymentTransition({ scenario: 'promote' });
72
- if (promote === null) return; // deployment seam unwired — soft-skip the whole behavioral suite
73
+ if (promote === null) return softSkip('blocked', 'precondition not met — `promote === null` returned early (deployment seam unwired — soft-skip the whole behavioral suite) (seam, prior step, or fixture unavailable)'); // deployment seam unwired — soft-skip the whole behavioral suite
73
74
 
74
75
  // The host has ADVERTISED agents.deployment AND wired the seam — missing
75
76
  // evidence is a FAILURE, not a soft-skip. A successful promote MUST return
76
77
  // a runId + a schema-valid record + emit ≥1 content-free deployment.promoted.
77
78
  expect(
78
79
  typeof promote.runId === 'string' && (promote.runId as string).length > 0,
79
- driver.describe('agent-deployment.md §E', 'a wired promote MUST return the runId'),
80
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E', 'a wired promote MUST return the runId'),
80
81
  ).toBe(true);
81
82
  expect(
82
83
  promote.record !== undefined && promote.record !== null,
83
- driver.describe('agent-deployment.md §E', 'a successful promote MUST return the deployment record'),
84
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E', 'a successful promote MUST return the deployment record'),
84
85
  ).toBe(true);
85
86
  expect(
86
87
  validateRecord(promote.record),
87
- driver.describe('agent-deployment.schema.json', `a promoted deployment record MUST validate (${ajv.errorsText(validateRecord.errors)})`),
88
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.schema.json', `a promoted deployment record MUST validate (${ajv.errorsText(validateRecord.errors)})`),
88
89
  ).toBe(true);
89
90
 
90
91
  const promotedEvents = requireEvents(
@@ -93,17 +94,17 @@ describe('agent-deployment-lifecycle (RFC 0082 §B/§E)', () => {
93
94
  );
94
95
  expect(
95
96
  promotedEvents.length >= 1,
96
- driver.describe('agent-deployment.md §E', 'a successful promote MUST emit at least one deployment.promoted'),
97
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E', 'a successful promote MUST emit at least one deployment.promoted'),
97
98
  ).toBe(true);
98
99
  for (const e of promotedEvents) {
99
100
  expectContentFree(e.payload, 'deployment.promoted');
100
101
  expect(
101
102
  typeof e.payload.toState === 'string' && DEPLOYMENT_STATES.includes(e.payload.toState as string),
102
- driver.describe('run-event-payloads.schema.json#/$defs/deploymentPromoted', 'toState MUST be in the seven-state vocabulary'),
103
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'run-event-payloads.schema.json#/$defs/deploymentPromoted', 'toState MUST be in the seven-state vocabulary'),
103
104
  ).toBe(true);
104
105
  expect(
105
106
  typeof e.payload.toVersion === 'string' && (e.payload.toVersion as string).length > 0,
106
- driver.describe('agent-deployment.md §D', 'deployment.promoted MUST carry the promoted toVersion'),
107
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §D', 'deployment.promoted MUST carry the promoted toVersion'),
107
108
  ).toBe(true);
108
109
  }
109
110
 
@@ -111,11 +112,11 @@ describe('agent-deployment-lifecycle (RFC 0082 §B/§E)', () => {
111
112
  const unauth = await driveDeploymentTransition({ scenario: 'unauthorized' });
112
113
  expect(
113
114
  unauth !== null && typeof unauth.runId === 'string' && (unauth.runId as string).length > 0,
114
- driver.describe('agent-deployment.md §E-1', 'the unauthorized scenario MUST return a runId to evidence the fail-closed denial'),
115
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E-1', 'the unauthorized scenario MUST return a runId to evidence the fail-closed denial'),
115
116
  ).toBe(true);
116
117
  expect(
117
118
  unauth!.allowed !== true,
118
- driver.describe('agent-deployment.md §E-1', 'a principal without deploy:promote MUST be denied (fail-closed)'),
119
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E-1', 'a principal without deploy:promote MUST be denied (fail-closed)'),
119
120
  ).toBe(true);
120
121
  const unauthPromoted = requireEvents(
121
122
  await queryTestEvents(unauth!.runId as string, { type: 'deployment.promoted' }),
@@ -123,18 +124,18 @@ describe('agent-deployment-lifecycle (RFC 0082 §B/§E)', () => {
123
124
  );
124
125
  expect(
125
126
  unauthPromoted.length === 0,
126
- driver.describe('SECURITY invariant deployment-promotion-fail-closed', 'a denied transition MUST emit NO deployment.promoted'),
127
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'SECURITY invariant deployment-promotion-fail-closed', 'a denied transition MUST emit NO deployment.promoted'),
127
128
  ).toBe(true);
128
129
 
129
130
  // ---- Leg 3: eval-gate-unmet denial (§E-3) ----------------------------
130
131
  const evalUnmet = await driveDeploymentTransition({ scenario: 'eval-gate-unmet' });
131
132
  expect(
132
133
  evalUnmet !== null && typeof evalUnmet.runId === 'string' && (evalUnmet.runId as string).length > 0,
133
- driver.describe('agent-deployment.md §E-3', 'the eval-gate-unmet scenario MUST return a runId to evidence the denial'),
134
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E-3', 'the eval-gate-unmet scenario MUST return a runId to evidence the denial'),
134
135
  ).toBe(true);
135
136
  expect(
136
137
  evalUnmet!.error === 'eval_gate_unmet' || evalUnmet!.allowed !== true,
137
- driver.describe('agent-deployment.md §E-3', 'a promote whose eval evidence has passed:false MUST be denied (eval_gate_unmet)'),
138
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E-3', 'a promote whose eval evidence has passed:false MUST be denied (eval_gate_unmet)'),
138
139
  ).toBe(true);
139
140
  const evalUnmetPromoted = requireEvents(
140
141
  await queryTestEvents(evalUnmet!.runId as string, { type: 'deployment.promoted' }),
@@ -142,14 +143,14 @@ describe('agent-deployment-lifecycle (RFC 0082 §B/§E)', () => {
142
143
  );
143
144
  expect(
144
145
  evalUnmetPromoted.length === 0,
145
- driver.describe('agent-deployment.md §E-3', 'an unmet eval gate MUST emit NO deployment.promoted'),
146
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §E-3', 'an unmet eval gate MUST emit NO deployment.promoted'),
146
147
  ).toBe(true);
147
148
 
148
149
  // ---- Leg 4: channel-resolution pin (§B) ------------------------------
149
150
  const pin = await driveDeploymentTransition({ scenario: 'channel-pin', channel: 'stable' });
150
151
  expect(
151
152
  pin !== null && typeof pin.runId === 'string' && (pin.runId as string).length > 0,
152
- driver.describe('agent-deployment.md §B', 'the channel-pin scenario MUST return a runId'),
153
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §B', 'the channel-pin scenario MUST return a runId'),
153
154
  ).toBe(true);
154
155
  const invEvents = requireEvents(
155
156
  await queryTestEvents(pin!.runId as string, { type: 'agent.invocation.started' }),
@@ -157,12 +158,12 @@ describe('agent-deployment-lifecycle (RFC 0082 §B/§E)', () => {
157
158
  );
158
159
  expect(
159
160
  invEvents.length >= 1,
160
- driver.describe('agent-deployment.md §B', 'a @channel-bound run MUST emit agent.invocation.started'),
161
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §B', 'a @channel-bound run MUST emit agent.invocation.started'),
161
162
  ).toBe(true);
162
163
  const startedInv = invEvents.sort((a, b) => a.sequence - b.sequence)[0]!;
163
164
  expect(
164
165
  typeof startedInv.payload.resolvedAgentVersion === 'string' && (startedInv.payload.resolvedAgentVersion as string).length > 0,
165
- driver.describe('agent-deployment.md §B', 'a @channel-bound run MUST record resolvedAgentVersion on agent.invocation.started (the recorded fact a replay re-reads)'),
166
+ req('openwop.it.agent-deployment-lifecycle.promotes-via-the-eval-rbac-approval-gate-fails-closed-without-scope-eval-and-pin', 'agent-deployment.md §B', 'a @channel-bound run MUST record resolvedAgentVersion on agent.invocation.started (the recorded fact a replay re-reads)'),
166
167
  ).toBe(true);
167
168
 
168
169
  await resetTestSeam();