@openwop/openwop-conformance 1.162.0 → 2.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (553) hide show
  1. package/README.md +11 -2
  2. package/dist/cli.js +54 -1
  3. package/dist/lib/paths.js +25 -3
  4. package/dist/lib/requirement-ids.js +34 -4
  5. package/dist/lib/scenario-disposition.js +1 -0
  6. package/dist/lib/spec-coherence.js +13 -32
  7. package/dist/spec-artifacts.lock.json +5 -0
  8. package/package.json +11 -33
  9. package/requirements.json +20303 -11809
  10. package/scenario-majors.json +1343 -0
  11. package/schemas/CORPUS-STAMP.json +138 -6
  12. package/src/cli.ts +47 -1
  13. package/src/global-setup.ts +3 -2
  14. package/src/lib/corpus-stamp.ts +29 -1
  15. package/src/lib/paths.ts +25 -3
  16. package/src/lib/requirement-ids.ts +33 -4
  17. package/src/lib/scenario-disposition.ts +1 -0
  18. package/src/lib/spec-coherence.ts +15 -32
  19. package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
  20. package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
  21. package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
  22. package/src/scenarios/a2a-peer-authority.test.ts +7 -6
  23. package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
  24. package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
  25. package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
  26. package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
  27. package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
  28. package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
  29. package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
  30. package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
  31. package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
  32. package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
  33. package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
  34. package/src/scenarios/agent-deployment-shape.test.ts +22 -24
  35. package/src/scenarios/agent-eval-run.test.ts +19 -18
  36. package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
  37. package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
  38. package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
  39. package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
  40. package/src/scenarios/agent-live-structured-output.test.ts +7 -6
  41. package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
  42. package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
  43. package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
  44. package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
  45. package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
  46. package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
  47. package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
  48. package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
  49. package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
  50. package/src/scenarios/agent-platform-profile.test.ts +18 -19
  51. package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
  52. package/src/scenarios/agent-roster-attribution.test.ts +18 -17
  53. package/src/scenarios/agent-roster-shape.test.ts +17 -19
  54. package/src/scenarios/agent-verifier-shape.test.ts +11 -11
  55. package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
  56. package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
  57. package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
  58. package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
  59. package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
  60. package/src/scenarios/agentMessageReducer.test.ts +2 -1
  61. package/src/scenarios/agentMetadata.test.ts +2 -1
  62. package/src/scenarios/agentPackCatalog.test.ts +23 -21
  63. package/src/scenarios/agentPackExport.test.ts +4 -2
  64. package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
  65. package/src/scenarios/agentPackInstall.test.ts +4 -2
  66. package/src/scenarios/agentPackProvenance.test.ts +2 -1
  67. package/src/scenarios/agentReasoningEvents.test.ts +3 -2
  68. package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
  69. package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
  70. package/src/scenarios/ai-envelope-shape.test.ts +31 -29
  71. package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
  72. package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
  73. package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
  74. package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
  75. package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
  76. package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
  77. package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
  78. package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
  79. package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
  80. package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
  81. package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
  82. package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
  83. package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
  84. package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
  85. package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
  86. package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
  87. package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
  88. package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
  89. package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
  90. package/src/scenarios/append-ordering.test.ts +7 -5
  91. package/src/scenarios/approval-gate-events.test.ts +4 -3
  92. package/src/scenarios/approval-gate-flow.test.ts +4 -3
  93. package/src/scenarios/approval-payload.test.ts +5 -4
  94. package/src/scenarios/artifact-auth.test.ts +7 -6
  95. package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
  96. package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
  97. package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
  98. package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
  99. package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
  100. package/src/scenarios/audit-log-integrity.test.ts +8 -6
  101. package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
  102. package/src/scenarios/auth-mtls.test.ts +22 -20
  103. package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
  104. package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
  105. package/src/scenarios/auth-saml-profile.test.ts +14 -12
  106. package/src/scenarios/auth-scim-profile.test.ts +3 -2
  107. package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
  108. package/src/scenarios/auth-subject-link.test.ts +11 -10
  109. package/src/scenarios/auth.test.ts +5 -4
  110. package/src/scenarios/authorization-fail-closed.test.ts +3 -2
  111. package/src/scenarios/authorization-roles-shape.test.ts +9 -7
  112. package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
  113. package/src/scenarios/blob-presign-expiry.test.ts +12 -10
  114. package/src/scenarios/blob-roundtrip.test.ts +0 -0
  115. package/src/scenarios/budget-enforcement.test.ts +15 -14
  116. package/src/scenarios/budget-policy-shape.test.ts +18 -19
  117. package/src/scenarios/bulk-cancel.test.ts +9 -8
  118. package/src/scenarios/byok-auth-modes.test.ts +13 -14
  119. package/src/scenarios/byok-roundtrip.test.ts +12 -10
  120. package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
  121. package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
  122. package/src/scenarios/callai-multimodal.test.ts +5 -3
  123. package/src/scenarios/cancellation.test.ts +6 -5
  124. package/src/scenarios/cap-breach.test.ts +15 -14
  125. package/src/scenarios/capability-arm-witness.test.ts +5 -3
  126. package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
  127. package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
  128. package/src/scenarios/certification-bundle-v2.test.ts +11 -10
  129. package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
  130. package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
  131. package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
  132. package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
  133. package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
  134. package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
  135. package/src/scenarios/channel-presence-shape.test.ts +11 -12
  136. package/src/scenarios/channel-ttl.test.ts +6 -5
  137. package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
  138. package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
  139. package/src/scenarios/commitment-fired.test.ts +6 -5
  140. package/src/scenarios/compensation-behavior.test.ts +24 -23
  141. package/src/scenarios/compensation-recovery.test.ts +28 -27
  142. package/src/scenarios/configurable-schema.test.ts +8 -6
  143. package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
  144. package/src/scenarios/conformance-execution-witness.test.ts +9 -8
  145. package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
  146. package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
  147. package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
  148. package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
  149. package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
  150. package/src/scenarios/connection-provider-resolution.test.ts +18 -16
  151. package/src/scenarios/connector-manifest-validity.test.ts +8 -7
  152. package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
  153. package/src/scenarios/context-summarization-replay.test.ts +14 -12
  154. package/src/scenarios/contract-provenance.test.ts +18 -18
  155. package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
  156. package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
  157. package/src/scenarios/conversationLifecycle.test.ts +2 -1
  158. package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
  159. package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
  160. package/src/scenarios/core-standard-profile.test.ts +8 -9
  161. package/src/scenarios/cost-attribution.test.ts +23 -21
  162. package/src/scenarios/credential-payload-redaction.test.ts +4 -3
  163. package/src/scenarios/credentials-capability-shape.test.ts +5 -4
  164. package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
  165. package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
  166. package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
  167. package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
  168. package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
  169. package/src/scenarios/data-residency-admission.test.ts +15 -14
  170. package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
  171. package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
  172. package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
  173. package/src/scenarios/debugBundle.test.ts +25 -23
  174. package/src/scenarios/discovery-families-view.test.ts +5 -4
  175. package/src/scenarios/discovery.test.ts +30 -29
  176. package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
  177. package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
  178. package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
  179. package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
  180. package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
  181. package/src/scenarios/dispatchLoop.test.ts +3 -2
  182. package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
  183. package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
  184. package/src/scenarios/distillation-shape.test.ts +4 -4
  185. package/src/scenarios/distillation-stable-archive.test.ts +6 -6
  186. package/src/scenarios/distillation-token-budget.test.ts +5 -5
  187. package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
  188. package/src/scenarios/egress-audience-binding.test.ts +11 -10
  189. package/src/scenarios/egress-decision-content-free.test.ts +6 -5
  190. package/src/scenarios/egress-provenance-shape.test.ts +17 -18
  191. package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
  192. package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
  193. package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
  194. package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
  195. package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
  196. package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
  197. package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
  198. package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
  199. package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
  200. package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
  201. package/src/scenarios/envelope-truncated.test.ts +19 -17
  202. package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
  203. package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
  204. package/src/scenarios/errors.test.ts +20 -19
  205. package/src/scenarios/eventOrdering.test.ts +16 -14
  206. package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
  207. package/src/scenarios/experimental-tier-shape.test.ts +17 -15
  208. package/src/scenarios/export-bundle-portability.test.ts +17 -17
  209. package/src/scenarios/failure-path.test.ts +7 -6
  210. package/src/scenarios/feedback-capability-shape.test.ts +4 -3
  211. package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
  212. package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
  213. package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
  214. package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
  215. package/src/scenarios/feedback-record-and-list.test.ts +2 -1
  216. package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
  217. package/src/scenarios/fixtures-gating.test.ts +29 -28
  218. package/src/scenarios/fixtures-valid.test.ts +16 -15
  219. package/src/scenarios/form-content-instantiation.test.ts +15 -14
  220. package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
  221. package/src/scenarios/fs-path-traversal.test.ts +14 -12
  222. package/src/scenarios/goal-standing-continuation.test.ts +21 -21
  223. package/src/scenarios/grpc-transport.test.ts +9 -7
  224. package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
  225. package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
  226. package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
  227. package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
  228. package/src/scenarios/highConcurrency.test.ts +14 -13
  229. package/src/scenarios/host-callback-declaration.test.ts +8 -7
  230. package/src/scenarios/http-client-ssrf.test.ts +7 -5
  231. package/src/scenarios/i18n-negotiation.test.ts +14 -12
  232. package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
  233. package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
  234. package/src/scenarios/idempotency.test.ts +8 -7
  235. package/src/scenarios/idempotencyRetry.test.ts +13 -11
  236. package/src/scenarios/identity-owner-shape.test.ts +6 -5
  237. package/src/scenarios/identity-passthrough.test.ts +4 -3
  238. package/src/scenarios/interrupt-approval.test.ts +6 -5
  239. package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
  240. package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
  241. package/src/scenarios/interrupt-clarification.test.ts +4 -3
  242. package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
  243. package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
  244. package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
  245. package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
  246. package/src/scenarios/interruptRace.test.ts +12 -10
  247. package/src/scenarios/kv-atomic-increment.test.ts +11 -9
  248. package/src/scenarios/kv-cas.test.ts +14 -12
  249. package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
  250. package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
  251. package/src/scenarios/localized-content-delivery.test.ts +24 -26
  252. package/src/scenarios/maliciousManifest.test.ts +10 -8
  253. package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
  254. package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
  255. package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
  256. package/src/scenarios/mcp-discoverability.test.ts +9 -7
  257. package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
  258. package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
  259. package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
  260. package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
  261. package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
  262. package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
  263. package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
  264. package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
  265. package/src/scenarios/mcp-stateless-request.test.ts +11 -10
  266. package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
  267. package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
  268. package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
  269. package/src/scenarios/media-url-inline-cap.test.ts +21 -19
  270. package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
  271. package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
  272. package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
  273. package/src/scenarios/memory-attribution-shape.test.ts +4 -3
  274. package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
  275. package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
  276. package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
  277. package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
  278. package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
  279. package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
  280. package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
  281. package/src/scenarios/memory-degraded-projection.test.ts +10 -9
  282. package/src/scenarios/memory-injection-budget.test.ts +15 -14
  283. package/src/scenarios/metric-emission.test.ts +4 -3
  284. package/src/scenarios/model-capability-insufficient.test.ts +19 -17
  285. package/src/scenarios/model-capability-substituted.test.ts +20 -18
  286. package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
  287. package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
  288. package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
  289. package/src/scenarios/multi-node-ordering.test.ts +4 -3
  290. package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
  291. package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
  292. package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
  293. package/src/scenarios/multi-region-idempotency.test.ts +6 -5
  294. package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
  295. package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
  296. package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
  297. package/src/scenarios/oauth-capability-shape.test.ts +5 -4
  298. package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
  299. package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
  300. package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
  301. package/src/scenarios/orchestratorDispatch.test.ts +2 -1
  302. package/src/scenarios/orchestratorTermination.test.ts +2 -1
  303. package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
  304. package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
  305. package/src/scenarios/otel-emission-grpc.test.ts +3 -2
  306. package/src/scenarios/otel-emission.test.ts +6 -5
  307. package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
  308. package/src/scenarios/otel-trace-propagation.test.ts +2 -1
  309. package/src/scenarios/owner-subject-echo.test.ts +13 -12
  310. package/src/scenarios/owner-subject-shape.test.ts +11 -10
  311. package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
  312. package/src/scenarios/pack-registry-isolation.test.ts +4 -3
  313. package/src/scenarios/pack-registry-publish.test.ts +65 -63
  314. package/src/scenarios/pack-registry.test.ts +38 -36
  315. package/src/scenarios/pause-resume.test.ts +18 -16
  316. package/src/scenarios/policies.test.ts +20 -18
  317. package/src/scenarios/production-backpressure.test.ts +18 -16
  318. package/src/scenarios/production-retention-expiry.test.ts +8 -6
  319. package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
  320. package/src/scenarios/profileDerivation.test.ts +34 -33
  321. package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
  322. package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
  323. package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
  324. package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
  325. package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
  326. package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
  327. package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
  328. package/src/scenarios/prompt-pack-install.test.ts +14 -12
  329. package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
  330. package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
  331. package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
  332. package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
  333. package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
  334. package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
  335. package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
  336. package/src/scenarios/prompt-template-shape.test.ts +30 -28
  337. package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
  338. package/src/scenarios/protocol-versions-array.test.ts +10 -9
  339. package/src/scenarios/provider-usage.test.ts +17 -15
  340. package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
  341. package/src/scenarios/purpose-propagation.test.ts +23 -21
  342. package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
  343. package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
  344. package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
  345. package/src/scenarios/rate-limit-envelope.test.ts +6 -5
  346. package/src/scenarios/redaction.test.ts +13 -11
  347. package/src/scenarios/redactionAdversarial.test.ts +11 -9
  348. package/src/scenarios/registry-public.test.ts +12 -11
  349. package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
  350. package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
  351. package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
  352. package/src/scenarios/replay-fork.test.ts +20 -19
  353. package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
  354. package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
  355. package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
  356. package/src/scenarios/replay-retention-expiry.test.ts +11 -9
  357. package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
  358. package/src/scenarios/replayDeterminism.test.ts +13 -12
  359. package/src/scenarios/requirement-ledger.test.ts +15 -14
  360. package/src/scenarios/restart-during-run.test.ts +3 -2
  361. package/src/scenarios/route-coverage.test.ts +20 -19
  362. package/src/scenarios/run-diff.test.ts +22 -20
  363. package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
  364. package/src/scenarios/run-transport-economy.test.ts +13 -11
  365. package/src/scenarios/runner-ledger.test.ts +17 -16
  366. package/src/scenarios/runs-lifecycle.test.ts +7 -6
  367. package/src/scenarios/runtime-capabilities.test.ts +12 -10
  368. package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
  369. package/src/scenarios/runtime-requires-shape.test.ts +7 -6
  370. package/src/scenarios/safefetch-behavior.test.ts +22 -21
  371. package/src/scenarios/safefetch-live-audit.test.ts +14 -13
  372. package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
  373. package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
  374. package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
  375. package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
  376. package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
  377. package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
  378. package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
  379. package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
  380. package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
  381. package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
  382. package/src/scenarios/self-hosted-runner.test.ts +26 -24
  383. package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
  384. package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
  385. package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
  386. package/src/scenarios/sql-injection-rejection.test.ts +8 -6
  387. package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
  388. package/src/scenarios/staleClaim.test.ts +5 -4
  389. package/src/scenarios/stream-modes-buffer.test.ts +8 -7
  390. package/src/scenarios/stream-modes-mixed.test.ts +10 -9
  391. package/src/scenarios/stream-modes.test.ts +12 -11
  392. package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
  393. package/src/scenarios/stream-text-fixture.test.ts +14 -13
  394. package/src/scenarios/streamReconnect.test.ts +13 -11
  395. package/src/scenarios/strict-behavior-gate.test.ts +9 -8
  396. package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
  397. package/src/scenarios/subrun-approval-gate.test.ts +3 -3
  398. package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
  399. package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
  400. package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
  401. package/src/scenarios/subworkflow.test.ts +10 -9
  402. package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
  403. package/src/scenarios/table-cursor-pagination.test.ts +8 -6
  404. package/src/scenarios/table-schema-enforcement.test.ts +7 -5
  405. package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
  406. package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
  407. package/src/scenarios/tool-catalog-projection.test.ts +11 -9
  408. package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
  409. package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
  410. package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
  411. package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
  412. package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
  413. package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
  414. package/src/scenarios/tool-hooks-shape.test.ts +3 -3
  415. package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
  416. package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
  417. package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
  418. package/src/scenarios/trigger-ingestion.test.ts +19 -17
  419. package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
  420. package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
  421. package/src/scenarios/verifier-gating.test.ts +8 -6
  422. package/src/scenarios/version-fold.test.ts +9 -8
  423. package/src/scenarios/version-negotiation.test.ts +12 -11
  424. package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
  425. package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
  426. package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
  427. package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
  428. package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
  429. package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
  430. package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
  431. package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
  432. package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
  433. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
  434. package/src/scenarios/wasm-pack-load.test.ts +4 -3
  435. package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
  436. package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
  437. package/src/scenarios/webhook-negative.test.ts +11 -9
  438. package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
  439. package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
  440. package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
  441. package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
  442. package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
  443. package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
  444. package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
  445. package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
  446. package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
  447. package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
  448. package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
  449. package/src/scenarios/workflow-variable-format.test.ts +24 -24
  450. package/src/scenarios/workload-identity-behavior.test.ts +15 -13
  451. package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
  452. package/src/scenarios/workspace-behavior.test.ts +19 -18
  453. package/src/scenarios/workspace-capability-shape.test.ts +3 -2
  454. package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
  455. package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
  456. package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
  457. package/src/setup.ts +4 -2
  458. package/vitest.config.ts +5 -1
  459. package/api/.redocly.lint-ignore.yaml +0 -22
  460. package/api/asyncapi.yaml +0 -834
  461. package/api/grpc/openwop.proto +0 -251
  462. package/api/openapi.yaml +0 -2693
  463. package/api/redocly.yaml +0 -23
  464. package/schemas/README.md +0 -144
  465. package/schemas/a2a-task-state.schema.json +0 -78
  466. package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
  467. package/schemas/agent-deployment-transition.schema.json +0 -49
  468. package/schemas/agent-deployment.schema.json +0 -54
  469. package/schemas/agent-eval-suite.schema.json +0 -140
  470. package/schemas/agent-inventory-response.schema.json +0 -115
  471. package/schemas/agent-manifest.schema.json +0 -156
  472. package/schemas/agent-org-chart.schema.json +0 -82
  473. package/schemas/agent-ref.schema.json +0 -63
  474. package/schemas/agent-roster-entry.schema.json +0 -81
  475. package/schemas/agent-roster-response.schema.json +0 -21
  476. package/schemas/ai-envelope.schema.json +0 -134
  477. package/schemas/annotation-create.schema.json +0 -37
  478. package/schemas/annotation.schema.json +0 -56
  479. package/schemas/artifact-type-pack-manifest.schema.json +0 -244
  480. package/schemas/audit-verify-result.schema.json +0 -90
  481. package/schemas/budget-policy.schema.json +0 -18
  482. package/schemas/capabilities.schema.json +0 -4124
  483. package/schemas/certification-bundle-v2.schema.json +0 -118
  484. package/schemas/channel-presence-payload.schema.json +0 -41
  485. package/schemas/channel-written-payload.schema.json +0 -55
  486. package/schemas/chat-card-pack-manifest.schema.json +0 -253
  487. package/schemas/compact-tool-descriptor.schema.json +0 -51
  488. package/schemas/compensation-policy.schema.json +0 -64
  489. package/schemas/conformance-certification-bundle.schema.json +0 -86
  490. package/schemas/connection-pack-manifest.schema.json +0 -353
  491. package/schemas/conversation-event.schema.json +0 -168
  492. package/schemas/conversation-turn.schema.json +0 -117
  493. package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
  494. package/schemas/credential-provenance.schema.json +0 -18
  495. package/schemas/credential-reference.schema.json +0 -21
  496. package/schemas/debug-bundle.schema.json +0 -196
  497. package/schemas/dispatch-config.schema.json +0 -112
  498. package/schemas/envelopes/clarification.request.schema.json +0 -52
  499. package/schemas/envelopes/error.schema.json +0 -30
  500. package/schemas/envelopes/media.audio.schema.json +0 -38
  501. package/schemas/envelopes/media.file.schema.json +0 -37
  502. package/schemas/envelopes/media.image.schema.json +0 -33
  503. package/schemas/envelopes/schema.request.schema.json +0 -26
  504. package/schemas/envelopes/schema.response.schema.json +0 -22
  505. package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
  506. package/schemas/error-envelope.schema.json +0 -25
  507. package/schemas/eval-summary.schema.json +0 -92
  508. package/schemas/export-bundle.schema.json +0 -66
  509. package/schemas/form-content-pack-manifest.schema.json +0 -243
  510. package/schemas/frontend-plugin-manifest.schema.json +0 -109
  511. package/schemas/goal.schema.json +0 -104
  512. package/schemas/heartbeat-evaluated.schema.json +0 -14
  513. package/schemas/heartbeat-state-changed.schema.json +0 -14
  514. package/schemas/localized-content-language-settings.schema.json +0 -26
  515. package/schemas/localized-content-page-response.schema.json +0 -60
  516. package/schemas/localized-content-page.schema.json +0 -62
  517. package/schemas/localized-content-section.schema.json +0 -51
  518. package/schemas/memory-entry.schema.json +0 -36
  519. package/schemas/memory-list-options.schema.json +0 -37
  520. package/schemas/node-pack-manifest.schema.json +0 -654
  521. package/schemas/orchestrator-decision.schema.json +0 -90
  522. package/schemas/org-chart-responsibility-view.schema.json +0 -26
  523. package/schemas/pack-lockfile.schema.json +0 -108
  524. package/schemas/prompt-kind.schema.json +0 -8
  525. package/schemas/prompt-pack-manifest.schema.json +0 -117
  526. package/schemas/prompt-ref.schema.json +0 -40
  527. package/schemas/prompt-template.schema.json +0 -149
  528. package/schemas/proposal.schema.json +0 -84
  529. package/schemas/registry-version-manifest.schema.json +0 -208
  530. package/schemas/residency.schema.json +0 -16
  531. package/schemas/run-ancestry-response.schema.json +0 -54
  532. package/schemas/run-diff-response.schema.json +0 -64
  533. package/schemas/run-event-payloads.schema.json +0 -4452
  534. package/schemas/run-event.schema.json +0 -211
  535. package/schemas/run-options.schema.json +0 -80
  536. package/schemas/run-orchestrator-decided-event.schema.json +0 -20
  537. package/schemas/run-snapshot.schema.json +0 -148
  538. package/schemas/security-advisory.schema.json +0 -109
  539. package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
  540. package/schemas/self-hosted-runner-registration.schema.json +0 -53
  541. package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
  542. package/schemas/subject.schema.json +0 -56
  543. package/schemas/suspend-request.schema.json +0 -207
  544. package/schemas/tool-descriptor.schema.json +0 -63
  545. package/schemas/trigger-event.schema.json +0 -222
  546. package/schemas/trigger-subscription-registration.schema.json +0 -67
  547. package/schemas/trigger-subscription.schema.json +0 -26
  548. package/schemas/ui-plugin-message.schema.json +0 -90
  549. package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
  550. package/schemas/workflow-definition.schema.json +0 -850
  551. package/schemas/workload-identity.schema.json +0 -79
  552. package/schemas/workspace-file-create.schema.json +0 -20
  553. package/schemas/workspace-file.schema.json +0 -39
