@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
@@ -15,34 +15,35 @@
15
15
  */
16
16
 
17
17
  import { describe, it, expect } from 'vitest';
18
- import { driver } from '../lib/driver.js';
19
18
  import { readManifestRuntimeCap, listManifestAgents, dispatchAgent } from '../lib/agentRuntime.js';
19
+ import { req } from '../lib/requirement-ids.js';
20
+ import { softSkip } from '../lib/soft-skip.js';
20
21
 
21
22
  describe('agent-manifest-runtime (RFC 0070)', () => {
22
23
  it('lists installed manifest agents and dispatches one with attributed events', async () => {
23
24
  const cap = await readManifestRuntimeCap();
24
- if (cap?.supported !== true) return; // unadvertised — soft-skip
25
+ if (cap?.supported !== true) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `cap?.supported !== true` returned early (unadvertised — soft-skip)'); // unadvertised — soft-skip
25
26
 
26
27
  // RFC 0074 §B — installScope governs how GET /v1/agents is scoped.
27
28
  const installScope = typeof cap.installScope === 'string' ? cap.installScope : 'host';
28
29
  expect(
29
30
  installScope === 'host' || installScope === 'tenant',
30
- driver.describe('RFC 0074 §B', "agents.manifestRuntime.installScope (when present) MUST be 'host' or 'tenant'"),
31
+ req('openwop.it.agent-manifest-runtime.lists-installed-manifest-agents-and-dispatches-one-with-attributed-events', 'RFC 0074 §B', "agents.manifestRuntime.installScope (when present) MUST be 'host' or 'tenant'"),
31
32
  ).toBe(true);
32
33
 
33
34
  const inv = await listManifestAgents();
34
- if (inv === null) return; // seam absent — soft-skip
35
+ if (inv === null) return softSkip('blocked', 'precondition not met — `inv === null` returned early (seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam absent — soft-skip
35
36
  const agents = inv.agents ?? [];
36
37
  expect(
37
38
  Array.isArray(agents),
38
- driver.describe('RFC 0072 §A', 'GET /v1/agents MUST return an agents[] array'),
39
+ req('openwop.it.agent-manifest-runtime.lists-installed-manifest-agents-and-dispatches-one-with-attributed-events', 'RFC 0072 §A', 'GET /v1/agents MUST return an agents[] array'),
39
40
  ).toBe(true);
40
41
 
41
42
  if (installScope === 'host') {
42
43
  // Host-global inventory (RFC 0072 §A): a manifestRuntime host MUST surface ≥1 agent.
43
44
  expect(
44
45
  agents.length > 0,
45
- driver.describe('RFC 0070 §A', 'a host-scoped manifestRuntime host MUST surface ≥1 installed manifest agent'),
46
+ req('openwop.it.agent-manifest-runtime.lists-installed-manifest-agents-and-dispatches-one-with-attributed-events', 'RFC 0070 §A', 'a host-scoped manifestRuntime host MUST surface ≥1 installed manifest agent'),
46
47
  ).toBe(true);
47
48
  } else if (agents.length === 0) {
48
49
  // RFC 0074 §A + Unresolved Q3 — tenant-scoped: GET /v1/agents is the
@@ -51,28 +52,28 @@ describe('agent-manifest-runtime (RFC 0070)', () => {
51
52
  // Empty is conformant; the cross-tenant no-disclosure 404 is covered by the
52
53
  // owner-triple isolation harness (RFC 0048/0059), not re-probed here. Nothing
53
54
  // to dispatch.
54
- return;
55
+ return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `agents.length === 0` returned early (RFC 0074 §A + Unresolved Q3 — tenant-scoped: GET /v1/agents is the authenticated principal\'s workspace set, which MAY be e…');
55
56
  }
56
57
 
57
58
  const agentId = agents[0]?.agentId;
58
- if (typeof agentId !== 'string') return;
59
+ if (typeof agentId !== 'string') return softSkip('blocked', 'precondition not met — `typeof agentId !== \'string\'` returned early (seam, prior step, or fixture unavailable)');
59
60
 
60
61
  // Opaque-payload dispatch (validateHandoff:false) so the assertion is
61
62
  // independent of the chosen agent's handoff schema.
62
63
  const res = await dispatchAgent(agentId, { task: {}, validateHandoff: false, availableTools: [] });
63
- if (res === null) return; // seam absent — soft-skip
64
+ if (res === null) return softSkip('blocked', 'precondition not met — `res === null` returned early (seam absent — soft-skip) (seam, prior step, or fixture unavailable)'); // seam absent — soft-skip
64
65
  expect(
65
66
  res.status === 'completed' || res.status === 'escalated',
66
- driver.describe('RFC 0070', 'dispatch MUST resolve to a terminal status (completed | escalated)'),
67
+ req('openwop.it.agent-manifest-runtime.lists-installed-manifest-agents-and-dispatches-one-with-attributed-events', 'RFC 0070', 'dispatch MUST resolve to a terminal status (completed | escalated)'),
67
68
  ).toBe(true);
68
69
  const types = (res.events ?? []).map((e) => e.type);
69
70
  expect(
70
71
  types.includes('agent.reasoned') && types.includes('agent.decided'),
71
- driver.describe('RFC 0002 §A', 'dispatch MUST emit attributed agent.reasoned + agent.decided events'),
72
+ req('openwop.it.agent-manifest-runtime.lists-installed-manifest-agents-and-dispatches-one-with-attributed-events', 'RFC 0002 §A', 'dispatch MUST emit attributed agent.reasoned + agent.decided events'),
72
73
  ).toBe(true);
73
74
  expect(
74
75
  (res.events ?? []).every((e) => e.agentId === agentId),
75
- driver.describe('RFC 0002 §A', 'every emitted agent.* event MUST carry the dispatched agentId'),
76
+ req('openwop.it.agent-manifest-runtime.lists-installed-manifest-agents-and-dispatches-one-with-attributed-events', 'RFC 0002 §A', 'every emitted agent.* event MUST carry the dispatched agentId'),
76
77
  ).toBe(true);
77
78
  });
78
79
 
@@ -29,9 +29,10 @@
29
29
  */
30
30
 
31
31
  import { describe, it, expect } from 'vitest';
32
- import { driver } from '../lib/driver.js';
33
32
  import { behaviorGate } from '../lib/behavior-gate.js';
34
33
  import { readOrgChartCap, getOrgChart, getDepartmentView } from '../lib/agentOrgChart.js';
34
+ import { req } from '../lib/requirement-ids.js';
35
+ import { softSkip } from '../lib/soft-skip.js';
35
36
 
36
37
  const ROSTER_ID_RE = /^host:[a-z0-9][a-z0-9._-]*$/;
37
38
 
@@ -43,17 +44,17 @@ describe('agent-org-chart-scoping (RFC 0087 §A/§C/§D)', () => {
43
44
  const installScope = typeof cap?.installScope === 'string' ? cap.installScope : 'tenant';
44
45
  expect(
45
46
  installScope === 'host' || installScope === 'tenant',
46
- driver.describe('RFC 0087 §E / RFC 0074', "agents.orgChart.installScope (when present) MUST be 'host' or 'tenant'"),
47
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'RFC 0087 §E / RFC 0074', "agents.orgChart.installScope (when present) MUST be 'host' or 'tenant'"),
47
48
  ).toBe(true);
48
49
 
49
50
  // ---- Leg 1: normative read (black-box) -------------------------------
50
51
  const chart = await getOrgChart();
51
- if (chart === null) return; // advertised but read not served yet — soft-skip
52
+ if (chart === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `chart === null` returned early (advertised but read not served yet — soft-skip)'); // advertised but read not served yet — soft-skip
52
53
  const departments = chart.departments ?? [];
53
54
  const members = chart.members ?? [];
54
55
  expect(
55
56
  Array.isArray(departments) && Array.isArray(members),
56
- driver.describe('agent-org-chart.schema.json', 'GET /v1/agents/org-chart MUST return departments[] + members[]'),
57
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.schema.json', 'GET /v1/agents/org-chart MUST return departments[] + members[]'),
57
58
  ).toBe(true);
58
59
 
59
60
  const deptIds = new Set(departments.map((d) => d.departmentId).filter((x): x is string => typeof x === 'string'));
@@ -62,7 +63,7 @@ describe('agent-org-chart-scoping (RFC 0087 §A/§C/§D)', () => {
62
63
  if (parent !== undefined && parent !== null) {
63
64
  expect(
64
65
  deptIds.has(parent),
65
- driver.describe('agent-org-chart.md §A', 'every parentDepartmentId MUST resolve to a department in the chart (a tree)'),
66
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §A', 'every parentDepartmentId MUST resolve to a department in the chart (a tree)'),
66
67
  ).toBe(true);
67
68
  }
68
69
  }
@@ -79,18 +80,18 @@ describe('agent-org-chart-scoping (RFC 0087 §A/§C/§D)', () => {
79
80
  }
80
81
  expect(
81
82
  steps <= departments.length,
82
- driver.describe('agent-org-chart.md §A', 'the department parent graph MUST be acyclic'),
83
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §A', 'the department parent graph MUST be acyclic'),
83
84
  ).toBe(true);
84
85
  }
85
86
  for (const m of members) {
86
87
  expect(
87
88
  typeof m.rosterId === 'string' && ROSTER_ID_RE.test(m.rosterId),
88
- driver.describe('agent-org-chart.md §A', 'each member MUST reference a roster entry (host:<id> rosterId)'),
89
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §A', 'each member MUST reference a roster entry (host:<id> rosterId)'),
89
90
  ).toBe(true);
90
91
  if (typeof m.departmentId === 'string') {
91
92
  expect(
92
93
  deptIds.size === 0 || deptIds.has(m.departmentId),
93
- driver.describe('agent-org-chart.md §A', "a member's departmentId MUST be a department in the chart"),
94
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §A', "a member's departmentId MUST be a department in the chart"),
94
95
  ).toBe(true);
95
96
  }
96
97
  }
@@ -102,23 +103,23 @@ describe('agent-org-chart-scoping (RFC 0087 §A/§C/§D)', () => {
102
103
  if (status === 200 && view) {
103
104
  expect(
104
105
  Array.isArray(view.responsibilities),
105
- driver.describe('agent-org-chart.md §D', 'the responsibility view MUST carry a responsibilities[] roll-up'),
106
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §D', 'the responsibility view MUST carry a responsibilities[] roll-up'),
106
107
  ).toBe(true);
107
108
  const r = view.responsibilities ?? [];
108
109
  expect(
109
110
  r.length === new Set(r).size,
110
- driver.describe('agent-org-chart.md §D', 'responsibilities MUST be a deduped union (no duplicate workflow ids)'),
111
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §D', 'responsibilities MUST be a deduped union (no duplicate workflow ids)'),
111
112
  ).toBe(true);
112
113
  expect(
113
114
  r.every((w) => typeof w === 'string'),
114
- driver.describe('org-chart-responsibility-view.schema.json', 'responsibilities[] entries MUST be workflow-id strings'),
115
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'org-chart-responsibility-view.schema.json', 'responsibilities[] entries MUST be workflow-id strings'),
115
116
  ).toBe(true);
116
117
  // recursive=false MUST keep the response shape (a subset roll-up).
117
118
  const direct = await getDepartmentView(probeDeptId, false);
118
119
  if (direct.status === 200 && direct.view) {
119
120
  expect(
120
121
  Array.isArray(direct.view.responsibilities),
121
- driver.describe('agent-org-chart.md §D', 'recursive=false MUST return the same shape, scoped to direct members'),
122
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §D', 'recursive=false MUST return the same shape, scoped to direct members'),
122
123
  ).toBe(true);
123
124
  }
124
125
  }
@@ -130,7 +131,7 @@ describe('agent-org-chart-scoping (RFC 0087 §A/§C/§D)', () => {
130
131
  const probe = await getDepartmentView(crossTenantDept);
131
132
  expect(
132
133
  probe.status === 404,
133
- driver.describe('agent-org-chart.md §C / RFC 0074', 'GET /v1/agents/org-chart/{id} for a cross-tenant department MUST 404 (no cross-tenant disclosure)'),
134
+ req('openwop.it.agent-org-chart-scoping.serves-the-normative-org-chart-responsibility-roll-up-tree-shaped-and-tenant-sco', 'agent-org-chart.md §C / RFC 0074', 'GET /v1/agents/org-chart/{id} for a cross-tenant department MUST 404 (no cross-tenant disclosure)'),
134
135
  ).toBe(true);
135
136
  }
136
137
  });
@@ -32,9 +32,7 @@ import { join } from 'node:path';
32
32
  import Ajv2020 from 'ajv/dist/2020.js';
33
33
  import addFormats from 'ajv-formats';
34
34
  import { SCHEMAS_DIR } from '../lib/paths.js';
35
-
36
- /** Server-free assertion-message helper. */
37
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
35
+ import { req } from '../lib/requirement-ids.js';
38
36
 
39
37
  function loadSchema(name: string): Record<string, unknown> {
40
38
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
@@ -64,9 +62,9 @@ describe('agent-org-chart-shape: capability advertisement (RFC 0087, server-free
64
62
  const caps = loadSchema('capabilities.schema.json');
65
63
  const agents = (caps.properties as Record<string, { properties?: Record<string, { properties?: Record<string, unknown> }> }>).agents;
66
64
  const orgChart = agents?.properties?.orgChart;
67
- expect(orgChart, why('capabilities.md §agents', 'agents.orgChart MUST be declared')).toBeDefined();
65
+ expect(orgChart, req('openwop.it.agent-org-chart-shape.the-capabilities-schema-declares-agents-orgchart-with-its-sub-flags', 'capabilities.md §agents', 'agents.orgChart MUST be declared')).toBeDefined();
68
66
  for (const flag of ['supported', 'installScope', 'departmentNesting', 'responsibilityView']) {
69
- expect(orgChart?.properties?.[flag], why('agent-org-chart.md §E', `agents.orgChart.${flag} MUST be declared`)).toBeDefined();
67
+ expect(orgChart?.properties?.[flag], req('openwop.it.agent-org-chart-shape.the-capabilities-schema-declares-agents-orgchart-with-its-sub-flags', 'agent-org-chart.md §E', `agents.orgChart.${flag} MUST be declared`)).toBeDefined();
70
68
  }
71
69
  });
72
70
  });
@@ -77,13 +75,13 @@ describe('agent-org-chart-shape: chart record (RFC 0087 §A, server-free)', () =
77
75
  const chart = ajv.compile(loadSchema('agent-org-chart.schema.json'));
78
76
 
79
77
  it('AgentOrgChart validates a conforming chart', () => {
80
- expect(chart(CHART), why('RFC 0087 §A', 'a conforming org-chart MUST validate')).toBe(true);
78
+ expect(chart(CHART), req('openwop.it.agent-org-chart-shape.agentorgchart-validates-a-conforming-chart', 'RFC 0087 §A', 'a conforming org-chart MUST validate')).toBe(true);
81
79
  });
82
80
 
83
81
  it('rejects a non-host: member rosterId and a chart missing required arrays', () => {
84
82
  const badMember = { ...CHART, members: [{ rosterId: 'core.openwop.agents.sally', departmentId: 'dept-marketing', roleId: 'role-bw', reportsTo: null }] };
85
- expect(chart(badMember), why('RFC 0087 §A', 'a non-`host:` member rosterId MUST be rejected')).toBe(false);
86
- expect(chart({ owner: { tenantId: 'acme' }, departments: [] }), why('RFC 0087 §A', 'a chart without `members` MUST be rejected')).toBe(false);
83
+ expect(chart(badMember), req('openwop.it.agent-org-chart-shape.rejects-a-non-host-member-rosterid-and-a-chart-missing-required-arrays', 'RFC 0087 §A', 'a non-`host:` member rosterId MUST be rejected')).toBe(false);
84
+ expect(chart({ owner: { tenantId: 'acme' }, departments: [] }), req('openwop.it.agent-org-chart-shape.rejects-a-non-host-member-rosterid-and-a-chart-missing-required-arrays', 'RFC 0087 §A', 'a chart without `members` MUST be rejected')).toBe(false);
87
85
  });
88
86
  });
89
87
 
@@ -100,14 +98,14 @@ describe('agent-org-chart-shape: §B non-authority guarantee (RFC 0087, server-f
100
98
  };
101
99
  expect(
102
100
  chart(withAuthority),
103
- why('SECURITY invariant org-position-no-authority-escalation', `a member carrying \`${authorityField}\` MUST be rejected (additionalProperties:false — position confers no authority)`),
101
+ req('openwop.it.agent-org-chart-shape.the-schema-rejects-an-authority-bearing-field-on-a-member-org-position-no-author', 'SECURITY invariant org-position-no-authority-escalation', `a member carrying \`${authorityField}\` MUST be rejected (additionalProperties:false — position confers no authority)`),
104
102
  ).toBe(false);
105
103
  }
106
104
  });
107
105
 
108
106
  it('a conforming member object carries exactly the descriptive key set — nothing authority-bearing', () => {
109
107
  const memberKeys = Object.keys(CHART.members[1]!).sort();
110
- expect(memberKeys, why('RFC 0087 §B', 'a member is descriptive only: {departmentId, reportsTo, roleId, rosterId}')).toEqual(['departmentId', 'reportsTo', 'roleId', 'rosterId']);
108
+ expect(memberKeys, req('openwop.it.agent-org-chart-shape.a-conforming-member-object-carries-exactly-the-descriptive-key-set-nothing-autho', 'RFC 0087 §B', 'a member is descriptive only: {departmentId, reportsTo, roleId, rosterId}')).toEqual(['departmentId', 'reportsTo', 'roleId', 'rosterId']);
111
109
  });
112
110
 
113
111
  it('the GET /v1/agents/org-chart/{departmentId} responsibility-view response validates (RFC 0087 §D)', () => {
@@ -120,8 +118,8 @@ describe('agent-org-chart-shape: §B non-authority guarantee (RFC 0087, server-f
120
118
  members: CHART.members,
121
119
  responsibilities: ['marketing-email-campaign', 'social-post-scheduler'],
122
120
  };
123
- expect(view(good), why('RFC 0087 §D', 'a conforming responsibility-view response MUST validate')).toBe(true);
124
- expect(view({ ...good, unexpected: true }), why('RFC 0087 §D', 'an extra top-level property MUST be rejected')).toBe(false);
125
- expect(view({ department: CHART.departments[0], members: CHART.members }), why('RFC 0087 §D', '`responsibilities` is required')).toBe(false);
121
+ expect(view(good), req('openwop.it.agent-org-chart-shape.the-get-v1-agents-org-chart-departmentid-responsibility-view-response-validates', 'RFC 0087 §D', 'a conforming responsibility-view response MUST validate')).toBe(true);
122
+ expect(view({ ...good, unexpected: true }), req('openwop.it.agent-org-chart-shape.the-get-v1-agents-org-chart-departmentid-responsibility-view-response-validates', 'RFC 0087 §D', 'an extra top-level property MUST be rejected')).toBe(false);
123
+ expect(view({ department: CHART.departments[0], members: CHART.members }), req('openwop.it.agent-org-chart-shape.the-get-v1-agents-org-chart-departmentid-responsibility-view-response-validates', 'RFC 0087 §D', '`responsibilities` is required')).toBe(false);
126
124
  });
127
125
  });
