@openwop/openwop-conformance 1.0.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 (175) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +241 -0
  3. package/api/asyncapi.yaml +481 -0
  4. package/api/openapi.yaml +830 -0
  5. package/api/redocly.yaml +8 -0
  6. package/coverage.md +80 -0
  7. package/dist/cli.js +161 -0
  8. package/fixtures/conformance-a2a-task-roundtrip.json +27 -0
  9. package/fixtures/conformance-agent-identity.json +27 -0
  10. package/fixtures/conformance-agent-low-confidence.json +29 -0
  11. package/fixtures/conformance-agent-memory-cross-tenant.json +28 -0
  12. package/fixtures/conformance-agent-memory-redaction.json +32 -0
  13. package/fixtures/conformance-agent-memory-roundtrip.json +32 -0
  14. package/fixtures/conformance-agent-memory-ttl.json +31 -0
  15. package/fixtures/conformance-agent-pack-export.json +26 -0
  16. package/fixtures/conformance-agent-pack-install.json +26 -0
  17. package/fixtures/conformance-agent-pack-provenance.json +31 -0
  18. package/fixtures/conformance-agent-reasoning.json +29 -0
  19. package/fixtures/conformance-approval.json +27 -0
  20. package/fixtures/conformance-cancellable.json +33 -0
  21. package/fixtures/conformance-cap-breach.json +27 -0
  22. package/fixtures/conformance-capability-missing.json +23 -0
  23. package/fixtures/conformance-channel-ttl.json +60 -0
  24. package/fixtures/conformance-clarification.json +30 -0
  25. package/fixtures/conformance-conversation-capability-negotiation.json +23 -0
  26. package/fixtures/conformance-conversation-lifecycle.json +32 -0
  27. package/fixtures/conformance-conversation-replay.json +33 -0
  28. package/fixtures/conformance-conversation-vs-clarification.json +26 -0
  29. package/fixtures/conformance-delay.json +33 -0
  30. package/fixtures/conformance-dispatch-loop.json +38 -0
  31. package/fixtures/conformance-failure.json +23 -0
  32. package/fixtures/conformance-idempotent.json +30 -0
  33. package/fixtures/conformance-identity.json +32 -0
  34. package/fixtures/conformance-interrupt-auth-required.json +28 -0
  35. package/fixtures/conformance-interrupt-external-event.json +33 -0
  36. package/fixtures/conformance-interrupt-parent-child-cancel-child.json +27 -0
  37. package/fixtures/conformance-interrupt-parent-child-cancel.json +26 -0
  38. package/fixtures/conformance-interrupt-quorum.json +30 -0
  39. package/fixtures/conformance-mcp-tool-roundtrip.json +32 -0
  40. package/fixtures/conformance-message-reducer.json +31 -0
  41. package/fixtures/conformance-multi-node.json +21 -0
  42. package/fixtures/conformance-noop.json +23 -0
  43. package/fixtures/conformance-orchestrator-dispatch.json +47 -0
  44. package/fixtures/conformance-orchestrator-low-confidence.json +41 -0
  45. package/fixtures/conformance-orchestrator-terminate.json +44 -0
  46. package/fixtures/conformance-stream-text.json +26 -0
  47. package/fixtures/conformance-subworkflow-child.json +21 -0
  48. package/fixtures/conformance-subworkflow-parent.json +49 -0
  49. package/fixtures/conformance-version-fold.json +23 -0
  50. package/fixtures/conformance-wasm-pack-roundtrip.json +25 -0
  51. package/fixtures/pack-manifests/pack-private-example.json +26 -0
  52. package/fixtures.md +404 -0
  53. package/package.json +48 -0
  54. package/schemas/README.md +75 -0
  55. package/schemas/agent-manifest.schema.json +107 -0
  56. package/schemas/agent-ref.schema.json +53 -0
  57. package/schemas/capabilities.schema.json +287 -0
  58. package/schemas/channel-written-payload.schema.json +55 -0
  59. package/schemas/conversation-event.schema.json +120 -0
  60. package/schemas/conversation-turn.schema.json +72 -0
  61. package/schemas/debug-bundle.schema.json +196 -0
  62. package/schemas/dispatch-config.schema.json +46 -0
  63. package/schemas/error-envelope.schema.json +25 -0
  64. package/schemas/memory-entry.schema.json +36 -0
  65. package/schemas/memory-list-options.schema.json +21 -0
  66. package/schemas/node-pack-manifest.schema.json +235 -0
  67. package/schemas/orchestrator-decision.schema.json +60 -0
  68. package/schemas/run-event-payloads.schema.json +663 -0
  69. package/schemas/run-event.schema.json +116 -0
  70. package/schemas/run-options.schema.json +81 -0
  71. package/schemas/run-orchestrator-decided-event.schema.json +20 -0
  72. package/schemas/run-snapshot.schema.json +121 -0
  73. package/schemas/suspend-request.schema.json +182 -0
  74. package/schemas/workflow-definition.schema.json +430 -0
  75. package/src/cli.ts +187 -0
  76. package/src/lib/a2a-fake-peer.ts +233 -0
  77. package/src/lib/canaries.ts +186 -0
  78. package/src/lib/driver.ts +96 -0
  79. package/src/lib/env.ts +49 -0
  80. package/src/lib/fixtures.ts +93 -0
  81. package/src/lib/mcp-fake-server.ts +185 -0
  82. package/src/lib/multi-agent-capabilities.ts +155 -0
  83. package/src/lib/multiProcess.ts +141 -0
  84. package/src/lib/otel-collector.ts +312 -0
  85. package/src/lib/paths.ts +198 -0
  86. package/src/lib/polling.ts +81 -0
  87. package/src/lib/profiles.ts +258 -0
  88. package/src/lib/sse.ts +172 -0
  89. package/src/scenarios/a2a-task-roundtrip.test.ts +149 -0
  90. package/src/scenarios/agentConfidenceEscalation.test.ts +61 -0
  91. package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +54 -0
  92. package/src/scenarios/agentMemoryRedactionContract.test.ts +46 -0
  93. package/src/scenarios/agentMemoryRoundTrip.test.ts +52 -0
  94. package/src/scenarios/agentMemoryTtlExpiry.test.ts +47 -0
  95. package/src/scenarios/agentMessageReducer.test.ts +57 -0
  96. package/src/scenarios/agentMetadata.test.ts +56 -0
  97. package/src/scenarios/agentPackExport.test.ts +45 -0
  98. package/src/scenarios/agentPackInstall.test.ts +50 -0
  99. package/src/scenarios/agentPackProvenance.test.ts +53 -0
  100. package/src/scenarios/agentReasoningEvents.test.ts +72 -0
  101. package/src/scenarios/append-ordering.test.ts +91 -0
  102. package/src/scenarios/approval-payload.test.ts +120 -0
  103. package/src/scenarios/audit-log-integrity.test.ts +106 -0
  104. package/src/scenarios/auth.test.ts +55 -0
  105. package/src/scenarios/byok-roundtrip.test.ts +166 -0
  106. package/src/scenarios/cancellation.test.ts +68 -0
  107. package/src/scenarios/cap-breach.test.ts +149 -0
  108. package/src/scenarios/channel-ttl.test.ts +70 -0
  109. package/src/scenarios/configurable-schema.test.ts +76 -0
  110. package/src/scenarios/conversationCapabilityNegotiation.test.ts +39 -0
  111. package/src/scenarios/conversationLifecycle.test.ts +64 -0
  112. package/src/scenarios/conversationReplayDeterminism.test.ts +52 -0
  113. package/src/scenarios/conversationVsLegacySuspend.test.ts +46 -0
  114. package/src/scenarios/cost-attribution.test.ts +207 -0
  115. package/src/scenarios/debugBundle.test.ts +222 -0
  116. package/src/scenarios/discovery.test.ts +147 -0
  117. package/src/scenarios/dispatchLoop.test.ts +52 -0
  118. package/src/scenarios/errors.test.ts +144 -0
  119. package/src/scenarios/eventOrdering.test.ts +144 -0
  120. package/src/scenarios/failure-path.test.ts +46 -0
  121. package/src/scenarios/fixtures-gating.test.ts +137 -0
  122. package/src/scenarios/fixtures-valid.test.ts +140 -0
  123. package/src/scenarios/highConcurrency.test.ts +263 -0
  124. package/src/scenarios/idempotency.test.ts +83 -0
  125. package/src/scenarios/idempotencyRetry.test.ts +130 -0
  126. package/src/scenarios/identity-passthrough.test.ts +54 -0
  127. package/src/scenarios/interrupt-approval.test.ts +97 -0
  128. package/src/scenarios/interrupt-auth-required-resume.test.ts +88 -0
  129. package/src/scenarios/interrupt-clarification.test.ts +45 -0
  130. package/src/scenarios/interrupt-external-event-correlation.test.ts +113 -0
  131. package/src/scenarios/interrupt-parent-child-cascade.test.ts +102 -0
  132. package/src/scenarios/interrupt-quorum-resolution.test.ts +97 -0
  133. package/src/scenarios/interruptRace.test.ts +176 -0
  134. package/src/scenarios/maliciousManifest.test.ts +154 -0
  135. package/src/scenarios/mcp-discoverability.test.ts +129 -0
  136. package/src/scenarios/mcp-tool-roundtrip.test.ts +149 -0
  137. package/src/scenarios/multi-node-ordering.test.ts +60 -0
  138. package/src/scenarios/multi-region-idempotency.test.ts +52 -0
  139. package/src/scenarios/orchestratorConservativePath.test.ts +63 -0
  140. package/src/scenarios/orchestratorDispatch.test.ts +66 -0
  141. package/src/scenarios/orchestratorTermination.test.ts +54 -0
  142. package/src/scenarios/otel-emission.test.ts +113 -0
  143. package/src/scenarios/otel-trace-propagation.test.ts +90 -0
  144. package/src/scenarios/pack-registry-publish.test.ts +93 -0
  145. package/src/scenarios/pack-registry.test.ts +328 -0
  146. package/src/scenarios/pause-resume.test.ts +109 -0
  147. package/src/scenarios/policies.test.ts +162 -0
  148. package/src/scenarios/profileDerivation.test.ts +335 -0
  149. package/src/scenarios/providerPolicyEnforcement.test.ts +132 -0
  150. package/src/scenarios/rate-limit-envelope.test.ts +97 -0
  151. package/src/scenarios/redaction.test.ts +254 -0
  152. package/src/scenarios/redactionAdversarial.test.ts +162 -0
  153. package/src/scenarios/replay-fork-arbitrary.test.ts +347 -0
  154. package/src/scenarios/replay-fork.test.ts +216 -0
  155. package/src/scenarios/replayDeterminism.test.ts +171 -0
  156. package/src/scenarios/route-coverage.test.ts +129 -0
  157. package/src/scenarios/runs-lifecycle.test.ts +65 -0
  158. package/src/scenarios/runtime-capabilities.test.ts +118 -0
  159. package/src/scenarios/spec-corpus-validity.test.ts +1257 -0
  160. package/src/scenarios/staleClaim.test.ts +223 -0
  161. package/src/scenarios/stream-modes-buffer.test.ts +148 -0
  162. package/src/scenarios/stream-modes-mixed.test.ts +149 -0
  163. package/src/scenarios/stream-modes.test.ts +139 -0
  164. package/src/scenarios/streamReconnect.test.ts +162 -0
  165. package/src/scenarios/subworkflow.test.ts +126 -0
  166. package/src/scenarios/version-negotiation.test.ts +157 -0
  167. package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +47 -0
  168. package/src/scenarios/wasm-pack-invoke-completed.test.ts +69 -0
  169. package/src/scenarios/wasm-pack-invoke-suspended.test.ts +74 -0
  170. package/src/scenarios/wasm-pack-load.test.ts +75 -0
  171. package/src/scenarios/wasm-pack-memory-cap.test.ts +43 -0
  172. package/src/scenarios/wasm-pack-replay-determinism.test.ts +61 -0
  173. package/src/scenarios/webhook-sig-algorithm.test.ts +61 -0
  174. package/src/setup.ts +173 -0
  175. package/vitest.config.ts +17 -0
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "conformance-cap-breach",
3
+ "name": "Conformance: Cap Breach (recursion limit)",
4
+ "version": "1.0",
5
+ "description": "Six-node noop chain. Run with `RunOptions.configurable.recursionLimit: 3` to trigger the per-run nodeExecutionCount breach at node 4 — verifies `cap.breached {kind: 'node-executions'}` emission + terminal `failed` with `error.code = 'recursion_limit_exceeded'`. Spec: run-options.md §recursionLimit + observability.md §cap.breached.",
6
+ "nodes": [
7
+ { "id": "n1", "typeId": "core.noop", "name": "N1", "position": { "x": 0, "y": 0 }, "config": {}, "inputs": {} },
8
+ { "id": "n2", "typeId": "core.noop", "name": "N2", "position": { "x": 200, "y": 0 }, "config": {}, "inputs": {} },
9
+ { "id": "n3", "typeId": "core.noop", "name": "N3", "position": { "x": 400, "y": 0 }, "config": {}, "inputs": {} },
10
+ { "id": "n4", "typeId": "core.noop", "name": "N4", "position": { "x": 600, "y": 0 }, "config": {}, "inputs": {} },
11
+ { "id": "n5", "typeId": "core.noop", "name": "N5", "position": { "x": 800, "y": 0 }, "config": {}, "inputs": {} },
12
+ { "id": "n6", "typeId": "core.noop", "name": "N6", "position": { "x": 1000, "y": 0 }, "config": {}, "inputs": {} }
13
+ ],
14
+ "edges": [
15
+ { "id": "e12", "sourceNodeId": "n1", "targetNodeId": "n2" },
16
+ { "id": "e23", "sourceNodeId": "n2", "targetNodeId": "n3" },
17
+ { "id": "e34", "sourceNodeId": "n3", "targetNodeId": "n4" },
18
+ { "id": "e45", "sourceNodeId": "n4", "targetNodeId": "n5" },
19
+ { "id": "e56", "sourceNodeId": "n5", "targetNodeId": "n6" }
20
+ ],
21
+ "triggers": [
22
+ { "id": "manual", "type": "manual", "enabled": true }
23
+ ],
24
+ "variables": [],
25
+ "metadata": { "tags": ["conformance", "cap-breach", "recursion-limit"] },
26
+ "settings": { "timeout": 30000, "maxRetries": 0 }
27
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "id": "conformance-capability-missing",
3
+ "name": "Conformance: Capability Missing",
4
+ "version": "1.0",
5
+ "description": "Single-node workflow whose node declares `requires: ['conformance.never-provided']`. The engine MUST refuse to dispatch the node and terminate the run with `error.code = 'capability_not_provided'`. Spec: capabilities.md §'Runtime capabilities'.",
6
+ "nodes": [
7
+ {
8
+ "id": "n1",
9
+ "typeId": "conformance.requiresMissing",
10
+ "name": "Requires Missing",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {},
13
+ "inputs": {}
14
+ }
15
+ ],
16
+ "edges": [],
17
+ "triggers": [
18
+ { "id": "manual", "type": "manual", "enabled": true }
19
+ ],
20
+ "variables": [],
21
+ "metadata": { "tags": ["conformance", "runtime-capability", "capability-not-provided"] },
22
+ "settings": { "timeout": 10000, "maxRetries": 0 }
23
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "id": "conformance-channel-ttl",
3
+ "name": "Conformance: Channel TTL",
4
+ "version": "1.0",
5
+ "description": "Writes 3 entries to channel `events` (ttlMs=200), waits 300ms, writes a 4th entry. The TTL filter at write time MUST drop all 3 priors so only the 4th entry remains. Spec: channels-and-reducers.md §append + §TTL (closes C3).",
6
+ "nodes": [
7
+ {
8
+ "id": "write-a",
9
+ "typeId": "core.channelWrite",
10
+ "name": "Write A",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": { "channelName": "events", "reducer": "append", "ttlMs": 200, "value": "a" },
13
+ "inputs": {}
14
+ },
15
+ {
16
+ "id": "write-b",
17
+ "typeId": "core.channelWrite",
18
+ "name": "Write B",
19
+ "position": { "x": 200, "y": 0 },
20
+ "config": { "channelName": "events", "reducer": "append", "ttlMs": 200, "value": "b" },
21
+ "inputs": {}
22
+ },
23
+ {
24
+ "id": "write-c",
25
+ "typeId": "core.channelWrite",
26
+ "name": "Write C",
27
+ "position": { "x": 400, "y": 0 },
28
+ "config": { "channelName": "events", "reducer": "append", "ttlMs": 200, "value": "c" },
29
+ "inputs": {}
30
+ },
31
+ {
32
+ "id": "ttl-wait",
33
+ "typeId": "core.delay",
34
+ "name": "Wait past TTL",
35
+ "position": { "x": 600, "y": 0 },
36
+ "config": { "ms": 300 },
37
+ "inputs": {}
38
+ },
39
+ {
40
+ "id": "write-d",
41
+ "typeId": "core.channelWrite",
42
+ "name": "Write D (after TTL)",
43
+ "position": { "x": 800, "y": 0 },
44
+ "config": { "channelName": "events", "reducer": "append", "ttlMs": 200, "value": "d" },
45
+ "inputs": {}
46
+ }
47
+ ],
48
+ "edges": [
49
+ { "id": "e1", "sourceNodeId": "write-a", "targetNodeId": "write-b" },
50
+ { "id": "e2", "sourceNodeId": "write-b", "targetNodeId": "write-c" },
51
+ { "id": "e3", "sourceNodeId": "write-c", "targetNodeId": "ttl-wait" },
52
+ { "id": "e4", "sourceNodeId": "ttl-wait", "targetNodeId": "write-d" }
53
+ ],
54
+ "triggers": [
55
+ { "id": "manual", "type": "manual", "enabled": true }
56
+ ],
57
+ "variables": [],
58
+ "metadata": { "tags": ["conformance", "channel-ttl"] },
59
+ "settings": { "timeout": 30000, "maxRetries": 0 }
60
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "id": "conformance-clarification",
3
+ "name": "Conformance: Clarification",
4
+ "version": "1.0",
5
+ "description": "Suspends on a clarification interrupt with one fixed question. Resume schema: {answers: {q1: string}}.",
6
+ "nodes": [
7
+ {
8
+ "id": "ask",
9
+ "typeId": "core.clarificationGate",
10
+ "name": "Clarification Gate",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "questions": [
14
+ {
15
+ "id": "q1",
16
+ "question": "What is your favorite color?"
17
+ }
18
+ ]
19
+ },
20
+ "inputs": {}
21
+ }
22
+ ],
23
+ "edges": [],
24
+ "triggers": [
25
+ { "id": "manual", "type": "manual", "enabled": true }
26
+ ],
27
+ "variables": [],
28
+ "metadata": { "tags": ["conformance", "hitl"] },
29
+ "settings": { "timeout": 0 }
30
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "id": "conformance-conversation-capability-negotiation",
3
+ "name": "Conformance: Conversation Capability Negotiation",
4
+ "version": "1.0",
5
+ "description": "Phase 4 — INVERTED gate. Declares a `core.conversationGate` node; hosts that do NOT advertise `capabilities.conversationPrimitive: true` MUST refuse this workflow at registration or run-create with `validation_error`. Hosts that DO advertise the capability would accept; this scenario runs ONLY against non-conversation hosts to verify the refusal contract. See conversationCapabilityNegotiation.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "convo",
9
+ "typeId": "core.conversationGate",
10
+ "name": "Conversation Gate (capability probe)",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {},
13
+ "inputs": {}
14
+ }
15
+ ],
16
+ "edges": [],
17
+ "triggers": [
18
+ { "id": "manual", "type": "manual", "enabled": true }
19
+ ],
20
+ "variables": [],
21
+ "metadata": { "tags": ["conformance", "multi-agent", "phase-4", "conversation", "capability-gate", "negative-test"] },
22
+ "settings": { "timeout": 5000 }
23
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "id": "conformance-conversation-lifecycle",
3
+ "name": "Conformance: Conversation Lifecycle",
4
+ "version": "1.0",
5
+ "description": "Phase 4. Opens a conversation, performs one exchange (host's conformance mock auto-resumes), closes. Emits conversation.opened → conversation.exchanged → conversation.closed events with matching conversationId. See conversationLifecycle.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "convo",
9
+ "typeId": "core.conversationGate",
10
+ "name": "Conversation Gate",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "lifecycle": "open-exchange-close",
14
+ "mockAutoResume": true
15
+ },
16
+ "inputs": {}
17
+ }
18
+ ],
19
+ "edges": [],
20
+ "triggers": [
21
+ { "id": "manual", "type": "manual", "enabled": true }
22
+ ],
23
+ "variables": [],
24
+ "channels": {
25
+ "conversation": {
26
+ "schema": { "type": "array" },
27
+ "reducer": "message"
28
+ }
29
+ },
30
+ "metadata": { "tags": ["conformance", "multi-agent", "phase-4", "conversation"] },
31
+ "settings": { "timeout": 20000 }
32
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "id": "conformance-conversation-replay",
3
+ "name": "Conformance: Conversation Replay Determinism",
4
+ "version": "1.0",
5
+ "description": "Phase 4. Runs a multi-turn conversation to completion, then `:fork` (mode: 'replay') the run. Forked run's `conversation` channel projection MUST be byte-equal to the source run's. See conversationReplayDeterminism.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "convo",
9
+ "typeId": "core.conversationGate",
10
+ "name": "Conversation Gate (multi-turn)",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "lifecycle": "open-exchange-close",
14
+ "mockAutoResume": true,
15
+ "turnCount": 3
16
+ },
17
+ "inputs": {}
18
+ }
19
+ ],
20
+ "edges": [],
21
+ "triggers": [
22
+ { "id": "manual", "type": "manual", "enabled": true }
23
+ ],
24
+ "variables": [],
25
+ "channels": {
26
+ "conversation": {
27
+ "schema": { "type": "array" },
28
+ "reducer": "message"
29
+ }
30
+ },
31
+ "metadata": { "tags": ["conformance", "multi-agent", "phase-4", "conversation", "replay-determinism"] },
32
+ "settings": { "timeout": 30000 }
33
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "conformance-conversation-vs-clarification",
3
+ "name": "Conformance: Conversation vs Clarification Disambiguation",
4
+ "version": "1.0",
5
+ "description": "Phase 4. Drives a `core.conversationGate` exchange and asserts the event log contains `conversation.*` event types — NOT `clarification.*`. Host MUST surface conversation suspends through the conversation event family, not the legacy clarification path. See conversationVsLegacySuspend.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "convo",
9
+ "typeId": "core.conversationGate",
10
+ "name": "Conversation Gate (single exchange)",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "lifecycle": "open-exchange-close",
14
+ "mockAutoResume": true
15
+ },
16
+ "inputs": {}
17
+ }
18
+ ],
19
+ "edges": [],
20
+ "triggers": [
21
+ { "id": "manual", "type": "manual", "enabled": true }
22
+ ],
23
+ "variables": [],
24
+ "metadata": { "tags": ["conformance", "multi-agent", "phase-4", "conversation", "disambiguation"] },
25
+ "settings": { "timeout": 15000 }
26
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "id": "conformance-delay",
3
+ "name": "Conformance: Delay",
4
+ "version": "1.0",
5
+ "description": "Sleeps for input.delayMs ms before completing. Verifies in-flight status visibility (poll + SSE).",
6
+ "nodes": [
7
+ {
8
+ "id": "wait",
9
+ "typeId": "core.delay",
10
+ "name": "Wait",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {},
13
+ "inputs": {
14
+ "delayMs": { "type": "variable", "variableName": "delayMs" }
15
+ }
16
+ }
17
+ ],
18
+ "edges": [],
19
+ "triggers": [
20
+ { "id": "manual", "type": "manual", "enabled": true }
21
+ ],
22
+ "variables": [
23
+ {
24
+ "name": "delayMs",
25
+ "type": "number",
26
+ "description": "Milliseconds to sleep. Bounded 0..30000.",
27
+ "required": true,
28
+ "defaultValue": 1000
29
+ }
30
+ ],
31
+ "metadata": { "tags": ["conformance"] },
32
+ "settings": { "timeout": 60000 }
33
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "id": "conformance-dispatch-loop",
3
+ "name": "Conformance: Dispatch Loop",
4
+ "version": "1.0",
5
+ "description": "Tests the core.dispatch loop mechanism by looping back to an orchestrator node.",
6
+ "nodes": [
7
+ {
8
+ "id": "orchestrator",
9
+ "typeId": "core.orchestrator.supervisor",
10
+ "name": "Supervisor",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {},
13
+ "inputs": {}
14
+ },
15
+ {
16
+ "id": "dispatch",
17
+ "typeId": "core.dispatch",
18
+ "name": "Dispatch",
19
+ "position": { "x": 200, "y": 0 },
20
+ "config": {
21
+ "askUserRouting": "auto",
22
+ "workerDispatchModel": "child-run",
23
+ "fanOutPolicy": "sequential"
24
+ },
25
+ "inputs": {}
26
+ }
27
+ ],
28
+ "edges": [
29
+ { "id": "e1", "sourceNodeId": "orchestrator", "targetNodeId": "dispatch" },
30
+ { "id": "e2", "sourceNodeId": "dispatch", "targetNodeId": "orchestrator" }
31
+ ],
32
+ "triggers": [
33
+ { "id": "manual", "type": "manual", "enabled": true }
34
+ ],
35
+ "variables": [],
36
+ "metadata": { "tags": ["conformance", "dispatch", "loop"] },
37
+ "settings": { "timeout": 60000, "maxRetries": 0 }
38
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "id": "conformance-failure",
3
+ "name": "Conformance: Failure",
4
+ "version": "1.0",
5
+ "description": "Always-fails workflow. Verifies failure event surface, terminal `failed` state, and RunSnapshot.error shape.",
6
+ "nodes": [
7
+ {
8
+ "id": "fail",
9
+ "typeId": "core.fail",
10
+ "name": "Fail",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {},
13
+ "inputs": {}
14
+ }
15
+ ],
16
+ "edges": [],
17
+ "triggers": [
18
+ { "id": "manual", "type": "manual", "enabled": true }
19
+ ],
20
+ "variables": [],
21
+ "metadata": { "tags": ["conformance"] },
22
+ "settings": { "timeout": 10000, "maxRetries": 0 }
23
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "id": "conformance-idempotent",
3
+ "name": "Conformance: Idempotent",
4
+ "version": "1.0",
5
+ "description": "Single-node workflow used purely for Idempotency-Key cache testing. The `nonce` input is not consumed — its only role is to vary the request body.",
6
+ "nodes": [
7
+ {
8
+ "id": "noop",
9
+ "typeId": "core.noop",
10
+ "name": "Noop",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {},
13
+ "inputs": {}
14
+ }
15
+ ],
16
+ "edges": [],
17
+ "triggers": [
18
+ { "id": "manual", "type": "manual", "enabled": true }
19
+ ],
20
+ "variables": [
21
+ {
22
+ "name": "nonce",
23
+ "type": "string",
24
+ "description": "Caller-supplied opaque token. Server MUST NOT use this for side effects.",
25
+ "required": true
26
+ }
27
+ ],
28
+ "metadata": { "tags": ["conformance"] },
29
+ "settings": { "timeout": 10000 }
30
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "id": "conformance-identity",
3
+ "name": "Conformance: Identity",
4
+ "version": "1.0",
5
+ "description": "Echoes input.payload to output.payload. Verifies input/output passthrough.",
6
+ "nodes": [
7
+ {
8
+ "id": "echo",
9
+ "typeId": "core.identity",
10
+ "name": "Echo",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {},
13
+ "inputs": {
14
+ "payload": { "type": "variable", "variableName": "payload" }
15
+ }
16
+ }
17
+ ],
18
+ "edges": [],
19
+ "triggers": [
20
+ { "id": "manual", "type": "manual", "enabled": true }
21
+ ],
22
+ "variables": [
23
+ {
24
+ "name": "payload",
25
+ "type": "object",
26
+ "description": "Arbitrary JSON payload to echo back.",
27
+ "required": true
28
+ }
29
+ ],
30
+ "metadata": { "tags": ["conformance"] },
31
+ "settings": { "timeout": 10000 }
32
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "id": "conformance-interrupt-auth-required",
3
+ "name": "Conformance: Interrupt — Auth-Required Resume",
4
+ "version": "1.0",
5
+ "description": "Auth-required interrupt fixture for the openwop-interrupt-auth-required profile (interrupt-profiles.md). Suspends on an approval gate that requires the resume caller to present a non-callback bearer (API key OR OAuth2 token) with the approvals:respond scope. The suite verifies (a) signed-token resume via /v1/interrupts/{token} is REJECTED when this profile is active (the profile elevates auth), (b) bearer-token resume succeeds, and (c) bearer-token resume with insufficient scope returns 403. Conformance scenario: interrupt-auth-required-resume.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "gate",
9
+ "typeId": "core.approvalGate",
10
+ "name": "Auth-Required Approval Gate",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "title": "Conformance auth-required approval",
14
+ "description": "Resolution requires a bearer credential with approvals:respond scope.",
15
+ "actions": ["accept", "reject"],
16
+ "profile": "openwop-interrupt-auth-required"
17
+ },
18
+ "inputs": {}
19
+ }
20
+ ],
21
+ "edges": [],
22
+ "triggers": [
23
+ { "id": "manual", "type": "manual", "enabled": true }
24
+ ],
25
+ "variables": [],
26
+ "metadata": { "tags": ["conformance", "hitl", "interrupt-profile", "auth-required"] },
27
+ "settings": { "timeout": 0 }
28
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "id": "conformance-interrupt-external-event",
3
+ "name": "Conformance: Interrupt — External Event",
4
+ "version": "1.0",
5
+ "description": "External-event interrupt fixture for the openwop-interrupt-external-event profile (interrupt-profiles.md). Suspends waiting for an external system to POST to /v1/interrupts/{token} with a correlation payload matching {orderId, status}. The suite verifies (a) the suspend persists a signed callback token, (b) a matching external POST resumes the run with the event body in the resume value, and (c) a mismatched correlation payload returns 422 without resuming. Conformance scenario: interrupt-external-event-correlation.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "wait-for-external",
9
+ "typeId": "core.interrupt",
10
+ "name": "Wait For External Event",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "kind": "external-event",
14
+ "data": {
15
+ "eventType": "conformance.external.completed",
16
+ "correlation": {
17
+ "orderId": "fixture-order-1",
18
+ "status": "completed"
19
+ }
20
+ },
21
+ "timeoutMs": 60000
22
+ },
23
+ "inputs": {}
24
+ }
25
+ ],
26
+ "edges": [],
27
+ "triggers": [
28
+ { "id": "manual", "type": "manual", "enabled": true }
29
+ ],
30
+ "variables": [],
31
+ "metadata": { "tags": ["conformance", "hitl", "interrupt-profile", "external-event"] },
32
+ "settings": { "timeout": 0 }
33
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "conformance-interrupt-parent-child-cancel-child",
3
+ "name": "Conformance: Interrupt — Parent/Child Cancel Cascade (Child)",
4
+ "version": "1.0",
5
+ "description": "Child fixture paired with conformance-interrupt-parent-child-cancel. Suspends on an approval that the parent's cancellation must invalidate. Standalone runs of this workflow behave like a vanilla approval gate; the cascade behavior is exercised only when invoked as a child sub-workflow.",
6
+ "nodes": [
7
+ {
8
+ "id": "child-gate",
9
+ "typeId": "core.approvalGate",
10
+ "name": "Child Approval Gate",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "title": "Child approval (will be cascaded-cancel)",
14
+ "description": "Used by parent-child cancel cascade conformance scenario.",
15
+ "actions": ["accept", "reject"]
16
+ },
17
+ "inputs": {}
18
+ }
19
+ ],
20
+ "edges": [],
21
+ "triggers": [
22
+ { "id": "manual", "type": "manual", "enabled": true }
23
+ ],
24
+ "variables": [],
25
+ "metadata": { "tags": ["conformance", "hitl", "interrupt-profile", "parent-child-cancel", "child"] },
26
+ "settings": { "timeout": 0 }
27
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "conformance-interrupt-parent-child-cancel",
3
+ "name": "Conformance: Interrupt — Parent/Child Cancel Cascade",
4
+ "version": "1.0",
5
+ "description": "Parent-side fixture for the openwop-interrupt-parent-child profile (interrupt-profiles.md). Starts a child sub-workflow (conformance-interrupt-parent-child-cancel-child) that suspends on an approval, then cancels the parent run mid-suspend. The suite verifies the cancellation cascades to the child: child run transitions to 'cancelled' with reason 'parent-cancelled', child's pending interrupt is invalidated, and any subsequent attempt to resolve the child interrupt returns 410 Gone. Conformance scenario: interrupt-parent-child-cascade.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "spawn-child",
9
+ "typeId": "core.subWorkflow",
10
+ "name": "Spawn Cancellable Child",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "workflowId": "conformance-interrupt-parent-child-cancel-child",
14
+ "propagateCancellation": true
15
+ },
16
+ "inputs": {}
17
+ }
18
+ ],
19
+ "edges": [],
20
+ "triggers": [
21
+ { "id": "manual", "type": "manual", "enabled": true }
22
+ ],
23
+ "variables": [],
24
+ "metadata": { "tags": ["conformance", "hitl", "interrupt-profile", "parent-child-cancel"] },
25
+ "settings": { "timeout": 0 }
26
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "id": "conformance-interrupt-quorum",
3
+ "name": "Conformance: Interrupt — Quorum Approval",
4
+ "version": "1.0",
5
+ "description": "Multi-approver quorum interrupt fixture for the openwop-interrupt-quorum profile (interrupt-profiles.md). Suspends with requiredApprovals: 3 and rejectionPolicy: 'majority'. The suite resolves the interrupt with sequential approvals and verifies (a) partial votes emit incremental events without resuming, (b) the third accept fires the suspend resume, and (c) a majority-reject path on a different run terminates the gate with the rejection envelope. Conformance scenario: interrupt-quorum-resolution.test.ts.",
6
+ "nodes": [
7
+ {
8
+ "id": "gate",
9
+ "typeId": "core.approvalGate",
10
+ "name": "Quorum Approval Gate",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "title": "Conformance quorum approval",
14
+ "description": "Three-approver quorum required.",
15
+ "actions": ["accept", "reject"],
16
+ "requiredApprovals": 3,
17
+ "rejectionPolicy": "majority",
18
+ "approversList": []
19
+ },
20
+ "inputs": {}
21
+ }
22
+ ],
23
+ "edges": [],
24
+ "triggers": [
25
+ { "id": "manual", "type": "manual", "enabled": true }
26
+ ],
27
+ "variables": [],
28
+ "metadata": { "tags": ["conformance", "hitl", "interrupt-profile", "quorum"] },
29
+ "settings": { "timeout": 0 }
30
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "id": "conformance-mcp-tool-roundtrip",
3
+ "name": "Conformance: MCP Tool Roundtrip",
4
+ "version": "1.0",
5
+ "description": "Track 6 fixture for `mcp-tool-roundtrip.test.ts`. Workflow invokes a single MCP tool (`echo`) on a host-configured MCP server. The conformance suite stands up a synthetic MCP server at startup; operators configure the host to use that server. The fixture's tool call MUST surface in the run's event log with the trust boundary intact per `threat-model-prompt-injection.md` §UNTRUSTED marker. Hosts that don't wire MCP-aware nodes can stub this fixture as `core.noop` — the host-mediated subtest skips when no `tools/call` invocations reach the synthetic server.",
6
+ "nodes": [
7
+ {
8
+ "id": "mcp-call",
9
+ "typeId": "core.ai.callPrompt",
10
+ "name": "Invoke MCP echo tool",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "mcp": {
14
+ "tool": "echo",
15
+ "arguments": {
16
+ "text": "roundtrip-probe"
17
+ }
18
+ }
19
+ },
20
+ "inputs": {}
21
+ }
22
+ ],
23
+ "edges": [],
24
+ "triggers": [
25
+ { "id": "manual", "type": "manual", "enabled": true }
26
+ ],
27
+ "variables": [
28
+ { "name": "text", "type": "string", "defaultValue": "roundtrip-probe" }
29
+ ],
30
+ "metadata": { "tags": ["conformance", "mcp", "roundtrip"] },
31
+ "settings": { "timeout": 0 }
32
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "id": "conformance-message-reducer",
3
+ "name": "Conformance: Message Reducer Idempotency",
4
+ "version": "1.0",
5
+ "description": "Phase 1. Declares a `messages` channel with the `message` reducer; the fixture intentionally emits the same `messageId` twice to exercise idempotency. Final channel state MUST contain each messageId exactly once. See agentMessageReducer.test.ts and channels-and-reducers.md §`message`.",
6
+ "nodes": [
7
+ {
8
+ "id": "emit-duplicate-message",
9
+ "typeId": "core.identity",
10
+ "name": "Emit (with intentional duplicate messageId)",
11
+ "position": { "x": 0, "y": 0 },
12
+ "config": {
13
+ "emitDuplicateMessageId": true
14
+ },
15
+ "inputs": {}
16
+ }
17
+ ],
18
+ "edges": [],
19
+ "triggers": [
20
+ { "id": "manual", "type": "manual", "enabled": true }
21
+ ],
22
+ "variables": [],
23
+ "channels": {
24
+ "messages": {
25
+ "schema": { "type": "array" },
26
+ "reducer": "message"
27
+ }
28
+ },
29
+ "metadata": { "tags": ["conformance", "multi-agent", "phase-1", "reducer", "idempotency"] },
30
+ "settings": { "timeout": 10000 }
31
+ }