@@ -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();
@@ -38,9 +38,7 @@ import { join } from 'node:path';
38
38
  import Ajv2020 from 'ajv/dist/2020.js';
39
39
  import addFormats from 'ajv-formats';
40
40
  import { SCHEMAS_DIR } from '../lib/paths.js';
41
-
42
- /** Server-free assertion-message helper. */
43
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
41
+ import { req } from '../lib/requirement-ids.js';
44
42
 
45
43
  function loadSchema(name: string): Record<string, unknown> {
46
44
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -51,11 +49,11 @@ describe('agent-deployment-shape: capability advertisement (RFC 0082, server-fre
51
49
  const caps = loadSchema('capabilities.schema.json');
52
50
  const agents = (caps.properties as Record<string, { properties?: Record<string, { properties?: Record<string, unknown> }> }>).agents;
53
51
  const deployment = agents?.properties?.deployment;
54
- expect(deployment, why('capabilities.md §agents', 'agents.deployment MUST be declared')).toBeDefined();
52
+ expect(deployment, req('openwop.it.agent-deployment-shape.the-capabilities-schema-declares-agents-deployment-with-its-sub-flags', 'capabilities.md §agents', 'agents.deployment MUST be declared')).toBeDefined();
55
53
  for (const flag of ['supported', 'channels', 'canary', 'rollback', 'states']) {
56
54
  expect(
57
55
  deployment?.properties?.[flag],
58
- why('agent-deployment.md §F', `agents.deployment.${flag} MUST be declared`),
56
+ req('openwop.it.agent-deployment-shape.the-capabilities-schema-declares-agents-deployment-with-its-sub-flags', 'agent-deployment.md §F', `agents.deployment.${flag} MUST be declared`),
59
57
  ).toBeDefined();
60
58
  }
61
59
  });
