@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
@@ -17,6 +17,7 @@ import { describe, it, expect } from 'vitest';
17
17
  import { softSkip } from '../lib/soft-skip.js';
18
18
  import { driver } from '../lib/driver.js';
19
19
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
20
+ import { req } from '../lib/requirement-ids.js';
20
21
 
21
22
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
22
23
 
@@ -45,7 +46,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-memory-cap: capability shape + behavioral (R
45
46
 
46
47
  expect(
47
48
  Number.isInteger(sb.memoryLimitBytes) && sb.memoryLimitBytes >= 1048576,
48
- driver.describe(
49
+ req('openwop.it.sandbox-memory-cap.memorylimitbytes-must-be-integer-1-mib-when-present-per-schema',
49
50
  'RFCS/0035-sandbox-execution-contract.md §A',
50
51
  'memoryLimitBytes MUST be integer ≥ 1 MiB (1048576)',
51
52
  ),
@@ -39,6 +39,7 @@ import { describe, it, expect } from 'vitest';
39
39
  import { softSkip } from '../lib/soft-skip.js';
40
40
  import { driver } from '../lib/driver.js';
41
41
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
42
+ import { req } from '../lib/requirement-ids.js';
42
43
 
43
44
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
44
45
 
@@ -84,20 +85,20 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
84
85
  if (!(await isSandboxAdvertised())) {
85
86
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
86
87
  ctx.skip();
87
- return;
88
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
88
89
  }
89
90
  const probe = await invoke('misbehave.fs-escape-read');
90
91
  expect(probe.status).toBe(200);
91
92
  expect(
92
93
  probe.body.error?.code,
93
- driver.describe(
94
+ req('openwop.it.sandbox-mvp-behavior.host-fs-escape-fs-access-from-sandboxed-code-fails-closed',
94
95
  'RFCS/0035-sandbox-execution-contract.md §B node-pack-sandbox-fs-gated',
95
96
  'sandboxed `require("fs")` MUST fail closed with `sandbox_escape_attempt`',
96
97
  ),
97
98
  ).toBe('sandbox_escape_attempt');
98
99
  expect(
99
100
  probe.body.error?.details?.escapeKind,
100
- driver.describe(
101
+ req('openwop.it.sandbox-mvp-behavior.host-fs-escape-fs-access-from-sandboxed-code-fails-closed',
101
102
  'RFCS/0035-sandbox-execution-contract.md §B',
102
103
  'escapeKind MUST be host-fs-escape',
103
104
  ),
@@ -108,13 +109,13 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
108
109
  if (!(await isSandboxAdvertised())) {
109
110
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
110
111
  ctx.skip();
111
- return;
112
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
112
113
  }
113
114
  const probe = await invoke('misbehave.env-leak');
114
115
  expect(probe.status).toBe(200);
115
116
  expect(
116
117
  probe.body.error?.code,
117
- driver.describe(
118
+ req('openwop.it.sandbox-mvp-behavior.host-env-leak-process-env-access-from-sandboxed-code-fails-closed',
118
119
  'RFCS/0035-sandbox-execution-contract.md §B node-pack-sandbox-no-env',
119
120
  'sandboxed `process.env` access MUST fail closed with `sandbox_escape_attempt`',
120
121
  ),
@@ -126,13 +127,13 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
126
127
  if (!(await isSandboxAdvertised())) {
127
128
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
128
129
  ctx.skip();
129
- return;
130
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
130
131
  }
131
132
  const probe = await invoke('misbehave.network-escape');
132
133
  expect(probe.status).toBe(200);
133
134
  expect(
134
135
  probe.body.error?.code,
135
- driver.describe(
136
+ req('openwop.it.sandbox-mvp-behavior.network-escape-http-net-access-from-sandboxed-code-fails-closed',
136
137
  'RFCS/0035-sandbox-execution-contract.md §B node-pack-sandbox-network-gated',
137
138
  'sandboxed `require("http")` MUST fail closed with `sandbox_escape_attempt`',
138
139
  ),
@@ -144,10 +145,10 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
144
145
  if (!(await isSandboxAdvertised())) {
145
146
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
146
147
  ctx.skip();
147
- return;
148
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
148
149
  }
149
150
  const probe = await invoke('misbehave.process-escape');
150
- expect(probe.status).toBe(200);
151
+ expect(probe.status, req('openwop.it.sandbox-mvp-behavior.host-process-escape-child-process-access-from-sandboxed-code-fails-closed', 'RFC 0035 §B', 'host-process-escape — child_process access from sandboxed code fails closed')).toBe(200);
151
152
  expect(probe.body.error?.code).toBe('sandbox_escape_attempt');
152
153
  // The heuristic may catch this as host-fs-escape (via "require") if
153
154
  // network/process patterns don't match first. Accept either as long
@@ -159,7 +160,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
159
160
  if (!(await isSandboxAdvertised())) {
160
161
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
161
162
  ctx.skip();
162
- return;
163
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
163
164
  }
164
165
  const start = Date.now();
165
166
  const probe = await invoke('misbehave.timeout');
@@ -167,7 +168,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
167
168
  expect(probe.status).toBe(200);
168
169
  expect(
169
170
  probe.body.error?.code,
170
- driver.describe(
171
+ req('openwop.it.sandbox-mvp-behavior.sandbox-timeout-runaway-loop-terminated-by-wallclocklimitms',
171
172
  'RFCS/0035-sandbox-execution-contract.md §B node-pack-sandbox-timeout',
172
173
  'sandboxed infinite-loop MUST be terminated with `sandbox_timeout`',
173
174
  ),
@@ -175,7 +176,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
175
176
  // Should terminate within ~2× wallClockLimitMs (1000ms config + overhead).
176
177
  expect(
177
178
  elapsed < 5000,
178
- driver.describe(
179
+ req('openwop.it.sandbox-mvp-behavior.sandbox-timeout-runaway-loop-terminated-by-wallclocklimitms',
179
180
  'RFCS/0035-sandbox-execution-contract.md §A wallClockLimitMs',
180
181
  `timeout MUST terminate within reasonable bound (got ${elapsed}ms; cap is 1000ms)`,
181
182
  ),
@@ -186,7 +187,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
186
187
  if (!(await isSandboxAdvertised())) {
187
188
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
188
189
  ctx.skip();
189
- return;
190
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
190
191
  }
191
192
  const r1 = await invoke('misbehave.cross-pack-mutate');
192
193
  const r2 = await invoke('misbehave.cross-pack-mutate');
@@ -202,7 +203,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
202
203
  const shared3 = (r3.body.result as { shared?: number })?.shared;
203
204
  expect(
204
205
  shared1 === 1 && shared2 === 1 && shared3 === 1,
205
- driver.describe(
206
+ req('openwop.it.sandbox-mvp-behavior.cross-pack-mutation-fresh-vm-context-per-invocation-no-state-leaks',
206
207
  'RFCS/0035-sandbox-execution-contract.md §B node-pack-sandbox-isolated-context',
207
208
  `each invocation MUST see fresh state (got shared=[${shared1}, ${shared2}, ${shared3}]; expected all 1)`,
208
209
  ),
@@ -213,20 +214,20 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
213
214
  if (!(await isSandboxAdvertised())) {
214
215
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
215
216
  ctx.skip();
216
- return;
217
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
217
218
  }
218
219
  const probe = await invoke('misbehave.capability-gate-violation', {}, []);
219
220
  expect(probe.status).toBe(200);
220
221
  expect(
221
222
  probe.body.error?.code,
222
- driver.describe(
223
+ req('openwop.it.sandbox-mvp-behavior.capability-gate-respected-host-call-not-in-allowedhostcalls-fails-with-sandbox-c',
223
224
  'spec/v1/host-capabilities.md §"Error codes" + §B node-pack-sandbox-capability-gate-respected',
224
225
  'capability-gate violation MUST fail closed with `sandbox_capability_denied` — distinct from `sandbox_escape_attempt` which covers forbidden-syscall escapes per the spec\'s 4-code catalog',
225
226
  ),
226
227
  ).toBe('sandbox_capability_denied');
227
228
  expect(
228
229
  probe.body.error?.details?.requestedCapability,
229
- driver.describe(
230
+ req('openwop.it.sandbox-mvp-behavior.capability-gate-respected-host-call-not-in-allowedhostcalls-fails-with-sandbox-c',
230
231
  'spec/v1/host-capabilities.md §"Error codes"',
231
232
  '`sandbox_capability_denied` MUST carry `details.requestedCapability` identifying the host method the sandboxed code attempted to call',
232
233
  ),
@@ -237,7 +238,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
237
238
  if (!(await isSandboxAdvertised())) {
238
239
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
239
240
  ctx.skip();
240
- return;
241
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
241
242
  }
242
243
  const probe = await invoke('misbehave.memory-bomb');
243
244
  expect(probe.status).toBe(200);
@@ -254,7 +255,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
254
255
  // legacy code.
255
256
  expect(
256
257
  ['sandbox_memory_exceeded', 'sandbox_timeout'].includes(probe.body.error?.code ?? ''),
257
- driver.describe(
258
+ req('openwop.it.sandbox-mvp-behavior.memory-exceeded-runaway-allocation-fails-with-sandbox-memory-exceeded',
258
259
  'spec/v1/host-capabilities.md §"Error codes" + §B node-pack-sandbox-memory-cap',
259
260
  `memory-bomb MUST surface either \`sandbox_memory_exceeded\` (when memoryLimitBytes caught it) or \`sandbox_timeout\` (when wallClockLimitMs caught it first) — got code: ${probe.body.error?.code}`,
260
261
  ),
@@ -265,13 +266,13 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
265
266
  if (!(await isSandboxAdvertised())) {
266
267
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
267
268
  ctx.skip();
268
- return;
269
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
269
270
  }
270
271
  const probe = await invoke('well-behaved.host-fetch', {}, ['fetch']);
271
272
  expect(probe.status).toBe(200);
272
273
  expect(
273
274
  probe.body.error,
274
- driver.describe(
275
+ req('openwop.it.sandbox-mvp-behavior.well-behaved-host-fetch-allowedhostcalls-fetch-permits-the-host-call',
275
276
  'RFCS/0035-sandbox-execution-contract.md §A allowedHostCalls',
276
277
  'host call IN allowedHostCalls MUST succeed (no error envelope)',
277
278
  ),
@@ -282,10 +283,10 @@ describe.skipIf(HTTP_SKIP)('sandbox-mvp-behavior: RFC 0035 §B failure-mode inva
282
283
  if (!(await isSandboxAdvertised())) {
283
284
  softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
284
285
  ctx.skip();
285
- return;
286
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isSandboxAdvertised())` returned early');
286
287
  }
287
288
  const probe = await invoke('well-behaved.echo', { input: 'hello-sandbox' });
288
- expect(probe.status).toBe(200);
289
+ expect(probe.status, req('openwop.it.sandbox-mvp-behavior.well-behaved-echo-sandboxed-code-returns-args-round-trip-when-no-escape-attempt', 'RFC 0035 §B', 'well-behaved.echo — sandboxed code returns args round-trip when no escape attempt')).toBe(200);
289
290
  expect(probe.body.error).toBeUndefined();
290
291
  expect((probe.body.result as { echoed?: string })?.echoed).toBe('hello-sandbox');
291
292
  });
@@ -28,6 +28,7 @@ import { describe, it, expect } from 'vitest';
28
28
  import { softSkip } from '../lib/soft-skip.js';
29
29
  import { driver } from '../lib/driver.js';
30
30
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
31
+ import { req } from '../lib/requirement-ids.js';
31
32
 
32
33
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
33
34
 
@@ -58,7 +59,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-no-host-fs-escape: capability shape (RFC 003
58
59
  const sb = await readSandboxCaps();
59
60
  if (sb === null) return softSkip('inapplicable', 'host omits the block — soft-skip cleanly (sb === null)');
60
61
 
61
- expect(typeof sb.supported, 'capabilities.sandbox.supported MUST be boolean when present').toBe('boolean');
62
+ expect(typeof sb.supported, req('openwop.it.sandbox-no-host-fs-escape.capabilities-sandbox-when-present-conforms-to-rfc-0035-a', 'RFCS/0035-sandbox-execution-contract.md §A', 'capabilities.sandbox.supported MUST be boolean when present')).toBe('boolean');
62
63
 
63
64
  if (sb.supported === true) {
64
65
  const m = sb.isolationModel as string;
@@ -66,7 +67,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-no-host-fs-escape: capability shape (RFC 003
66
67
  const isExtension = /^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$/.test(m);
67
68
  expect(
68
69
  isCategorical || isExtension,
69
- driver.describe(
70
+ req('openwop.it.sandbox-no-host-fs-escape.capabilities-sandbox-when-present-conforms-to-rfc-0035-a',
70
71
  'RFCS/0035-sandbox-execution-contract.md §A',
71
72
  'isolationModel MUST be one of {wasm, process, container, vm} OR match ^x-host-<host>-<key>$ pattern',
72
73
  ),
@@ -17,6 +17,7 @@ import { describe, it, expect } from 'vitest';
17
17
  import { softSkip } from '../lib/soft-skip.js';
18
18
  import { driver } from '../lib/driver.js';
19
19
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
20
+ import { req } from '../lib/requirement-ids.js';
20
21
 
21
22
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
22
23
 
@@ -45,7 +46,7 @@ describe.skipIf(HTTP_SKIP)('sandbox-timeout-cap: capability shape + behavioral (
45
46
 
46
47
  expect(
47
48
  Number.isInteger(sb.wallClockLimitMs) && sb.wallClockLimitMs >= 100,
48
- driver.describe(
49
+ req('openwop.it.sandbox-timeout-cap.wallclocklimitms-must-be-integer-100-ms-when-present-per-schema',
49
50
  'RFCS/0035-sandbox-execution-contract.md §A',
50
51
  'wallClockLimitMs MUST be integer ≥ 100 ms',
51
52
  ),
@@ -31,8 +31,7 @@ import { readFileSync } from 'node:fs';
31
31
  import { join } from 'node:path';
32
32
  import { FIXTURES_DIR } from '../lib/paths.js';
33
33
  import { probeSandboxed } from '../lib/wasm-sandbox-probe.js';
34
-
35
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
34
+ import { req } from '../lib/requirement-ids.js';
36
35
  const dir = join(FIXTURES_DIR, 'wasm-sandbox');
37
36
  const fix = (name: string): Uint8Array => new Uint8Array(readFileSync(join(dir, `${name}.wasm`)));
38
37
  const BASE = { allowedHostCalls: [] as string[], memoryLimitBytes: 2 * 1024 * 1024 };
@@ -40,14 +39,14 @@ const BASE = { allowedHostCalls: [] as string[], memoryLimitBytes: 2 * 1024 * 10
40
39
  describe('sandbox-wasm-isolation: positive controls (RFC 0035 §B, server-free)', () => {
41
40
  it('a well-behaved pure module runs and returns its input', () => {
42
41
  const r = probeSandboxed(fix('well-behaved-echo'), BASE, 'invoke', 42);
43
- expect(r.ok, why('RFC 0035 §B', 'a pure-compute module runs')).toBe(true);
44
- expect(r.result).toBe(42);
42
+ expect(r.ok, req('openwop.it.sandbox-wasm-isolation.a-well-behaved-pure-module-runs-and-returns-its-input', 'RFC 0035 §B', 'a pure-compute module runs')).toBe(true);
43
+ expect(r.result, req('openwop.it.sandbox-wasm-isolation.a-well-behaved-pure-module-runs-and-returns-its-input', 'RFC 0035 §B', 'a well-behaved pure module runs and returns its input')).toBe(42);
45
44
  });
46
45
 
47
46
  it('a granted host capability is callable when in allowedHostCalls', () => {
48
47
  const r = probeSandboxed(fix('well-behaved-host-fetch'), { ...BASE, allowedHostCalls: ['fetch'] }, 'invoke', 7);
49
- expect(r.ok, why('RFC 0035 §B invariant 7', 'a granted openwop.* capability is callable')).toBe(true);
50
- expect(r.result).toBe(7);
48
+ expect(r.ok, req('openwop.it.sandbox-wasm-isolation.a-granted-host-capability-is-callable-when-in-allowedhostcalls', 'RFC 0035 §B invariant 7', 'a granted openwop.* capability is callable')).toBe(true);
49
+ expect(r.result, req('openwop.it.sandbox-wasm-isolation.a-granted-host-capability-is-callable-when-in-allowedhostcalls', 'RFC 0035 §B', 'a granted host capability is callable when in allowedHostCalls')).toBe(7);
51
50
  });
52
51
  });
53
52
 
@@ -61,8 +60,8 @@ describe('sandbox-wasm-isolation: escape attempts fail closed (RFC 0035 §B 1–
61
60
  for (const [fixture, escapeKind, invariant] of cases) {
62
61
  it(`${invariant}: ${fixture} → sandbox_escape_attempt (${escapeKind})`, () => {
63
62
  const r = probeSandboxed(fix(fixture), BASE);
64
- expect(r.code, why('RFC 0035 §B', `${invariant} fails closed before instantiation`)).toBe('sandbox_escape_attempt');
65
- expect(r.escapeKind).toBe(escapeKind);
63
+ expect(r.code, req('openwop.it.sandbox-wasm-isolation.sandbox-escape-attempt', 'RFC 0035 §B', `${invariant} fails closed before instantiation`)).toBe('sandbox_escape_attempt');
64
+ expect(r.escapeKind, req('openwop.it.sandbox-wasm-isolation.sandbox-escape-attempt', 'RFC 0035 §B', ': → sandbox_escape_attempt ( )')).toBe(escapeKind);
66
65
  });
67
66
  }
68
67
  });
@@ -70,13 +69,13 @@ describe('sandbox-wasm-isolation: escape attempts fail closed (RFC 0035 §B 1–
70
69
  describe('sandbox-wasm-isolation: capability gate (RFC 0035 §B 7, server-free)', () => {
71
70
  it('an un-granted openwop capability is denied with its name', () => {
72
71
  const r = probeSandboxed(fix('misbehaving-capability-gate'), BASE);
73
- expect(r.code, why('RFC 0035 §B invariant 7', 'undeclared host capability fails closed')).toBe('sandbox_capability_denied');
74
- expect(r.requestedCapability).toBe('privileged');
72
+ expect(r.code, req('openwop.it.sandbox-wasm-isolation.an-un-granted-openwop-capability-is-denied-with-its-name', 'RFC 0035 §B invariant 7', 'undeclared host capability fails closed')).toBe('sandbox_capability_denied');
73
+ expect(r.requestedCapability, req('openwop.it.sandbox-wasm-isolation.an-un-granted-openwop-capability-is-denied-with-its-name', 'RFC 0035 §B', 'an un-granted openwop capability is denied with its name')).toBe('privileged');
75
74
  });
76
75
 
77
76
  it('host-fetch WITHOUT the grant is denied (the gate works both directions)', () => {
78
77
  const r = probeSandboxed(fix('well-behaved-host-fetch'), BASE);
79
- expect(r.code).toBe('sandbox_capability_denied');
78
+ expect(r.code, req('openwop.it.sandbox-wasm-isolation.host-fetch-without-the-grant-is-denied-the-gate-works-both-directions', 'RFC 0035 §B', 'host-fetch WITHOUT the grant is denied (the gate works both directions)')).toBe('sandbox_capability_denied');
80
79
  expect(r.requestedCapability).toBe('fetch');
81
80
  });
82
81
  });
@@ -84,15 +83,15 @@ describe('sandbox-wasm-isolation: capability gate (RFC 0035 §B 7, server-free)'
84
83
  describe('sandbox-wasm-isolation: memory cap (RFC 0035 §B 5, server-free)', () => {
85
84
  it('node-pack-sandbox-memory-cap: access beyond the host memory bound is sandbox_memory_exceeded', () => {
86
85
  const r = probeSandboxed(fix('misbehaving-memory'), BASE);
87
- expect(r.ok, why('RFC 0035 §B invariant 5', 'memory bound is engine-enforced')).toBe(false);
88
- expect(r.code).toBe('sandbox_memory_exceeded');
86
+ expect(r.ok, req('openwop.it.sandbox-wasm-isolation.node-pack-sandbox-memory-cap-access-beyond-the-host-memory-bound-is-sandbox-memo', 'RFC 0035 §B invariant 5', 'memory bound is engine-enforced')).toBe(false);
87
+ expect(r.code, req('openwop.it.sandbox-wasm-isolation.node-pack-sandbox-memory-cap-access-beyond-the-host-memory-bound-is-sandbox-memo', 'RFC 0035 §B', 'node-pack-sandbox-memory-cap: access beyond the host memory bound is sandbox_memory_exceeded')).toBe('sandbox_memory_exceeded');
89
88
  });
90
89
  });
91
90
 
92
91
  describe('sandbox-wasm-isolation: isolated context (RFC 0035 §B 8, server-free)', () => {
93
92
  it('node-pack-sandbox-isolated-context: each invocation gets a fresh instance (no cross-pack state)', () => {
94
93
  const iso = fix('isolation-global');
95
- expect(probeSandboxed(iso, BASE, 'bump').result, why('RFC 0035 §B invariant 8', 'a fresh instance starts at 0')).toBe(1);
96
- expect(probeSandboxed(iso, BASE, 'read').result, why('RFC 0035 §B invariant 8', 'no state leaks across invocations')).toBe(0);
94
+ expect(probeSandboxed(iso, BASE, 'bump').result, req('openwop.it.sandbox-wasm-isolation.node-pack-sandbox-isolated-context-each-invocation-gets-a-fresh-instance-no-cros', 'RFC 0035 §B invariant 8', 'a fresh instance starts at 0')).toBe(1);
95
+ expect(probeSandboxed(iso, BASE, 'read').result, req('openwop.it.sandbox-wasm-isolation.node-pack-sandbox-isolated-context-each-invocation-gets-a-fresh-instance-no-cros', 'RFC 0035 §B invariant 8', 'no state leaks across invocations')).toBe(0);
97
96
  });
98
97
  });
@@ -20,21 +20,20 @@ import { readFileSync } from 'node:fs';
20
20
  import { join } from 'node:path';
21
21
  import { FIXTURES_DIR } from '../lib/paths.js';
22
22
  import { probeTimeout } from '../lib/wasm-sandbox-probe.js';
23
-
24
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
23
+ import { req } from '../lib/requirement-ids.js';
25
24
  const dir = join(FIXTURES_DIR, 'wasm-sandbox');
26
25
  const fix = (name: string): Uint8Array => new Uint8Array(readFileSync(join(dir, `${name}.wasm`)));
27
26
 
28
27
  describe('sandbox-wasm-timeout: wall-clock cap is engine/worker-enforced (RFC 0035 §B 6, server-free)', () => {
29
28
  it('node-pack-sandbox-timeout: a non-terminating module is killed with sandbox_timeout', async () => {
30
29
  const r = await probeTimeout(fix('misbehaving-timeout'), { memoryLimitBytes: 2 * 1024 * 1024, wallClockLimitMs: 300 });
31
- expect(r.ok, why('RFC 0035 §B invariant 6', 'an over-budget invocation MUST fail')).toBe(false);
32
- expect(r.code, why('RFC 0035 §C', 'the failure code MUST be sandbox_timeout')).toBe('sandbox_timeout');
30
+ expect(r.ok, req('openwop.it.sandbox-wasm-timeout.node-pack-sandbox-timeout-a-non-terminating-module-is-killed-with-sandbox-timeou', 'RFC 0035 §B invariant 6', 'an over-budget invocation MUST fail')).toBe(false);
31
+ expect(r.code, req('openwop.it.sandbox-wasm-timeout.node-pack-sandbox-timeout-a-non-terminating-module-is-killed-with-sandbox-timeou', 'RFC 0035 §C', 'the failure code MUST be sandbox_timeout')).toBe('sandbox_timeout');
33
32
  });
34
33
 
35
34
  it('positive control: a well-behaved module completes within the budget (the kill-timer does not false-positive)', async () => {
36
35
  const r = await probeTimeout(fix('well-behaved-echo'), { memoryLimitBytes: 2 * 1024 * 1024, wallClockLimitMs: 1000 }, 'invoke', 7);
37
- expect(r.ok, why('RFC 0035 §B', 'a within-budget invocation completes before the kill-timer')).toBe(true);
38
- expect(r.result).toBe(7);
36
+ expect(r.ok, req('openwop.it.sandbox-wasm-timeout.positive-control-a-well-behaved-module-completes-within-the-budget-the-kill-time', 'RFC 0035 §B', 'a within-budget invocation completes before the kill-timer')).toBe(true);
37
+ expect(r.result, req('openwop.it.sandbox-wasm-timeout.positive-control-a-well-behaved-module-completes-within-the-budget-the-kill-time', 'RFC 0035 §B', 'positive control: a well-behaved module completes within the budget (the kill-timer does not false-positive)')).toBe(7);
39
38
  });
40
39
  });
@@ -21,6 +21,8 @@
21
21
  import { describe, it, expect } from 'vitest';
22
22
  import { driver } from '../lib/driver.js';
23
23
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
24
+ import { req } from '../lib/requirement-ids.js';
25
+ import { softSkip } from '../lib/soft-skip.js';
24
26
 
25
27
  interface DiscoveryScheduling {
26
28
  supported?: boolean;
@@ -46,10 +48,10 @@ async function readScheduling(): Promise<DiscoveryScheduling | null> {
46
48
  describe('scheduling-capability-shape: advertisement shape (RFC 0052 §A)', () => {
47
49
  it('capabilities.scheduling is either absent or well-formed', async () => {
48
50
  const sched = await readScheduling();
49
- if (sched === null) return; // host doesn't advertise scheduling at all
51
+ if (sched === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `sched === null` returned early (host doesn\'t advertise scheduling at all)'); // host doesn't advertise scheduling at all
50
52
  expect(
51
53
  typeof sched.supported,
52
- driver.describe(
54
+ req('openwop.it.scheduling-capability-shape.capabilities-scheduling-is-either-absent-or-well-formed',
53
55
  'capabilities.schema.json §scheduling',
54
56
  'capabilities.scheduling.supported MUST be a boolean when scheduling is advertised',
55
57
  ),
@@ -58,22 +60,22 @@ describe('scheduling-capability-shape: advertisement shape (RFC 0052 §A)', () =
58
60
 
59
61
  it('cron/delayed/calendar are booleans when present + supported', async () => {
60
62
  const sched = await readScheduling();
61
- if (!sched?.supported) return;
63
+ if (!sched?.supported) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!sched?.supported` returned early');
62
64
  for (const k of ['cron', 'delayed', 'calendar'] as const) {
63
65
  if (sched[k] === undefined) continue;
64
66
  expect(
65
67
  typeof sched[k],
66
- driver.describe('RFC 0052 §A', `capabilities.scheduling.${k} MUST be a boolean when present`),
68
+ req('openwop.it.scheduling-capability-shape.cron-delayed-calendar-are-booleans-when-present-supported', 'RFC 0052 §A', `capabilities.scheduling.${k} MUST be a boolean when present`),
67
69
  ).toBe('boolean');
68
70
  }
69
71
  });
70
72
 
71
73
  it('maxFutureHorizon is an ISO-8601 duration when present', async () => {
72
74
  const sched = await readScheduling();
73
- if (!sched?.supported || sched.maxFutureHorizon === undefined) return;
75
+ if (!sched?.supported || sched.maxFutureHorizon === undefined) return softSkip('blocked', 'precondition not met — `!sched?.supported || sched.maxFutureHorizon === undefined` returned early (seam, prior step, or fixture unavailable)');
74
76
  expect(
75
77
  ISO_DURATION.test(sched.maxFutureHorizon),
76
- driver.describe(
78
+ req('openwop.it.scheduling-capability-shape.maxfuturehorizon-is-an-iso-8601-duration-when-present',
77
79
  'RFC 0052 §A',
78
80
  `capabilities.scheduling.maxFutureHorizon MUST be an ISO-8601 duration, got: ${sched.maxFutureHorizon}`,
79
81
  ),
@@ -27,6 +27,8 @@
27
27
  import { describe, it, expect } from 'vitest';
28
28
  import { driver } from '../lib/driver.js';
29
29
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
30
+ import { req } from '../lib/requirement-ids.js';
31
+ import { softSkip } from '../lib/soft-skip.js';
30
32
 
31
33
  interface DiscoveryDoc {
32
34
  capabilities?: { scheduling?: { supported?: boolean; cron?: boolean } };
@@ -40,25 +42,25 @@ async function readScheduling(): Promise<{ supported?: boolean; cron?: boolean }
40
42
  describe('scheduling-cron-fires-once: once-per-tick + missed-tick (RFC 0052 §B)', () => {
41
43
  it('a single cron tick produces exactly one run', async () => {
42
44
  const sched = await readScheduling();
43
- if (!sched?.supported || sched.cron !== true) return; // capability-gated
45
+ if (!sched?.supported || sched.cron !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!sched?.supported || sched.cron !== true` returned early (capability-gated)'); // capability-gated
44
46
  const res = await driver.post('/v1/host/sample/scheduling/tick', { scenario: 'single-tick' });
45
- if (res.status === 404) return; // seam unwired — soft-skip
47
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
46
48
  const body = res.json as { runsFired?: number } | undefined;
47
49
  expect(
48
50
  body?.runsFired,
49
- driver.describe('RFC 0052 §B.2', 'a single cron tick MUST fire exactly one run (no duplicate concurrent firing)'),
51
+ req('openwop.it.scheduling-cron-fires-once.a-single-cron-tick-produces-exactly-one-run', 'RFC 0052 §B.2', 'a single cron tick MUST fire exactly one run (no duplicate concurrent firing)'),
50
52
  ).toBe(1);
51
53
  });
52
54
 
53
55
  it('a missed-tick window does not produce a backlog flood', async () => {
54
56
  const sched = await readScheduling();
55
- if (!sched?.supported || sched.cron !== true) return; // capability-gated
57
+ if (!sched?.supported || sched.cron !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!sched?.supported || sched.cron !== true` returned early (capability-gated)'); // capability-gated
56
58
  const res = await driver.post('/v1/host/sample/scheduling/tick', { scenario: 'missed-window', missedTicks: 5 });
57
- if (res.status === 404) return; // seam unwired — soft-skip
59
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
58
60
  const body = res.json as { runsFired?: number } | undefined;
59
61
  expect(
60
62
  typeof body?.runsFired === 'number' && body.runsFired <= 1,
61
- driver.describe(
63
+ req('openwop.it.scheduling-cron-fires-once.a-missed-tick-window-does-not-produce-a-backlog-flood',
62
64
  'RFC 0052 §B.4',
63
65
  `a missed-tick window MUST apply the advertised policy (fire-once-on-recovery or skip), never N backlogged runs; got runsFired=${body?.runsFired}`,
64
66
  ),
@@ -16,6 +16,8 @@
16
16
  import { describe, it, expect } from 'vitest';
17
17
  import { driver } from '../lib/driver.js';
18
18
  import { discoveryFamilies } from '../lib/discovery-capabilities.js';
19
+ import { req } from '../lib/requirement-ids.js';
20
+ import { softSkip } from '../lib/soft-skip.js';
19
21
 
20
22
  interface DiscoveryDoc {
21
23
  capabilities?: Record<string, unknown>;
@@ -32,10 +34,10 @@ async function readCap(): Promise<Record<string, unknown> | null> {
32
34
  describe('search-bm25-roundtrip: advertisement shape (RFC 0018)', () => {
33
35
  it('capabilities.searchIndex is either absent or a well-formed object', async () => {
34
36
  const cap = await readCap();
35
- if (cap === null) return; // host doesn't advertise — skip
37
+ if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early (host doesn\'t advertise — skip)'); // host doesn't advertise — skip
36
38
  expect(
37
39
  typeof cap.supported,
38
- driver.describe(
40
+ req('openwop.it.search-bm25-roundtrip.capabilities-searchindex-is-either-absent-or-a-well-formed-object',
39
41
  'capabilities.schema.json §searchIndex',
40
42
  'capabilities.searchIndex.supported MUST be a boolean when present',
41
43
  ),
@@ -50,7 +52,7 @@ async function call(op: string, args: Record<string, unknown>) {
50
52
  describe('search-bm25-roundtrip: behavioral (RFC 0018 §A.searchIndex)', () => {
51
53
  it('index 3 docs → query for a distinguishing keyword returns the matching doc as top hit', async () => {
52
54
  const probe = await call('query', { index: '__probe__', q: 'hello' });
53
- if (probe.status === 404) return; // seam not exposed
55
+ if (probe.status === 404) return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam not exposed) (seam, prior step, or fixture unavailable)'); // seam not exposed
54
56
  const index = `idx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
55
57
  const idx = await call('index', {
56
58
  index,
@@ -69,7 +71,7 @@ describe('search-bm25-roundtrip: behavioral (RFC 0018 §A.searchIndex)', () => {
69
71
  expect(Array.isArray(body.hits) && body.hits.length > 0).toBe(true);
70
72
  expect(
71
73
  body.hits![0]!.id,
72
- driver.describe('RFC 0018 §A.searchIndex', 'query for the doc\'s distinguishing tokens MUST return that doc as top-1'),
74
+ req('openwop.it.search-bm25-roundtrip.index-3-docs-query-for-a-distinguishing-keyword-returns-the-matching-doc-as-top', 'RFC 0018 §A.searchIndex', 'query for the doc\'s distinguishing tokens MUST return that doc as top-1'),
73
75
  ).toBe('doc-2');
74
76
  // Top hit's score MUST be strictly greater than any tied below-rank.
75
77
  if (body.hits!.length > 1) {
@@ -79,7 +81,7 @@ describe('search-bm25-roundtrip: behavioral (RFC 0018 §A.searchIndex)', () => {
79
81
 
80
82
  it('k limit caps the result set', async () => {
81
83
  const probe = await call('query', { index: '__probe__', q: 'hello' });
82
- if (probe.status === 404) return;
84
+ if (probe.status === 404) return softSkip('blocked', 'precondition not met — `probe.status === 404` returned early (seam, prior step, or fixture unavailable)');
83
85
  const index = `idx-k-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
84
86
  const docs = Array.from({ length: 5 }, (_, i) => ({ id: `d-${i}`, fields: { body: 'apple orange banana' } }));
85
87
  await call('index', { index, docs });
@@ -87,7 +89,7 @@ describe('search-bm25-roundtrip: behavioral (RFC 0018 §A.searchIndex)', () => {
87
89
  const body = q.json as { hits?: unknown[] };
88
90
  expect(
89
91
  Array.isArray(body.hits) && body.hits.length <= 2,
90
- driver.describe('RFC 0018 §A.searchIndex', 'query MUST return at most k hits'),
92
+ req('openwop.it.search-bm25-roundtrip.k-limit-caps-the-result-set', 'RFC 0018 §A.searchIndex', 'query MUST return at most k hits'),
91
93
  ).toBe(true);
92
94
  });
93
95
  });