@openwop/spec-artifacts 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 (229) hide show
  1. package/CORPUS-STAMP.json +234 -0
  2. package/LICENSE +201 -0
  3. package/README.md +7 -0
  4. package/api/.redocly.lint-ignore.yaml +22 -0
  5. package/api/asyncapi.yaml +834 -0
  6. package/api/grpc/openwop.proto +251 -0
  7. package/api/openapi.yaml +2693 -0
  8. package/api/redocly.yaml +23 -0
  9. package/api/seams-v2.yaml +680 -0
  10. package/api/v2/asyncapi.yaml +528 -0
  11. package/api/v2/openapi.yaml +3139 -0
  12. package/api/v2/redocly.yaml +16 -0
  13. package/package.json +10 -0
  14. package/schemas/README.md +144 -0
  15. package/schemas/a2a-task-state.schema.json +78 -0
  16. package/schemas/a2ui-surface-delta-frame.schema.json +48 -0
  17. package/schemas/agent-deployment-transition.schema.json +49 -0
  18. package/schemas/agent-deployment.schema.json +54 -0
  19. package/schemas/agent-eval-suite.schema.json +140 -0
  20. package/schemas/agent-inventory-response.schema.json +115 -0
  21. package/schemas/agent-manifest.schema.json +156 -0
  22. package/schemas/agent-org-chart.schema.json +82 -0
  23. package/schemas/agent-ref.schema.json +63 -0
  24. package/schemas/agent-roster-entry.schema.json +81 -0
  25. package/schemas/agent-roster-response.schema.json +21 -0
  26. package/schemas/ai-envelope.schema.json +134 -0
  27. package/schemas/annotation-create.schema.json +37 -0
  28. package/schemas/annotation.schema.json +56 -0
  29. package/schemas/artifact-type-pack-manifest.schema.json +244 -0
  30. package/schemas/audit-verify-result.schema.json +90 -0
  31. package/schemas/budget-policy.schema.json +18 -0
  32. package/schemas/capabilities.schema.json +4160 -0
  33. package/schemas/certification-bundle-v2.schema.json +118 -0
  34. package/schemas/channel-presence-payload.schema.json +41 -0
  35. package/schemas/channel-written-payload.schema.json +55 -0
  36. package/schemas/chat-card-pack-manifest.schema.json +253 -0
  37. package/schemas/compact-tool-descriptor.schema.json +51 -0
  38. package/schemas/compensation-policy.schema.json +64 -0
  39. package/schemas/conformance-certification-bundle.schema.json +86 -0
  40. package/schemas/connection-pack-manifest.schema.json +353 -0
  41. package/schemas/conversation-event.schema.json +168 -0
  42. package/schemas/conversation-turn.schema.json +117 -0
  43. package/schemas/core-conformance-mock-agent-config.schema.json +152 -0
  44. package/schemas/credential-provenance.schema.json +18 -0
  45. package/schemas/credential-reference.schema.json +21 -0
  46. package/schemas/debug-bundle.schema.json +196 -0
  47. package/schemas/dispatch-config.schema.json +112 -0
  48. package/schemas/envelopes/clarification.request.schema.json +52 -0
  49. package/schemas/envelopes/error.schema.json +30 -0
  50. package/schemas/envelopes/media.audio.schema.json +38 -0
  51. package/schemas/envelopes/media.file.schema.json +37 -0
  52. package/schemas/envelopes/media.image.schema.json +33 -0
  53. package/schemas/envelopes/schema.request.schema.json +26 -0
  54. package/schemas/envelopes/schema.response.schema.json +22 -0
  55. package/schemas/envelopes/ui.a2ui-surface.schema.json +154 -0
  56. package/schemas/error-envelope.schema.json +25 -0
  57. package/schemas/eval-summary.schema.json +92 -0
  58. package/schemas/export-bundle.schema.json +66 -0
  59. package/schemas/form-content-pack-manifest.schema.json +243 -0
  60. package/schemas/frontend-plugin-manifest.schema.json +109 -0
  61. package/schemas/goal.schema.json +104 -0
  62. package/schemas/heartbeat-evaluated.schema.json +14 -0
  63. package/schemas/heartbeat-state-changed.schema.json +14 -0
  64. package/schemas/localized-content-language-settings.schema.json +26 -0
  65. package/schemas/localized-content-page-response.schema.json +60 -0
  66. package/schemas/localized-content-page.schema.json +62 -0
  67. package/schemas/localized-content-section.schema.json +51 -0
  68. package/schemas/memory-entry.schema.json +36 -0
  69. package/schemas/memory-list-options.schema.json +37 -0
  70. package/schemas/node-pack-manifest.schema.json +654 -0
  71. package/schemas/orchestrator-decision.schema.json +90 -0
  72. package/schemas/org-chart-responsibility-view.schema.json +26 -0
  73. package/schemas/pack-lockfile.schema.json +108 -0
  74. package/schemas/prompt-kind.schema.json +8 -0
  75. package/schemas/prompt-pack-manifest.schema.json +117 -0
  76. package/schemas/prompt-ref.schema.json +40 -0
  77. package/schemas/prompt-template.schema.json +149 -0
  78. package/schemas/proposal.schema.json +84 -0
  79. package/schemas/registry-version-manifest.schema.json +208 -0
  80. package/schemas/residency.schema.json +16 -0
  81. package/schemas/run-ancestry-response.schema.json +54 -0
  82. package/schemas/run-diff-response.schema.json +64 -0
  83. package/schemas/run-event-payloads.schema.json +4452 -0
  84. package/schemas/run-event.schema.json +211 -0
  85. package/schemas/run-options.schema.json +80 -0
  86. package/schemas/run-orchestrator-decided-event.schema.json +20 -0
  87. package/schemas/run-snapshot.schema.json +148 -0
  88. package/schemas/security-advisory.schema.json +109 -0
  89. package/schemas/self-hosted-runner-dispatch-frame.schema.json +79 -0
  90. package/schemas/self-hosted-runner-registration.schema.json +53 -0
  91. package/schemas/self-hosted-runner-result-frame.schema.json +38 -0
  92. package/schemas/subject.schema.json +56 -0
  93. package/schemas/suspend-request.schema.json +207 -0
  94. package/schemas/tool-descriptor.schema.json +63 -0
  95. package/schemas/trigger-event.schema.json +222 -0
  96. package/schemas/trigger-subscription-registration.schema.json +67 -0
  97. package/schemas/trigger-subscription.schema.json +26 -0
  98. package/schemas/ui-plugin-message.schema.json +90 -0
  99. package/schemas/v2/a2a-task-state.schema.json +102 -0
  100. package/schemas/v2/a2ui-surface-delta-frame.schema.json +62 -0
  101. package/schemas/v2/agent-deployment-transition.schema.json +67 -0
  102. package/schemas/v2/agent-deployment.schema.json +68 -0
  103. package/schemas/v2/agent-eval-suite.schema.json +214 -0
  104. package/schemas/v2/agent-inventory-response.schema.json +172 -0
  105. package/schemas/v2/agent-manifest.schema.json +218 -0
  106. package/schemas/v2/agent-org-chart.schema.json +149 -0
  107. package/schemas/v2/agent-ref.schema.json +67 -0
  108. package/schemas/v2/agent-roster-entry.schema.json +104 -0
  109. package/schemas/v2/agent-roster-response.schema.json +27 -0
  110. package/schemas/v2/ai-envelope.schema.json +167 -0
  111. package/schemas/v2/annotation-create.schema.json +109 -0
  112. package/schemas/v2/annotation.schema.json +142 -0
  113. package/schemas/v2/artifact-type-pack-manifest.schema.json +245 -0
  114. package/schemas/v2/audit-verify-result.schema.json +110 -0
  115. package/schemas/v2/budget-policy.schema.json +61 -0
  116. package/schemas/v2/capabilities.schema.json +7644 -0
  117. package/schemas/v2/certification-bundle.schema.json +401 -0
  118. package/schemas/v2/channel-presence-payload.schema.json +60 -0
  119. package/schemas/v2/channel-written-payload.schema.json +64 -0
  120. package/schemas/v2/chat-card-pack-manifest.schema.json +254 -0
  121. package/schemas/v2/compact-tool-descriptor.schema.json +108 -0
  122. package/schemas/v2/compensation-policy.schema.json +91 -0
  123. package/schemas/v2/compensation-projection.schema.json +95 -0
  124. package/schemas/v2/configurable.schema.json +110 -0
  125. package/schemas/v2/connection-pack-manifest.schema.json +354 -0
  126. package/schemas/v2/conversation-event.schema.json +281 -0
  127. package/schemas/v2/conversation-turn.schema.json +165 -0
  128. package/schemas/v2/credential-provenance.schema.json +62 -0
  129. package/schemas/v2/credential-reference.schema.json +28 -0
  130. package/schemas/v2/debug-bundle.schema.json +312 -0
  131. package/schemas/v2/dispatch-config.schema.json +147 -0
  132. package/schemas/v2/effect-ledger-projection.schema.json +71 -0
  133. package/schemas/v2/effect-seam-manifest.schema.json +98 -0
  134. package/schemas/v2/envelopes/clarification.request.schema.json +59 -0
  135. package/schemas/v2/envelopes/error.schema.json +35 -0
  136. package/schemas/v2/envelopes/media.audio.schema.json +41 -0
  137. package/schemas/v2/envelopes/media.file.schema.json +40 -0
  138. package/schemas/v2/envelopes/media.image.schema.json +36 -0
  139. package/schemas/v2/envelopes/schema.request.schema.json +29 -0
  140. package/schemas/v2/envelopes/schema.response.schema.json +26 -0
  141. package/schemas/v2/envelopes/ui.a2ui-surface.schema.json +292 -0
  142. package/schemas/v2/error-envelope.schema.json +229 -0
  143. package/schemas/v2/eval-summary.schema.json +166 -0
  144. package/schemas/v2/export-bundle.schema.json +94 -0
  145. package/schemas/v2/form-content-pack-manifest.schema.json +241 -0
  146. package/schemas/v2/frontend-plugin-manifest.schema.json +152 -0
  147. package/schemas/v2/goal.schema.json +188 -0
  148. package/schemas/v2/heartbeat-evaluated.schema.json +34 -0
  149. package/schemas/v2/heartbeat-state-changed.schema.json +31 -0
  150. package/schemas/v2/ids.schema.json +31 -0
  151. package/schemas/v2/localized-content-language-settings.schema.json +34 -0
  152. package/schemas/v2/localized-content-page-response.schema.json +94 -0
  153. package/schemas/v2/localized-content-page.schema.json +87 -0
  154. package/schemas/v2/localized-content-section.schema.json +63 -0
  155. package/schemas/v2/memory-entry.schema.json +45 -0
  156. package/schemas/v2/memory-list-options.schema.json +41 -0
  157. package/schemas/v2/node-pack-manifest.schema.json +657 -0
  158. package/schemas/v2/orchestrator-decision.schema.json +120 -0
  159. package/schemas/v2/org-chart-responsibility-view.schema.json +36 -0
  160. package/schemas/v2/pack-lockfile.schema.json +139 -0
  161. package/schemas/v2/prompt-kind.schema.json +14 -0
  162. package/schemas/v2/prompt-pack-manifest.schema.json +118 -0
  163. package/schemas/v2/prompt-ref.schema.json +42 -0
  164. package/schemas/v2/prompt-template.schema.json +209 -0
  165. package/schemas/v2/proposal.schema.json +145 -0
  166. package/schemas/v2/registry-version-manifest.schema.json +292 -0
  167. package/schemas/v2/residency.schema.json +19 -0
  168. package/schemas/v2/run-ancestry-response.schema.json +68 -0
  169. package/schemas/v2/run-diff-response.schema.json +80 -0
  170. package/schemas/v2/run-event-payloads.schema.json +4588 -0
  171. package/schemas/v2/run-event.schema.json +324 -0
  172. package/schemas/v2/run-options.schema.json +90 -0
  173. package/schemas/v2/run-orchestrator-decided-event.schema.json +22 -0
  174. package/schemas/v2/run-snapshot.schema.json +207 -0
  175. package/schemas/v2/security-advisory.schema.json +138 -0
  176. package/schemas/v2/self-hosted-runner-dispatch-frame.schema.json +119 -0
  177. package/schemas/v2/self-hosted-runner-registration.schema.json +74 -0
  178. package/schemas/v2/self-hosted-runner-result-frame.schema.json +47 -0
  179. package/schemas/v2/subject-link.schema.json +69 -0
  180. package/schemas/v2/subject.schema.json +597 -0
  181. package/schemas/v2/suspend-request.schema.json +370 -0
  182. package/schemas/v2/tool-descriptor.schema.json +150 -0
  183. package/schemas/v2/trigger-event.schema.json +508 -0
  184. package/schemas/v2/trigger-subscription-registration.schema.json +99 -0
  185. package/schemas/v2/trigger-subscription.schema.json +79 -0
  186. package/schemas/v2/ui-plugin-message.schema.json +149 -0
  187. package/schemas/v2/workflow-chain-pack-manifest.schema.json +610 -0
  188. package/schemas/v2/workflow-definition.schema.json +864 -0
  189. package/schemas/v2/workload-identity.schema.json +115 -0
  190. package/schemas/v2/workspace-file-create.schema.json +23 -0
  191. package/schemas/v2/workspace-file.schema.json +45 -0
  192. package/schemas/workflow-chain-pack-manifest.schema.json +615 -0
  193. package/schemas/workflow-definition.schema.json +850 -0
  194. package/schemas/workload-identity.schema.json +79 -0
  195. package/schemas/workspace-file-create.schema.json +20 -0
  196. package/schemas/workspace-file.schema.json +39 -0
  197. package/spec/v1/alias-detectors.json +283 -0
  198. package/spec/v1/capability-declaration-classes.json +176 -0
  199. package/spec/v1/core-standard-manifest.json +423 -0
  200. package/spec/v1/deprecations.json +854 -0
  201. package/spec/v1/deprecations.schema.json +187 -0
  202. package/spec/v1/event-codemap.json +1089 -0
  203. package/spec/v1/event-codemap.schema.json +41 -0
  204. package/spec/v1/extensions.json +1273 -0
  205. package/spec/v1/gaps.json +14581 -0
  206. package/spec/v1/gaps.schema.json +55 -0
  207. package/spec/v1/migrations.json +1822 -0
  208. package/spec/v1/migrations.schema.json +44 -0
  209. package/spec/v1/operation-path-manifest.json +462 -0
  210. package/spec/v1/spec-gaps.json +4823 -0
  211. package/spec/v2/declaration.json +1862 -0
  212. package/spec/v2/declaration.schema.json +305 -0
  213. package/spec/v2/errors.json +837 -0
  214. package/spec/v2/event-codemap.json +1099 -0
  215. package/spec/v2/event-codemap.schema.json +114 -0
  216. package/spec/v2/ext/provider-idempotency/registry.json +6 -0
  217. package/spec/v2/facets/a2a.schema.json +51 -0
  218. package/spec/v2/facets/aiProviders.schema.json +56 -0
  219. package/spec/v2/facets/auth.schema.json +91 -0
  220. package/spec/v2/facets/heartbeat.schema.json +20 -0
  221. package/spec/v2/facets/interrupt.schema.json +29 -0
  222. package/spec/v2/facets/mcp.schema.json +81 -0
  223. package/spec/v2/facets/replay.schema.json +34 -0
  224. package/spec/v2/facets/sandbox.schema.json +31 -0
  225. package/spec/v2/facets/webhooks.schema.json +18 -0
  226. package/spec/v2/path-manifest.json +279 -0
  227. package/spec/v2/peer-dependency-aliases.json +165 -0
  228. package/spec/v2/profiles.json +45 -0
  229. package/spec/v2/release.json +6 -0