@@ -69,16 +67,16 @@ describe('agent-deployment-shape: deployment record + AgentRef binding (RFC 0082
69
67
 
70
68
  it('AgentDeployment validates a conforming record and rejects a bad state / out-of-range canary', () => {
71
69
  const good = { agentId: 'core.openwop.agents.support-resolver', version: '2.4.0', state: 'active', canaryPercent: 10, channels: ['stable'] };
72
- expect(record(good), why('RFC 0082 §C', 'a conforming deployment record MUST validate')).toBe(true);
73
- expect(record({ ...good, state: 'live' }), why('RFC 0082 §C', 'an out-of-enum state MUST be rejected')).toBe(false);
74
- expect(record({ ...good, canaryPercent: 150 }), why('RFC 0082 §C', 'canaryPercent > 100 MUST be rejected')).toBe(false);
70
+ expect(record(good), req('openwop.it.agent-deployment-shape.agentdeployment-validates-a-conforming-record-and-rejects-a-bad-state-out-of-ran', 'RFC 0082 §C', 'a conforming deployment record MUST validate')).toBe(true);
71
+ expect(record({ ...good, state: 'live' }), req('openwop.it.agent-deployment-shape.agentdeployment-validates-a-conforming-record-and-rejects-a-bad-state-out-of-ran', 'RFC 0082 §C', 'an out-of-enum state MUST be rejected')).toBe(false);
72
+ expect(record({ ...good, canaryPercent: 150 }), req('openwop.it.agent-deployment-shape.agentdeployment-validates-a-conforming-record-and-rejects-a-bad-state-out-of-ran', 'RFC 0082 §C', 'canaryPercent > 100 MUST be rejected')).toBe(false);
75
73
  });
76
74
 
77
75
  it('AgentRef channel XOR version: each alone and neither validate; both is rejected (RFC 0082 §A)', () => {
78
- expect(agentRef({ agentId: 'core.x.y.z', version: '1.0.0' }), why('RFC 0082 §A', 'version-only AgentRef MUST validate')).toBe(true);
79
- expect(agentRef({ agentId: 'core.x.y.z', channel: 'stable' }), why('RFC 0082 §A', 'channel-only AgentRef MUST validate')).toBe(true);
80
- expect(agentRef({ agentId: 'core.x.y.z' }), why('RFC 0082 §A', 'a ref with neither version nor channel MUST validate (host default)')).toBe(true);
81
- expect(agentRef({ agentId: 'core.x.y.z', version: '1.0.0', channel: 'stable' }), why('RFC 0082 §A', 'a ref with BOTH version and channel MUST be rejected')).toBe(false);
76
+ expect(agentRef({ agentId: 'core.x.y.z', version: '1.0.0' }), req('openwop.it.agent-deployment-shape.agentref-channel-xor-version-each-alone-and-neither-validate-both-is-rejected-rf', 'RFC 0082 §A', 'version-only AgentRef MUST validate')).toBe(true);
77
+ expect(agentRef({ agentId: 'core.x.y.z', channel: 'stable' }), req('openwop.it.agent-deployment-shape.agentref-channel-xor-version-each-alone-and-neither-validate-both-is-rejected-rf', 'RFC 0082 §A', 'channel-only AgentRef MUST validate')).toBe(true);
78
+ expect(agentRef({ agentId: 'core.x.y.z' }), req('openwop.it.agent-deployment-shape.agentref-channel-xor-version-each-alone-and-neither-validate-both-is-rejected-rf', 'RFC 0082 §A', 'a ref with neither version nor channel MUST validate (host default)')).toBe(true);
79
+ expect(agentRef({ agentId: 'core.x.y.z', version: '1.0.0', channel: 'stable' }), req('openwop.it.agent-deployment-shape.agentref-channel-xor-version-each-alone-and-neither-validate-both-is-rejected-rf', 'RFC 0082 §A', 'a ref with BOTH version and channel MUST be rejected')).toBe(false);
82
80
  });
83
81
  });