@@ -29,6 +29,7 @@ import { describe, it, expect } from 'vitest';
29
29
  import { driver } from '../lib/driver.js';
30
30
  import { behaviorGate } from '../lib/behavior-gate.js';
31
31
  import { isAgentPlatformPartial, isAgentPlatformFull, agentPlatformStatus, agentPlatformSatisfiedTerms } from '../lib/profiles.js';
32
+ import { req } from '../lib/requirement-ids.js';
32
33
 
33
34
  describe('agent-platform-aggregate-evidence (RFC 0085 §C)', () => {
34
35
  it('a host claiming openwop-agent-platform satisfies the §B floor on live discovery; full when the operator certifies full', async () => {
@@ -43,13 +44,13 @@ describe('agent-platform-aggregate-evidence (RFC 0085 §C)', () => {
43
44
  // the profile string alone.
44
45
  expect(
45
46
  isAgentPlatformPartial(disco!),
46
- driver.describe('agent-platform-profile.md §C', 'claiming openwop-agent-platform MUST satisfy the §B floor predicate on live discovery (claim backed by per-capability evidence)'),
47
+ req('openwop.it.agent-platform-aggregate-evidence.a-host-claiming-openwop-agent-platform-satisfies-the-b-floor-on-live-discovery-f', 'agent-platform-profile.md §C', 'claiming openwop-agent-platform MUST satisfy the §B floor predicate on live discovery (claim backed by per-capability evidence)'),
47
48
  ).toBe(true);
48
49
 
49
50
  const status = agentPlatformStatus(disco!);
50
51
  expect(
51
52
  status === 'partial' || status === 'full',
52
- driver.describe('agent-platform-profile.md §D', 'a claimed openwop-agent-platform host MUST derive to partial or full, never none'),
53
+ req('openwop.it.agent-platform-aggregate-evidence.a-host-claiming-openwop-agent-platform-satisfies-the-b-floor-on-live-discovery-f', 'agent-platform-profile.md §D', 'a claimed openwop-agent-platform host MUST derive to partial or full, never none'),
53
54
  ).toBe(true);
54
55
 
55
56
  // Non-vacuous FULL bar: when the operator declares the cert tier `full`,
@@ -57,11 +58,11 @@ describe('agent-platform-aggregate-evidence (RFC 0085 §C)', () => {
57
58
  if (process.env.OPENWOP_AGENT_PLATFORM_TIER === 'full') {
58
59
  expect(
59
60
  isAgentPlatformFull(disco!),
60
- driver.describe('agent-platform-profile.md §B/§D', 'a host certifying `full` MUST satisfy every governance term: authorization + tenant installScope + memory.attribution + debugBundle + triggerBridge + httpClient.egressPolicy'),
61
+ req('openwop.it.agent-platform-aggregate-evidence.a-host-claiming-openwop-agent-platform-satisfies-the-b-floor-on-live-discovery-f', 'agent-platform-profile.md §B/§D', 'a host certifying `full` MUST satisfy every governance term: authorization + tenant installScope + memory.attribution + debugBundle + triggerBridge + httpClient.egressPolicy'),
61
62
  ).toBe(true);
62
63
  expect(
63
64
  agentPlatformSatisfiedTerms(disco!).length,
64
- driver.describe('agent-platform-profile.md §D', 'a host certifying `full` satisfies all 16 §D terms'),
65
+ req('openwop.it.agent-platform-aggregate-evidence.a-host-claiming-openwop-agent-platform-satisfies-the-b-floor-on-live-discovery-f', 'agent-platform-profile.md §D', 'a host certifying `full` satisfies all 16 §D terms'),
65
66
  ).toBe(16);
66
67
  }
67
68
  });
@@ -29,8 +29,7 @@ import { readFileSync } from 'node:fs';
29
29
  import { join } from 'node:path';
30
30
  import { SCHEMAS_DIR } from '../lib/paths.js';
31
31
  import { isAgentPlatformPartial, isAgentPlatformFull, agentPlatformStatus, agentPlatformSatisfiedTerms } from '../lib/profiles.js';
32
-
33
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
32
+ import { req } from '../lib/requirement-ids.js';
34
33
 
35
34
  const CORE = {
36
35
  protocolVersion: '1.0',
@@ -59,24 +58,24 @@ function floorPayload(extra: Record<string, unknown> = {}): Record<string, unkno
59
58
  describe('agent-platform-profile: floor (partial) predicate (RFC 0085 §B, server-free)', () => {
60
59
  it('a host meeting all floor flags is partial', () => {
61
60
  const c = floorPayload();
62
- expect(isAgentPlatformPartial(c), why('agent-platform-profile.md §B', 'all floor flags ⇒ partial')).toBe(true);
63
- expect(agentPlatformStatus(c)).toBe('partial');
61
+ expect(isAgentPlatformPartial(c), req('openwop.it.agent-platform-profile.a-host-meeting-all-floor-flags-is-partial', 'agent-platform-profile.md §B', 'all floor flags ⇒ partial')).toBe(true);
62
+ expect(agentPlatformStatus(c), req('openwop.it.agent-platform-profile.a-host-meeting-all-floor-flags-is-partial', 'RFC 0085', 'a host meeting all floor flags is partial')).toBe('partial');
64
63
  });
65
64
 
66
65
  it('missing a single floor flag (feedback) ⇒ none', () => {
67
66
  const c = floorPayload({ feedback: { supported: false } });
68
- expect(isAgentPlatformPartial(c), why('agent-platform-profile.md §B', 'a missing floor flag ⇒ not partial')).toBe(false);
69
- expect(agentPlatformStatus(c)).toBe('none');
67
+ expect(isAgentPlatformPartial(c), req('openwop.it.agent-platform-profile.missing-a-single-floor-flag-feedback-none', 'agent-platform-profile.md §B', 'a missing floor flag ⇒ not partial')).toBe(false);
68
+ expect(agentPlatformStatus(c), req('openwop.it.agent-platform-profile.missing-a-single-floor-flag-feedback-none', 'RFC 0085', 'missing a single floor flag (feedback) ⇒ none')).toBe('none');
70
69
  });
71
70
 
72
71
  it('replay-OR-nondeterminism: no replay but declared nondeterminism still meets the floor', () => {
73
72
  const c = floorPayload({ replay: { supported: false }, nondeterminismPolicy: { declared: true } });
74
- expect(isAgentPlatformPartial(c), why('agent-platform-profile.md §B', 'declared nondeterminism satisfies the replay-OR term')).toBe(true);
73
+ expect(isAgentPlatformPartial(c), req('openwop.it.agent-platform-profile.replay-or-nondeterminism-no-replay-but-declared-nondeterminism-still-meets-the-f', 'agent-platform-profile.md §B', 'declared nondeterminism satisfies the replay-OR term')).toBe(true);
75
74
  });
76
75
 
77
76
  it('neither replay nor declared nondeterminism ⇒ floor unmet', () => {
78
77
  const c = floorPayload({ replay: { supported: false } });
79
- expect(isAgentPlatformPartial(c), why('agent-platform-profile.md §B', 'neither replay nor declared policy ⇒ not partial')).toBe(false);
78
+ expect(isAgentPlatformPartial(c), req('openwop.it.agent-platform-profile.neither-replay-nor-declared-nondeterminism-floor-unmet', 'agent-platform-profile.md §B', 'neither replay nor declared policy ⇒ not partial')).toBe(false);
80
79
  });
81
80
  });
82
81
 
@@ -92,8 +91,8 @@ describe('agent-platform-profile: full predicate + honest-advertisement (RFC 008
92
91
 
93
92
  it('a host meeting floor + all governance terms is full', () => {
94
93
  const c = floorPayload(fullExtra);
95
- expect(isAgentPlatformFull(c), why('agent-platform-profile.md §B', 'floor + governance ⇒ full')).toBe(true);
96
- expect(agentPlatformStatus(c)).toBe('full');
94
+ expect(isAgentPlatformFull(c), req('openwop.it.agent-platform-profile.a-host-meeting-floor-all-governance-terms-is-full', 'agent-platform-profile.md §B', 'floor + governance ⇒ full')).toBe(true);
95
+ expect(agentPlatformStatus(c), req('openwop.it.agent-platform-profile.a-host-meeting-floor-all-governance-terms-is-full', 'RFC 0085', 'a host meeting floor + all governance terms is full')).toBe('full');
97
96
  });
98
97
 
99
98
  it('a host advertising governance flags but missing tenant installScope reports partial, not full', () => {
@@ -101,13 +100,13 @@ describe('agent-platform-profile: full predicate + honest-advertisement (RFC 008
101
100
  ...fullExtra,
102
101
  agents: { manifestRuntime: { supported: true, installScope: 'host' }, liveRuntime: { supported: true } },
103
102
  });
104
- expect(isAgentPlatformFull(c), why('agent-platform-profile.md §D', 'missing a governance term ⇒ MUST NOT be full')).toBe(false);
105
- expect(agentPlatformStatus(c)).toBe('partial');
103
+ expect(isAgentPlatformFull(c), req('openwop.it.agent-platform-profile.a-host-advertising-governance-flags-but-missing-tenant-installscope-reports-part', 'agent-platform-profile.md §D', 'missing a governance term ⇒ MUST NOT be full')).toBe(false);
104
+ expect(agentPlatformStatus(c), req('openwop.it.agent-platform-profile.a-host-advertising-governance-flags-but-missing-tenant-installscope-reports-part', 'RFC 0085', 'a host advertising governance flags but missing tenant installScope reports partial, not full')).toBe('partial');
106
105
  });
107
106
 
108
107
  it('eval/deploy/budget are NOT hard full terms (a full host without them is still full)', () => {
109
108
  const c = floorPayload(fullExtra); // no agents.evalSuite / agents.deployment / budget
110
- expect(isAgentPlatformFull(c), why('agent-platform-profile.md §B', 'platform-plus tier is advisory, not a hard full term')).toBe(true);
109
+ expect(isAgentPlatformFull(c), req('openwop.it.agent-platform-profile.eval-deploy-budget-are-not-hard-full-terms-a-full-host-without-them-is-still-ful', 'agent-platform-profile.md §B', 'platform-plus tier is advisory, not a hard full term')).toBe(true);
111
110
  });
112
111
  });
113
112
 
@@ -126,12 +125,12 @@ describe('agent-platform-profile: satisfiedTerms[] non-contiguous adoption (RFC
126
125
  feedback: { supported: true },
127
126
  replay: { supported: true },
128
127
  } as Record<string, unknown>;
129
- expect(agentPlatformStatus(c), why('agent-platform-profile.md §D', 'floor unmet ⇒ none')).toBe('none');
128
+ expect(agentPlatformStatus(c), req('openwop.it.agent-platform-profile.a-host-honoring-full-tier-terms-but-failing-floor-terms-is-status-none-yet-has-a', 'agent-platform-profile.md §D', 'floor unmet ⇒ none')).toBe('none');
130
129
  const terms = agentPlatformSatisfiedTerms(c);
131
- expect(terms.includes('full:authorization'), why('§D', 'a satisfied full term is reported even at none')).toBe(true);
132
- expect(terms.includes('full:memory.attribution')).toBe(true);
130
+ expect(terms.includes('full:authorization'), req('openwop.it.agent-platform-profile.a-host-honoring-full-tier-terms-but-failing-floor-terms-is-status-none-yet-has-a', '§D', 'a satisfied full term is reported even at none')).toBe(true);
131
+ expect(terms.includes('full:memory.attribution'), req('openwop.it.agent-platform-profile.a-host-honoring-full-tier-terms-but-failing-floor-terms-is-status-none-yet-has-a', 'RFC 0085', 'a host honoring full-tier terms but failing floor terms is status none yet has a non-empty satisfiedTerms[]')).toBe(true);
133
132
  expect(terms.includes('full:tenant-installScope')).toBe(true);
134
- expect(terms.includes('floor:agents.liveRuntime'), why('§D', 'an unmet floor term is NOT reported')).toBe(false);
133
+ expect(terms.includes('floor:agents.liveRuntime'), req('openwop.it.agent-platform-profile.a-host-honoring-full-tier-terms-but-failing-floor-terms-is-status-none-yet-has-a', '§D', 'an unmet floor term is NOT reported')).toBe(false);
135
134
  expect(terms.length).toBeGreaterThan(0); // distinguishable from a 0/16 do-nothing host
136
135
  });
137
136
 
@@ -144,7 +143,7 @@ describe('agent-platform-profile: satisfiedTerms[] non-contiguous adoption (RFC
144
143
  triggerBridge: { supported: true },
145
144
  httpClient: { safeFetch: { supported: true }, egressPolicy: { supported: true } },
146
145
  });
147
- expect(agentPlatformSatisfiedTerms(c).length, why('§D', 'a full host satisfies all 16 terms')).toBe(16);
146
+ expect(agentPlatformSatisfiedTerms(c).length, req('openwop.it.agent-platform-profile.a-full-host-reports-all-sixteen-terms-satisfied', '§D', 'a full host satisfies all 16 terms')).toBe(16);
148
147
  });
