@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
@@ -37,6 +37,8 @@ import { SCHEMAS_DIR } from '../lib/paths.js';
37
37
  import { driver } from '../lib/driver.js';
38
38
  import { behaviorGate } from '../lib/behavior-gate.js';
39
39
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
40
+ import { req } from '../lib/requirement-ids.js';
41
+ import { softSkip } from '../lib/soft-skip.js';
40
42
 
41
43
  const DISPATCH_CONFIG = join(SCHEMAS_DIR, 'dispatch-config.schema.json');
42
44
  const EVENT_PAYLOADS = join(SCHEMAS_DIR, 'run-event-payloads.schema.json');
@@ -58,7 +60,7 @@ describe('dispatch-fanout: DispatchConfig schema (always-on, server-free)', () =
58
60
  maxConcurrency: 5,
59
61
  joinPolicy: { mode: 'wait-all', onChildFailure: 'collect' },
60
62
  };
61
- expect(validate(cfg), `node-packs.md §parallel fan-out — a valid parallel config MUST validate. Errors: ${JSON.stringify(validate.errors)}`).toBe(true);
63
+ expect(validate(cfg), req('openwop.it.dispatch-fanout-parallel.accepts-fanoutpolicy-parallel-with-a-wait-all-collect-joinpolicy-maxconcurrency', 'node-packs.md', `node-packs.md §parallel fan-out — a valid parallel config MUST validate. Errors: ${JSON.stringify(validate.errors)}`)).toBe(true);
62
64
  });
63
65
 
64
66
  it('accepts each joinPolicy.mode (wait-all/quorum/first/race)', () => {
@@ -68,26 +70,26 @@ describe('dispatch-fanout: DispatchConfig schema (always-on, server-free)', () =
68
70
  { mode: 'first' },
69
71
  { mode: 'race' },
70
72
  ]) {
71
- expect(validate({ fanOutPolicy: 'parallel', joinPolicy: jp }), `joinPolicy ${JSON.stringify(jp)} MUST validate`).toBe(true);
73
+ expect(validate({ fanOutPolicy: 'parallel', joinPolicy: jp }), req('openwop.it.dispatch-fanout-parallel.accepts-each-joinpolicy-mode-wait-all-quorum-first-race', 'node-packs.md', `joinPolicy ${JSON.stringify(jp)} MUST validate`)).toBe(true);
72
74
  }
73
75
  });
74
76
 
75
77
  it('rejects an unknown fanOutPolicy and an unknown joinPolicy.mode', () => {
76
- expect(validate({ fanOutPolicy: 'broadcast' }), "fanOutPolicy MUST be one of sequential/reject/parallel").toBe(false);
77
- expect(validate({ fanOutPolicy: 'parallel', joinPolicy: { mode: 'any' } }), 'joinPolicy.mode MUST be in the closed enum').toBe(false);
78
+ expect(validate({ fanOutPolicy: 'broadcast' }), req('openwop.it.dispatch-fanout-parallel.rejects-an-unknown-fanoutpolicy-and-an-unknown-joinpolicy-mode', 'node-packs.md', "fanOutPolicy MUST be one of sequential/reject/parallel")).toBe(false);
79
+ expect(validate({ fanOutPolicy: 'parallel', joinPolicy: { mode: 'any' } }), req('openwop.it.dispatch-fanout-parallel.rejects-an-unknown-fanoutpolicy-and-an-unknown-joinpolicy-mode', 'node-packs.md', 'joinPolicy.mode MUST be in the closed enum')).toBe(false);
78
80
  });
79
81
 
80
82
  it('rejects an unknown onChildFailure and additionalProperties on joinPolicy', () => {
81
- expect(validate({ fanOutPolicy: 'parallel', joinPolicy: { onChildFailure: 'explode' } }), 'onChildFailure MUST be collect/fail-fast/absorb').toBe(false);
82
- expect(validate({ fanOutPolicy: 'parallel', joinPolicy: { mode: 'wait-all', extra: 1 } }), 'joinPolicy is additionalProperties:false').toBe(false);
83
+ expect(validate({ fanOutPolicy: 'parallel', joinPolicy: { onChildFailure: 'explode' } }), req('openwop.it.dispatch-fanout-parallel.rejects-an-unknown-onchildfailure-and-additionalproperties-on-joinpolicy', 'node-packs.md', 'onChildFailure MUST be collect/fail-fast/absorb')).toBe(false);
84
+ expect(validate({ fanOutPolicy: 'parallel', joinPolicy: { mode: 'wait-all', extra: 1 } }), req('openwop.it.dispatch-fanout-parallel.rejects-an-unknown-onchildfailure-and-additionalproperties-on-joinpolicy', 'node-packs.md', 'joinPolicy is additionalProperties:false')).toBe(false);
83
85
  });
84
86
 
85
87
  it('rejects a non-positive maxConcurrency', () => {
86
- expect(validate({ fanOutPolicy: 'parallel', maxConcurrency: 0 }), 'maxConcurrency minimum is 1').toBe(false);
88
+ expect(validate({ fanOutPolicy: 'parallel', maxConcurrency: 0 }), req('openwop.it.dispatch-fanout-parallel.rejects-a-non-positive-maxconcurrency', 'node-packs.md', 'maxConcurrency minimum is 1')).toBe(false);
87
89
  });
88
90
 
89
91
  it('the default config (no fanOutPolicy) stays valid — additive, default sequential', () => {
90
- expect(validate({ workerDispatchModel: 'child-run' }), 'a pre-RFC-0118 config MUST stay valid').toBe(true);
92
+ expect(validate({ workerDispatchModel: 'child-run' }), req('openwop.it.dispatch-fanout-parallel.the-default-config-no-fanoutpolicy-stays-valid-additive-default-sequential', 'node-packs.md', 'a pre-RFC-0118 config MUST stay valid')).toBe(true);
91
93
  });
92
94
  });
93
95
 
