@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
@@ -32,6 +32,8 @@
32
32
  import { describe, it, expect } from 'vitest';
33
33
  import { driver } from '../lib/driver.js';
34
34
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
35
+ import { req } from '../lib/requirement-ids.js';
36
+ import { softSkip } from '../lib/soft-skip.js';
35
37
 
36
38
  interface PromptPrefixCacheCap {
37
39
  supported?: unknown;
@@ -76,10 +78,10 @@ async function generate(args: {
76
78
  describe('prompt-prefix-cache: advertisement shape (RFC 0116)', () => {
77
79
  it('aiProviders.promptPrefixCache is either absent or a well-formed object', async () => {
78
80
  const cap = await readCap();
79
- if (cap === null) return; // not advertised — skip
81
+ if (cap === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap === null` returned early (not advertised — skip)'); // not advertised — skip
80
82
  expect(
81
83
  typeof cap.supported,
82
- driver.describe(
84
+ req('openwop.it.prompt-prefix-cache.aiproviders-promptprefixcache-is-either-absent-or-a-well-formed-object',
83
85
  'capabilities.schema.json §aiProviders.promptPrefixCache',
84
86
  'promptPrefixCache.supported MUST be a boolean when the block is present',
85
87
  ),
@@ -87,7 +89,7 @@ describe('prompt-prefix-cache: advertisement shape (RFC 0116)', () => {
87
89
  if (cap.providers !== undefined) {
88
90
  expect(
89
91
  Array.isArray(cap.providers),
90
- driver.describe(
92
+ req('openwop.it.prompt-prefix-cache.aiproviders-promptprefixcache-is-either-absent-or-a-well-formed-object',
91
93
  'capabilities.schema.json §aiProviders.promptPrefixCache',
92
94
  'promptPrefixCache.providers MUST be an array of provider ids when present (provider-scoped)',
93
95
  ),
@@ -99,19 +101,19 @@ describe('prompt-prefix-cache: advertisement shape (RFC 0116)', () => {
99
101
  describe('prompt-prefix-cache: behavioral (RFC 0116 §"Normative requirements")', () => {
100
102
  it('(a) outcome-invariance — cachePrefixId vs control → same envelope + identical input/output tokens', async () => {
101
103
  const cap = await readCap();
102
- if (!cap || cap.supported !== true) return; // not advertised — skip
104
+ if (!cap || cap.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!cap || cap.supported !== true` returned early (not advertised — skip)'); // not advertised — skip
103
105
  const prefixId = `inv-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
104
106
 
105
107
  const control = await generate({ tenantId: 'tenant-a' });
106
- if (control.status === 404 || control.status === 405) return; // seam not wired
107
- expect(control.status, driver.describe('host-sample-test-seams.md §16', 'generate seam MUST return 200')).toBe(200);
108
+ if (control.status === 404 || control.status === 405) return softSkip('blocked', 'precondition not met — `control.status === 404 || control.status === 405` returned early (seam not wired) (seam, prior step, or fixture unavailable)'); // seam not wired
109
+ expect(control.status, req('openwop.it.prompt-prefix-cache.a-outcome-invariance-cacheprefixid-vs-control-same-envelope-identical-input-outp', 'host-sample-test-seams.md §16', 'generate seam MUST return 200')).toBe(200);
108
110
 
109
111
  const withPrefix = await generate({ tenantId: 'tenant-a', cachePrefixId: prefixId });
110
112
  expect(withPrefix.status).toBe(200);
111
113
 
112
114
  expect(
113
115
  withPrefix.body.envelope?.envelopeType,
114
- driver.describe(
116
+ req('openwop.it.prompt-prefix-cache.a-outcome-invariance-cacheprefixid-vs-control-same-envelope-identical-input-outp',
115
117
  'ai-envelope.md §"Prompt-prefix cache (RFC 0116)" rule 3',
116
118
  'cachePrefixId is a cost hint, never semantic: the accepted envelope MUST be identical hit-vs-miss',
117
119
  ),
@@ -119,7 +121,7 @@ describe('prompt-prefix-cache: behavioral (RFC 0116 §"Normative requirements")'
119
121
  expect(withPrefix.body.usage?.inputTokens).toBe(control.body.usage?.inputTokens);
120
122
  expect(
121
123
  withPrefix.body.usage?.outputTokens,
122
- driver.describe(
124
+ req('openwop.it.prompt-prefix-cache.a-outcome-invariance-cacheprefixid-vs-control-same-envelope-identical-input-outp',
123
125
  'ai-envelope.md §"Prompt-prefix cache (RFC 0116)" rule 3',
124
126
  'provider.usage.inputTokens/outputTokens MUST be identical hit-vs-miss (replay-invariant)',
125
127
  ),
@@ -128,18 +130,18 @@ describe('prompt-prefix-cache: behavioral (RFC 0116 §"Normative requirements")'
128
130
 
129
131
  it('(b) cache hit observable — a repeat generate shows cacheReadTokens > 0 while tokens stay invariant', async () => {
130
132
  const cap = await readCap();
131
- if (!cap || cap.supported !== true) return; // not advertised — skip
133
+ if (!cap || cap.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!cap || cap.supported !== true` returned early (not advertised — skip)'); // not advertised — skip
132
134
  const prefixId = `hit-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
133
135
 
134
136
  const prime = await generate({ tenantId: 'tenant-a', cachePrefixId: prefixId });
135
- if (prime.status === 404 || prime.status === 405) return; // seam not wired
137
+ if (prime.status === 404 || prime.status === 405) return softSkip('blocked', 'precondition not met — `prime.status === 404 || prime.status === 405` returned early (seam not wired) (seam, prior step, or fixture unavailable)'); // seam not wired
136
138
  expect(prime.status).toBe(200);
137
139
 
138
140
  const repeat = await generate({ tenantId: 'tenant-a', cachePrefixId: prefixId });
139
141
  expect(repeat.status).toBe(200);
140
142
  expect(
141
143
  repeat.body.usage?.cacheReadTokens ?? 0,
142
- driver.describe(
144
+ req('openwop.it.prompt-prefix-cache.b-cache-hit-observable-a-repeat-generate-shows-cachereadtokens-0-while-tokens-st',
143
145
  'ai-envelope.md §"Prompt-prefix cache (RFC 0116)" rule 4',
144
146
  'a repeat generate with the same cachePrefixId for the SAME tenant MUST be an observable cache hit (cacheReadTokens > 0)',
145
147
  ),
@@ -151,12 +153,12 @@ describe('prompt-prefix-cache: behavioral (RFC 0116 §"Normative requirements")'
151
153
 
152
154
  it('(c) cross-tenant isolation — tenant B first use of tenant A\'s cachePrefixId → cacheReadTokens == 0', async () => {
153
155
  const cap = await readCap();
154
- if (!cap || cap.supported !== true) return; // not advertised — skip
156
+ if (!cap || cap.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!cap || cap.supported !== true` returned early (not advertised — skip)'); // not advertised — skip
155
157
  const prefixId = `xtenant-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
156
158
 
157
159
  // Tenant A primes the cache under a shared, predictable cachePrefixId.
158
160
  const aPrime = await generate({ tenantId: 'tenant-a', cachePrefixId: prefixId });
159
- if (aPrime.status === 404 || aPrime.status === 405) return; // seam not wired
161
+ if (aPrime.status === 404 || aPrime.status === 405) return softSkip('blocked', 'precondition not met — `aPrime.status === 404 || aPrime.status === 405` returned early (seam not wired) (seam, prior step, or fixture unavailable)'); // seam not wired
160
162
  expect(aPrime.status).toBe(200);
161
163
 
162
164
  // Tenant B's FIRST use of the SAME cachePrefixId MUST be a miss — the host
@@ -165,7 +167,7 @@ describe('prompt-prefix-cache: behavioral (RFC 0116 §"Normative requirements")'
165
167
  expect(bFirst.status).toBe(200);
166
168
  expect(
167
169
  bFirst.body.usage?.cacheReadTokens ?? 0,
168
- driver.describe(
170
+ req('openwop.it.prompt-prefix-cache.c-cross-tenant-isolation-tenant-b-first-use-of-tenant-a-s-cacheprefixid-cacherea',
169
171
  'SECURITY/invariants.yaml prompt-prefix-cache-cross-tenant-isolation',
170
172
  'tenant B\'s first use of tenant A\'s cachePrefixId MUST be a cache MISS (cacheReadTokens == 0) — the cache MUST be keyed by (tenant, cachePrefixId), never global; cross-tenant sharing is context leakage',
171
173
  ),
@@ -174,11 +176,11 @@ describe('prompt-prefix-cache: behavioral (RFC 0116 §"Normative requirements")'
174
176
 
175
177
  it('(d) secret-free — the response never echoes cachePrefixId in a SR-1-sensitive position', async () => {
176
178
  const cap = await readCap();
177
- if (!cap || cap.supported !== true) return; // not advertised — skip
179
+ if (!cap || cap.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!cap || cap.supported !== true` returned early (not advertised — skip)'); // not advertised — skip
178
180
  const prefixId = `secretfree-${Date.now()}`;
179
181
 
180
182
  const res = await generate({ tenantId: 'tenant-a', cachePrefixId: prefixId });
181
- if (res.status === 404 || res.status === 405) return; // seam not wired
183
+ if (res.status === 404 || res.status === 405) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 405` returned early (seam not wired) (seam, prior step, or fixture unavailable)'); // seam not wired
182
184
  expect(res.status).toBe(200);
183
185
  // The usage block is cost-only; it MUST NOT carry prompt/response substrings
184
186
  // (SR-1). cachePrefixId is a public cache key, but the cost witness fields
@@ -189,7 +191,7 @@ describe('prompt-prefix-cache: behavioral (RFC 0116 §"Normative requirements")'
189
191
  if (v !== undefined) {
190
192
  expect(
191
193
  typeof v,
192
- driver.describe(
194
+ req('openwop.it.prompt-prefix-cache.d-secret-free-the-response-never-echoes-cacheprefixid-in-a-sr-1-sensitive-positi',
193
195
  'run-event-payloads.schema.json §providerUsage',
194
196
  `provider.usage.${k} MUST be a cost-only integer (no prompt substrings per SR-1)`,
195
197
  ),
@@ -68,6 +68,8 @@ import { describe, it, expect } from 'vitest';
68
68
  import { randomUUID } from 'node:crypto';
69
69
  import { driver } from '../lib/driver.js';
70
70
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
71
+ import { req } from '../lib/requirement-ids.js';
72
+ import { softSkip } from '../lib/soft-skip.js';
71
73
 
72
74
  const HTTP_SKIP = !process.env.OPENWOP_BASE_URL;
73
75
 
@@ -100,12 +102,12 @@ describe.skipIf(HTTP_SKIP)(
100
102
  const d = await readDiscovery();
101
103
  if (d === null) {
102
104
  ctx.skip();
103
- return;
105
+ return softSkip('blocked', 'precondition not met — `d === null` returned early (seam, prior step, or fixture unavailable)');
104
106
  }
105
107
  const promptsSupported = capabilityFamily(d, 'prompts')?.supported;
106
108
  if (promptsSupported !== true) {
107
109
  ctx.skip();
108
- return;
110
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `promptsSupported !== true` returned early');
109
111
  }
110
112
 
111
113
  const nonMemberWorkspaceId =
@@ -125,18 +127,18 @@ describe.skipIf(HTTP_SKIP)(
125
127
  const body = res.json as { error?: unknown } | null;
126
128
  expect(
127
129
  body?.error,
128
- driver.describe(
130
+ req('openwop.it.prompt-read-workspace-membership-enforced.get-v1-prompts-workspaceid-non-member-must-refuse-or-return-empty-templates-neve',
129
131
  'spec/v1/rest-endpoints.md §Common error codes — workspace_membership_required',
130
132
  `403 refusal of a workspace-scoped read MUST carry error: "workspace_membership_required"; got error: ${JSON.stringify(body?.error)}`,
131
133
  ),
132
134
  ).toBe('workspace_membership_required');
133
135
  }
134
- return;
136
+ return softSkip('blocked', 'precondition not met — `res.status >= 400 && res.status < 500` returned early (4xx — refused. Acceptable shape for the membership-required failure (and any other refusal mode the host chooses: 401, 404 for existence-d…');
135
137
  }
136
138
 
137
139
  // 5xx — refused (infrastructure failure is acceptable; envelope shape
138
140
  // unconstrained).
139
- if (res.status >= 500) return;
141
+ if (res.status >= 500) return softSkip('blocked', 'precondition not met — `res.status >= 500` returned early (5xx — refused (infrastructure failure is acceptable; envelope shape unconstrained).) (seam, prior step, or fixture unavailable)');
140
142
 
141
143
  // 2xx — must inspect the response body. The failure mode this
142
144
  // invariant guards against is a 200 response that LEAKS templates
@@ -154,13 +156,13 @@ describe.skipIf(HTTP_SKIP)(
154
156
  // workspace-scoped reads, and a host without that surface is
155
157
  // simply out of scope.
156
158
  ctx.skip();
157
- return;
159
+ return softSkip('blocked', 'precondition not met — `body === null || typeof body !== \'object\' || !(\'templates\' in body)` returned early (seam, prior step, or fixture unavailable)');
158
160
  }
159
161
  const templates = body.templates;
160
162
  if (!Array.isArray(templates)) {
161
163
  // Same: unrecognized shape, skip.
162
164
  ctx.skip();
163
- return;
165
+ return softSkip('blocked', 'precondition not met — `!Array.isArray(templates)` returned early (seam, prior step, or fixture unavailable)');
164
166
  }
165
167
 
166
168
  // A random non-member workspaceId can never legitimately contain
@@ -168,12 +170,12 @@ describe.skipIf(HTTP_SKIP)(
168
170
  // is a cross-tenant data leak.
169
171
  expect(
170
172
  templates.length,
171
- driver.describe(
173
+ req('openwop.it.prompt-read-workspace-membership-enforced.get-v1-prompts-workspaceid-non-member-must-refuse-or-return-empty-templates-neve',
172
174
  'spec/v1/prompts.md §Workspace membership on workspace-scoped reads and writes',
173
175
  `GET /v1/prompts?workspaceId=<random-non-member> MUST NOT return any templates; got ${templates.length} templates which is a cross-tenant data leak (the random workspaceId is freshly generated per probe and cannot legitimately contain authorized content)`,
174
176
  ),
175
177
  ).toBe(0);
176
- return;
178
+ return softSkip('blocked', 'precondition not met — `res.status >= 200 && res.status < 300` returned early (2xx — must inspect the response body. The failure mode this invariant guards against is a 200 response that LEAKS templates from a workspa…');
177
179
  }
178
180
 
179
181
  // Other status codes (1xx, 3xx) — soft-skip with note. Not a clear
@@ -24,6 +24,8 @@ import { describe, it, expect } from 'vitest';
24
24
  import { driver } from '../lib/driver.js';
25
25
  import { behaviorGate } from '../lib/behavior-gate.js';
26
26
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
27
+ import { req } from '../lib/requirement-ids.js';
28
+ import { softSkip } from '../lib/soft-skip.js';
27
29
 
28
30
  interface DiscoveryDoc {
29
31
  capabilities?: {
@@ -91,7 +93,7 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
91
93
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
92
94
 
93
95
  const template = await pickTemplateWithInputVar();
94
- if (!template) return;
96
+ if (!template) return softSkip('blocked', 'precondition not met — `!template` returned early (seam, prior step, or fixture unavailable)');
95
97
 
96
98
  const variableNames = (template.variables ?? [])
97
99
  .filter((v) => v.source !== 'secret')
@@ -103,7 +105,7 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
103
105
 
104
106
  const ref = `prompt:${template.templateId}@${template.version}`;
105
107
  const first = await driver.post('/v1/prompts:render', { ref, variables });
106
- if (first.status !== 200) return;
108
+ if (first.status !== 200) return softSkip('blocked', 'precondition not met — `first.status !== 200` returned early (seam, prior step, or fixture unavailable)');
107
109
  const second = await driver.post('/v1/prompts:render', { ref, variables });
108
110
  expect(second.status).toBe(200);
109
111
 
@@ -112,14 +114,14 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
112
114
 
113
115
  expect(
114
116
  a.hash,
115
- driver.describe(
117
+ req('openwop.it.prompt-render-deterministic.identical-ref-variables-inputs-produce-identical-hash-variablehashes',
116
118
  'spec/v1/prompts.md §Discovery & distribution',
117
119
  'render hash MUST be stable across identical (ref, variables) inputs',
118
120
  ),
119
121
  ).toBe(b.hash);
120
122
  expect(
121
123
  Object.keys(a.variableHashes).sort(),
122
- driver.describe(
124
+ req('openwop.it.prompt-render-deterministic.identical-ref-variables-inputs-produce-identical-hash-variablehashes',
123
125
  'spec/v1/prompts.md §Discovery & distribution',
124
126
  'variableHashes key set MUST be stable',
125
127
  ),
@@ -134,11 +136,11 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
134
136
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
135
137
 
136
138
  const template = await pickTemplateWithInputVar();
137
- if (!template) return;
139
+ if (!template) return softSkip('blocked', 'precondition not met — `!template` returned early (seam, prior step, or fixture unavailable)');
138
140
  const requiredVars = (template.variables ?? []).filter(
139
141
  (v) => v.source !== 'secret' && v.required === true,
140
142
  );
141
- if (requiredVars.length === 0) return; // no required var to toggle
143
+ if (requiredVars.length === 0) return softSkip('blocked', 'precondition not met — `requiredVars.length === 0` returned early (no required var to toggle) (seam, prior step, or fixture unavailable)'); // no required var to toggle
142
144
 
143
145
  const variables: Record<string, unknown> = {};
144
146
  for (const v of template.variables ?? []) {
@@ -148,7 +150,7 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
148
150
 
149
151
  const ref = `prompt:${template.templateId}@${template.version}`;
150
152
  const baseline = await driver.post('/v1/prompts:render', { ref, variables });
151
- if (baseline.status !== 200) return;
153
+ if (baseline.status !== 200) return softSkip('blocked', 'precondition not met — `baseline.status !== 200` returned early (seam, prior step, or fixture unavailable)');
152
154
 
153
155
  // Toggle one required variable.
154
156
  const toggled = { ...variables, [requiredVars[0]!.name]: 'conformance-toggled-value' };
@@ -160,14 +162,14 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
160
162
 
161
163
  expect(
162
164
  a.hash,
163
- driver.describe(
165
+ req('openwop.it.prompt-render-deterministic.different-variable-values-produce-different-hash-at-least-one-different-variable',
164
166
  'spec/v1/prompts.md §Discovery & distribution',
165
167
  'render hash MUST differ when any variable binding differs',
166
168
  ),
167
169
  ).not.toBe(b.hash);
168
170
  expect(
169
171
  a.variableHashes[requiredVars[0]!.name],
170
- driver.describe(
172
+ req('openwop.it.prompt-render-deterministic.different-variable-values-produce-different-hash-at-least-one-different-variable',
171
173
  'spec/v1/prompts.md §Discovery & distribution',
172
174
  'variableHashes[name] MUST differ when name binding differs',
173
175
  ),
@@ -179,7 +181,7 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
179
181
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
180
182
 
181
183
  const template = await pickTemplateWithInputVar();
182
- if (!template) return;
184
+ if (!template) return softSkip('blocked', 'precondition not met — `!template` returned early (seam, prior step, or fixture unavailable)');
183
185
  const variables: Record<string, unknown> = {};
184
186
  for (const v of template.variables ?? []) {
185
187
  if (v.source === 'secret') continue;
@@ -187,12 +189,12 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
187
189
  }
188
190
  const ref = `prompt:${template.templateId}@${template.version}`;
189
191
  const res = await driver.post('/v1/prompts:render', { ref, variables });
190
- if (res.status !== 200) return;
192
+ if (res.status !== 200) return softSkip('blocked', 'precondition not met — `res.status !== 200` returned early (seam, prior step, or fixture unavailable)');
191
193
  const r = res.json as RenderResponse;
192
194
 
193
195
  expect(
194
196
  /^sha256:[0-9a-f]{64}$/.test(r.hash),
195
- driver.describe(
197
+ req('openwop.it.prompt-render-deterministic.hash-variablehashes-must-match-sha256-hex64-pattern',
196
198
  'schemas/run-event-payloads.schema.json §promptComposed.hash',
197
199
  'hash MUST match `^sha256:[0-9a-f]{64}$`',
198
200
  ),
@@ -200,7 +202,7 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
200
202
  for (const [name, h] of Object.entries(r.variableHashes)) {
201
203
  expect(
202
204
  /^sha256:[0-9a-f]{64}$/.test(h),
203
- `variableHashes[${name}] MUST match sha256:<hex64>; got ${h}`,
205
+ req('openwop.it.prompt-render-deterministic.hash-variablehashes-must-match-sha256-hex64-pattern', 'schemas/run-event-payloads.schema.json §promptComposed.hash', `variableHashes[${name}] MUST match sha256:<hex64>; got ${h}`),
204
206
  ).toBe(true);
205
207
  }
206
208
  });
@@ -214,12 +216,12 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
214
216
  const d = await readDiscovery();
215
217
  if (!behaviorGate('prompts-endpoints', endpointsSupported(d))) return;
216
218
  const list = await driver.get('/v1/prompts?source=host&limit=200');
217
- if (list.status !== 200) return;
219
+ if (list.status !== 200) return softSkip('blocked', 'precondition not met — `list.status !== 200` returned early (seam, prior step, or fixture unavailable)');
218
220
  const body = list.json as ListResponse;
219
221
  const nonSystemUser = body.items.find(
220
222
  (t) => t.kind === 'few-shot' || t.kind === 'schema-hint',
221
223
  );
222
- if (!nonSystemUser) return; // host doesn't ship one — soft-skip
224
+ if (!nonSystemUser) return softSkip('blocked', 'precondition not met — `!nonSystemUser` returned early (host doesn\'t ship one — soft-skip) (seam, prior step, or fixture unavailable)'); // host doesn't ship one — soft-skip
223
225
 
224
226
  const variables: Record<string, unknown> = {};
225
227
  for (const v of nonSystemUser.variables ?? []) {
@@ -228,11 +230,11 @@ describe.skipIf(HTTP_SKIP)('prompt-render-deterministic: hash stable across iden
228
230
  }
229
231
  const ref = `prompt:${nonSystemUser.templateId}@${nonSystemUser.version}`;
230
232
  const res = await driver.post('/v1/prompts:render', { ref, variables });
231
- if (res.status !== 200) return;
233
+ if (res.status !== 200) return softSkip('blocked', 'precondition not met — `res.status !== 200` returned early (seam, prior step, or fixture unavailable)');
232
234
  const r = res.json as RenderResponse;
233
235
  expect(
234
236
  typeof r.composed === 'string' && r.composed.length > 0,
235
- driver.describe(
237
+ req('openwop.it.prompt-render-deterministic.renders-few-shot-schema-hint-kinds-with-non-empty-composed-body',
236
238
  'spec/v1/prompts.md §Discovery & distribution',
237
239
  '`composed` body MUST populate for every PromptKind under observability: full',
238
240
  ),
@@ -31,6 +31,8 @@ import { describe, it, expect } from 'vitest';
31
31
  import { driver } from '../lib/driver.js';
32
32
  import { behaviorGate } from '../lib/behavior-gate.js';
33
33
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
34
+ import { req } from '../lib/requirement-ids.js';
35
+ import { softSkip } from '../lib/soft-skip.js';
34
36
 
35
37
  interface DiscoveryDoc {
36
38
  capabilities?: {
@@ -101,7 +103,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-agent-intrinsic: layer-2 age
101
103
  system: 'prompt:host-default@1.0.0',
102
104
  },
103
105
  });
104
- if (res.status === 404) return;
106
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
105
107
  expect(res.status).toBe(200);
106
108
 
107
109
  const payload = res.json as AgentPromptResolvedPayload;
@@ -109,14 +111,14 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-agent-intrinsic: layer-2 age
109
111
  const appliedEntries = payload.chain.filter((c) => c.applied);
110
112
  expect(
111
113
  appliedEntries.length,
112
- driver.describe(
114
+ req('openwop.it.prompt-resolution-chain-agent-intrinsic.agent-intrinsic-systempromptref-wins-over-workflow-defaults-host-defaults-when-n',
113
115
  'spec/v1/prompts.md §Resolution chain (normative)',
114
116
  'exactly one chain entry MUST carry applied: true',
115
117
  ),
116
118
  ).toBe(1);
117
119
  expect(
118
120
  appliedEntries[0]?.layer,
119
- driver.describe(
121
+ req('openwop.it.prompt-resolution-chain-agent-intrinsic.agent-intrinsic-systempromptref-wins-over-workflow-defaults-host-defaults-when-n',
120
122
  'spec/v1/prompts.md §Resolution chain (normative) — Layer 2',
121
123
  'system-kind resolution MUST prefer agent intrinsic (systemPromptRef) over agent-overrides when both are set',
122
124
  ),
@@ -124,7 +126,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-agent-intrinsic: layer-2 age
124
126
 
125
127
  expect(
126
128
  payload.resolved,
127
- driver.describe(
129
+ req('openwop.it.prompt-resolution-chain-agent-intrinsic.agent-intrinsic-systempromptref-wins-over-workflow-defaults-host-defaults-when-n',
128
130
  'spec/v1/prompts.md §Resolution chain (normative) — Layer 2',
129
131
  'resolved MUST mirror the winning chain entry source',
130
132
  ),
@@ -132,7 +134,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-agent-intrinsic: layer-2 age
132
134
 
133
135
  expect(
134
136
  payload.agentId,
135
- driver.describe(
137
+ req('openwop.it.prompt-resolution-chain-agent-intrinsic.agent-intrinsic-systempromptref-wins-over-workflow-defaults-host-defaults-when-n',
136
138
  'spec/v1/prompts.md §Resolution chain (normative)',
137
139
  'agent.promptResolved.agentId MUST be set when config.agentId resolves to a known agent',
138
140
  ),
@@ -30,6 +30,8 @@ import { describe, it, expect } from 'vitest';
30
30
  import { driver } from '../lib/driver.js';
31
31
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
32
32
  import { pollUntilTerminal } from '../lib/polling.js';
33
+ import { req } from '../lib/requirement-ids.js';
34
+ import { softSkip } from '../lib/soft-skip.js';
33
35
 
34
36
  const PROMPT_FIXTURE_ID = 'conformance-prompt-end-to-end';
35
37
  const VALID_LAYERS = new Set([
@@ -48,17 +50,17 @@ async function promptsSupported(): Promise<boolean> {
48
50
 
49
51
  describe('prompt-resolution-chain-event (black-box): agent.promptResolved carries the precedence record (RFC 0029)', () => {
50
52
  it('the production agent.promptResolved event records the full four-layer resolution chain', async () => {
51
- if (!(await promptsSupported())) return; // capability not advertised — skip
53
+ if (!(await promptsSupported())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await promptsSupported())` returned early (capability not advertised — skip)'); // capability not advertised — skip
52
54
 
53
55
  const create = await driver.post('/v1/runs', { workflowId: PROMPT_FIXTURE_ID });
54
56
  if (create.status !== 201) {
55
57
  // Fixture not seeded / run not accepted — not a prompt-chain failure.
56
58
  // eslint-disable-next-line no-console
57
59
  console.warn(`[prompt-resolution-chain-event] POST /v1/runs for ${PROMPT_FIXTURE_ID} returned ${create.status}; skipping the production-path assertion`);
58
- return;
60
+ return softSkip('blocked', 'precondition not met — `create.status !== 201` returned early ([prompt-resolution-chain-event] POST /v1/runs for … returned …; skipping the production-path assertion) (seam, prior step, or fixture unavailable)');
59
61
  }
60
62
  const runId = (create.json as { runId?: string }).runId;
61
- if (!runId) return;
63
+ if (!runId) return softSkip('blocked', 'precondition not met — `!runId` returned early (seam, prior step, or fixture unavailable)');
62
64
  await pollUntilTerminal(runId);
63
65
 
64
66
  const poll = await driver.get(`/v1/runs/${encodeURIComponent(runId)}/events/poll`);
@@ -69,14 +71,14 @@ describe('prompt-resolution-chain-event (black-box): agent.promptResolved carrie
69
71
  // (RFC 0029 emission is staged) — soft-skip the behavioral assertion.
70
72
  // eslint-disable-next-line no-console
71
73
  console.warn('[prompt-resolution-chain-event] host emitted no agent.promptResolved event; skipping (RFC 0029 emission staged)');
72
- return;
74
+ return softSkip('blocked', 'precondition not met — `resolved.length === 0` returned early ([prompt-resolution-chain-event] host emitted no agent.promptResolved event; skipping (RFC 0029 emission staged)) (seam, prior step, or fixture unavailable)');
73
75
  }
74
76
 
75
77
  for (const ev of resolved) {
76
78
  const chain = ev.payload?.chain;
77
79
  expect(
78
80
  Array.isArray(chain) && chain.length > 0,
79
- driver.describe('prompts.md §Resolution chain', 'agent.promptResolved MUST carry a non-empty chain[] of attempted layers'),
81
+ req('openwop.it.prompt-resolution-chain-event.the-production-agent-promptresolved-event-records-the-full-four-layer-resolution', 'prompts.md §Resolution chain', 'agent.promptResolved MUST carry a non-empty chain[] of attempted layers'),
80
82
  ).toBe(true);
81
83
  const entries = chain as ChainEntry[];
82
84
 
@@ -84,28 +86,28 @@ describe('prompt-resolution-chain-event (black-box): agent.promptResolved carrie
84
86
  for (const e of entries) {
85
87
  expect(
86
88
  typeof e.layer === 'string' && VALID_LAYERS.has(e.layer),
87
- driver.describe('prompts.md §Resolution chain', `each chain entry MUST name a valid layer, got ${String(e.layer)}`),
89
+ req('openwop.it.prompt-resolution-chain-event.the-production-agent-promptresolved-event-records-the-full-four-layer-resolution', 'prompts.md §Resolution chain', `each chain entry MUST name a valid layer, got ${String(e.layer)}`),
88
90
  ).toBe(true);
89
- expect(typeof e.applied, driver.describe('prompts.md §Resolution chain', 'each chain entry MUST carry a boolean `applied`')).toBe('boolean');
91
+ expect(typeof e.applied, req('openwop.it.prompt-resolution-chain-event.the-production-agent-promptresolved-event-records-the-full-four-layer-resolution', 'prompts.md §Resolution chain', 'each chain entry MUST carry a boolean `applied`')).toBe('boolean');
90
92
  }
91
93
 
92
94
  // Exactly one layer wins (or none, when resolved is null).
93
95
  const applied = entries.filter((e) => e.applied === true);
94
96
  expect(
95
97
  applied.length <= 1,
96
- driver.describe('prompts.md §Resolution chain', 'AT MOST one chain entry MAY be applied: true (the winning layer)'),
98
+ req('openwop.it.prompt-resolution-chain-event.the-production-agent-promptresolved-event-records-the-full-four-layer-resolution', 'prompts.md §Resolution chain', 'AT MOST one chain entry MAY be applied: true (the winning layer)'),
97
99
  ).toBe(true);
98
100
 
99
101
  // resolved mirrors the applied entry's source (RFC 0029 §B).
100
102
  if (applied.length === 1) {
101
103
  expect(
102
104
  ev.payload?.resolved,
103
- driver.describe('run-event-payloads.schema.json agentPromptResolved', '`resolved` MUST mirror the applied chain entry\'s `source`'),
105
+ req('openwop.it.prompt-resolution-chain-event.the-production-agent-promptresolved-event-records-the-full-four-layer-resolution', 'run-event-payloads.schema.json agentPromptResolved', '`resolved` MUST mirror the applied chain entry\'s `source`'),
104
106
  ).toBe(applied[0]?.source);
105
107
  } else {
106
108
  expect(
107
109
  ev.payload?.resolved === null || ev.payload?.resolved === undefined,
108
- driver.describe('run-event-payloads.schema.json agentPromptResolved', 'with no applied layer, `resolved` MUST be null'),
110
+ req('openwop.it.prompt-resolution-chain-event.the-production-agent-promptresolved-event-records-the-full-four-layer-resolution', 'run-event-payloads.schema.json agentPromptResolved', 'with no applied layer, `resolved` MUST be null'),
109
111
  ).toBe(true);
110
112
  }
111
113
  }
@@ -32,6 +32,8 @@ import { describe, it, expect } from 'vitest';
32
32
  import { driver } from '../lib/driver.js';
33
33
  import { behaviorGate } from '../lib/behavior-gate.js';
34
34
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
35
+ import { req } from '../lib/requirement-ids.js';
36
+ import { softSkip } from '../lib/soft-skip.js';
35
37
 
36
38
  interface DiscoveryDoc {
37
39
  capabilities?: {
@@ -88,7 +90,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-fallback-cascade: layers 3 +
88
90
  system: 'prompt:host-default@1.0.0',
89
91
  },
90
92
  });
91
- if (res.status === 404) return;
93
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
92
94
  expect(res.status).toBe(200);
93
95
 
94
96
  const payload = res.json as AgentPromptResolvedPayload;
@@ -96,7 +98,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-fallback-cascade: layers 3 +
96
98
  expect(applied?.layer).toBe('workflow-defaults');
97
99
  expect(
98
100
  payload.resolved,
99
- driver.describe(
101
+ req('openwop.it.prompt-resolution-chain-fallback-cascade.workflow-defaults-win-over-host-defaults-when-both-are-set',
100
102
  'spec/v1/prompts.md §Resolution chain (normative) — Layer 3',
101
103
  'workflow-defaults MUST win over host-defaults when both are set',
102
104
  ),
@@ -115,14 +117,14 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-fallback-cascade: layers 3 +
115
117
  system: 'prompt:host-default@1.0.0',
116
118
  },
117
119
  });
118
- if (res.status === 404) return;
120
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
119
121
  expect(res.status).toBe(200);
120
122
 
121
123
  const payload = res.json as AgentPromptResolvedPayload;
122
124
  const applied = payload.chain.find((c) => c.applied);
123
125
  expect(
124
126
  applied?.layer,
125
- driver.describe(
127
+ req('openwop.it.prompt-resolution-chain-fallback-cascade.host-defaults-win-when-workflow-defaults-are-also-absent',
126
128
  'spec/v1/prompts.md §Resolution chain (normative) — Layer 4',
127
129
  'host-defaults MUST apply when layers 1-3 yield null',
128
130
  ),
@@ -139,13 +141,13 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-fallback-cascade: layers 3 +
139
141
  node: { nodeId: 'writer', config: {} },
140
142
  // workflowDefaults + hostDefaults intentionally omitted.
141
143
  });
142
- if (res.status === 404) return;
144
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (seam, prior step, or fixture unavailable)');
143
145
  expect(res.status).toBe(200);
144
146
 
145
147
  const payload = res.json as AgentPromptResolvedPayload;
146
148
  expect(
147
149
  payload.resolved,
148
- driver.describe(
150
+ req('openwop.it.prompt-resolution-chain-fallback-cascade.resolved-is-null-and-chain-still-lists-every-attempted-layer-when-all-four-yield',
149
151
  'spec/v1/prompts.md §Resolution chain (normative)',
150
152
  'resolved MUST be null when all four layers yield null',
151
153
  ),
@@ -154,7 +156,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-fallback-cascade: layers 3 +
154
156
  const appliedEntries = payload.chain.filter((c) => c.applied);
155
157
  expect(
156
158
  appliedEntries.length,
157
- driver.describe(
159
+ req('openwop.it.prompt-resolution-chain-fallback-cascade.resolved-is-null-and-chain-still-lists-every-attempted-layer-when-all-four-yield',
158
160
  'spec/v1/prompts.md §Resolution chain (normative)',
159
161
  'zero applied entries when no layer yielded a candidate',
160
162
  ),
@@ -164,7 +166,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-fallback-cascade: layers 3 +
164
166
  // see why the resolution returned null.
165
167
  expect(
166
168
  payload.chain.length,
167
- driver.describe(
169
+ req('openwop.it.prompt-resolution-chain-fallback-cascade.resolved-is-null-and-chain-still-lists-every-attempted-layer-when-all-four-yield',
168
170
  'spec/v1/prompts.md §Resolution chain (normative)',
169
171
  'chain[] MUST list every layer attempted, even when none applied',
170
172
  ),
@@ -30,6 +30,8 @@ import { describe, it, expect } from 'vitest';
30
30
  import { driver } from '../lib/driver.js';
31
31
  import { behaviorGate } from '../lib/behavior-gate.js';
32
32
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
33
+ import { req } from '../lib/requirement-ids.js';
34
+ import { softSkip } from '../lib/soft-skip.js';
33
35
 
34
36
  interface DiscoveryDoc {
35
37
  capabilities?: {
@@ -104,14 +106,14 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-node-wins: layer-1 node-conf
104
106
  system: 'prompt:host-default@1.0.0',
105
107
  },
106
108
  });
107
- if (res.status === 404) return; // host doesn't expose the seam
108
- expect(res.status, 'resolve seam MUST return 200').toBe(200);
109
+ 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
110
+ expect(res.status, req('openwop.it.prompt-resolution-chain-node-wins.node-level-systempromptref-wins-over-agent-intrinsic-workflow-defaults-host-defa', 'spec/v1/prompts.md §Resolution chain (normative)', 'resolve seam MUST return 200')).toBe(200);
109
111
 
110
112
  const payload = res.json as AgentPromptResolvedPayload;
111
113
 
112
114
  expect(
113
115
  payload.kind,
114
- driver.describe(
116
+ req('openwop.it.prompt-resolution-chain-node-wins.node-level-systempromptref-wins-over-agent-intrinsic-workflow-defaults-host-defa',
115
117
  'spec/v1/prompts.md §Resolution chain (normative)',
116
118
  'agent.promptResolved.kind MUST match the requested kind',
117
119
  ),
@@ -119,7 +121,7 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-node-wins: layer-1 node-conf
119
121
 
120
122
  expect(
121
123
  payload.resolved,
122
- driver.describe(
124
+ req('openwop.it.prompt-resolution-chain-node-wins.node-level-systempromptref-wins-over-agent-intrinsic-workflow-defaults-host-defa',
123
125
  'spec/v1/prompts.md §Resolution chain (normative) — Layer 1',
124
126
  'node-level systemPromptRef MUST win over agent intrinsic + overrides + workflow defaults + host defaults',
125
127
  ),
@@ -128,13 +130,13 @@ describe.skipIf(HTTP_SKIP)('prompt-resolution-chain-node-wins: layer-1 node-conf
128
130
  // chain[] MUST list the layers attempted in precedence order. The
129
131
  // node layer (first entry of the resolution chain) MUST carry
130
132
  // applied: true; every other layer applied: false.
131
- expect(Array.isArray(payload.chain), 'agent.promptResolved.chain MUST be an array').toBe(true);
133
+ expect(Array.isArray(payload.chain), req('openwop.it.prompt-resolution-chain-node-wins.node-level-systempromptref-wins-over-agent-intrinsic-workflow-defaults-host-defa', 'spec/v1/prompts.md §Resolution chain (normative) — Layer 1', 'agent.promptResolved.chain MUST be an array')).toBe(true);
132
134
  expect(payload.chain.length).toBeGreaterThan(0);
133
135
 
134
136
  const appliedEntries = payload.chain.filter((c) => c.applied);
135
137
  expect(
136
138
  appliedEntries.length,
137
- driver.describe(
139
+ req('openwop.it.prompt-resolution-chain-node-wins.node-level-systempromptref-wins-over-agent-intrinsic-workflow-defaults-host-defa',
138
140
  'spec/v1/prompts.md §Resolution chain (normative)',
139
141
  'exactly one chain entry MUST carry applied: true',
140
142
  ),