84
82
 
@@ -94,29 +92,29 @@ describe('agent-deployment-shape: deployment.* event payloads (RFC 0082, server-
94
92
  const stateChanged = ajv.getSchema('payloads#/$defs/deploymentStateChanged');
95
93
 
96
94
  it('deployment.promoted validates a content-free promotion record and requires toVersion + toState', () => {
97
- expect(promoted, 'the deploymentPromoted $def MUST exist').toBeTruthy();
95
+ expect(promoted, req('openwop.it.agent-deployment-shape.deployment-promoted-validates-a-content-free-promotion-record-and-requires-tover', 'RFC 0082', 'the deploymentPromoted $def MUST exist')).toBeTruthy();
98
96
  expect(
99
97
  promoted!({ agentId: 'core.openwop.agents.support-resolver', toVersion: '2.4.0', toState: 'active', channel: 'stable', canaryPercent: 10, evalRunId: 'run_abc' }),
100
- why('RFC 0082 §D', 'a conforming deployment.promoted payload MUST validate'),
98
+ req('openwop.it.agent-deployment-shape.deployment-promoted-validates-a-content-free-promotion-record-and-requires-tover', 'RFC 0082 §D', 'a conforming deployment.promoted payload MUST validate'),
101
99
  ).toBe(true);
102
- expect(promoted!({ agentId: 'a' }), why('RFC 0082 §D', 'deployment.promoted without toVersion/toState MUST be rejected')).toBe(false);
100
+ expect(promoted!({ agentId: 'a' }), req('openwop.it.agent-deployment-shape.deployment-promoted-validates-a-content-free-promotion-record-and-requires-tover', 'RFC 0082 §D', 'deployment.promoted without toVersion/toState MUST be rejected')).toBe(false);
103
101
  });
104
102
 
105
103
  it('deployment.rolled-back / canary.adjusted / state.changed validate conforming records', () => {
106
- expect(rolledBack!({ agentId: 'a', fromVersion: '2.4.0', toVersion: '2.3.1', rollbackPointer: '2.3.1' }), why('RFC 0082 §D', 'a conforming deployment.rolled-back MUST validate')).toBe(true);
107
- expect(canary!({ agentId: 'a', version: '2.4.0', fromPercent: 10, toPercent: 50 }), why('RFC 0082 §D', 'a conforming deployment.canary.adjusted MUST validate')).toBe(true);
108
- expect(stateChanged!({ agentId: 'a', version: '2.4.0', fromState: 'active', toState: 'paused' }), why('RFC 0082 §D', 'a conforming deployment.state.changed MUST validate')).toBe(true);
109
- expect(stateChanged!({ agentId: 'a', version: '2.4.0', fromState: 'active', toState: 'live' }), why('RFC 0082 §D', 'an out-of-enum toState MUST be rejected')).toBe(false);
104
+ expect(rolledBack!({ agentId: 'a', fromVersion: '2.4.0', toVersion: '2.3.1', rollbackPointer: '2.3.1' }), req('openwop.it.agent-deployment-shape.deployment-rolled-back-canary-adjusted-state-changed-validate-conforming-records', 'RFC 0082 §D', 'a conforming deployment.rolled-back MUST validate')).toBe(true);
105
+ expect(canary!({ agentId: 'a', version: '2.4.0', fromPercent: 10, toPercent: 50 }), req('openwop.it.agent-deployment-shape.deployment-rolled-back-canary-adjusted-state-changed-validate-conforming-records', 'RFC 0082 §D', 'a conforming deployment.canary.adjusted MUST validate')).toBe(true);
106
+ expect(stateChanged!({ agentId: 'a', version: '2.4.0', fromState: 'active', toState: 'paused' }), req('openwop.it.agent-deployment-shape.deployment-rolled-back-canary-adjusted-state-changed-validate-conforming-records', 'RFC 0082 §D', 'a conforming deployment.state.changed MUST validate')).toBe(true);
107
+ expect(stateChanged!({ agentId: 'a', version: '2.4.0', fromState: 'active', toState: 'live' }), req('openwop.it.agent-deployment-shape.deployment-rolled-back-canary-adjusted-state-changed-validate-conforming-records', 'RFC 0082 §D', 'an out-of-enum toState MUST be rejected')).toBe(false);
110
108
  });
111
109
 
112
110
  it('deployment.* events are content-free — a manifest body and a prompt are rejected (deployment-event-no-content-leak)', () => {
113
111
  expect(
114
112
  promoted!({ agentId: 'a', toVersion: '2.4.0', toState: 'active', manifestBody: '{...}' }),
115
- why('SECURITY invariant deployment-event-no-content-leak', 'a deployment.promoted MUST NOT carry a manifest body'),
113
+ req('openwop.it.agent-deployment-shape.deployment-events-are-content-free-a-manifest-body-and-a-prompt-are-rejected-dep', 'SECURITY invariant deployment-event-no-content-leak', 'a deployment.promoted MUST NOT carry a manifest body'),
116
114
  ).toBe(false);
117
115
  expect(
118
116
  stateChanged!({ agentId: 'a', version: '2.4.0', fromState: 'active', toState: 'paused', prompt: 'system: …' }),
119
- why('SECURITY invariant deployment-event-no-content-leak', 'a deployment.state.changed MUST NOT carry prompt content'),
117
+ req('openwop.it.agent-deployment-shape.deployment-events-are-content-free-a-manifest-body-and-a-prompt-are-rejected-dep', 'SECURITY invariant deployment-event-no-content-leak', 'a deployment.state.changed MUST NOT carry prompt content'),
120
118
  ).toBe(false);
121
119
  });
122
120
  });