@@ -99,8 +101,8 @@ describe('dispatch-fanout: event $defs (always-on, server-free)', () => {
99
101
 
100
102
  it('a well-formed core.dispatch.fanOut payload validates; fanOutPolicy is const "parallel"', () => {
101
103
  expect(validateFanOut({ fanOutPolicy: 'parallel', childCount: 5, maxConcurrency: 5, joinMode: 'wait-all' })).toBe(true);
102
- expect(validateFanOut({ fanOutPolicy: 'sequential', childCount: 5 }), 'fanOut is emitted only on the parallel path (const)').toBe(false);
103
- expect(validateFanOut({ fanOutPolicy: 'parallel', childCount: 1 }), 'childCount minimum is 2 (> 1 by construction)').toBe(false);
104
+ expect(validateFanOut({ fanOutPolicy: 'sequential', childCount: 5 }), req('openwop.it.dispatch-fanout-parallel.a-well-formed-core-dispatch-fanout-payload-validates-fanoutpolicy-is-const-paral', 'node-packs.md', 'fanOut is emitted only on the parallel path (const)')).toBe(false);
105
+ expect(validateFanOut({ fanOutPolicy: 'parallel', childCount: 1 }), req('openwop.it.dispatch-fanout-parallel.a-well-formed-core-dispatch-fanout-payload-validates-fanoutpolicy-is-const-paral', 'node-packs.md', 'childCount minimum is 2 (> 1 by construction)')).toBe(false);
104
106
  });
105
107
 
106
108
  it('a well-formed core.dispatch.join payload carries mergeOrder (replay tiebreak)', () => {
@@ -111,9 +113,9 @@ describe('dispatch-fanout: event $defs (always-on, server-free)', () => {
111
113
  cancelledCount: 0,
112
114
  mergeOrder: ['run-a', 'run-b', 'run-c'],
113
115
  };
114
- expect(validateJoin(ok), `node-packs.md §parallel — join carries mergeOrder. Errors: ${JSON.stringify(validateJoin.errors)}`).toBe(true);
115
- expect(validateJoin({ joinOutcome: 'satisfied', completedCount: 3, failedCount: 0 }), 'mergeOrder is required (replay determinism)').toBe(false);
116
- expect(validateJoin({ ...ok, joinOutcome: 'aborted' }), 'joinOutcome MUST be satisfied/failed/partial').toBe(false);
116
+ expect(validateJoin(ok), req('openwop.it.dispatch-fanout-parallel.a-well-formed-core-dispatch-join-payload-carries-mergeorder-replay-tiebreak', 'node-packs.md', `node-packs.md §parallel — join carries mergeOrder. Errors: ${JSON.stringify(validateJoin.errors)}`)).toBe(true);
117
+ expect(validateJoin({ joinOutcome: 'satisfied', completedCount: 3, failedCount: 0 }), req('openwop.it.dispatch-fanout-parallel.a-well-formed-core-dispatch-join-payload-carries-mergeorder-replay-tiebreak', 'node-packs.md', 'mergeOrder is required (replay determinism)')).toBe(false);
118
+ expect(validateJoin({ ...ok, joinOutcome: 'aborted' }), req('openwop.it.dispatch-fanout-parallel.a-well-formed-core-dispatch-join-payload-carries-mergeorder-replay-tiebreak', 'node-packs.md', 'joinOutcome MUST be satisfied/failed/partial')).toBe(false);
117
119
  });
118
120
  });
119
121
 
@@ -121,43 +123,43 @@ describe('dispatch-fanout: parallel behavior (capability-gated, RFC 0118)', () =
121
123
  it('a wait-all/collect parallel fan-out joins on all children with joinOutcome satisfied', async () => {
122
124
  const dispatch = await readCapabilityFamily<{ fanOutSupported?: boolean; fanOutPolicies?: string[] }>('dispatch');
123
125
  if (!behaviorGate('dispatch.fanOutSupported', dispatch?.fanOutSupported === true)) return;
124
- if (!(dispatch?.fanOutPolicies ?? []).includes('parallel')) return; // parallel unsupported → out of scope
126
+ if (!(dispatch?.fanOutPolicies ?? []).includes('parallel')) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(dispatch?.fanOutPolicies ?? []).includes(\'parallel\')` returned early (parallel unsupported → out of scope)'); // parallel unsupported → out of scope
125
127
 
126
128
  const res = await driver.post('/v1/host/sample/dispatch/fanout', {
127
129
  nextWorkerIds: ['conformance.child.a', 'conformance.child.b', 'conformance.child.c'],
128
130
  config: { fanOutPolicy: 'parallel', joinPolicy: { mode: 'wait-all', onChildFailure: 'collect' } },
129
131
  });
130
- if (res.status === 404 || res.status === 403) return; // seam unwired — soft-skip
132
+ if (res.status === 404 || res.status === 403) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 403` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
131
133
 
132
134
  const body = res.json as { joinOutcome?: string; children?: unknown[]; mergeOrder?: string[] } | undefined;
133
135
  expect(
134
136
  body?.joinOutcome,
135
- driver.describe('node-packs.md §parallel fan-out', 'wait-all + collect over all-completing children → joinOutcome satisfied'),
137
+ req('openwop.it.dispatch-fanout-parallel.a-wait-all-collect-parallel-fan-out-joins-on-all-children-with-joinoutcome-satis', 'node-packs.md §parallel fan-out', 'wait-all + collect over all-completing children → joinOutcome satisfied'),
136
138
  ).toBe('satisfied');
137
139
  expect(
138
140
  body?.children?.length,
139
- driver.describe('node-packs.md §parallel fan-out', 'the output children[] reports every dispatched child'),
141
+ req('openwop.it.dispatch-fanout-parallel.a-wait-all-collect-parallel-fan-out-joins-on-all-children-with-joinoutcome-satis', 'node-packs.md §parallel fan-out', 'the output children[] reports every dispatched child'),
140
142
  ).toBe(3);
141
143
  expect(
142
144
  Array.isArray(body?.mergeOrder),
143
- driver.describe('node-packs.md §parallel fan-out', 'the join records mergeOrder for replay-deterministic output merge'),
145
+ req('openwop.it.dispatch-fanout-parallel.a-wait-all-collect-parallel-fan-out-joins-on-all-children-with-joinoutcome-satis', 'node-packs.md §parallel fan-out', 'the join records mergeOrder for replay-deterministic output merge'),
144
146
  ).toBe(true);
145
147
  });
146
148
 
147
149
  it('parallel fan-out is rejected at registration on a host advertising fanOutSupported:false', async () => {
148
150
  const dispatch = await readCapabilityFamily<{ supported?: boolean; fanOutSupported?: boolean }>('dispatch');
149
- if (!dispatch?.supported) return; // no dispatch surface → out of scope
150
- if (dispatch.fanOutSupported === true) return; // this leg targets non-supporting hosts
151
+ if (!dispatch?.supported) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!dispatch?.supported` returned early (no dispatch surface → out of scope)'); // no dispatch surface → out of scope
152
+ if (dispatch.fanOutSupported === true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `dispatch.fanOutSupported === true` returned early (this leg targets non-supporting hosts)'); // this leg targets non-supporting hosts
151
153
 
152
154
  const res = await driver.post('/v1/workflows', {
153
155
  id: 'conformance.dispatch.parallel-unsupported',
154
156
  nodes: [{ nodeId: 'd', typeId: 'core.dispatch', config: { fanOutPolicy: 'parallel', joinPolicy: { mode: 'wait-all' } } }],
155
157
  });
156
- if (res.status === 404) return; // registration surface not exposed here — soft-skip
158
+ if (res.status === 404) return softSkip('blocked', 'precondition not met — `res.status === 404` returned early (registration surface not exposed here — soft-skip) (seam, prior step, or fixture unavailable)'); // registration surface not exposed here — soft-skip
157
159
 
158
160
  expect(
159
161
  res.status >= 400 && res.status < 500,
160
- driver.describe('node-packs.md §parallel fan-out', "a host advertising fanOutSupported:false MUST reject fanOutPolicy:'parallel' with a validation_error (4xx), never accept it"),
162
+ req('openwop.it.dispatch-fanout-parallel.parallel-fan-out-is-rejected-at-registration-on-a-host-advertising-fanoutsupport', 'node-packs.md §parallel fan-out', "a host advertising fanOutSupported:false MUST reject fanOutPolicy:'parallel' with a validation_error (4xx), never accept it"),
161
163
  ).toBe(true);
162
164
  });
163
165
  });
@@ -25,6 +25,8 @@ import { driver } from '../lib/driver.js';
25
25
  import { pollUntilTerminal } from '../lib/polling.js';
26
26
  import { isFixtureAdvertised } from '../lib/fixtures.js';
27
27
  import { setHostCapability, resetHostCapabilities, isToggleAvailable } from '../lib/host-toggle.js';
28
+ import { req } from '../lib/requirement-ids.js';
29
+ import { softSkip } from '../lib/soft-skip.js';
28
30
 
29
31
  const PARENT = 'conformance-dispatch-input-mapping';
30
32
  const CHILD = 'conformance-dispatch-input-mapping-child';
@@ -49,7 +51,7 @@ describe.skipIf(SKIP)('dispatch-input-mapping: parent → child variable project
49
51
  const parentRunId = (create.json as { runId: string }).runId;
50
52
 
51
53
  const parentTerminal = (await pollUntilTerminal(parentRunId)) as RunSnapshot;
52
- expect(parentTerminal.status, driver.describe(
54
+ expect(parentTerminal.status, req('openwop.it.dispatch-input-mapping.hvmap-1a-inputmapping-projects-parent-variables-into-child-inputs',
53
55
  'RFCS/0022-dispatch-input-output-mapping.md §A',
54
56
  'parent run MUST reach terminal `completed` once the dispatch loop terminates',
55
57
  )).toBe('completed');
@@ -61,7 +63,7 @@ describe.skipIf(SKIP)('dispatch-input-mapping: parent → child variable project
61
63
  const dispatched = events.find(
62
64
  (e) => e.type === 'node.dispatched' && e.payload?.childWorkflowId === CHILD,
63
65
  );
64
- expect(dispatched, driver.describe(
66
+ expect(dispatched, req('openwop.it.dispatch-input-mapping.hvmap-1a-inputmapping-projects-parent-variables-into-child-inputs',
65
67
  'RFCS/0007-dispatch.md §D',
66
68
  'parent event log MUST contain a `node.dispatched` event naming the child workflow',
67
69
  )).toBeDefined();
@@ -74,12 +76,12 @@ describe.skipIf(SKIP)('dispatch-input-mapping: parent → child variable project
74
76
  const childSnapshotRes = await driver.get(`/v1/runs/${encodeURIComponent(childRunId!)}`);
75
77
  expect(childSnapshotRes.status).toBe(200);
76
78
  const childSnapshot = childSnapshotRes.json as RunSnapshot;
77
- expect(childSnapshot.status, driver.describe(
79
+ expect(childSnapshot.status, req('openwop.it.dispatch-input-mapping.hvmap-1a-inputmapping-projects-parent-variables-into-child-inputs',
78
80
  'RFCS/0007-dispatch.md',
79
81
  'child run MUST reach terminal `completed`',
80
82
  )).toBe('completed');
81
83
  const childInputs = childSnapshot.inputs ?? {};
82
- expect(childInputs.childGreeting, driver.describe(
84
+ expect(childInputs.childGreeting, req('openwop.it.dispatch-input-mapping.hvmap-1a-inputmapping-projects-parent-variables-into-child-inputs',
83
85
  'RFCS/0022-dispatch-input-output-mapping.md §A',
84
86
  'child `inputs.childGreeting` MUST be parent\'s `parentName` projection ("Alice") per inputMapping',
85
87
  )).toBe('Alice');
@@ -87,7 +89,7 @@ describe.skipIf(SKIP)('dispatch-input-mapping: parent → child variable project
87
89
 
88
90
  it('HVMAP-1a-null: parent variable unset → child input surfaces as `undefined` per §A', async () => {
89
91
  const PARENT_NO_DEFAULT = 'conformance-dispatch-input-mapping-no-default';
90
- if (!isFixtureAdvertised(PARENT_NO_DEFAULT) || !isFixtureAdvertised(CHILD)) return; // fixture not seeded — soft-skip
92
+ if (!isFixtureAdvertised(PARENT_NO_DEFAULT) || !isFixtureAdvertised(CHILD)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(PARENT_NO_DEFAULT) || !isFixtureAdvertised(CHILD)` returned early (fixture not seeded — soft-skip)'); // fixture not seeded — soft-skip
91
93
  const create = await driver.post('/v1/runs', { workflowId: PARENT_NO_DEFAULT });
92
94
  expect(create.status).toBe(201);
93
95
  const parentRunId = (create.json as { runId: string }).runId;
@@ -98,7 +100,7 @@ describe.skipIf(SKIP)('dispatch-input-mapping: parent → child variable project
98
100
  const dispatched = events.find(
99
101
  (e) => e.type === 'node.dispatched' && e.payload?.childWorkflowId === CHILD,
100
102
  );
101
- if (!dispatched) return; // host doesn't emit node.dispatched — soft-skip
103
+ if (!dispatched) return softSkip('blocked', 'precondition not met — `!dispatched` returned early (host doesn\'t emit node.dispatched — soft-skip) (seam, prior step, or fixture unavailable)'); // host doesn't emit node.dispatched — soft-skip
102
104
  const childRunId = dispatched.payload?.childRunId;
103
105
 
104
106
  const childRes = await driver.get(`/v1/runs/${encodeURIComponent(childRunId!)}`);
@@ -111,7 +113,7 @@ describe.skipIf(SKIP)('dispatch-input-mapping: parent → child variable project
111
113
  const v = inputs.childGreeting;
112
114
  expect(
113
115
  v === undefined || !('childGreeting' in inputs),
114
- driver.describe(
116
+ req('openwop.it.dispatch-input-mapping.hvmap-1a-null-parent-variable-unset-child-input-surfaces-as-undefined-per-a',
115
117
  'RFCS/0022-dispatch-input-output-mapping.md §A',
116
118
  'unset parent variable projection MUST surface as undefined (NOT null, NOT a default placeholder)',
117
119
  ),
@@ -123,7 +125,7 @@ describe.skipIf(SKIP)('dispatch-input-mapping: parent → child variable project
123
125
 
124
126
  describe('dispatch-input-mapping: registration refusal (RFC 0022 §C HVMAP-1a-refusal)', () => {
125
127
  it('host with agents.dispatchMapping toggled OFF MUST refuse non-empty inputMapping at registration', async () => {
126
- if (!(await isToggleAvailable())) return; // seam not exposed — soft-skip
128
+ if (!(await isToggleAvailable())) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!(await isToggleAvailable())` returned early (seam not exposed — soft-skip)'); // seam not exposed — soft-skip
127
129
  await setHostCapability('agents.dispatchMapping', false);
128
130
  try {
129
131
  const workflow = {
@@ -142,7 +144,7 @@ describe('dispatch-input-mapping: registration refusal (RFC 0022 §C HVMAP-1a-re
142
144
  const res = await driver.post('/v1/host/sample/workflows', workflow);
143
145
  expect(
144
146
  res.status,
145
- driver.describe(
147
+ req('openwop.it.dispatch-input-mapping.host-with-agents-dispatchmapping-toggled-off-must-refuse-non-empty-inputmapping',
146
148
  'RFCS/0022-dispatch-input-output-mapping.md §C',
147
149
  'workflow with non-empty inputMapping MUST be refused when capabilities.agents.dispatchMapping is not advertised',
148
150
  ),
@@ -151,7 +153,7 @@ describe('dispatch-input-mapping: registration refusal (RFC 0022 §C HVMAP-1a-re
151
153
  expect(body.error).toBe('validation_error');
152
154
  expect(
153
155
  body.details?.requiredCapability,
154
- driver.describe(
156
+ req('openwop.it.dispatch-input-mapping.host-with-agents-dispatchmapping-toggled-off-must-refuse-non-empty-inputmapping',
155
157
  'RFCS/0022-dispatch-input-output-mapping.md §C',
156
158
  'refusal MUST surface requiredCapability: "agents.dispatchMapping"',
157
159
  ),
@@ -22,6 +22,8 @@ import { describe, it, expect } from 'vitest';
22
22
  import { driver } from '../lib/driver.js';
23
23
  import { pollUntilTerminal } from '../lib/polling.js';
24
24
  import { isFixtureAdvertised } from '../lib/fixtures.js';
25
+ import { req } from '../lib/requirement-ids.js';
26
+ import { softSkip } from '../lib/soft-skip.js';
25
27
 
26
28
  const PARENT = 'conformance-dispatch-output-mapping';
27
29
  const CHILD = 'conformance-dispatch-output-mapping-child';
@@ -39,7 +41,7 @@ describe.skipIf(SKIP)('dispatch-output-mapping: child → parent variable harves
39
41
  const parentRunId = (create.json as { runId: string }).runId;
40
42
 
41
43
  const parentTerminal = (await pollUntilTerminal(parentRunId)) as RunSnapshot;
42
- expect(parentTerminal.status, driver.describe(
44
+ expect(parentTerminal.status, req('openwop.it.dispatch-output-mapping.hvmap-1b-outputmapping-harvests-child-variables-into-parent-variables-on-termina',
43
45
  'RFCS/0022-dispatch-input-output-mapping.md §A',
44
46
  'parent run MUST reach terminal `completed` once the dispatch loop terminates',
45
47
  )).toBe('completed');
@@ -49,7 +51,7 @@ describe.skipIf(SKIP)('dispatch-output-mapping: child → parent variable harves
49
51
  // Child declares childOutcome.defaultValue='done' so the value is
50
52
  // present in the child's variables_json at terminal time.
51
53
  const parentVars = parentTerminal.variables ?? {};
52
- expect(parentVars.parentResult, driver.describe(
54
+ expect(parentVars.parentResult, req('openwop.it.dispatch-output-mapping.hvmap-1b-outputmapping-harvests-child-variables-into-parent-variables-on-termina',
53
55
  'RFCS/0022-dispatch-input-output-mapping.md §A',
54
56
  'parent `parentResult` MUST be child\'s `childOutcome` projection ("done") per outputMapping',
55
57
  )).toBe('done');
@@ -99,7 +101,7 @@ async function registerParent(childFixtureId: string): Promise<string | null> {
99
101
  describe.skipIf(!isFixtureAdvertised('conformance-dispatch-deterministic-fail-child'))('dispatch-output-mapping: HVMAP-1b-failed (RFC 0022 §B)', () => {
100
102
  it('child terminates `failed` → outputMapping MUST be skipped; parent.parentResult stays at sentinel', async () => {
101
103
  const parentId = await registerParent('conformance-dispatch-deterministic-fail-child');
102
- if (!parentId) return; // workflow-register seam not exposed — soft-skip
104
+ if (!parentId) return softSkip('blocked', 'precondition not met — `!parentId` returned early (workflow-register seam not exposed — soft-skip) (seam, prior step, or fixture unavailable)'); // workflow-register seam not exposed — soft-skip
103
105
  const create = await driver.post('/v1/runs', { workflowId: parentId });
104
106
  expect(create.status).toBe(201);
105
107
  const parentRunId = (create.json as { runId: string }).runId;
@@ -109,7 +111,7 @@ describe.skipIf(!isFixtureAdvertised('conformance-dispatch-deterministic-fail-ch
109
111
  const parentVars = terminal.variables ?? {};
110
112
  expect(
111
113
  parentVars.parentResult,
112
- driver.describe(
114
+ req('openwop.it.dispatch-output-mapping.child-terminates-failed-outputmapping-must-be-skipped-parent-parentresult-stays',
113
115
  'RFCS/0022-dispatch-input-output-mapping.md §B',
114
116
  'outputMapping MUST be SKIPPED when child terminates failed; parent variable MUST NOT be overwritten',
115
117
  ),
@@ -120,7 +122,7 @@ describe.skipIf(!isFixtureAdvertised('conformance-dispatch-deterministic-fail-ch
120
122
  describe.skipIf(!isFixtureAdvertised('conformance-dispatch-cancellable-child'))('dispatch-output-mapping: HVMAP-1b-cancelled (RFC 0022 §B)', () => {
121
123
  it('child terminates `cancelled` → outputMapping MUST be skipped; parent.parentResult stays at sentinel', async () => {
122
124
  const parentId = await registerParent('conformance-dispatch-cancellable-child');
123
- if (!parentId) return; // soft-skip
125
+ if (!parentId) return softSkip('blocked', 'precondition not met — `!parentId` returned early (soft-skip) (seam, prior step, or fixture unavailable)'); // soft-skip
124
126
  const create = await driver.post('/v1/runs', { workflowId: parentId });
125
127
  expect(create.status).toBe(201);
126
128
  const parentRunId = (create.json as { runId: string }).runId;
@@ -138,7 +140,7 @@ describe.skipIf(!isFixtureAdvertised('conformance-dispatch-cancellable-child'))(
138
140
  }
139
141
  await new Promise((r) => setTimeout(r, 250));
140
142
  }
141
- if (!childRunId) return; // dispatch didn't surface child run id — soft-skip
143
+ if (!childRunId) return softSkip('blocked', 'precondition not met — `!childRunId` returned early (dispatch didn\'t surface child run id — soft-skip) (seam, prior step, or fixture unavailable)'); // dispatch didn't surface child run id — soft-skip
142
144
  const cancelRes = await driver.post(`/v1/runs/${encodeURIComponent(childRunId)}/cancel`, { reason: 'hvmap-1b-cancelled test' });
143
145
  expect(cancelRes.status === 200 || cancelRes.status === 202).toBe(true);
144
146
 
@@ -146,7 +148,7 @@ describe.skipIf(!isFixtureAdvertised('conformance-dispatch-cancellable-child'))(
146
148
  const parentVars = terminal.variables ?? {};
147
149
  expect(
148
150
  parentVars.parentResult,
149
- driver.describe(
151
+ req('openwop.it.dispatch-output-mapping.child-terminates-cancelled-outputmapping-must-be-skipped-parent-parentresult-sta',
150
152
  'RFCS/0022-dispatch-input-output-mapping.md §B',
151
153
  'outputMapping MUST be SKIPPED when child terminates cancelled; parent variable MUST NOT be overwritten',
152
154
  ),
@@ -44,6 +44,8 @@ import { SCHEMAS_DIR } from '../lib/paths.js';
44
44
  import { driver } from '../lib/driver.js';
45
45
  import { behaviorGate } from '../lib/behavior-gate.js';
46
46
  import { readCapabilityFamily } from '../lib/discovery-capabilities.js';
47
+ import { req } from '../lib/requirement-ids.js';
48
+ import { softSkip } from '../lib/soft-skip.js';
47
49
 
48
50
  const DECISION = join(SCHEMAS_DIR, 'orchestrator-decision.schema.json');
49
51
 
@@ -60,39 +62,39 @@ describe('dispatch-per-item: NextWorkerDecision.nextWorkerInputs schema (always-
60
62
  };
61
63
  expect(
62
64
  validate(decision),
63
- `orchestrator-decision.schema.json §NextWorkerDecision — a well-formed nextWorkerInputs MUST validate. Errors: ${JSON.stringify(validate.errors)}`,
65
+ req('openwop.it.dispatch-per-item-input.accepts-a-next-worker-decision-carrying-a-well-formed-index-aligned-nextworkerin', 'node-packs.md', `orchestrator-decision.schema.json §NextWorkerDecision — a well-formed nextWorkerInputs MUST validate. Errors: ${JSON.stringify(validate.errors)}`),
64
66
  ).toBe(true);
65
67
  });
66
68
 
67
69
  it('still accepts a next-worker decision that omits nextWorkerInputs (additive / back-compat)', () => {
68
70
  expect(
69
71
  validate({ kind: 'next-worker', nextWorkerIds: ['pack.child'] }),
70
- 'a pre-RFC-0126 next-worker decision MUST stay valid — the field is OPTIONAL',
72
+ req('openwop.it.dispatch-per-item-input.still-accepts-a-next-worker-decision-that-omits-nextworkerinputs-additive-back-c', 'node-packs.md', 'a pre-RFC-0126 next-worker decision MUST stay valid — the field is OPTIONAL'),
71
73
  ).toBe(true);
72
74
  });
73
75
 
74
76
  it('rejects a non-object nextWorkerInputs item', () => {
75
77
  expect(
76
78
  validate({ kind: 'next-worker', nextWorkerIds: ['a'], nextWorkerInputs: ['not-an-object'] }),
77
- 'each nextWorkerInputs entry MUST be a per-child input object',
79
+ req('openwop.it.dispatch-per-item-input.rejects-a-non-object-nextworkerinputs-item', 'node-packs.md', 'each nextWorkerInputs entry MUST be a per-child input object'),
78
80
  ).toBe(false);
79
81
  expect(
80
82
  validate({ kind: 'next-worker', nextWorkerIds: ['a'], nextWorkerInputs: 'nope' }),
81
- 'nextWorkerInputs MUST be an array',
83
+ req('openwop.it.dispatch-per-item-input.rejects-a-non-object-nextworkerinputs-item', 'node-packs.md', 'nextWorkerInputs MUST be an array'),
82
84
  ).toBe(false);
83
85
  });
84
86
 
85
87
  it('still rejects an unknown property (additionalProperties:false) — the fail-closed gate', () => {
86
88
  expect(
87
89
  validate({ kind: 'next-worker', nextWorkerIds: ['a'], perItemInputs: [{ x: 1 }] }),
88
- 'NextWorkerDecision is additionalProperties:false — a mis-named field MUST be rejected, so old strict validators fail closed on unknown per-item shapes',
90
+ req('openwop.it.dispatch-per-item-input.still-rejects-an-unknown-property-additionalproperties-false-the-fail-closed-gat', 'node-packs.md', 'NextWorkerDecision is additionalProperties:false — a mis-named field MUST be rejected, so old strict validators fail closed on unknown per-item shapes'),
89
91
  ).toBe(false);
90
92
  });
91
93
 
92
94
  it('ADMITS a length-mismatch — array-length equality is a runtime MUST, not schema-expressible', () => {
93
95
  expect(
94
96
  validate({ kind: 'next-worker', nextWorkerIds: ['a', 'b'], nextWorkerInputs: [{ x: 1 }] }),
95
- 'the wire schema cannot express nextWorkerInputs.length == nextWorkerIds.length; the host enforces it at decision time (layer B)',
97
+ req('openwop.it.dispatch-per-item-input.admits-a-length-mismatch-array-length-equality-is-a-runtime-must-not-schema-expr', 'node-packs.md', 'the wire schema cannot express nextWorkerInputs.length == nextWorkerIds.length; the host enforces it at decision time (layer B)'),
96
98
  ).toBe(true);
97
99
  });
98
100
  });
@@ -106,16 +108,16 @@ describe('dispatch-per-item: per-item input behavior (capability-gated, RFC 0126
106
108
  nextWorkerIds: ['conformance.child', 'conformance.child'],
107
109
  nextWorkerInputs: [{ contactId: 'c-1' }, { contactId: 'c-2' }],
108
110
  });
109
- if (res.status === 404 || res.status === 403) return; // seam unwired — soft-skip
111
+ if (res.status === 404 || res.status === 403) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 403` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
110
112
 
111
113
  const body = res.json as { children?: Array<{ inputs?: Record<string, unknown> }> } | undefined;
112
114
  expect(
113
115
  body?.children?.length,
114
- driver.describe('node-packs.md §core.dispatch per-item input', 'one child dispatched per nextWorkerIds entry'),
116
+ req('openwop.it.dispatch-per-item-input.a-host-advertising-periteminput-projects-nextworkerinputs-i-into-child-i', 'node-packs.md §core.dispatch per-item input', 'one child dispatched per nextWorkerIds entry'),
115
117
  ).toBe(2);
116
118
  expect(
117
119
  body?.children?.map((c) => c.inputs?.contactId),
118
- driver.describe('node-packs.md §core.dispatch per-item input', 'each child receives its own nextWorkerInputs[i] (per-item value wins over inputMapping)'),
120
+ req('openwop.it.dispatch-per-item-input.a-host-advertising-periteminput-projects-nextworkerinputs-i-into-child-i', 'node-packs.md §core.dispatch per-item input', 'each child receives its own nextWorkerInputs[i] (per-item value wins over inputMapping)'),
119
121
  ).toEqual(['c-1', 'c-2']);
120
122
  });
121
123
 
@@ -127,11 +129,11 @@ describe('dispatch-per-item: per-item input behavior (capability-gated, RFC 0126
127
129
  nextWorkerIds: ['conformance.child', 'conformance.child'],
128
130
  nextWorkerInputs: [{ contactId: 'c-1' }],
129
131
  });
130
- if (res.status === 404 || res.status === 403) return; // seam unwired — soft-skip
132
+ if (res.status === 404 || res.status === 403) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 403` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
131
133
 
132
134
  expect(
133
135
  res.status >= 400 && res.status < 500,
134
- driver.describe('node-packs.md §core.dispatch per-item input', 'nextWorkerInputs.length != nextWorkerIds.length MUST fail the dispatch node (4xx validation_error), dispatching no child'),
136
+ req('openwop.it.dispatch-per-item-input.a-length-mismatched-nextworkerinputs-fails-with-a-validation-error-and-dispatche', 'node-packs.md §core.dispatch per-item input', 'nextWorkerInputs.length != nextWorkerIds.length MUST fail the dispatch node (4xx validation_error), dispatching no child'),
135
137
  ).toBe(true);
136
138
  });
137
139
 
@@ -146,16 +148,16 @@ describe('dispatch-per-item: per-item input behavior (capability-gated, RFC 0126
146
148
  inputMapping: { contactId: 'from-mapping', region: 'us' },
147
149
  nextWorkerInputs: [{ contactId: 'c-1' }, { contactId: 'c-2' }],
148
150
  });
149
- if (res.status === 404 || res.status === 403) return; // seam unwired — soft-skip
151
+ if (res.status === 404 || res.status === 403) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 403` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
150
152
 
151
153
  const body = res.json as { children?: Array<{ inputs?: Record<string, unknown> }> } | undefined;
152
154
  expect(
153
155
  body?.children?.map((c) => c.inputs?.contactId),
154
- driver.describe('node-packs.md §core.dispatch per-item input', 'on key collision the per-item value wins over inputMapping (G1)'),
156
+ req('openwop.it.dispatch-per-item-input.nextworkerinputs-i-overrides-the-inputmapping-projection-on-key-collision-g1-pre', 'node-packs.md §core.dispatch per-item input', 'on key collision the per-item value wins over inputMapping (G1)'),
155
157
  ).toEqual(['c-1', 'c-2']);
156
158
  expect(
157
159
  body?.children?.every((c) => c.inputs?.region === 'us'),
158
- driver.describe('node-packs.md §core.dispatch per-item input', 'non-colliding inputMapping keys still project (per-item merges OVER, does not replace)'),
160
+ req('openwop.it.dispatch-per-item-input.nextworkerinputs-i-overrides-the-inputmapping-projection-on-key-collision-g1-pre', 'node-packs.md §core.dispatch per-item input', 'non-colliding inputMapping keys still project (per-item merges OVER, does not replace)'),
159
161
  ).toBe(true);
160
162
  });
161
163
 
@@ -170,29 +172,29 @@ describe('dispatch-per-item: per-item input behavior (capability-gated, RFC 0126
170
172
  nextWorkerInputs: [{ contactId: 'c-1' }, { contactId: 'c-2' }],
171
173
  replay: true,
172
174
  });
173
- if (res.status === 404 || res.status === 403) return; // seam unwired — soft-skip
175
+ if (res.status === 404 || res.status === 403) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 403` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
174
176
 
175
177
  const body = res.json as { children?: Array<{ inputs?: Record<string, unknown> }>; replayed?: boolean } | undefined;
176
178
  expect(
177
179
  body?.children?.map((c) => c.inputs?.contactId),
178
- driver.describe('node-packs.md §core.dispatch per-item input', 'replay/:fork reproduces the recorded per-item children verbatim (frozen at decision time)'),
180
+ req('openwop.it.dispatch-per-item-input.replay-re-reads-the-recorded-nextworkerinputs-verbatim-no-recomputation-r5-repla', 'node-packs.md §core.dispatch per-item input', 'replay/:fork reproduces the recorded per-item children verbatim (frozen at decision time)'),
179
181
  ).toEqual(['c-1', 'c-2']);
180
182
  });
181
183
 
182
184
  it('a host NOT advertising perItemInput MUST fail closed on a non-empty nextWorkerInputs', async () => {
183
185
  const dispatch = await readCapabilityFamily<{ supported?: boolean; perItemInput?: boolean }>('dispatch');
184
- if (!dispatch?.supported) return; // no dispatch surface → out of scope
185
- if (dispatch.perItemInput === true) return; // this leg targets non-supporting hosts
186
+ if (!dispatch?.supported) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!dispatch?.supported` returned early (no dispatch surface → out of scope)'); // no dispatch surface → out of scope
187
+ if (dispatch.perItemInput === true) return softSkip('blocked', 'precondition not met — `dispatch.perItemInput === true` returned early (this leg targets non-supporting hosts) (seam, prior step, or fixture unavailable)'); // this leg targets non-supporting hosts
186
188
 
187
189
  const res = await driver.post('/v1/host/sample/dispatch/per-item', {
188
190
  nextWorkerIds: ['conformance.child', 'conformance.child'],
189
191
  nextWorkerInputs: [{ contactId: 'c-1' }, { contactId: 'c-2' }],
190
192
  });
191
- if (res.status === 404 || res.status === 403) return; // seam unwired — soft-skip
193
+ if (res.status === 404 || res.status === 403) return softSkip('blocked', 'precondition not met — `res.status === 404 || res.status === 403` returned early (seam unwired — soft-skip) (seam, prior step, or fixture unavailable)'); // seam unwired — soft-skip
192
194
 
193
195
  expect(
194
196
  res.status >= 400 && res.status < 500,
195
- driver.describe('node-packs.md §core.dispatch per-item input', 'a host not advertising perItemInput MUST fail closed (4xx) on a non-empty nextWorkerInputs — never silently drop it and dispatch N identical children'),
197
+ req('openwop.it.dispatch-per-item-input.a-host-not-advertising-periteminput-must-fail-closed-on-a-non-empty-nextworkerin', 'node-packs.md §core.dispatch per-item input', 'a host not advertising perItemInput MUST fail closed (4xx) on a non-empty nextWorkerInputs — never silently drop it and dispatch N identical children'),
196
198
  ).toBe(true);
197
199
  });
198
200
  });
@@ -15,6 +15,7 @@ import { describe, it, expect } from 'vitest';
15
15
  import { driver } from '../lib/driver.js';
16
16
  import { pollUntilTerminal } from '../lib/polling.js';
17
17
  import { isFixtureAdvertised } from '../lib/fixtures.js';
18
+ import { req } from '../lib/requirement-ids.js';
18
19
 
19
20
  const DISPATCH_LOOP_WORKFLOW_ID = 'conformance-dispatch-loop';
20
21
  const SKIP_NO_FIXTURE = !isFixtureAdvertised(DISPATCH_LOOP_WORKFLOW_ID);
@@ -30,7 +31,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('dispatchLoop: core.dispatch consumes Orchestra
30
31
  // mock. The black-box contract here is terminal completion.
31
32
 
32
33
  const terminal = await pollUntilTerminal(runId);
33
- expect(terminal.status, driver.describe(
34
+ expect(terminal.status, req('openwop.it.dispatchLoop.host-correctly-processes-orchestrator-decisions-and-terminates',
34
35
  'RFCS/0007-dispatch-loop.md §H',
35
36
  'run MUST reach terminal `completed` after dispatch processes terminate decision',
36
37
  )).toBe('completed');
@@ -44,7 +45,7 @@ describe.skipIf(SKIP_NO_FIXTURE)('dispatchLoop: core.dispatch consumes Orchestra
44
45
  .filter((e) => e.type === 'runOrchestrator.decided')
45
46
  .map((e) => e.payload?.decision?.kind);
46
47
 
47
- expect(decisions, driver.describe(
48
+ expect(decisions, req('openwop.it.dispatchLoop.host-correctly-processes-orchestrator-decisions-and-terminates',
48
49
  'RFCS/0007-dispatch-loop.md §D',
49
50
  'host MUST emit next-worker then terminate in a loop topology'
50
51
  )).toEqual(['next-worker', 'terminate']);
@@ -15,8 +15,8 @@
15
15
 
16
16
  import { describe, it, expect } from 'vitest';
17
17
  import { softSkip } from '../lib/soft-skip.js';
18
- import { driver } from '../lib/driver.js';
19
18
  import { readDistillationCap, invokeDistill } from '../lib/distillation.js';
19
+ import { req } from '../lib/requirement-ids.js';
20
20
 
21
21
  describe('distillation-index-roundtrip (RFC 0062 §B)', () => {
22
22
  it('an indexEmitted run updates a retrievable memory-index manifest', async () => {
@@ -26,11 +26,11 @@ describe('distillation-index-roundtrip (RFC 0062 §B)', () => {
26
26
  if (res === null) return softSkip('blocked', 'seam absent — soft-skip');
27
27
  expect(
28
28
  res.body.indexUpdated === true || res.body.event?.distillation?.indexUpdated === true,
29
- driver.describe('RFC 0062 §B', 'an indexEmitted distillation MUST report updating the memory index'),
29
+ req('openwop.it.distillation-index-roundtrip.an-indexemitted-run-updates-a-retrievable-memory-index-manifest', 'RFC 0062 §B', 'an indexEmitted distillation MUST report updating the memory index'),
30
30
  ).toBe(true);
31
31
  expect(
32
32
  res.body.indexFile !== undefined && res.body.indexFile !== null,
33
- driver.describe('RFC 0062 §B', 'the MEMORY-INDEX.json manifest MUST be retrievable after distillation'),
33
+ req('openwop.it.distillation-index-roundtrip.an-indexemitted-run-updates-a-retrievable-memory-index-manifest', 'RFC 0062 §B', 'the MEMORY-INDEX.json manifest MUST be retrievable after distillation'),
34
34
  ).toBe(true);
35
35
  });
36
36
  });
@@ -13,8 +13,8 @@
13
13
 
14
14
  import { describe, it, expect } from 'vitest';
15
15
  import { softSkip } from '../lib/soft-skip.js';
16
- import { driver } from '../lib/driver.js';
17
16
  import { readDistillationCap, invokeDistill } from '../lib/distillation.js';
17
+ import { req } from '../lib/requirement-ids.js';
18
18
 
19
19
  const CANARY = 'sk-canary-rfc0062-do-not-leak-qrs456';
20
20
 
@@ -30,7 +30,7 @@ describe('distillation-secret-carryforward (RFC 0062 §B)', () => {
30
30
  if (res === null) return softSkip('blocked', 'seam absent — soft-skip');
31
31
  expect(
32
32
  JSON.stringify(res.body).includes(CANARY),
33
- driver.describe('RFC 0062 §B', 'SR-1 carry-forward: a redacted secret MUST NOT re-appear in the archive or memory.compacted event'),
33
+ req('openwop.it.distillation-secret-carryforward.a-redacted-secret-in-source-memory-never-appears-in-the-distilled-output', 'RFC 0062 §B', 'SR-1 carry-forward: a redacted secret MUST NOT re-appear in the archive or memory.compacted event'),
34
34
  ).toBe(false);
35
35
  });
36
36
  });
@@ -13,8 +13,8 @@
13
13
 
14
14
  import { describe, it, expect } from 'vitest';
15
15
  import { softSkip } from '../lib/soft-skip.js';
16
- import { driver } from '../lib/driver.js';
17
16
  import { readDistillationCap } from '../lib/distillation.js';
17
+ import { req } from '../lib/requirement-ids.js';
18
18
 
19
19
  describe('distillation-shape: advertisement (RFC 0062 §A)', () => {
20
20
  it('capabilities.memory.distillation is absent or a well-formed object', async () => {
@@ -22,19 +22,19 @@ describe('distillation-shape: advertisement (RFC 0062 §A)', () => {
22
22
  if (cap === null) return softSkip('inapplicable', 'not advertised — valid');
23
23
  expect(
24
24
  typeof cap.supported,
25
- driver.describe('capabilities.schema.json §memory.distillation', 'distillation.supported MUST be a boolean when the block is present'),
25
+ req('openwop.it.distillation-shape.capabilities-memory-distillation-is-absent-or-a-well-formed-object', 'capabilities.schema.json §memory.distillation', 'distillation.supported MUST be a boolean when the block is present'),
26
26
  ).toBe('boolean');
27
27
  if (cap.maxTokenBudget !== undefined) {
28
28
  expect(
29
29
  typeof cap.maxTokenBudget === 'number' && (cap.maxTokenBudget as number) >= 1,
30
- driver.describe('capabilities.schema.json §memory.distillation', 'maxTokenBudget MUST be a positive integer when present'),
30
+ req('openwop.it.distillation-shape.capabilities-memory-distillation-is-absent-or-a-well-formed-object', 'capabilities.schema.json §memory.distillation', 'maxTokenBudget MUST be a positive integer when present'),
31
31
  ).toBe(true);
32
32
  }
33
33
  for (const k of ['scheduled', 'indexEmitted'] as const) {
34
34
  if (cap[k] !== undefined) {
35
35
  expect(
36
36
  typeof cap[k],
37
- driver.describe('capabilities.schema.json §memory.distillation', `distillation.${k} MUST be a boolean when present`),
37
+ req('openwop.it.distillation-shape.capabilities-memory-distillation-is-absent-or-a-well-formed-object', 'capabilities.schema.json §memory.distillation', `distillation.${k} MUST be a boolean when present`),
38
38
  ).toBe('boolean');
39
39
  }
40
40
  }
@@ -11,28 +11,28 @@
11
11
 
12
12
  import { describe, it, expect } from 'vitest';
13
13
  import { softSkip } from '../lib/soft-skip.js';
14
- import { driver } from '../lib/driver.js';
15
14
  import { readDistillationCap, invokeDistill } from '../lib/distillation.js';
15
+ import { req } from '../lib/requirement-ids.js';
16
16
 
17
17
  describe('distillation-stable-archive (RFC 0062 §B)', () => {
18
18
  it('identical sources + budget produce an identical archive checksum', async () => {
19
19
  if ((await readDistillationCap())?.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `(await readDistillationCap())?.supported !== true` returned early');
20
- const req = {
20
+ const reqBody = {
21
21
  memoryRef: 'conformance-distill',
22
22
  tokenBudget: 8000,
23
23
  sources: ['s1', 's2', 's3'],
24
24
  };
25
- const a = await invokeDistill(req);
25
+ const a = await invokeDistill(reqBody);
26
26
  if (a === null) return softSkip('blocked', 'seam absent — soft-skip');
27
- const b = await invokeDistill(req);
27
+ const b = await invokeDistill(reqBody);
28
28
  if (b === null) return softSkip('blocked', 'precondition not met — `b === null` returned early (seam, prior step, or fixture unavailable)');
29
29
  expect(
30
30
  typeof a.body.archiveChecksum === 'string' && (a.body.archiveChecksum as string).length > 0,
31
- driver.describe('RFC 0062 §B', 'a distillation run MUST produce a non-empty archive checksum'),
31
+ req('openwop.it.distillation-stable-archive.identical-sources-budget-produce-an-identical-archive-checksum', 'RFC 0062 §B', 'a distillation run MUST produce a non-empty archive checksum'),
32
32
  ).toBe(true);
33
33
  expect(
34
34
  b.body.archiveChecksum,
35
- driver.describe('RFC 0062 §B', 'the same source set + budget MUST yield a byte-stable archive'),
35
+ req('openwop.it.distillation-stable-archive.identical-sources-budget-produce-an-identical-archive-checksum', 'RFC 0062 §B', 'the same source set + budget MUST yield a byte-stable archive'),
36
36
  ).toBe(a.body.archiveChecksum);
37
37
  });
38
38
  });