149
148
  });
150
149
 
@@ -153,7 +152,7 @@ describe('agent-platform-profile: capability shape (RFC 0085, server-free)', ()
153
152
  const caps = JSON.parse(readFileSync(join(SCHEMAS_DIR, 'capabilities.schema.json'), 'utf8')) as { properties?: Record<string, { properties?: Record<string, unknown> }> };
154
153
  expect(
155
154
  caps.properties?.nondeterminismPolicy?.properties?.declared,
156
- why('agent-platform-profile.md §B', 'capabilities.nondeterminismPolicy.declared MUST be declared'),
155
+ req('openwop.it.agent-platform-profile.capabilities-nondeterminismpolicy-declared-is-declared', 'agent-platform-profile.md §B', 'capabilities.nondeterminismPolicy.declared MUST be declared'),
157
156
  ).toBeDefined();
158
157
  });
159
158
  });
@@ -21,9 +21,9 @@ import { join } from 'node:path';
21
21
  import Ajv2020 from 'ajv/dist/2020.js';
22
22
  import addFormats from 'ajv-formats';
23
23
  import { SCHEMAS_DIR } from '../lib/paths.js';
24
+ import { req } from '../lib/requirement-ids.js';
24
25
 
25
26
  const BASE = 'https://openwop.dev/spec/v1/';