@@ -125,15 +123,15 @@ describe('agent-deployment-shape: §B recorded-fact pin + enum (RFC 0082, server
125
123
  it('agent.invocation.started carries the additive recorded-fact resolvedAgentVersion / resolvedChannel', () => {
126
124
  const payloads = loadSchema('run-event-payloads.schema.json');
127
125
  const started = ((payloads.$defs as Record<string, { properties?: Record<string, unknown> }>).agentInvocationStarted)?.properties ?? {};
128
- expect(started.resolvedAgentVersion, why('RFC 0082 §B', 'agent.invocation.started.resolvedAgentVersion MUST be declared (the channel pin)')).toBeDefined();
129
- expect(started.resolvedChannel, why('RFC 0082 §B', 'agent.invocation.started.resolvedChannel MUST be declared')).toBeDefined();
126
+ expect(started.resolvedAgentVersion, req('openwop.it.agent-deployment-shape.agent-invocation-started-carries-the-additive-recorded-fact-resolvedagentversion', 'RFC 0082 §B', 'agent.invocation.started.resolvedAgentVersion MUST be declared (the channel pin)')).toBeDefined();
127
+ expect(started.resolvedChannel, req('openwop.it.agent-deployment-shape.agent-invocation-started-carries-the-additive-recorded-fact-resolvedagentversion', 'RFC 0082 §B', 'agent.invocation.started.resolvedChannel MUST be declared')).toBeDefined();
130
128
  });
131
129
 
132
130
  it('all four deployment event names appear in the RunEventType enum', () => {
133
131
  const runEvent = loadSchema('run-event.schema.json');
134
132
  const enumVals = (runEvent.$defs as Record<string, { enum?: string[] }>).RunEventType?.enum ?? [];
135
133
  for (const e of ['deployment.promoted', 'deployment.rolled-back', 'deployment.canary.adjusted', 'deployment.state.changed']) {
136
- expect(enumVals).toContain(e);
134
+ expect(enumVals, req('openwop.it.agent-deployment-shape.all-four-deployment-event-names-appear-in-the-runeventtype-enum', 'RFC 0082', 'all four deployment event names appear in the RunEventType enum')).toContain(e);
137
135
  }
138
136
  });
139
137
  });
