@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
@@ -34,6 +34,8 @@ import { describe, it, expect } from 'vitest';
34
34
  import { driver } from '../lib/driver.js';
35
35
  import { behaviorGate } from '../lib/behavior-gate.js';
36
36
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
37
+ import { req } from '../lib/requirement-ids.js';
38
+ import { softSkip } from '../lib/soft-skip.js';
37
39
 
38
40
  interface DiscoveryDoc {
39
41
  capabilities?: {
@@ -97,8 +99,8 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
97
99
  },
98
100
  observability: 'full',
99
101
  });
100
- if (res.status === 404) return; // host doesn't expose the seam
101
- expect(res.status, 'compose seam MUST return 200').toBe(200);
102
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (host doesn\'t expose the seam) (seam, prior step, or fixture unavailable)'); // host doesn't expose the seam
103
+ expect(res.status, req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value', 'spec/v1/prompts.md §Composition + observability', 'compose seam MUST return 200')).toBe(200);
102
104
 
103
105
  const payload = res.json as PromptComposedPayload;
104
106
 
@@ -108,14 +110,14 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
108
110
  const userBody = payload.userPrompt ?? '';
109
111
  expect(
110
112
  systemBody.includes(CANARY_FRAGMENT),
111
- driver.describe(
113
+ req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
112
114
  'spec/v1/prompts.md §Composition + observability',
113
115
  'prompt.composed.systemPrompt MUST NOT contain plaintext secret value',
114
116
  ),
115
117
  ).toBe(false);
116
118
  expect(
117
119
  userBody.includes(CANARY_FRAGMENT),
118
- driver.describe(
120
+ req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
119
121
  'spec/v1/prompts.md §Composition + observability',
120
122
  'prompt.composed.userPrompt MUST NOT contain plaintext secret value',
121
123
  ),
@@ -127,7 +129,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
127
129
  const combined = systemBody + userBody;
128
130
  expect(
129
131
  /\[REDACTED:[a-zA-Z0-9._-]+\]/.test(combined),
130
- driver.describe(
132
+ req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
131
133
  'spec/v1/prompts.md §Composition + observability',
132
134
  'composed body MUST carry [REDACTED:<secretId>] marker where secret-sourced variables appear',
133
135
  ),
@@ -140,7 +142,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
140
142
  if (typeof value === 'string') {
141
143
  expect(
142
144
  value.includes(CANARY_FRAGMENT),
143
- driver.describe(
145
+ req('openwop.it.prompt-composed-secret-redaction.emits-prompt-composed-with-redacted-id-in-place-of-secret-sourced-variable-value',
144
146
  'spec/v1/prompts.md §Composition + observability',
145
147
  `variableBindings[${name}] MUST NOT contain plaintext secret value`,
146
148
  ),
@@ -158,19 +160,19 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-secret-redaction: composed body reda
158
160
  bindings: { apiKey: 'openwop-conformance-canary-secret' },
159
161
  observability: 'full',
160
162
  });
161
- if (res.status === 404) return;
163
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
162
164
  expect(res.status).toBe(200);
163
165
  const payload = res.json as PromptComposedPayload;
164
166
  expect(
165
167
  payload.hash && /^sha256:[0-9a-f]{64}$/.test(payload.hash),
166
- driver.describe(
168
+ req('openwop.it.prompt-composed-secret-redaction.emits-variablehashes-for-the-secret-sourced-binding-regardless-of-observability',
167
169
  'spec/v1/prompts.md §Composition + observability',
168
170
  'prompt.composed.hash MUST be present and match sha256:<hex64>',
169
171
  ),
170
172
  ).toBe(true);
171
173
  expect(
172
174
  payload.variableHashes !== undefined,
173
- driver.describe(
175
+ req('openwop.it.prompt-composed-secret-redaction.emits-variablehashes-for-the-secret-sourced-binding-regardless-of-observability',
174
176
  'spec/v1/prompts.md §Composition + observability',
175
177
  'prompt.composed.variableHashes MUST be present under all non-off observability modes',
176
178
  ),
@@ -33,6 +33,8 @@ import { describe, it, expect } from 'vitest';
33
33
  import { driver } from '../lib/driver.js';
34
34
  import { behaviorGate } from '../lib/behavior-gate.js';
35
35
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
36
+ import { req } from '../lib/requirement-ids.js';
37
+ import { softSkip } from '../lib/soft-skip.js';
36
38
 
37
39
  interface DiscoveryDoc {
38
40
  capabilities?: {
@@ -81,13 +83,13 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
81
83
  bindingTrust: { userPayload: 'untrusted' },
82
84
  observability: 'full',
83
85
  });
84
- if (res.status === 404) return;
86
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
85
87
  expect(res.status).toBe(200);
86
88
 
87
89
  const payload = res.json as PromptComposedPayload;
88
90
  expect(
89
91
  payload.contentTrust,
90
- driver.describe(
92
+ req('openwop.it.prompt-composed-trust-marker.sets-contenttrust-untrusted-when-any-contributing-input-is-untrusted',
91
93
  'spec/v1/prompts.md §Composition + observability',
92
94
  'prompt.composed.contentTrust MUST be "untrusted" when ANY contributing input is untrusted',
93
95
  ),
@@ -104,7 +106,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
104
106
  bindingTrust: { userPayload: 'untrusted' },
105
107
  observability: 'full',
106
108
  });
107
- if (res.status === 404) return;
109
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
108
110
  expect(res.status).toBe(200);
109
111
 
110
112
  const payload = res.json as PromptComposedPayload;
@@ -112,7 +114,7 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
112
114
 
113
115
  expect(
114
116
  combined.includes('<UNTRUSTED>') && combined.includes('</UNTRUSTED>'),
115
- driver.describe(
117
+ req('openwop.it.prompt-composed-trust-marker.wraps-untrusted-segments-in-untrusted-untrusted-markers-within-composed-bodies',
116
118
  'spec/v1/prompts.md §Composition + observability',
117
119
  'composed body MUST wrap untrusted segments with <UNTRUSTED>...</UNTRUSTED> markers',
118
120
  ),
@@ -127,14 +129,14 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
127
129
  const outsideMarkers = markerRegions.filter((_, i) => i % 2 === 0).join(' ');
128
130
  expect(
129
131
  insideMarkers.includes(UNTRUSTED_PAYLOAD),
130
- driver.describe(
132
+ req('openwop.it.prompt-composed-trust-marker.wraps-untrusted-segments-in-untrusted-untrusted-markers-within-composed-bodies',
131
133
  'spec/v1/prompts.md §Composition + observability',
132
134
  'untrusted payload content MUST appear inside <UNTRUSTED>...</UNTRUSTED> markers',
133
135
  ),
134
136
  ).toBe(true);
135
137
  expect(
136
138
  outsideMarkers.includes(UNTRUSTED_PAYLOAD),
137
- driver.describe(
139
+ req('openwop.it.prompt-composed-trust-marker.wraps-untrusted-segments-in-untrusted-untrusted-markers-within-composed-bodies',
138
140
  'spec/v1/prompts.md §Composition + observability',
139
141
  'untrusted payload content MUST NOT appear outside the markers',
140
142
  ),
@@ -151,13 +153,13 @@ describe.skipIf(HTTP_SKIP)('prompt-composed-trust-marker: untrusted input wrappe
151
153
  bindingTrust: { userPayload: 'trusted' },
152
154
  observability: 'full',
153
155
  });
154
- if (res.status === 404) return;
156
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
155
157
  expect(res.status).toBe(200);
156
158
 
157
159
  const payload = res.json as PromptComposedPayload;
158
160
  expect(
159
161
  payload.contentTrust,
160
- driver.describe(
162
+ req('openwop.it.prompt-composed-trust-marker.keeps-contenttrust-trusted-when-all-contributing-inputs-are-trusted',
161
163
  'spec/v1/prompts.md §Composition + observability',
162
164
  'prompt.composed.contentTrust MUST be "trusted" when no contributing input is untrusted',
163
165
  ),
@@ -35,6 +35,8 @@ import { pollUntilTerminal } from '../lib/polling.js';
35
35
  import { isFixtureAdvertised } from '../lib/fixtures.js';
36
36
  import { behaviorGate } from '../lib/behavior-gate.js';
37
37
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
38
+ import { req } from '../lib/requirement-ids.js';
39
+ import { softSkip } from '../lib/soft-skip.js';
38
40
 
39
41
  const WORKFLOW_ID = 'conformance-prompt-end-to-end';
40
42
  const SKIP_NO_FIXTURE = !isFixtureAdvertised(WORKFLOW_ID);
@@ -88,7 +90,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
88
90
  const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
89
91
  expect(
90
92
  create.status,
91
- driver.describe(
93
+ req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
92
94
  'spec/v1/rest-endpoints.md',
93
95
  'POST /v1/runs MUST return 201 on accepted creation',
94
96
  ),
@@ -98,7 +100,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
98
100
  const terminal = await pollUntilTerminal(runId);
99
101
  expect(
100
102
  terminal.status,
101
- driver.describe(
103
+ req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
102
104
  'fixtures.md conformance-prompt-end-to-end §Terminal status',
103
105
  'fixture MUST reach terminal `completed`',
104
106
  ),
@@ -108,7 +110,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
108
110
  const resolved = events.find((e) => e.type === 'agent.promptResolved');
109
111
  expect(
110
112
  resolved,
111
- driver.describe(
113
+ req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
112
114
  'spec/v1/prompts.md §"Resolution chain (normative)"',
113
115
  'host MUST emit `agent.promptResolved` when a node carries a `*PromptRef` and prompts.supported is advertised',
114
116
  ),
@@ -120,12 +122,12 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
120
122
  chain?: Array<{ layer?: string; applied?: boolean; source?: string }>;
121
123
  resolved?: string | null;
122
124
  };
123
- expect(payload.nodeId, 'agent.promptResolved.nodeId MUST be set').toBe('writer');
124
- expect(payload.kind, 'agent.promptResolved.kind MUST match the resolved kind').toBe('system');
125
+ expect(payload.nodeId, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'agent.promptResolved.nodeId MUST be set')).toBe('writer');
126
+ expect(payload.kind, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'agent.promptResolved.kind MUST match the resolved kind')).toBe('system');
125
127
  const applied = (payload.chain ?? []).find((c) => c.applied === true);
126
128
  expect(
127
129
  applied?.layer,
128
- driver.describe(
130
+ req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-with-chain-applied-true-for-layer-node-when-systempro',
129
131
  'spec/v1/prompts.md §"Resolution chain (normative)" — Layer 1',
130
132
  'node-config ref MUST win when no higher-precedence run-configurable layer is configured',
131
133
  ),
@@ -138,7 +140,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
138
140
  if (!behaviorGate('prompts-supported', promptsSupported(d))) return;
139
141
 
140
142
  const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
141
- if (create.status !== 201) return;
143
+ if (create.status !== 201) return softSkip('blocked', 'precondition not met — `create.status !== 201` returned early (seam, prior step, or fixture unavailable)');
142
144
  const { runId } = create.json as { runId: string };
143
145
  await pollUntilTerminal(runId);
144
146
  const events = await readAllEvents(runId);
@@ -146,7 +148,7 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
146
148
  const composed = events.find((e) => e.type === 'prompt.composed');
147
149
  expect(
148
150
  composed,
149
- driver.describe(
151
+ req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system',
150
152
  'spec/v1/prompts.md §"Composition + observability"',
151
153
  'host MUST emit `prompt.composed` after `agent.promptResolved` when a ref resolves and observability !== off',
152
154
  ),
@@ -162,15 +164,15 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
162
164
  };
163
165
  expect(
164
166
  payload.hash && /^sha256:[0-9a-f]{64}$/.test(payload.hash),
165
- driver.describe(
167
+ req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system',
166
168
  'schemas/run-event-payloads.schema.json §promptComposed.hash',
167
169
  'hash MUST match `^sha256:[0-9a-f]{64}$`',
168
170
  ),
169
171
  ).toBe(true);
170
- expect(payload.kind, 'system-only kind composition').toBe('system-only');
172
+ expect(payload.kind, req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system', 'schemas/run-event-payloads.schema.json §promptComposed.hash', 'system-only kind composition')).toBe('system-only');
171
173
  expect(
172
174
  typeof payload.composed === 'string' && payload.composed.length > 0,
173
- driver.describe(
175
+ req('openwop.it.prompt-end-to-end-events.emits-prompt-composed-with-sha256-hex64-hash-non-empty-composed-body-for-system',
174
176
  'spec/v1/prompts.md §"Composition + observability"',
175
177
  'composed body MUST be non-empty for system-kind under observability: full',
176
178
  ),
@@ -183,18 +185,18 @@ describe.skipIf(SKIP_NO_FIXTURE || HTTP_SKIP)('prompt-end-to-end-events: real di
183
185
  const d = await readDiscovery();
184
186
  if (!behaviorGate('prompts-supported', promptsSupported(d))) return;
185
187
  const create = await driver.post('/v1/runs', { workflowId: WORKFLOW_ID });
186
- if (create.status !== 201) return;
188
+ if (create.status !== 201) return softSkip('blocked', 'precondition not met — `create.status !== 201` returned early (seam, prior step, or fixture unavailable)');
187
189
  const { runId } = create.json as { runId: string };
188
190
  await pollUntilTerminal(runId);
189
191
  const events = await readAllEvents(runId);
190
192
 
191
193
  const resolvedIdx = events.findIndex((e) => e.type === 'agent.promptResolved');
192
194
  const composedIdx = events.findIndex((e) => e.type === 'prompt.composed');
193
- expect(resolvedIdx, 'agent.promptResolved MUST appear in the event log').toBeGreaterThanOrEqual(0);
194
- expect(composedIdx, 'prompt.composed MUST appear in the event log').toBeGreaterThanOrEqual(0);
195
+ expect(resolvedIdx, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-before-prompt-composed-causal-ordering', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'agent.promptResolved MUST appear in the event log')).toBeGreaterThanOrEqual(0);
196
+ expect(composedIdx, req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-before-prompt-composed-causal-ordering', 'spec/v1/prompts.md §"Resolution chain (normative)"', 'prompt.composed MUST appear in the event log')).toBeGreaterThanOrEqual(0);
195
197
  expect(
196
198
  resolvedIdx,
197
- driver.describe(
199
+ req('openwop.it.prompt-end-to-end-events.emits-agent-promptresolved-before-prompt-composed-causal-ordering',
198
200
  'spec/v1/prompts.md §"Resolution chain (normative)"',
199
201
  'agent.promptResolved MUST emit BEFORE the corresponding prompt.composed (resolution precedes composition)',
200
202
  ),
@@ -35,6 +35,8 @@ import { driver } from '../lib/driver.js';
35
35
  import { SCHEMAS_DIR } from '../lib/paths.js';
36
36
  import { behaviorGate } from '../lib/behavior-gate.js';
37
37
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
38
+ import { req } from '../lib/requirement-ids.js';
39
+ import { softSkip } from '../lib/soft-skip.js';
38
40
 
39
41
  interface DiscoveryDoc {
40
42
  capabilities?: {
@@ -86,17 +88,17 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
86
88
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
87
89
 
88
90
  const res = await driver.get('/v1/prompts');
89
- expect(res.status, driver.describe('spec/v1/prompts.md §Discovery & distribution', 'GET /v1/prompts MUST return 200 when endpointsSupported: true')).toBe(200);
91
+ expect(res.status, req('openwop.it.prompt-list-and-fetch.get-v1-prompts-returns-items-prompttemplate-nextcursor-when-endpointssupported-i', 'spec/v1/prompts.md §Discovery & distribution', 'GET /v1/prompts MUST return 200 when endpointsSupported: true')).toBe(200);
90
92
  const body = res.json as ListResponse;
91
93
  expect(
92
94
  Array.isArray(body.items),
93
- driver.describe('spec/v1/prompts.md §Discovery & distribution', 'response MUST contain an `items` array'),
95
+ req('openwop.it.prompt-list-and-fetch.get-v1-prompts-returns-items-prompttemplate-nextcursor-when-endpointssupported-i', 'spec/v1/prompts.md §Discovery & distribution', 'response MUST contain an `items` array'),
94
96
  ).toBe(true);
95
97
  for (const item of body.items) {
96
98
  const ok = validate(item);
97
99
  expect(
98
100
  ok,
99
- driver.describe(
101
+ req('openwop.it.prompt-list-and-fetch.get-v1-prompts-returns-items-prompttemplate-nextcursor-when-endpointssupported-i',
100
102
  'spec/v1/prompts.md §PromptTemplate',
101
103
  `every list item MUST validate against prompt-template.schema.json; errors: ${JSON.stringify(validate.errors)}`,
102
104
  ),
@@ -113,7 +115,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
113
115
  for (const item of body.items) {
114
116
  expect(
115
117
  item.meta?.source,
116
- driver.describe(
118
+ req('openwop.it.prompt-list-and-fetch.get-v1-prompts-source-host-narrows-to-host-built-in-templates',
117
119
  'spec/v1/prompts.md §Discovery & distribution',
118
120
  'source filter MUST narrow to templates whose meta.source matches',
119
121
  ),
@@ -125,7 +127,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
125
127
  const d = await readDiscovery();
126
128
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
127
129
  const res = await driver.get('/v1/prompts?kind=system');
128
- expect(res.status).toBe(200);
130
+ expect(res.status, req('openwop.it.prompt-list-and-fetch.get-v1-prompts-kind-system-narrows-to-system-kind-templates', 'RFC 0028 §A', 'GET /v1/prompts?kind=system narrows to system-kind templates')).toBe(200);
129
131
  const body = res.json as ListResponse;
130
132
  for (const item of body.items) {
131
133
  expect(item.kind).toBe('system');
@@ -138,9 +140,9 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
138
140
 
139
141
  // List first to discover a known templateId we can fetch.
140
142
  const list = await driver.get('/v1/prompts?source=host&limit=1');
141
- if (list.status !== 200) return;
143
+ if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
142
144
  const body = list.json as ListResponse;
143
- if (body.items.length === 0) return; // host advertises endpoints but ships no fixtures — tolerable
145
+ if (body.items.length === 0) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `body.items.length === 0` returned early (host advertises endpoints but ships no fixtures — tolerable)'); // host advertises endpoints but ships no fixtures — tolerable
144
146
  const known = body.items[0]!;
145
147
 
146
148
  const fetched = await driver.get(`/v1/prompts/${encodeURIComponent(known.templateId)}`);
@@ -153,7 +155,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
153
155
  const etag = fetched.headers?.get('etag');
154
156
  expect(
155
157
  typeof etag === 'string' && etag.length > 0,
156
- driver.describe(
158
+ req('openwop.it.prompt-list-and-fetch.get-v1-prompts-templateid-returns-the-template-etag-header-for-a-known-fixture',
157
159
  'spec/v1/prompts.md §Discovery & distribution',
158
160
  'GET /v1/prompts/{templateId} SHOULD set an ETag header (RFC 0028 §A cache semantics)',
159
161
  ),
@@ -164,22 +166,22 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
164
166
  const d = await readDiscovery();
165
167
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
166
168
  const list = await driver.get('/v1/prompts?source=host&limit=1');
167
- if (list.status !== 200) return;
169
+ if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
168
170
  const body = list.json as ListResponse;
169
- if (body.items.length === 0) return;
171
+ if (body.items.length === 0) return softSkip('blocked', 'precondition not met — `body.items.length === 0` returned early (seam, prior step, or fixture unavailable)');
170
172
  const known = body.items[0]!;
171
173
 
172
174
  const first = await driver.get(`/v1/prompts/${encodeURIComponent(known.templateId)}`);
173
- if (first.status !== 200) return;
175
+ if (first.status !== 200) return softSkip('blocked', 'precondition not met — `first.status !== 200` returned early (seam, prior step, or fixture unavailable)');
174
176
  const etag = first.headers?.get('etag') ?? undefined;
175
- if (!etag) return; // ETag is SHOULD, not MUST — soft-skip when absent
177
+ if (!etag) return softSkip('blocked', 'precondition not met — `!etag` returned early (ETag is SHOULD, not MUST — soft-skip when absent) (seam, prior step, or fixture unavailable)'); // ETag is SHOULD, not MUST — soft-skip when absent
176
178
 
177
179
  const second = await driver.get(`/v1/prompts/${encodeURIComponent(known.templateId)}`, {
178
180
  headers: { 'If-None-Match': etag },
179
181
  });
180
182
  expect(
181
183
  second.status,
182
- driver.describe(
184
+ req('openwop.it.prompt-list-and-fetch.get-v1-prompts-templateid-with-if-none-match-returns-304-when-etag-matches',
183
185
  'spec/v1/prompts.md §Discovery & distribution',
184
186
  'conditional revalidation MUST return 304 when ETag matches',
185
187
  ),
@@ -198,7 +200,7 @@ describe.skipIf(HTTP_SKIP)('prompt-list-and-fetch: REST surface shape (RFC 0028
198
200
  const body = res.json as { error?: unknown; message?: unknown };
199
201
  expect(
200
202
  typeof body.error,
201
- driver.describe(
203
+ req('openwop.it.prompt-list-and-fetch.get-v1-prompts-unknown-template-returns-404-with-errorenvelope',
202
204
  'schemas/error-envelope.schema.json',
203
205
  '404 response MUST carry canonical ErrorEnvelope: `error` is a machine-readable code STRING (flat shape per the schema, not nested)',
204
206
  ),
@@ -36,6 +36,8 @@ import { describe, it, expect } from 'vitest';
36
36
  import { driver } from '../lib/driver.js';
37
37
  import { behaviorGate } from '../lib/behavior-gate.js';
38
38
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
39
+ import { req } from '../lib/requirement-ids.js';
40
+ import { softSkip } from '../lib/soft-skip.js';
39
41
 
40
42
  interface DiscoveryDoc {
41
43
  capabilities?: {
@@ -83,7 +85,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
83
85
  const res = await driver.post('/v1/prompts', body);
84
86
  expect(
85
87
  res.status,
86
- driver.describe(
88
+ req('openwop.it.prompt-mutable-lifecycle.post-v1-prompts-creates-a-user-source-template-201-location',
87
89
  'spec/v1/prompts.md §Discovery & distribution',
88
90
  'POST /v1/prompts MUST return 201 on successful user-source create',
89
91
  ),
@@ -91,7 +93,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
91
93
  const location = res.headers?.get?.('location');
92
94
  expect(
93
95
  typeof location === 'string' && location.includes(TEMPLATE_ID),
94
- driver.describe(
96
+ req('openwop.it.prompt-mutable-lifecycle.post-v1-prompts-creates-a-user-source-template-201-location',
95
97
  'spec/v1/prompts.md §Discovery & distribution',
96
98
  '201 response MUST set a Location header referencing the new templateId',
97
99
  ),
@@ -107,7 +109,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
107
109
  expect(tpl.templateId).toBe(TEMPLATE_ID);
108
110
  expect(
109
111
  tpl.meta?.source,
110
- driver.describe(
112
+ req('openwop.it.prompt-mutable-lifecycle.get-v1-prompts-templateid-returns-the-new-template-with-meta-source-user',
111
113
  'spec/v1/prompts.md §PromptTemplate',
112
114
  'host MUST stamp meta.source: "user" on POST-created templates',
113
115
  ),
@@ -126,7 +128,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
126
128
  const res = await driver.post('/v1/prompts', body);
127
129
  expect(
128
130
  res.status,
129
- driver.describe(
131
+ req('openwop.it.prompt-mutable-lifecycle.post-v1-prompts-with-same-templateid-version-returns-409',
130
132
  'spec/v1/prompts.md §Discovery & distribution',
131
133
  'POST /v1/prompts MUST return 409 on (templateId, version) duplicate',
132
134
  ),
@@ -145,7 +147,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
145
147
  const res = await driver.put(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`, body);
146
148
  expect(
147
149
  res.status,
148
- driver.describe(
150
+ req('openwop.it.prompt-mutable-lifecycle.put-v1-prompts-templateid-with-strictly-greater-semver-replaces-the-template',
149
151
  'spec/v1/prompts.md §Discovery & distribution',
150
152
  'PUT /v1/prompts/{templateId} MUST return 200 on monotonic-SemVer update',
151
153
  ),
@@ -167,7 +169,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
167
169
  const res = await driver.put(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`, body);
168
170
  expect(
169
171
  res.status,
170
- driver.describe(
172
+ req('openwop.it.prompt-mutable-lifecycle.put-v1-prompts-templateid-with-non-monotonic-semver-returns-409',
171
173
  'spec/v1/prompts.md §Discovery & distribution',
172
174
  'PUT MUST return 409 when submitted version does not exceed stored',
173
175
  ),
@@ -180,7 +182,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
180
182
  const del = await driver.delete(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`);
181
183
  expect(
182
184
  del.status,
183
- driver.describe(
185
+ req('openwop.it.prompt-mutable-lifecycle.delete-v1-prompts-templateid-returns-204-and-subsequent-get-returns-404',
184
186
  'spec/v1/prompts.md §Discovery & distribution',
185
187
  'DELETE /v1/prompts/{templateId} MUST return 204 on successful delete',
186
188
  ),
@@ -188,7 +190,7 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
188
190
  const after = await driver.get(`/v1/prompts/${encodeURIComponent(TEMPLATE_ID)}`);
189
191
  expect(
190
192
  after.status,
191
- driver.describe(
193
+ req('openwop.it.prompt-mutable-lifecycle.delete-v1-prompts-templateid-returns-204-and-subsequent-get-returns-404',
192
194
  'spec/v1/prompts.md §Discovery & distribution',
193
195
  'GET after DELETE MUST return 404',
194
196
  ),
@@ -201,14 +203,14 @@ describe.skipIf(HTTP_SKIP)('prompt-mutable-lifecycle: user-source create/update/
201
203
  // Find a host-built-in to probe; the conformance-fixture set
202
204
  // is the standard source for this test.
203
205
  const list = await driver.get('/v1/prompts?source=host&limit=1');
204
- if (list.status !== 200) return;
206
+ if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
205
207
  const body = list.json as { items: PromptTemplate[] };
206
- if (body.items.length === 0) return;
208
+ if (body.items.length === 0) return softSkip('blocked', 'precondition not met — `body.items.length === 0` returned early (seam, prior step, or fixture unavailable)');
207
209
  const hostTemplate = body.items[0]!;
208
210
  const res = await driver.delete(`/v1/prompts/${encodeURIComponent(hostTemplate.templateId)}`);
209
211
  expect(
210
212
  res.status,
211
- driver.describe(
213
+ req('openwop.it.prompt-mutable-lifecycle.delete-on-a-host-built-in-template-returns-403',
212
214
  'spec/v1/prompts.md §Discovery & distribution',
213
215
  'DELETE on a host-built-in template MUST return 403 (read-only)',
214
216
  ),
@@ -42,6 +42,8 @@ import { describe, it, expect } from 'vitest';
42
42
  import { randomUUID } from 'node:crypto';
43
43
  import { driver } from '../lib/driver.js';
44
44
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
45
+ import { req } from '../lib/requirement-ids.js';
46
+ import { softSkip } from '../lib/soft-skip.js';
45
47
 
46
48
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
47
49
 
@@ -70,12 +72,12 @@ describe.skipIf(HTTP_SKIP)(
70
72
  const d = await readDiscovery();
71
73
  if (d === null) {
72
74
  ctx.skip();
73
- return;
75
+ return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
74
76
  }
75
77
  const mutableLibrary = capabilityFamily(d, 'prompts')?.mutableLibrary;
76
78
  if (mutableLibrary !== true) {
77
79
  ctx.skip();
78
- return;
80
+ return softSkip('blocked', 'precondition not met — `mutableLibrary !== true` returned early (seam, prior step, or fixture unavailable)');
79
81
  }
80
82
 
81
83
  const nonMemberWorkspaceId =
@@ -96,7 +98,7 @@ describe.skipIf(HTTP_SKIP)(
96
98
  // 0028 Tier-2 self-disclosed vulnerability demonstrated.
97
99
  expect(
98
100
  res.status,
99
- driver.describe(
101
+ req('openwop.it.prompt-mutation-workspace-membership-enforced.post-v1-prompts-with-a-workspaceid-the-principal-is-not-a-member-of-must-not-suc',
100
102
  'spec/v1/prompts.md §Workspace membership on workspace-scoped reads and writes',
101
103
  `mutating /v1/prompts MUST refuse a write to a non-member workspace; ` +
102
104
  `got ${res.status} ${res.text.slice(0, 200)}`,
@@ -116,7 +118,7 @@ describe.skipIf(HTTP_SKIP)(
116
118
  const body = res.json as { error?: unknown } | null;
117
119
  expect(
118
120
  body?.error,
119
- driver.describe(
121
+ req('openwop.it.prompt-mutation-workspace-membership-enforced.post-v1-prompts-with-a-workspaceid-the-principal-is-not-a-member-of-must-not-suc',
120
122
  'spec/v1/rest-endpoints.md §Common error codes — workspace_membership_required',
121
123
  `403 refusal of a workspace-scoped mutation MUST carry error: "workspace_membership_required"; got error: ${JSON.stringify(body?.error)}`,
122
124
  ),
@@ -47,6 +47,8 @@ import { describe, it, expect } from 'vitest';
47
47
  import { driver } from '../lib/driver.js';
48
48
  import { behaviorGate } from '../lib/behavior-gate.js';
49
49
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
50
+ import { req } from '../lib/requirement-ids.js';
51
+ import { softSkip } from '../lib/soft-skip.js';
50
52
 
51
53
  interface DiscoveryDoc {
52
54
  capabilities?: {
@@ -94,7 +96,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
94
96
  const res = await driver.get('/v1/prompts?source=pack');
95
97
  expect(
96
98
  res.status,
97
- driver.describe(
99
+ req('openwop.it.prompt-pack-install.get-v1-prompts-source-pack-returns-200-an-array-of-prompttemplate-objects-when-e',
98
100
  'spec/v1/prompts.md §"Discovery & distribution"',
99
101
  'GET /v1/prompts MUST return 200 when prompts.endpointsSupported is advertised',
100
102
  ),
@@ -103,7 +105,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
103
105
  const body = res.json as ListResponse;
104
106
  expect(
105
107
  Array.isArray(body.items),
106
- driver.describe(
108
+ req('openwop.it.prompt-pack-install.get-v1-prompts-source-pack-returns-200-an-array-of-prompttemplate-objects-when-e',
107
109
  'RFCS/0028-prompt-library-endpoints.md §A',
108
110
  '`items` MUST be an array of PromptTemplate objects',
109
111
  ),
@@ -117,7 +119,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
117
119
  const packItems = body.items.filter((t) => t.meta?.source === 'pack');
118
120
  expect(
119
121
  packItems.length,
120
- driver.describe(
122
+ req('openwop.it.prompt-pack-install.get-v1-prompts-source-pack-returns-200-an-array-of-prompttemplate-objects-when-e',
121
123
  'RFCS/0028-prompt-library-endpoints.md §B',
122
124
  'OPENWOP_TEST_PROMPT_PACK_INSTALLED=true asserts the boot-time loader installed at least one pack',
123
125
  ),
@@ -130,29 +132,29 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
130
132
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
131
133
 
132
134
  const res = await driver.get('/v1/prompts?source=pack');
133
- if (res.status !== 200) return;
135
+ if (res.status !== 200) return softSkip('blocked', 'precondition not met — `res.status !== 200` returned early (seam, prior step, or fixture unavailable)');
134
136
  const body = res.json as ListResponse;
135
137
  const packItems = body.items.filter((t) => t.meta?.source === 'pack');
136
- if (packItems.length === 0) return; // gated above
138
+ if (packItems.length === 0) return softSkip('blocked', 'precondition not met — `packItems.length === 0` returned early (gated above) (seam, prior step, or fixture unavailable)'); // gated above
137
139
 
138
140
  for (const t of packItems) {
139
141
  expect(
140
142
  t.meta?.source,
141
- driver.describe(
143
+ req('openwop.it.prompt-pack-install.each-pack-source-template-carries-meta-source-packname-packversion-stamps-per-rf',
142
144
  'schemas/prompt-template.schema.json §meta.source',
143
145
  'pack-installed templates MUST stamp `meta.source: "pack"`',
144
146
  ),
145
147
  ).toBe('pack');
146
148
  expect(
147
149
  typeof t.meta?.packName === 'string' && (t.meta?.packName?.length ?? 0) > 0,
148
- driver.describe(
150
+ req('openwop.it.prompt-pack-install.each-pack-source-template-carries-meta-source-packname-packversion-stamps-per-rf',
149
151
  'RFCS/0028-prompt-library-endpoints.md §B',
150
152
  'pack-installed templates MUST stamp `meta.packName`',
151
153
  ),
152
154
  ).toBe(true);
153
155
  expect(
154
156
  typeof t.meta?.packVersion === 'string' && /^\d+\.\d+\.\d+/.test(t.meta?.packVersion ?? ''),
155
- driver.describe(
157
+ req('openwop.it.prompt-pack-install.each-pack-source-template-carries-meta-source-packname-packversion-stamps-per-rf',
156
158
  'RFCS/0028-prompt-library-endpoints.md §B',
157
159
  'pack-installed templates MUST stamp a semver `meta.packVersion`',
158
160
  ),
@@ -165,15 +167,15 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
165
167
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
166
168
 
167
169
  const list = await driver.get('/v1/prompts?source=pack');
168
- if (list.status !== 200) return;
170
+ if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
169
171
  const body = list.json as ListResponse;
170
172
  const writer = body.items.find((t) => t.templateId === 'writer-system' && t.meta?.source === 'pack');
171
- if (!writer) return; // host may have installed a different reference pack; skip silently
173
+ if (!writer) return softSkip('blocked', 'precondition not met — `!writer` returned early (host may have installed a different reference pack; skip silently) (seam, prior step, or fixture unavailable)'); // host may have installed a different reference pack; skip silently
172
174
 
173
175
  const fetched = await driver.get(`/v1/prompts/${encodeURIComponent('writer-system')}`);
174
176
  expect(
175
177
  fetched.status,
176
- driver.describe(
178
+ req('openwop.it.prompt-pack-install.get-v1-prompts-templateid-returns-a-pack-source-template-by-id-reference-pack-wr',
177
179
  'RFCS/0028-prompt-library-endpoints.md §A',
178
180
  'GET /v1/prompts/{templateId} MUST return 200 for a known pack-source template id',
179
181
  ),
@@ -182,7 +184,7 @@ describe.skipIf(HTTP_SKIP)('prompt-pack-install: boot-time loader surfaces pack
182
184
  expect(t.templateId).toBe('writer-system');
183
185
  expect(
184
186
  t.meta?.source,
185
- 'fetched template MUST preserve `meta.source: "pack"` provenance',
187
+ req('openwop.it.prompt-pack-install.get-v1-prompts-templateid-returns-a-pack-source-template-by-id-reference-pack-wr', 'RFCS/0028-prompt-library-endpoints.md §A', 'fetched template MUST preserve `meta.source: "pack"` provenance'),
186
188
  ).toBe('pack');
187
189
  });
188
190
  });