@@ -0,0 +1,117 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/conversation-turn.schema.json",
4
+ "title": "ConversationTurn",
5
+ "description": "One turn in a multi-turn conversation. Structural superset of `ConversationMessage` (RFC 0002 §G — append-only, idempotent on `messageId`, replay-deterministic). Adds `role`, optional `agent` reference, and `turnIndex` discriminators. Folds through the existing `applyMessage` reducer unchanged. See RFC 0005 §C.",
6
+ "type": "object",
7
+ "required": ["messageId", "from", "content", "ts", "role", "turnIndex"],
8
+ "properties": {
9
+ "messageId": {
10
+ "type": "string",
11
+ "description": "Dedup key. Producers MUST construct a deterministic id so re-folding is idempotent. Recommended encoding: `${conversationId}:${turnIndex}:${role}` (e.g., `run-abc:n1:0:7:agent`).",
12
+ "minLength": 1,
13
+ "maxLength": 256
14
+ },
15
+ "from": {
16
+ "type": "string",
17
+ "description": "Sender identity. Either an agent ID (RFC 0002 §A1) or the literal `'user'` for human-originated turns.",
18
+ "minLength": 1,
19
+ "maxLength": 256
20
+ },
21
+ "to": {
22
+ "type": "string",
23
+ "description": "Optional addressee. Absent = broadcast to the conversation's group (or the run's default participants).",
24
+ "maxLength": 256
25
+ },
26
+ "groupId": {
27
+ "type": "string",
28
+ "description": "Optional shared-agent group ID. When set, the turn is scoped to the `shared:<groupId>` agent context per RFC 0002 §A8.",
29
+ "maxLength": 256
30
+ },
31
+ "content": {
32
+ "description": "Opaque turn content. Protocol does not standardize the shape; hosts use Zod schemas at the application layer for structured turns. Pass-through for any JSON value.",
33
+ "type": ["object", "array", "string", "number", "boolean", "null"]
34
+ },
35
+ "ts": {
36
+ "type": "integer",
37
+ "minimum": 0,
38
+ "description": "Turn timestamp (ms epoch). Caller's clock; replay carries through unchanged for determinism."
39
+ },
40
+ "role": {
41
+ "type": "string",
42
+ "enum": ["user", "agent", "system"],
43
+ "description": "Discriminator distinguishing human-originated turns (`'user'`), AI-agent-originated turns (`'agent'`), and host-emitted procedural turns (`'system'` — e.g., `'conversation timed out'`)."
44
+ },
45
+ "agent": {
46
+ "type": "object",
47
+ "description": "Optional agent reference (RFC 0002 §A1 `AgentRef`) for `role: 'agent'` turns. The same shape RFC 0002 reserves on `RunSnapshot.agent` and `node.started.payload.agent` — propagated through inheritance.",
48
+ "properties": {
49
+ "agentId": {
50
+ "type": "string",
51
+ "minLength": 1
52
+ },
53
+ "agentSharing": {
54
+ "type": "string",
55
+ "enum": ["isolated", "shared", "shared:%shared%"],
56
+ "description": "Per RFC 0002 §A8 — `shared:<groupId>` requires a `groupId` field on the message."
57
+ },
58
+ "memoryRef": {
59
+ "type": "string",
60
+ "description": "Opaque memory reference per RFC 0002 §A + RFC 0004 §A. Resolves to `MemoryEntry[]` via host `MemoryAdapter` for cross-run conversation continuity."
61
+ },
62
+ "model": {
63
+ "type": "object",
64
+ "description": "RFC 0109 — OPTIONAL provenance: which model produced this `role: 'agent'` turn. NON-SECRET, NON-PII: provider + model identifiers ONLY (`additionalProperties: false` forbids any credential/endpoint/prompt leaking in — the SR-1 secret-redaction guard). Stamped at emit; read VERBATIM on `:fork` (never re-resolved). A host that stamps it MUST advertise `conversationTurnModelProvenance.supported: true`. Absent ⇒ no advertisement; clients MUST tolerate its absence.",
65
+ "additionalProperties": false,
66
+ "required": ["provider", "model"],
67
+ "properties": {
68
+ "provider": { "type": "string", "minLength": 1, "maxLength": 128, "description": "Provider identifier (e.g. `anthropic`, `openai`, `google`). Non-secret." },
69
+ "model": { "type": "string", "minLength": 1, "maxLength": 256, "description": "Model identifier as the provider names it (e.g. `claude-opus-4-8`). Non-secret." }
70
+ }
71
+ }
72
+ },
73
+ "additionalProperties": true
74
+ },
75
+ "turnIndex": {
76
+ "type": "integer",
77
+ "minimum": 0,
78
+ "description": "0-based index within the conversation. `conversation.opened.initialTurn` carries `turnIndex: 0`; subsequent `conversation.exchanged` turns increment monotonically; `conversation.closed.finalTurn` carries the highest index."
79
+ },
80
+ "speakerId": {
81
+ "type": "string",
82
+ "minLength": 1,
83
+ "maxLength": 256,
84
+ "description": "RFC 0101. Stable speaker identity of this turn — the roster INSTANCE id of the agent that produced it (the `host:<id>` AgentRef agentId per `agent-roster-entry.schema.json` §A / RFC 0086), NOT the manifest/class `AgentRef.agentId`. REQUIRED when `role: 'agent'` (the conditional below) so that 'turn N was spoken by agent X' is an observable, replay-stable, cross-host-projectable fact in a multi-party transcript. When a `participants` roster is declared on `conversation.opened` (RFC 0101), `speakerId` MUST be a member of that roster; a turn whose `speakerId` is not a participant MUST be rejected (host-enforced, capability-gated on `multiPartyConversation.supported`). For `role: 'user'` / `role: 'system'` turns the field is OPTIONAL and carries no normative meaning. Additive-safe: pre-RFC-0101 `role: 'agent'` turns that omit it are accepted by hosts that do NOT advertise `multiPartyConversation`."
85
+ }
86
+ },
87
+ "allOf": [
88
+ {
89
+ "$comment": "RFC 0101 — agent turns MUST carry speaker attribution. Conditional (not unconditional `required`) so the field is only mandatory for `role: 'agent'`; `user`/`system` turns and pre-RFC-0101 producers on non-multi-party hosts are unaffected. Capability-gated: hosts enforce this only when advertising `multiPartyConversation.supported` (capabilities.schema.json).",
90
+ "if": { "properties": { "role": { "const": "agent" } }, "required": ["role"] },
91
+ "then": { "required": ["speakerId"] }
92
+ }
93
+ ],
94
+ "examples": [
95
+ {
96
+ "$comment": "RFC 0101 POSITIVE — an agent turn in a multi-party council carrying speaker attribution (the roster instance id).",
97
+ "messageId": "council-q1:1:agent",
98
+ "from": "host:advisor-cfo",
99
+ "content": "From a cash-runway view I'd push the launch one quarter.",
100
+ "ts": 1718900000000,
101
+ "role": "agent",
102
+ "turnIndex": 1,
103
+ "speakerId": "host:advisor-cfo"
104
+ },
105
+ {
106
+ "$comment": "RFC 0101 POSITIVE — a user turn; speakerId is OPTIONAL for non-agent roles and omitted here.",
107
+ "messageId": "council-q1:0:user",
108
+ "from": "user",
109
+ "content": "Should we launch in Q3 or Q4?",
110
+ "ts": 1718900000000,
111
+ "role": "user",
112
+ "turnIndex": 0
113
+ }
114
+ ],
115
+ "$comment": "RFC 0101 NEGATIVE (covered by the `allOf`/`if` conditional + conversation scenarios, NOT validatable as an `examples[]` entry which must be VALID): a `{ role: 'agent', ... }` turn that OMITS `speakerId` MUST FAIL validation; see conformance/src/scenarios/multi-party-conversation-shape.test.ts.",
116
+ "additionalProperties": true
117
+ }
@@ -0,0 +1,152 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/core-conformance-mock-agent-config.schema.json",
4
+ "title": "CoreConformanceMockAgentConfig",
5
+ "description": "Config shape for the `core.conformance.mock-agent` typeId (RFC 0023). Conformance-only — hosts MUST refuse this typeId for production tenants unless `capabilities.conformance.mockAgent` is advertised. Emission contract is normative per RFC 0023 §B: when set, the host fires `agent.reasoned`, `agent.toolCalled`/`agent.toolReturned` pairs, `agent.handoff`, and `agent.decided` in the order documented, then evaluates the resolved escalation threshold against any `confidence` value and follows with `node.suspended { reason: 'low-confidence' }` when below threshold (`spec/v1/interrupt.md` §`kind: \"low-confidence\"`).",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "agentId": {
10
+ "type": "string",
11
+ "minLength": 3,
12
+ "description": "Optional override for the `agentId` field carried on emitted `agent.*` events. Resolution order: this field → `nodes[].agent.agentId` (the workflow-level pin) → a host-minted synthetic id (e.g., `host:mock-agent:<nodeId>`). Hosts SHOULD prefer the workflow-level pin so conformance fixtures stay self-describing."
13
+ },
14
+ "mockReasoning": {
15
+ "oneOf": [
16
+ { "type": "boolean" },
17
+ {
18
+ "type": "object",
19
+ "required": ["summary"],
20
+ "additionalProperties": false,
21
+ "properties": {
22
+ "summary": {
23
+ "type": "string",
24
+ "description": "Short one-line digest, projected onto `agent.reasoned.payload.summary` per RFC 0002 §B."
25
+ },
26
+ "trace": {
27
+ "type": "string",
28
+ "description": "Full reasoning text. Hosts SHOULD redact when the run advertises BYOK + redaction per RFC 0002 §B (`agent.reasoned`)."
29
+ },
30
+ "tokenCount": {
31
+ "type": "integer",
32
+ "minimum": 0,
33
+ "description": "Optional reasoning-token count for observability/cost attribution."
34
+ },
35
+ "streamChunks": {
36
+ "type": "array",
37
+ "items": { "type": "string" },
38
+ "description": "RFC 0024. When present, the host MUST emit one `agent.reasoning.delta` event per array entry (in order; `sequence` starts at 0 and increments by 1), THEN emit the closing `agent.reasoned` event whose `reasoning` field equals the concatenation of all `streamChunks`. When absent, only the closing `agent.reasoned` event fires (the pre-RFC-0024 behavior). Gated at conformance test time on `capabilities.agents.reasoning.streaming: true`."
39
+ }
40
+ }
41
+ }
42
+ ],
43
+ "description": "When set, emit `agent.reasoned`. Boolean `true` MUST surface a host-generated stub summary; an object is projected onto the `agent.reasoned` payload shape from RFC 0002 §B. When unset, no `agent.reasoned` event is emitted."
44
+ },
45
+ "mockToolCalls": {
46
+ "type": "array",
47
+ "description": "Emit `agent.toolCalled` + `agent.toolReturned` pairs in array order. Each pair shares a host-minted `callId`; the `agent.toolReturned.causationId` MUST equal the corresponding `agent.toolCalled.eventId` per RFC 0002 §B. An entry without `result` and without `error` is invalid and MUST be rejected at registration.",
48
+ "items": {
49
+ "type": "object",
50
+ "required": ["toolId"],
51
+ "additionalProperties": false,
52
+ "properties": {
53
+ "toolId": {
54
+ "type": "string",
55
+ "description": "Tool identifier in `<scope>:<tool-id>` form, projected onto `agent.toolCalled.payload.toolId` and `agent.toolReturned.payload.toolId`."
56
+ },
57
+ "arguments": {
58
+ "description": "Arguments object projected onto `agent.toolCalled.payload.arguments`. Any JSON value."
59
+ },
60
+ "result": {
61
+ "description": "Success result projected onto `agent.toolReturned.payload.result`. Any JSON value. Mutually exclusive with `error` (validators that need stricter enforcement SHOULD layer it host-side)."
62
+ },
63
+ "error": {
64
+ "$ref": "#/$defs/ErrorEnvelope",
65
+ "description": "Failure projected onto `agent.toolReturned.payload.error`. Shape matches `error-envelope.schema.json` (inlined here as `$defs.ErrorEnvelope` so the spec-corpus validity test can compile this schema in isolation). When present, the paired `agent.toolReturned` event MUST omit `result`."
66
+ },
67
+ "durationMs": {
68
+ "type": "integer",
69
+ "minimum": 0,
70
+ "description": "Optional duration projected onto `agent.toolReturned.payload.durationMs`."
71
+ }
72
+ }
73
+ }
74
+ },
75
+ "mockHandoff": {
76
+ "type": "object",
77
+ "required": ["toAgentId"],
78
+ "additionalProperties": false,
79
+ "description": "When set, emit `agent.handoff` with `from` taken from `nodes[].agent` (the current node's pin) and `to.agentId` taken from `toAgentId`. When `nodes[].agent` is absent, hosts MUST use a synthetic `from` AgentRef referencing the resolved emitter `agentId`.",
80
+ "properties": {
81
+ "toAgentId": {
82
+ "type": "string",
83
+ "minLength": 3,
84
+ "description": "Destination agent identifier; projected onto `agent.handoff.payload.to.agentId` per RFC 0002 §B (`agent.handoff`)."
85
+ },
86
+ "reason": {
87
+ "type": "string",
88
+ "description": "Optional free-form reason; projected onto `agent.handoff.payload.reason`."
89
+ },
90
+ "context": {
91
+ "description": "Optional payload value handed across the boundary; projected onto `agent.handoff.payload.context`."
92
+ }
93
+ }
94
+ },
95
+ "mockDecision": {
96
+ "type": "object",
97
+ "required": ["decision"],
98
+ "additionalProperties": false,
99
+ "description": "When set, emit `agent.decided`. When `confidence` is present AND below the resolved escalation threshold (`RunOptions.configurable.escalationThreshold` overrides `agent-manifest.confidence.defaultThreshold` overrides the spec default `0.7`), the host MUST follow the `agent.decided` event with `node.suspended { reason: 'low-confidence' }` and transition the run to `'waiting-approval'` per `spec/v1/interrupt.md:278`.",
100
+ "properties": {
101
+ "decision": {
102
+ "description": "Host-defined decision payload projected onto `agent.decided.payload.decision`. Any JSON value."
103
+ },
104
+ "confidence": {
105
+ "type": "number",
106
+ "minimum": 0,
107
+ "maximum": 1,
108
+ "description": "Optional confidence in `[0.0, 1.0]`. Triggers the §F escalation contract from RFC 0002 when below the resolved threshold."
109
+ },
110
+ "reasoning": {
111
+ "type": "string",
112
+ "description": "Optional rationale projected onto `agent.decided.payload.reasoning`."
113
+ }
114
+ }
115
+ },
116
+ "mockConfidence": {
117
+ "type": "number",
118
+ "minimum": 0,
119
+ "maximum": 1,
120
+ "description": "Shorthand. When set AND `mockDecision` is absent, the host emits `agent.decided` with a synthetic decision payload (host-defined; the conformance suite does not assert on its shape) carrying this confidence. Triggers the same escalation contract as `mockDecision.confidence`. Retained for compatibility with the pre-RFC-0023 fixture surface; new fixtures SHOULD prefer the explicit `mockDecision` form."
121
+ }
122
+ },
123
+ "examples": [
124
+ {
125
+ "mockReasoning": { "summary": "Considered three options; chose A.", "tokenCount": 42 },
126
+ "mockToolCalls": [
127
+ { "toolId": "openwop.search.web", "arguments": { "q": "openwop" }, "result": ["hit-1", "hit-2"], "durationMs": 12 }
128
+ ],
129
+ "mockDecision": { "decision": { "next": "summarize" }, "confidence": 0.92 }
130
+ },
131
+ {
132
+ "mockDecision": { "decision": { "kind": "stub-low-conf" }, "confidence": 0.5 }
133
+ },
134
+ {
135
+ "mockConfidence": 0.5
136
+ }
137
+ ],
138
+ "$defs": {
139
+ "ErrorEnvelope": {
140
+ "title": "ErrorEnvelope",
141
+ "description": "Inlined from `error-envelope.schema.json` for in-isolation Ajv compile. Spec corpus schemas compile under the conformance suite's per-file Ajv harness which does not preload sibling schemas — cross-file `$ref`s would fail. The wire shape MUST match `https://openwop.dev/spec/v1/error-envelope.schema.json`; this $defs entry is a copy, not a divergence.",
142
+ "type": "object",
143
+ "required": ["error", "message"],
144
+ "properties": {
145
+ "error": { "type": "string", "minLength": 1 },
146
+ "message": { "type": "string", "minLength": 1 },
147
+ "details": { "type": "object" }
148
+ },
149
+ "additionalProperties": false
150
+ }
151
+ }
152
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/credential-provenance.schema.json",
4
+ "title": "CredentialProvenance",
5
+ "description": "RFC 0079 §A. Metadata ABOUT a host-issued credential (an RFC 0046 stored reference or an RFC 0047 OAuth token) attached at the tool/egress boundary — never the secret value (SR-1; reuses the RFC 0046 `credential-payload-redaction` posture). Travels with the egress decision, not the credential material. The §C audience-binding MUST is evaluated against `audiences`.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["credentialId", "issuer", "audiences"],
9
+ "properties": {
10
+ "credentialId": { "type": "string", "minLength": 1, "description": "Stable host-issued id for the credential (the RFC 0046 `ref`, or an OAuth-grant id). Correlates audit + the Keys-page view. NOT the secret value." },
11
+ "issuer": { "type": "string", "minLength": 1, "description": "Who minted/owns the credential — the host itself (`host`), an RFC 0047 OAuth provider id, or a BYOK principal (RFC 0046). Lets a consumer distinguish host-managed from caller-supplied credentials." },
12
+ "audiences": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "REQUIRED. The destination hosts/domains (or destination-class ids) the credential is valid for. The §C binding MUST is evaluated against this list — a credential MUST NOT be attached to an egress outside its audiences. Matching is exact host or an explicit `*.domain` suffix form (no arbitrary regex — injection risk; RFC 0079 §UQ1)." },
13
+ "scopes": { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "description": "MAY — RFC 0049 scopes the credential grants (e.g. `egress:stripe:charge`)." },
14
+ "expiresAt": { "type": "string", "format": "date-time", "description": "MAY — credential expiry; an expired credential MUST NOT be attached (deny, `reason: \"expired\"`)." },
15
+ "redactionPolicy": { "type": "string", "enum": ["always", "hash", "host-policy"], "description": "MAY — how the credential surfaces in logs/events. `always`: never appears (default posture, SR-1); `hash`: an SR-1-redacted digest MAY appear; `host-policy`: host-defined. The secret value itself is NEVER on the wire regardless." },
16
+ "auditCorrelationId": { "type": "string", "minLength": 1, "description": "MAY — id correlating this credential's egress decisions across the run's `egress.decided` events + the host audit log." }
17
+ }
18
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/credential-reference.schema.json",
4
+ "title": "CredentialReference",
5
+ "description": "RFC 0046. An opaque, host-issued handle to a stored credential. This is the ONLY credential artifact permitted on the wire — it NEVER carries key material. The host's host.credentials resolver dereferences it into the node sandbox at execution time (SECURITY invariant `credential-payload-redaction`).",
6
+ "type": "object",
7
+ "required": ["ref"],
8
+ "properties": {
9
+ "ref": {
10
+ "type": "string",
11
+ "minLength": 1,
12
+ "description": "Opaque host-issued identifier, e.g. `cred_a3b9c2`. Hosts MUST NOT encode secret material in the ref."
13
+ },
14
+ "scope": {
15
+ "type": "string",
16
+ "enum": ["user", "workspace", "tenant"],
17
+ "description": "Resolution scope. MUST match a scope in `capabilities.credentials.scopes`. Absent ⇒ the host's default scope."
18
+ }
19
+ },
20
+ "additionalProperties": false
21
+ }
@@ -0,0 +1,196 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/debug-bundle.schema.json",
4
+ "title": "RunDebugBundle",
5
+ "description": "Portable JSON export of a single run's diagnostic state. See spec/v1/debug-bundle.md. Additive over v1 per COMPATIBILITY.md §2.1: optional endpoint; hosts MAY omit.",
6
+ "type": "object",
7
+ "required": [
8
+ "bundleVersion",
9
+ "generatedAt",
10
+ "host",
11
+ "run",
12
+ "events",
13
+ "redactionApplied",
14
+ "redactionMode"
15
+ ],
16
+ "properties": {
17
+ "bundleVersion": {
18
+ "type": "string",
19
+ "description": "Schema version of the bundle. v1.x bundles are '1'.",
20
+ "pattern": "^[0-9]+(\\.[0-9]+)?$"
21
+ },
22
+ "generatedAt": {
23
+ "type": "string",
24
+ "format": "date-time",
25
+ "description": "ISO 8601 timestamp when the host generated this response."
26
+ },
27
+ "host": {
28
+ "type": "object",
29
+ "description": "Identifies the host that produced the bundle.",
30
+ "required": ["name", "version"],
31
+ "properties": {
32
+ "name": { "type": "string", "minLength": 1 },
33
+ "version": { "type": "string", "minLength": 1 },
34
+ "vendor": { "type": "string" }
35
+ },
36
+ "additionalProperties": false
37
+ },
38
+ "run": {
39
+ "type": "object",
40
+ "description": "Run snapshot — same shape as GET /v1/runs/{runId}. See run-snapshot.schema.json.",
41
+ "required": ["runId", "workflowId", "status"],
42
+ "properties": {
43
+ "runId": { "type": "string", "minLength": 1 },
44
+ "workflowId": { "type": "string", "minLength": 1 },
45
+ "status": {
46
+ "type": "string",
47
+ "enum": [
48
+ "pending",
49
+ "running",
50
+ "completed",
51
+ "failed",
52
+ "cancelled",
53
+ "waiting-approval",
54
+ "waiting-clarification"
55
+ ]
56
+ },
57
+ "startedAt": { "type": "string", "format": "date-time" },
58
+ "endedAt": {
59
+ "oneOf": [
60
+ { "type": "string", "format": "date-time" },
61
+ { "type": "null" }
62
+ ]
63
+ },
64
+ "error": {
65
+ "oneOf": [
66
+ { "type": "null" },
67
+ {
68
+ "type": "object",
69
+ "required": ["code"],
70
+ "properties": {
71
+ "code": { "type": "string", "minLength": 1 },
72
+ "message": { "type": "string" }
73
+ },
74
+ "additionalProperties": true
75
+ }
76
+ ]
77
+ },
78
+ "inputs": { "type": "object" },
79
+ "variables": { "type": "object" },
80
+ "currentNodeId": {
81
+ "oneOf": [{ "type": "string" }, { "type": "null" }]
82
+ },
83
+ "nodeStates": { "type": "object" },
84
+ "metrics": { "type": "object" }
85
+ },
86
+ "additionalProperties": true
87
+ },
88
+ "events": {
89
+ "type": "array",
90
+ "description": "Full event log for this run, in order. Each entry follows run-event.schema.json.",
91
+ "items": {
92
+ "type": "object",
93
+ "properties": {
94
+ "sequence": {
95
+ "oneOf": [
96
+ { "type": "integer", "minimum": 0 },
97
+ { "type": "null" }
98
+ ]
99
+ },
100
+ "seq": {
101
+ "oneOf": [
102
+ { "type": "integer", "minimum": 0 },
103
+ { "type": "null" }
104
+ ],
105
+ "description": "Legacy alias for `sequence`. Hosts that pre-date the rename emit `seq`. Clients accept either."
106
+ },
107
+ "type": { "type": "string", "minLength": 1 },
108
+ "timestamp": { "type": "string", "format": "date-time" },
109
+ "nodeId": {
110
+ "oneOf": [{ "type": "string" }, { "type": "null" }]
111
+ },
112
+ "data": {}
113
+ },
114
+ "additionalProperties": true
115
+ }
116
+ },
117
+ "spans": {
118
+ "type": "array",
119
+ "description": "OTel-format spans per spec/v1/observability.md. Empty array if host doesn't emit spans.",
120
+ "items": {
121
+ "type": "object",
122
+ "required": ["name"],
123
+ "properties": {
124
+ "name": { "type": "string", "minLength": 1 },
125
+ "spanId": { "type": "string" },
126
+ "parentSpanId": {
127
+ "oneOf": [{ "type": "string" }, { "type": "null" }]
128
+ },
129
+ "startedAt": { "type": "string", "format": "date-time" },
130
+ "endedAt": {
131
+ "oneOf": [
132
+ { "type": "string", "format": "date-time" },
133
+ { "type": "null" }
134
+ ]
135
+ },
136
+ "attributes": { "type": "object" }
137
+ },
138
+ "additionalProperties": true
139
+ }
140
+ },
141
+ "metrics": {
142
+ "type": "object",
143
+ "description": "Aggregate metrics for the run.",
144
+ "properties": {
145
+ "openwopCost": {
146
+ "oneOf": [
147
+ { "type": "null" },
148
+ {
149
+ "type": "object",
150
+ "properties": {
151
+ "usd": { "type": "number", "minimum": 0 },
152
+ "tokens": {
153
+ "type": "object",
154
+ "properties": {
155
+ "input": { "type": "integer", "minimum": 0 },
156
+ "output": { "type": "integer", "minimum": 0 }
157
+ },
158
+ "additionalProperties": false
159
+ },
160
+ "model": { "type": "string" },
161
+ "provider": { "type": "string" },
162
+ "duration_ms": { "type": "number", "minimum": 0 }
163
+ },
164
+ "additionalProperties": true
165
+ }
166
+ ]
167
+ },
168
+ "nodeCount": { "type": "integer", "minimum": 0 },
169
+ "eventCount": {
170
+ "type": "integer",
171
+ "minimum": 0,
172
+ "description": "MUST equal events.length per spec/v1/debug-bundle.md."
173
+ }
174
+ },
175
+ "additionalProperties": true
176
+ },
177
+ "redactionApplied": {
178
+ "type": "boolean",
179
+ "description": "True if any field in this bundle was masked/omitted/hashed by the host's redaction harness."
180
+ },
181
+ "redactionMode": {
182
+ "type": "string",
183
+ "enum": ["mask", "omit", "hash", "passthrough"],
184
+ "description": "Masking mode in effect per capabilities.compliance.defaultMode."
185
+ },
186
+ "truncated": {
187
+ "type": "boolean",
188
+ "description": "True when the bundle was truncated to fit the host's size cap."
189
+ },
190
+ "truncatedReason": {
191
+ "type": "string",
192
+ "description": "Why truncation occurred (e.g., 'events_truncated_to_size_cap')."
193
+ }
194
+ },
195
+ "additionalProperties": true
196
+ }
@@ -0,0 +1,112 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/dispatch-config.schema.json",
4
+ "title": "DispatchConfig",
5
+ "description": "Configuration for the `core.dispatch` node typeId (RFC 0007). Pins per-`kind` routing strategies for the dispatch loop. The dispatch node consumes the latest `OrchestratorDecision` (RFC 0006 §C) from the run's projection and acts on it per the per-`kind` semantics in RFC 0007 §D.",
6
+ "type": "object",
7
+ "required": [],
8
+ "properties": {
9
+ "askUserRouting": {
10
+ "type": "string",
11
+ "enum": ["conversation", "clarification", "auto"],
12
+ "default": "auto",
13
+ "description": "Routing surface for `kind: 'ask-user'` decisions. `'conversation'` requires the host to advertise `capabilities.conversationPrimitive: true` (RFC 0005) and uses `conversation.exchange`; `'clarification'` uses the existing `clarification.requested` interrupt (pre-RFC-0010 path); `'auto'` selects `conversation` when the host advertises the conversation-primitive capability and `clarification` otherwise. Hosts that select `'conversation'` without advertising the capability MUST surface a `validation_error` at workflow registration time."
14
+ },
15
+ "workerDispatchModel": {
16
+ "type": "string",
17
+ "enum": ["child-run"],
18
+ "default": "child-run",
19
+ "description": "How `kind: 'next-worker'` is dispatched. v1.x normates only `'child-run'` — each `nextWorkerIds[i]` resolves to a workflow id and is dispatched as a child run via the existing `core.subWorkflow` machinery. Same-run DAG navigation is OUT OF SCOPE for v1.x (deferred to RFC 0013 / v1.3+). Hosts MAY add vendor-extension dispatch models under `vendor.<host>.<model>`; conformance scenarios validate `'child-run'` only."
20
+ },
21
+ "fanOutPolicy": {
22
+ "type": "string",
23
+ "enum": ["sequential", "reject", "parallel"],
24
+ "default": "sequential",
25
+ "description": "Behavior when `decision.kind === 'next-worker'` and `nextWorkerIds.length > 1`. `'sequential'` (default) dispatches each in array order, blocking on each child terminal before starting the next; the dispatch node's output reports the LAST child's `childRunId`/`childStatus` (intermediate child-run identifiers surface in the run's event log via standard `node.*` events). `'reject'` fails the dispatch with a structured `'fan_out_unsupported'` error envelope per `error-envelope.md`. `'parallel'` (RFC 0118) dispatches ALL `nextWorkerIds[i]` as child runs concurrently (bounded by `maxConcurrency`) and joins on their terminals per `joinPolicy`; it REQUIRES the host to advertise `capabilities.dispatch.fanOutSupported: true` — a host that does not MUST surface a `validation_error` at `POST /v1/workflows`."
26
+ },
27
+ "joinPolicy": {
28
+ "type": "object",
29
+ "description": "RFC 0118. Completion + error-aggregation semantics for `fanOutPolicy: 'parallel'`. Meaningful ONLY when `fanOutPolicy === 'parallel'`; a host MUST surface a `validation_error` at registration if `joinPolicy` is present while `fanOutPolicy !== 'parallel'`. `mode` and `onChildFailure` are orthogonal axes (completion condition vs error aggregation).",
30
+ "properties": {
31
+ "mode": {
32
+ "type": "string",
33
+ "enum": ["wait-all", "quorum", "first", "race"],
34
+ "default": "wait-all",
35
+ "description": "When the join is satisfied. `'wait-all'` (default) — the dispatch node stays suspended until EVERY dispatched child reaches a terminal state (`completed`/`failed`/`cancelled`); the only mode that never discards a child's outcome. `'quorum'` — satisfied at `quorum` `completed` children (REQUIRES `quorum`, `1 ≤ quorum ≤ nextWorkerIds.length`; a missing/out-of-range `quorum` is a registration `validation_error`); in-flight children are cancelled per the `interrupt-profiles.md` parent-child cascade. `'first'` — satisfied at the first `completed`; remaining cancelled. `'race'` — satisfied at the first terminal of ANY kind (`completed` OR `failed`); remaining cancelled."
36
+ },
37
+ "quorum": {
38
+ "type": "integer",
39
+ "minimum": 1,
40
+ "description": "Required iff `mode === 'quorum'`. The number of `completed` children that satisfies the join. MUST be `1 ≤ quorum ≤ nextWorkerIds.length`."
41
+ },
42
+ "onChildFailure": {
43
+ "type": "string",
44
+ "enum": ["collect", "fail-fast", "absorb"],
45
+ "default": "collect",
46
+ "description": "How a non-`completed` child terminal affects the dispatch node. `'collect'` (default) — no individual failure short-circuits; the node waits per `mode`, then reports per-child outcomes in its output (§D). `'fail-fast'` — the first child to reach `failed`/`cancelled` immediately fails the dispatch node and cancels the rest (equivalent to single-child `fail-parent` applied at first failure). `'absorb'` — failed children are recorded in the log + node output but never fail the parent; the join still completes per `mode`. The default deliberately DIVERGES from single-child `core.subWorkflow.onChildFailure: 'fail-parent'` because independent fan-out siblings are the common case (RFC 0118 §Resolved Q1)."
47
+ }
48
+ },
49
+ "required": [],
50
+ "additionalProperties": false
51
+ },
52
+ "maxConcurrency": {
53
+ "type": "integer",
54
+ "minimum": 1,
55
+ "description": "RFC 0118. Maximum number of children dispatched concurrently under `fanOutPolicy: 'parallel'`. When `nextWorkerIds.length` exceeds this, the host dispatches in waves of at most `maxConcurrency`, starting a queued child as each in-flight child terminates (the host MUST NOT silently drop children above the ceiling). Absent → host-defined effective concurrency (a host MAY cap to protect itself and MUST advertise that cap as `capabilities.dispatch.maxFanOut`). The EFFECTIVE concurrency is `min(maxConcurrency ?? ∞, capabilities.dispatch.maxFanOut ?? ∞)`. Does not change join semantics — `joinPolicy` evaluates over the full `nextWorkerIds` set. Meaningful only under `fanOutPolicy: 'parallel'`."
56
+ },
57
+ "iterationCap": {
58
+ "type": "integer",
59
+ "minimum": 1,
60
+ "description": "Optional per-run hard cap on dispatch-node executions (across all dispatch nodes in the same run). Independent of `RunOptions.configurable.recursionLimit` / `Capabilities.limits.maxNodeExecutions` — when set, the engine MUST surface a `cap.breached` event with `kind: 'dispatch-iterations'` once exceeded and transition the run to `'failed'`. When absent, the run-level `recursionLimit` cap applies normally (each dispatch counts as one node execution against the run total)."
61
+ },
62
+ "inputMapping": {
63
+ "type": "object",
64
+ "additionalProperties": { "type": "string" },
65
+ "description": "RFC 0022. Default input mapping applied to every dispatched child on the `next-worker` path. Keys are CHILD variable names; values are PARENT variable names. Child receives `inputs[childKey] = parentVariables[parentKey]`. Per-worker overrides (see `perWorkerInputMappings`) take precedence. Mirrors `core.control.subWorkflow.inputMapping` semantics. Gated on `capabilities.agents.dispatchMapping: true`; hosts without that advertisement MUST surface `validation_error` at registration if this field is non-empty."
66
+ },
67
+ "outputMapping": {
68
+ "type": "object",
69
+ "additionalProperties": { "type": "string" },
70
+ "description": "RFC 0022. Default output mapping applied to every completed child on the `next-worker` path. Keys are PARENT variable names; values are CHILD variable names. After a child reaches terminal `completed`, parent's `parentKey` is set to `childVariables[childKey]`. Failed / cancelled children skip the mapping. Per-worker overrides (see `perWorkerOutputMappings`) take precedence. Mirrors `core.control.subWorkflow.outputMapping` semantics. Gated on `capabilities.agents.dispatchMapping: true`."
71
+ },
72
+ "perWorkerInputMappings": {
73
+ "type": "object",
74
+ "additionalProperties": {
75
+ "type": "object",
76
+ "additionalProperties": { "type": "string" }
77
+ },
78
+ "description": "RFC 0022. Per-worker input mapping overrides, keyed by the child `workflowId` that the supervisor may select. When the supervisor's `next-worker` decision names a `workerId` present in this map, the dispatch node uses `perWorkerInputMappings[workerId]` instead of the default `inputMapping`. Lets authors wire distinct variable subsets per potential child."
79
+ },
80
+ "perWorkerOutputMappings": {
81
+ "type": "object",
82
+ "additionalProperties": {
83
+ "type": "object",
84
+ "additionalProperties": { "type": "string" }
85
+ },
86
+ "description": "RFC 0022. Per-worker output mapping overrides, same fallback semantics as `perWorkerInputMappings`."
87
+ }
88
+ },
89
+ "additionalProperties": false,
90
+ "examples": [
91
+ {
92
+ "askUserRouting": "auto",
93
+ "workerDispatchModel": "child-run",
94
+ "fanOutPolicy": "sequential"
95
+ },
96
+ {
97
+ "askUserRouting": "clarification",
98
+ "fanOutPolicy": "reject",
99
+ "iterationCap": 25
100
+ },
101
+ {
102
+ "workerDispatchModel": "child-run",
103
+ "fanOutPolicy": "parallel",
104
+ "maxConcurrency": 5,
105
+ "joinPolicy": { "mode": "wait-all", "onChildFailure": "collect" }
106
+ },
107
+ {
108
+ "fanOutPolicy": "parallel",
109
+ "joinPolicy": { "mode": "quorum", "quorum": 3, "onChildFailure": "fail-fast" }
110
+ }
111
+ ]
112
+ }