@@ -29,7 +29,6 @@ import { readFileSync } from 'node:fs';
29
29
  import { join } from 'node:path';
30
30
  import Ajv2020 from 'ajv/dist/2020.js';
31
31
  import addFormats from 'ajv-formats';
32
- import { driver } from '../lib/driver.js';
33
32
  import { behaviorGate } from '../lib/behavior-gate.js';
34
33
  import { SCHEMAS_DIR } from '../lib/paths.js';
35
34
  import {
@@ -39,6 +38,8 @@ import {
39
38
  EVAL_CONTENT_FORBIDDEN,
40
39
  } from '../lib/agentEval.js';
41
40
  import { queryTestEvents, requireEvents, isEventLogSeamAvailable, resetTestSeam } from '../lib/event-log-query.js';
41
+ import { req } from '../lib/requirement-ids.js';
42
+ import { softSkip } from '../lib/soft-skip.js';
42
43
 
43
44
  function loadSchema(name: string): Record<string, unknown> {
44
45
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -48,7 +49,7 @@ function expectContentFree(payload: Record<string, unknown>, where: string): voi
48
49
  for (const f of EVAL_CONTENT_FORBIDDEN) {
49
50
  expect(
50
51
  !(f in payload),
51
- driver.describe('RFC 0081 §C (eval-summary-no-content-leak)', `${where} MUST be content-free (no ${f})`),
52
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'RFC 0081 §C (eval-summary-no-content-leak)', `${where} MUST be content-free (no ${f})`),
52
53
  ).toBe(true);
53
54
  }
54
55
  }