26
- const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
27
27
  function loadSchema(name: string): Record<string, unknown> {
28
28
  return JSON.parse(readFileSync(join(SCHEMAS_DIR, name), 'utf8')) as Record<string, unknown>;
29
29
  }
@@ -47,18 +47,18 @@ describe('agent-requires-capabilities-shape: AgentManifest.requiresCapabilities
47
47
  it('a manifest WITH requiresCapabilities validates', () => {
48
48
  expect(
49
49
  manifest({ ...base, requiresCapabilities: ['host.workspace', 'aiProviders.toolCalling'] }),
50
- why('RFC 0092 §A', 'a manifest declaring requiresCapabilities MUST validate'),
50
+ req('openwop.it.agent-requires-capabilities-shape.a-manifest-with-requirescapabilities-validates', 'RFC 0092 §A', 'a manifest declaring requiresCapabilities MUST validate'),
51
51
  ).toBe(true);
52
52
  });
53
53
 
54
54
  it('a manifest WITHOUT it still validates (absent ⇒ no requirements)', () => {
55
- expect(manifest(base), why('RFC 0092 §A', 'requiresCapabilities is optional')).toBe(true);
55
+ expect(manifest(base), req('openwop.it.agent-requires-capabilities-shape.a-manifest-without-it-still-validates-absent-no-requirements', 'RFC 0092 §A', 'requiresCapabilities is optional')).toBe(true);
56
56
  });
57
57
 
58
58
  it('rejects a non-string-array value', () => {
59
59
  expect(
60
60
  manifest({ ...base, requiresCapabilities: [123] }),
61
- why('RFC 0092 §A', 'requiresCapabilities items MUST be non-empty strings'),
61
+ req('openwop.it.agent-requires-capabilities-shape.rejects-a-non-string-array-value', 'RFC 0092 §A', 'requiresCapabilities items MUST be non-empty strings'),
62
62
  ).toBe(false);
63
63
  });
64
64
  });
@@ -34,7 +34,6 @@
34
34
  */
35
35
 
36
36
  import { describe, it, expect } from 'vitest';
37
- import { driver } from '../lib/driver.js';
38
37
  import { behaviorGate } from '../lib/behavior-gate.js';
39
38
  import { readRosterCap, listRoster, getRosterEntry, fireRosterPortfolio } from '../lib/agentRoster.js';
40
39
  import {
@@ -43,6 +42,8 @@ import {
43
42
  resetTestSeam,
44
43
  type TestEvent,
45
44
  } from '../lib/event-log-query.js';
45
+ import { req } from '../lib/requirement-ids.js';
46
+ import { softSkip } from '../lib/soft-skip.js';
46
47
 
47
48
  const ROSTER_ID_RE = /^host:[a-z0-9][a-z0-9._-]*$/;
48
49
 
@@ -62,42 +63,42 @@ describe('agent-roster-attribution (RFC 0086 §B/§C)', () => {
62
63
  const installScope = typeof cap?.installScope === 'string' ? cap.installScope : 'host';
63
64
  expect(
64
65
  installScope === 'host' || installScope === 'tenant',
65
- driver.describe('RFC 0086 §F / RFC 0074 §B', "agents.roster.installScope (when present) MUST be 'host' or 'tenant'"),
66
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'RFC 0086 §F / RFC 0074 §B', "agents.roster.installScope (when present) MUST be 'host' or 'tenant'"),
66
67
  ).toBe(true);
67
68
 
68
69
  // ---- Leg 1: normative read (black-box on any roster host) -------------
69
70
  const body = await listRoster();
70
- if (body === null) return; // host advertises roster but doesn't serve the read yet — soft-skip
71
+ if (body === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `body === null` returned early (host advertises roster but doesn\'t serve the read yet — soft-skip)'); // host advertises roster but doesn't serve the read yet — soft-skip
71
72
  const roster = body.roster ?? [];
72
73
  expect(
73
74
  Array.isArray(roster),
74
- driver.describe('agent-roster.md §B', 'GET /v1/agents/roster MUST return a roster[] array'),
75
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §B', 'GET /v1/agents/roster MUST return a roster[] array'),
75
76
  ).toBe(true);
76
77
  expect(
77
78
  body.total === roster.length,
78
- driver.describe('agent-roster-response.schema.json', 'total MUST equal roster.length'),
79
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster-response.schema.json', 'total MUST equal roster.length'),
79
80
  ).toBe(true);
80
81
  for (const entry of roster) {
81
82
  expect(
82
83
  typeof entry.rosterId === 'string' && ROSTER_ID_RE.test(entry.rosterId),
83
- driver.describe('agent-roster-entry.schema.json', 'each entry MUST carry a host:<id> rosterId'),
84
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster-entry.schema.json', 'each entry MUST carry a host:<id> rosterId'),
84
85
  ).toBe(true);
85
86
  expect(
86
87
  typeof entry.persona === 'string' && entry.persona.length > 0,
87
- driver.describe('agent-roster.md §A', 'each entry MUST carry a non-empty persona'),
88
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §A', 'each entry MUST carry a non-empty persona'),
88
89
  ).toBe(true);
89
90
  expect(
90
91
  typeof entry.agentRef?.agentId === 'string',
91
- driver.describe('agent-roster.md §A', 'each entry MUST reference an agentRef.agentId'),
92
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §A', 'each entry MUST reference an agentRef.agentId'),
92
93
  ).toBe(true);
93
94
  expect(
94
95
  typeof entry.owner?.tenantId === 'string',
95
- driver.describe('agent-roster.md §B / RFC 0074', 'each entry MUST carry an owner.tenantId scope'),
96
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §B / RFC 0074', 'each entry MUST carry an owner.tenantId scope'),
96
97
  ).toBe(true);
97
98
  // RFC 0082 §A XOR: an agentRef MUST NOT pin both version and channel.
98
99
  expect(
99
100
  !(entry.agentRef?.version !== undefined && entry.agentRef?.channel !== undefined),
100
- driver.describe('RFC 0082 §A', 'agentRef MUST NOT carry both version and channel'),
101
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'RFC 0082 §A', 'agentRef MUST NOT carry both version and channel'),
101
102
  ).toBe(true);
102
103
  }
103
104
 
@@ -111,7 +112,7 @@ describe('agent-roster-attribution (RFC 0086 §B/§C)', () => {
111
112
  const init = firstOf(q.events, ['roster.run.initiated']);
112
113
  expect(
113
114
  init !== undefined,
114
- driver.describe('agent-roster.md §C', 'a portfolio fire MUST emit roster.run.initiated'),
115
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §C', 'a portfolio fire MUST emit roster.run.initiated'),
115
116
  ).toBe(true);
116
117
 
117
118
  if (init) {
@@ -124,7 +125,7 @@ describe('agent-roster-attribution (RFC 0086 §B/§C)', () => {
124
125
  if (firstAgent) {
125
126
  expect(
126
127
  init.sequence < firstAgent.sequence,
127
- driver.describe('agent-roster.md §C', 'roster.run.initiated MUST precede any agent.* event in the run'),
128
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §C', 'roster.run.initiated MUST precede any agent.* event in the run'),
128
129
  ).toBe(true);
129
130
  }
130
131
 
@@ -133,18 +134,18 @@ describe('agent-roster-attribution (RFC 0086 §B/§C)', () => {
133
134
  for (const key of ['rosterId', 'persona', 'agentId', 'workflowId', 'triggerSource']) {
134
135
  expect(
135
136
  typeof p[key] === 'string' && (p[key] as string).length > 0,
136
- driver.describe('run-event-payloads.schema.json#rosterRunInitiated', `roster.run.initiated MUST carry ${key}`),
137
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'run-event-payloads.schema.json#rosterRunInitiated', `roster.run.initiated MUST carry ${key}`),
137
138
  ).toBe(true);
138
139
  }
139
140
  for (const forbidden of ['body', 'prompt', 'input', 'payload', 'apiKey', 'secret', 'credentials', 'token']) {
140
141
  expect(
141
142
  !(forbidden in p),
142
- driver.describe('SECURITY roster-attribution-no-content', `roster.run.initiated MUST be content-free (no ${forbidden})`),
143
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'SECURITY roster-attribution-no-content', `roster.run.initiated MUST be content-free (no ${forbidden})`),
143
144
  ).toBe(true);
144
145
  }
145
146
  expect(
146
147
  typeof p.rosterId === 'string' && ROSTER_ID_RE.test(p.rosterId),
147
- driver.describe('agent-roster.md §C', 'roster.run.initiated.rosterId MUST be a host:<id> AgentRef id'),
148
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §C', 'roster.run.initiated.rosterId MUST be a host:<id> AgentRef id'),
148
149
  ).toBe(true);
149
150
  }
150
151
  }
@@ -158,7 +159,7 @@ describe('agent-roster-attribution (RFC 0086 §B/§C)', () => {
158
159
  const p = q.events[0].payload;
159
160
  expect(
160
161
  typeof p.triggerSubscriptionId === 'string' && (p.triggerSubscriptionId as string).length > 0,
161
- driver.describe('agent-roster.md §D / RFC 0083', 'a durable work-item fire MUST carry triggerSubscriptionId for trigger→run→roster ancestry'),
162
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §D / RFC 0083', 'a durable work-item fire MUST carry triggerSubscriptionId for trigger→run→roster ancestry'),
162
163
  ).toBe(true);
163
164
  }
164
165
  }
@@ -172,7 +173,7 @@ describe('agent-roster-attribution (RFC 0086 §B/§C)', () => {
172
173
  const probe = await getRosterEntry(crossTenantId);
173
174
  expect(
174
175
  probe.status === 404,
175
- driver.describe('agent-roster.md §B / RFC 0074', "GET /v1/agents/roster/{id} for a cross-tenant id MUST 404 (no cross-tenant disclosure)"),
176
+ req('openwop.it.agent-roster-attribution.serves-the-normative-roster-attributes-a-portfolio-fire-content-free-ordered-and', 'agent-roster.md §B / RFC 0074', "GET /v1/agents/roster/{id} for a cross-tenant id MUST 404 (no cross-tenant disclosure)"),
176
177
  ).toBe(true);
177
178
  }
178
179
  });