@@ -57,10 +58,10 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
57
58
  it('emits eval.started → per-task eval.scored → eval.completed and serves a content-free EvalSummary', async () => {
58
59
  const cap = await readEvalSuiteCap();
59
60
  if (!behaviorGate('openwop-eval-run', cap?.supported === true)) return;
60
- if (!(await isEventLogSeamAvailable())) return; // event-log seam absent — soft-skip
61
+ 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
61
62
 
62
63
  const run = await driveEvalRun({ modes: ['golden'] });
63
- if (run === null) return; // eval-run seam unwired — soft-skip the whole behavioral suite
64
+ if (run === null) return softSkip('blocked', 'precondition not met — `run === null` returned early (eval-run seam unwired — soft-skip the whole behavioral suite) (seam, prior step, or fixture unavailable)'); // eval-run seam unwired — soft-skip the whole behavioral suite
64
65
 
65
66
  // From here the host has ADVERTISED agents.evalSuite AND wired the eval-run
66
67
  // seam — missing evidence is a FAILURE, not a soft-skip. A host claiming the
@@ -68,7 +69,7 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
68
69
  // normative EvalSummary, or it is advertising a capability it doesn't deliver.
69
70
  expect(
70
71
  typeof run.runId === 'string' && run.runId.length > 0,
71
- driver.describe('agent-evaluation.md §B', 'a wired eval-run seam MUST return the projected runId'),
72
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §B', 'a wired eval-run seam MUST return the projected runId'),
72
73
  ).toBe(true);
73
74
  const runId = run.runId as string;
74
75
 
@@ -87,15 +88,15 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
87
88
  // ≥1 eval.scored — a wired eval run MUST emit the full sequence.
88
89
  expect(
89
90
  startedEvents.length === 1,
90
- driver.describe('agent-evaluation.md §C', 'an eval run MUST emit exactly one eval.started'),
91
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', 'an eval run MUST emit exactly one eval.started'),
91
92
  ).toBe(true);
92
93
  expect(
93
94
  scoredEvents.length >= 1,
94
- driver.describe('agent-evaluation.md §C', 'an eval run MUST emit at least one eval.scored'),
95
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', 'an eval run MUST emit at least one eval.scored'),
95
96
  ).toBe(true);
96
97
  expect(
97
98
  completedEvents.length === 1,
98
- driver.describe('agent-evaluation.md §C', 'an eval run MUST emit exactly one eval.completed'),
99
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', 'an eval run MUST emit exactly one eval.completed'),
99
100
  ).toBe(true);
100
101
  const started = startedEvents[0]!;
101
102
  const completed = completedEvents[0]!;
@@ -104,22 +105,22 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
104
105
  for (const s of scoredEvents) {
105
106
  expect(
106
107
  started.sequence < s.sequence,
107
- driver.describe('agent-evaluation.md §C', 'eval.started MUST precede every eval.scored'),
108
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', 'eval.started MUST precede every eval.scored'),
108
109
  ).toBe(true);
109
110
  expect(
110
111
  s.sequence < completed.sequence,
111
- driver.describe('agent-evaluation.md §C', 'every eval.scored MUST precede eval.completed'),
112
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', 'every eval.scored MUST precede eval.completed'),
112
113
  ).toBe(true);
113
114
  }
114
115
 
115
116
  // One eval.scored per task (count == eval.completed.taskCount).
116
117
  expect(
117
118
  typeof completed.payload.taskCount === 'number',
118
- driver.describe('run-event-payloads.schema.json#/$defs/evalCompleted', 'eval.completed MUST carry a numeric taskCount'),
119
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'run-event-payloads.schema.json#/$defs/evalCompleted', 'eval.completed MUST carry a numeric taskCount'),
119
120
  ).toBe(true);
120
121
  expect(
121
122
  scoredEvents.length === completed.payload.taskCount,
122
- driver.describe('agent-evaluation.md §C', 'one eval.scored per task (count == eval.completed.taskCount)'),
123
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', 'one eval.scored per task (count == eval.completed.taskCount)'),
123
124
  ).toBe(true);
124
125
 
125
126
  // Content-free (§C / eval-summary-no-content-leak) + score ∈ 0..1, passed boolean.
@@ -129,11 +130,11 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
129
130
  expectContentFree(s.payload, 'eval.scored');
130
131
  expect(
131
132
  typeof s.payload.score === 'number' && (s.payload.score as number) >= 0 && (s.payload.score as number) <= 1,
132
- driver.describe('run-event-payloads.schema.json#/$defs/evalScored', 'eval.scored.score MUST be in 0..1'),
133
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'run-event-payloads.schema.json#/$defs/evalScored', 'eval.scored.score MUST be in 0..1'),
133
134
  ).toBe(true);
134
135
  expect(
135
136
  typeof s.payload.passed === 'boolean',
136
- driver.describe('run-event-payloads.schema.json#/$defs/evalScored', 'eval.scored.passed MUST be a boolean'),
137
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'run-event-payloads.schema.json#/$defs/evalScored', 'eval.scored.passed MUST be a boolean'),
137
138
  ).toBe(true);
138
139
  }
139
140
 
@@ -141,7 +142,7 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
141
142
  const { status, summary } = await getEvalSummary(runId);
142
143
  expect(
143
144
  status === 200 && summary !== undefined,
144
- driver.describe('agent-evaluation.md §C', `GET /v1/runs/{runId}/eval-summary MUST serve a 200 EvalSummary for a completed eval run (got ${status})`),
145
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', `GET /v1/runs/{runId}/eval-summary MUST serve a 200 EvalSummary for a completed eval run (got ${status})`),
145
146
  ).toBe(true);
146
147
  const sum = summary as Record<string, unknown>;
147
148
  const ajv = new Ajv2020({ strict: false, allErrors: true });
@@ -149,7 +150,7 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
149
150
  const validate = ajv.compile(loadSchema('eval-summary.schema.json'));
150
151
  expect(
151
152
  validate(sum),
152
- driver.describe('eval-summary.schema.json', `EvalSummary MUST be schema-valid (${ajv.errorsText(validate.errors)})`),
153
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'eval-summary.schema.json', `EvalSummary MUST be schema-valid (${ajv.errorsText(validate.errors)})`),
153
154
  ).toBe(true);
154
155
 
155
156
  const tasks = (sum.tasks as Array<Record<string, unknown>> | undefined) ?? [];
@@ -157,11 +158,11 @@ describe('agent-eval-run (RFC 0081 §B/§C)', () => {
157
158
  const taskCount = sum.taskCount as number | undefined;
158
159
  expect(
159
160
  typeof passedCount === 'number' && typeof taskCount === 'number',
160
- driver.describe('eval-summary.schema.json', 'EvalSummary MUST carry numeric passedCount + taskCount'),
161
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'eval-summary.schema.json', 'EvalSummary MUST carry numeric passedCount + taskCount'),
161
162
  ).toBe(true);
162
163
  expect(
163
164
  (passedCount as number) <= (taskCount as number),
164
- driver.describe('agent-evaluation.md §C', 'EvalSummary.passedCount MUST NOT exceed taskCount'),
165
+ req('openwop.it.agent-eval-run.emits-eval-started-per-task-eval-scored-eval-completed-and-serves-a-content-free', 'agent-evaluation.md §C', 'EvalSummary.passedCount MUST NOT exceed taskCount'),
165
166
  ).toBe(true);
166
167
  for (const t of tasks) {
167
168
  expectContentFree(t, 'EvalSummary.tasks[]');