@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,4588 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v2/run-event-payloads.schema.json",
4
+ "title": "RunEventPayloads",
5
+ "description": "Per-RunEventType payload schemas. The base RunEventDoc shape (run-event.schema.json) leaves `payload` permissive for forward-compat. This schema defines the canonical payload contract for each known RunEventType. Consumers MAY pin strict payload validation via `$defs.<typeId>` and `ajv.validate(schema.$defs[event.type], event.payload)`. Unknown event types MUST be tolerated (no $defs match → fold best-effort).\n\n117 variants from `run-event.schema.json#$defs.RunEventType` are covered, grouped into ~20 shape families with shared $defs. Naming convention: camelCase keys mirror dotted RunEventType names (e.g., `run.started` → `runStarted`). v2: every definition closed; _typeIndex normative; the legacy interrupt payloads (approval*/clarification*) removed per deprecation row legacy-interrupt-payloads.",
6
+ "type": "object",
7
+ "$defs": {
8
+ "_typeIndex": {
9
+ "description": "Lookup map: RunEventType → $defs key. Informative — consumers can derive this themselves but having it explicit aids tooling.",
10
+ "type": "object",
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "run.started": {
14
+ "$ref": "#/$defs/runStarted"
15
+ },
16
+ "run.completed": {
17
+ "$ref": "#/$defs/runCompleted"
18
+ },
19
+ "run.failed": {
20
+ "$ref": "#/$defs/runFailed"
21
+ },
22
+ "run.cancelled": {
23
+ "$ref": "#/$defs/runCancelled"
24
+ },
25
+ "run.resuming": {
26
+ "$ref": "#/$defs/runResuming"
27
+ },
28
+ "run.paused": {
29
+ "$ref": "#/$defs/runPaused"
30
+ },
31
+ "run.resumed": {
32
+ "$ref": "#/$defs/runResumed"
33
+ },
34
+ "run.restored-from-snapshot": {
35
+ "$ref": "#/$defs/runRestoredFromSnapshot"
36
+ },
37
+ "run.dead_lettered": {
38
+ "$ref": "#/$defs/runDeadLettered"
39
+ },
40
+ "node.started": {
41
+ "$ref": "#/$defs/nodeStarted"
42
+ },
43
+ "node.completed": {
44
+ "$ref": "#/$defs/nodeCompleted"
45
+ },
46
+ "node.failed": {
47
+ "$ref": "#/$defs/nodeFailed"
48
+ },
49
+ "node.suspended": {
50
+ "$ref": "#/$defs/nodeSuspended"
51
+ },
52
+ "node.suspend-failed": {
53
+ "$ref": "#/$defs/nodeSuspendFailed"
54
+ },
55
+ "node.resumed": {
56
+ "$ref": "#/$defs/nodeResumed"
57
+ },
58
+ "node.retried": {
59
+ "$ref": "#/$defs/nodeRetried"
60
+ },
61
+ "node.skipped": {
62
+ "$ref": "#/$defs/nodeSkipped"
63
+ },
64
+ "node.cancelled": {
65
+ "$ref": "#/$defs/nodeCancelled"
66
+ },
67
+ "approval.requested": {
68
+ "$ref": "#/$defs/approvalRequested"
69
+ },
70
+ "approval.received": {
71
+ "$ref": "#/$defs/approvalReceived"
72
+ },
73
+ "approval.granted": {
74
+ "$ref": "#/$defs/approvalGranted"
75
+ },
76
+ "approval.rejected": {
77
+ "$ref": "#/$defs/approvalRejected"
78
+ },
79
+ "approval.overridden": {
80
+ "$ref": "#/$defs/approvalOverridden"
81
+ },
82
+ "clarification.requested": {
83
+ "$ref": "#/$defs/clarificationRequested"
84
+ },
85
+ "clarification.resolved": {
86
+ "$ref": "#/$defs/clarificationResolved"
87
+ },
88
+ "interrupt.requested": {
89
+ "$ref": "#/$defs/interruptRequested"
90
+ },
91
+ "interrupt.resolved": {
92
+ "$ref": "#/$defs/interruptResolved"
93
+ },
94
+ "channel.written": {
95
+ "$ref": "#/$defs/channelWritten"
96
+ },
97
+ "channel.presence": {
98
+ "$ref": "#/$defs/channelPresence"
99
+ },
100
+ "context.summarized": {
101
+ "$ref": "#/$defs/contextSummarized"
102
+ },
103
+ "artifact.created": {
104
+ "$ref": "#/$defs/artifactCreated"
105
+ },
106
+ "output.chunk": {
107
+ "$ref": "#/$defs/outputChunk"
108
+ },
109
+ "variable.changed": {
110
+ "$ref": "#/$defs/variableChanged"
111
+ },
112
+ "log.appended": {
113
+ "$ref": "#/$defs/logAppended"
114
+ },
115
+ "version.pinned": {
116
+ "$ref": "#/$defs/versionPinned"
117
+ },
118
+ "workflow.restored": {
119
+ "$ref": "#/$defs/workflowRestored"
120
+ },
121
+ "workflow.loopback-limit": {
122
+ "$ref": "#/$defs/workflowLoopbackLimit"
123
+ },
124
+ "workflow.stalled": {
125
+ "$ref": "#/$defs/workflowStalled"
126
+ },
127
+ "cap.breached": {
128
+ "$ref": "#/$defs/capBreached"
129
+ },
130
+ "lease.acquired": {
131
+ "$ref": "#/$defs/leaseLifecycle"
132
+ },
133
+ "lease.renewed": {
134
+ "$ref": "#/$defs/leaseLifecycle"
135
+ },
136
+ "lease.lost": {
137
+ "$ref": "#/$defs/leaseLifecycle"
138
+ },
139
+ "lease.handed-off": {
140
+ "$ref": "#/$defs/leaseHandedOff"
141
+ },
142
+ "replay.diverged": {
143
+ "$ref": "#/$defs/replayDiverged"
144
+ },
145
+ "replay.divergedAtRefusal": {
146
+ "$ref": "#/$defs/replayDivergedAtRefusal"
147
+ },
148
+ "agent.reasoned": {
149
+ "$ref": "#/$defs/agentReasoned"
150
+ },
151
+ "agent.reasoning.delta": {
152
+ "$ref": "#/$defs/agentReasoningDelta"
153
+ },
154
+ "provider.usage": {
155
+ "$ref": "#/$defs/providerUsage"
156
+ },
157
+ "prompt.composed": {
158
+ "$ref": "#/$defs/promptComposed"
159
+ },
160
+ "agent.promptResolved": {
161
+ "$ref": "#/$defs/agentPromptResolved"
162
+ },
163
+ "model.capability.substituted": {
164
+ "$ref": "#/$defs/modelCapabilitySubstituted"
165
+ },
166
+ "model.capability.insufficient": {
167
+ "$ref": "#/$defs/modelCapabilityInsufficient"
168
+ },
169
+ "envelope.retry.attempted": {
170
+ "$ref": "#/$defs/envelopeRetryAttempted"
171
+ },
172
+ "envelope.retry.exhausted": {
173
+ "$ref": "#/$defs/envelopeRetryExhausted"
174
+ },
175
+ "envelope.refusal": {
176
+ "$ref": "#/$defs/envelopeRefusal"
177
+ },
178
+ "envelope.truncated": {
179
+ "$ref": "#/$defs/envelopeTruncated"
180
+ },
181
+ "envelope.nlToFormat.engaged": {
182
+ "$ref": "#/$defs/envelopeNlToFormatEngaged"
183
+ },
184
+ "envelope.recovery.applied": {
185
+ "$ref": "#/$defs/envelopeRecoveryApplied"
186
+ },
187
+ "agent.toolCalled": {
188
+ "$ref": "#/$defs/agentToolCalled"
189
+ },
190
+ "agent.toolReturned": {
191
+ "$ref": "#/$defs/agentToolReturned"
192
+ },
193
+ "agent.handoff": {
194
+ "$ref": "#/$defs/agentHandoff"
195
+ },
196
+ "agent.decided": {
197
+ "$ref": "#/$defs/agentDecided"
198
+ },
199
+ "agent.verified": {
200
+ "$ref": "#/$defs/agentVerified"
201
+ },
202
+ "runOrchestrator.decided": {
203
+ "$ref": "#/$defs/runOrchestratorDecided"
204
+ },
205
+ "node.dispatched": {
206
+ "$ref": "#/$defs/nodeDispatched"
207
+ },
208
+ "core.dispatch.fanOut": {
209
+ "$ref": "#/$defs/dispatchFanOut"
210
+ },
211
+ "core.dispatch.join": {
212
+ "$ref": "#/$defs/dispatchJoin"
213
+ },
214
+ "conversation.opened": {
215
+ "$ref": "#/$defs/conversationOpened"
216
+ },
217
+ "conversation.exchanged": {
218
+ "$ref": "#/$defs/conversationExchanged"
219
+ },
220
+ "conversation.closed": {
221
+ "$ref": "#/$defs/conversationClosed"
222
+ },
223
+ "memory.compacted": {
224
+ "$ref": "#/$defs/memoryCompacted"
225
+ },
226
+ "memory.written": {
227
+ "$ref": "#/$defs/memoryWritten"
228
+ },
229
+ "agent.memory.consolidated": {
230
+ "$ref": "#/$defs/agentMemoryConsolidated"
231
+ },
232
+ "commitment.fired": {
233
+ "$ref": "#/$defs/commitmentFired"
234
+ },
235
+ "agent.invocation.started": {
236
+ "$ref": "#/$defs/agentInvocationStarted"
237
+ },
238
+ "agent.invocation.completed": {
239
+ "$ref": "#/$defs/agentInvocationCompleted"
240
+ },
241
+ "workspace.updated": {
242
+ "$ref": "#/$defs/workspaceUpdated"
243
+ },
244
+ "core.workflowChain.event": {
245
+ "$ref": "#/$defs/coreWorkflowChainEvent"
246
+ },
247
+ "core.workflowChain.confidence-escalated": {
248
+ "$ref": "#/$defs/coreWorkflowChainConfidenceEscalated"
249
+ },
250
+ "connector.authorized": {
251
+ "$ref": "#/$defs/connectorAuthorized"
252
+ },
253
+ "connector.auth_expired": {
254
+ "$ref": "#/$defs/connectorAuthExpired"
255
+ },
256
+ "authorization.decided": {
257
+ "$ref": "#/$defs/authorizationDecided"
258
+ },
259
+ "eval.started": {
260
+ "$ref": "#/$defs/evalStarted"
261
+ },
262
+ "eval.scored": {
263
+ "$ref": "#/$defs/evalScored"
264
+ },
265
+ "eval.completed": {
266
+ "$ref": "#/$defs/evalCompleted"
267
+ },
268
+ "deployment.promoted": {
269
+ "$ref": "#/$defs/deploymentPromoted"
270
+ },
271
+ "deployment.rolled-back": {
272
+ "$ref": "#/$defs/deploymentRolledBack"
273
+ },
274
+ "deployment.canary.adjusted": {
275
+ "$ref": "#/$defs/deploymentCanaryAdjusted"
276
+ },
277
+ "deployment.state.changed": {
278
+ "$ref": "#/$defs/deploymentStateChanged"
279
+ },
280
+ "roster.run.initiated": {
281
+ "$ref": "#/$defs/rosterRunInitiated"
282
+ },
283
+ "tool.session.opened": {
284
+ "$ref": "#/$defs/toolSessionOpened"
285
+ },
286
+ "tool.session.closed": {
287
+ "$ref": "#/$defs/toolSessionClosed"
288
+ },
289
+ "egress.decided": {
290
+ "$ref": "#/$defs/egressDecided"
291
+ },
292
+ "trigger.subscription.state.changed": {
293
+ "$ref": "#/$defs/triggerSubscriptionStateChanged"
294
+ },
295
+ "trigger.delivery.attempted": {
296
+ "$ref": "#/$defs/triggerDeliveryAttempted"
297
+ },
298
+ "budget.reserved": {
299
+ "$ref": "#/$defs/budgetReserved"
300
+ },
301
+ "budget.consumed": {
302
+ "$ref": "#/$defs/budgetConsumed"
303
+ },
304
+ "budget.threshold.crossed": {
305
+ "$ref": "#/$defs/budgetThresholdCrossed"
306
+ },
307
+ "budget.exhausted": {
308
+ "$ref": "#/$defs/budgetExhausted"
309
+ },
310
+ "proposal.created": {
311
+ "$ref": "#/$defs/proposalCreated"
312
+ },
313
+ "proposal.activated": {
314
+ "$ref": "#/$defs/proposalActivated"
315
+ },
316
+ "goal.evaluated": {
317
+ "$ref": "#/$defs/goalEvaluated"
318
+ },
319
+ "goal.closed": {
320
+ "$ref": "#/$defs/goalClosed"
321
+ },
322
+ "import.applied": {
323
+ "$ref": "#/$defs/importApplied"
324
+ },
325
+ "voice.speech_start": {
326
+ "$ref": "#/$defs/voiceSpeechStart"
327
+ },
328
+ "voice.transcript": {
329
+ "$ref": "#/$defs/voiceTranscript"
330
+ },
331
+ "voice.endpoint_candidate": {
332
+ "$ref": "#/$defs/voiceEndpointCandidate"
333
+ },
334
+ "voice.turn_commit": {
335
+ "$ref": "#/$defs/voiceTurnCommit"
336
+ },
337
+ "voice.synthesis_chunk": {
338
+ "$ref": "#/$defs/voiceSynthesisChunk"
339
+ },
340
+ "voice.barge_in": {
341
+ "$ref": "#/$defs/voiceBargeIn"
342
+ },
343
+ "voice.cancelled": {
344
+ "$ref": "#/$defs/voiceCancelled"
345
+ },
346
+ "compensation.requested": {
347
+ "$ref": "#/$defs/compensationRequested"
348
+ },
349
+ "compensation.started": {
350
+ "$ref": "#/$defs/compensationStarted"
351
+ },
352
+ "compensation.completed": {
353
+ "$ref": "#/$defs/compensationCompleted"
354
+ },
355
+ "compensation.failed": {
356
+ "$ref": "#/$defs/compensationFailed"
357
+ },
358
+ "compensation.paused": {
359
+ "$ref": "#/$defs/compensationPaused"
360
+ },
361
+ "compensation.manual_intervention_required": {
362
+ "$ref": "#/$defs/compensationManualInterventionRequired"
363
+ }
364
+ }
365
+ },
366
+ "voiceSpeechStart": {
367
+ "description": "RFC 0106 §D. Emitted when inbound user speech onset is detected in a live voice session. Content-free (a timestamp only). MUST NOT be emitted unless `aiProviders.realtimeVoice.transcription: \"streaming\"` is advertised.",
368
+ "type": "object",
369
+ "additionalProperties": false,
370
+ "required": [
371
+ "atMs"
372
+ ],
373
+ "properties": {
374
+ "atMs": {
375
+ "type": "integer",
376
+ "minimum": 0,
377
+ "description": "Session-relative onset timestamp (ms)."
378
+ }
379
+ }
380
+ },
381
+ "voiceTranscript": {
382
+ "description": "RFC 0106 §B/§D. A settled or provisional transcript part for the current turn, emitted on the durable event log as the single canonical record (the `ctx.callTranscriber` Promise resolves separately at `turn_commit`). `text` is the recognized speech — UNTRUSTED input (anyone in acoustic range is an unauthenticated writer): it MUST carry `contentTrust: \"untrusted\"` and MUST NOT be promoted to system/developer authority (SECURITY invariant `voice-transcript-untrusted`). A part with `isFinal: false` is provisional and MUST NOT be persisted to durable memory / the replay log / RAG or drive a side-effecting tool call before it finalizes (`voice-interim-not-durable`).",
383
+ "type": "object",
384
+ "additionalProperties": false,
385
+ "required": [
386
+ "text",
387
+ "isFinal",
388
+ "atMs",
389
+ "contentTrust"
390
+ ],
391
+ "properties": {
392
+ "text": {
393
+ "type": "string",
394
+ "description": "The current hypothesis for this segment (editable tail when `isFinal:false`)."
395
+ },
396
+ "isFinal": {
397
+ "type": "boolean",
398
+ "description": "true ⇒ this segment's text is settled and will not change."
399
+ },
400
+ "committedPrefix": {
401
+ "type": "string",
402
+ "description": "The leading portion the host guarantees will not change (Deepgram/Web-Speech model)."
403
+ },
404
+ "stability": {
405
+ "type": "number",
406
+ "minimum": 0,
407
+ "maximum": 1,
408
+ "description": "Graded tail confidence (Google `stability`); omit/1.0 for immutable ASR."
409
+ },
410
+ "formatted": {
411
+ "type": "boolean",
412
+ "description": "Punctuation/casing/ITN applied; absent ⇒ raw."
413
+ },
414
+ "atMs": {
415
+ "type": "integer",
416
+ "minimum": 0
417
+ },
418
+ "contentTrust": {
419
+ "const": "untrusted",
420
+ "description": "MUST be `\"untrusted\"` — live transcript is untrusted ingress (`voice-transcript-untrusted`); never promote to higher authority."
421
+ }
422
+ }
423
+ },
424
+ "voiceEndpointCandidate": {
425
+ "description": "RFC 0106 §B/§D. A silence boundary / likely end-of-turn appeared (only when `turnDetection: \"semantic\"`), DISTINCT from `voice.turn_commit` (Deepgram `UtteranceEnd` vs `speech_final`). Content-free.",
426
+ "type": "object",
427
+ "additionalProperties": false,
428
+ "required": [
429
+ "atMs"
430
+ ],
431
+ "properties": {
432
+ "atMs": {
433
+ "type": "integer",
434
+ "minimum": 0
435
+ },
436
+ "confidence": {
437
+ "type": "number",
438
+ "minimum": 0,
439
+ "maximum": 1,
440
+ "description": "Optional end-of-turn confidence."
441
+ }
442
+ }
443
+ },
444
+ "voiceTurnCommit": {
445
+ "description": "RFC 0106 §B/§D. The user yielded the floor (turn boundary). This is where the `ctx.callTranscriber` Promise resolves. `finalText` is the settled transcript and is UNTRUSTED (it inherits the `voice.transcript` boundary).",
446
+ "type": "object",
447
+ "additionalProperties": false,
448
+ "required": [
449
+ "atMs",
450
+ "finalText"
451
+ ],
452
+ "properties": {
453
+ "atMs": {
454
+ "type": "integer",
455
+ "minimum": 0
456
+ },
457
+ "finalText": {
458
+ "type": "string",
459
+ "description": "The settled transcript for the committed turn (untrusted input)."
460
+ }
461
+ }
462
+ },
463
+ "voiceSynthesisChunk": {
464
+ "description": "RFC 0106 §C. Announces a clause-boundary streaming-synthesis chunk. METADATA ONLY — the audio bytes are referenced by a session-scoped `streamRef`/`url`, NOT inlined on the event log past the host's inline cap (RFC 0055 256 KiB precedent; spill to a tenant-scoped `url`), so replay/`:fork` stays bounded over long sessions. MUST NOT be emitted unless `aiProviders.realtimeVoice.synthesis: \"streaming\"` is advertised.",
465
+ "type": "object",
466
+ "additionalProperties": false,
467
+ "required": [
468
+ "seq",
469
+ "mimeType"
470
+ ],
471
+ "properties": {
472
+ "seq": {
473
+ "type": "integer",
474
+ "minimum": 0,
475
+ "description": "Monotonic chunk sequence."
476
+ },
477
+ "mimeType": {
478
+ "type": "string",
479
+ "minLength": 1,
480
+ "description": "Audio chunk type (e.g. `audio/mpeg`)."
481
+ },
482
+ "durationMs": {
483
+ "type": "integer",
484
+ "minimum": 0,
485
+ "description": "Optional chunk duration."
486
+ },
487
+ "url": {
488
+ "type": "string",
489
+ "description": "Tenant-scoped, SSRF-guarded (RFC 0076) reference to the chunk bytes."
490
+ },
491
+ "streamRef": {
492
+ "type": "string",
493
+ "description": "Session-scoped live-stream handle for the chunk bytes."
494
+ },
495
+ "base64": {
496
+ "type": "string",
497
+ "description": "OPTIONAL inline bytes, permitted ONLY while under the host's inline cap; past the cap the host MUST use `url`/`streamRef`."
498
+ },
499
+ "final": {
500
+ "type": "boolean",
501
+ "description": "true on the terminal chunk."
502
+ }
503
+ }
504
+ },
505
+ "voiceBargeIn": {
506
+ "description": "RFC 0106 §D. User speech overlapped active assistant playback (probable cut-in). A host advertising `realtimeVoice.bargeIn: \"supported\"` MUST emit this on detected overlap. Content-free. Distinct from `voice.cancelled` (a backchannel \"uh-huh\" MAY produce `barge_in` with no `cancelled`).",
507
+ "type": "object",
508
+ "additionalProperties": false,
509
+ "required": [
510
+ "atMs"
511
+ ],
512
+ "properties": {
513
+ "atMs": {
514
+ "type": "integer",
515
+ "minimum": 0
516
+ }
517
+ }
518
+ },
519
+ "voiceCancelled": {
520
+ "description": "RFC 0106 §D. Downstream LLM/TTS work was cancelled (barge-in or explicit). A cancellation MUST NOT emit partial tool outputs or partial un-guardrailed model output and MUST roll back or fully complete an in-flight side effect (SECURITY invariant `voice-bargein-no-partial-leak`). Content-free.",
521
+ "type": "object",
522
+ "additionalProperties": false,
523
+ "required": [
524
+ "atMs"
525
+ ],
526
+ "properties": {
527
+ "atMs": {
528
+ "type": "integer",
529
+ "minimum": 0
530
+ },
531
+ "reason": {
532
+ "type": "string",
533
+ "enum": [
534
+ "barge-in",
535
+ "explicit"
536
+ ],
537
+ "description": "Why downstream work was cancelled."
538
+ }
539
+ }
540
+ },
541
+ "authorizationDecided": {
542
+ "description": "RFC 0049 — emitted on a role-based authorization decision (allow or deny). Redaction-safe: `principal` is an opaque RFC 0048 id; `reason` carries no credential material. Every deny SHOULD be emitted and SHOULD feed the audit log (RFC 0009/0010). MUST NOT be emitted unless `capabilities.authorization.supported: true`.",
543
+ "type": "object",
544
+ "additionalProperties": false,
545
+ "required": [
546
+ "principal",
547
+ "action",
548
+ "resource",
549
+ "allowed"
550
+ ],
551
+ "properties": {
552
+ "principal": {
553
+ "type": "string",
554
+ "minLength": 1,
555
+ "description": "Opaque RFC 0048 principal id — never PII."
556
+ },
557
+ "action": {
558
+ "type": "string",
559
+ "minLength": 1,
560
+ "description": "The attempted action, e.g. `runs:cancel`."
561
+ },
562
+ "resource": {
563
+ "type": "string",
564
+ "minLength": 1,
565
+ "description": "The target, e.g. a runId or workflowId."
566
+ },
567
+ "allowed": {
568
+ "type": "boolean"
569
+ },
570
+ "reason": {
571
+ "type": "string",
572
+ "description": "Human-readable, redaction-safe — no credential material."
573
+ }
574
+ }
575
+ },
576
+ "proposalCreated": {
577
+ "description": "RFC 0096 §D. Emitted when the host synthesizes a reviewable-learning draft. Content-free: ids / kind / content-free references only — NEVER the artifact body or the rationale text (those live behind the authed read). Redaction-safe (SECURITY invariant `proposal-inert-until-applied` covers the behavior; SR-1 covers the payload). MUST NOT be emitted unless `capabilities.agents.proposals` is advertised.",
578
+ "type": "object",
579
+ "additionalProperties": false,
580
+ "required": [
581
+ "proposalId",
582
+ "kind"
583
+ ],
584
+ "properties": {
585
+ "proposalId": {
586
+ "type": "string",
587
+ "minLength": 1,
588
+ "description": "The created proposal's stable id."
589
+ },
590
+ "kind": {
591
+ "type": "string",
592
+ "enum": [
593
+ "agent-pack",
594
+ "workflow-chain-pack",
595
+ "prompt-template",
596
+ "automation"
597
+ ],
598
+ "description": "The proposed artifact kind."
599
+ },
600
+ "sourceRunIds": {
601
+ "type": "array",
602
+ "items": {
603
+ "type": "string"
604
+ },
605
+ "description": "Runs whose traces produced the draft (RFC 0040 causation-compatible). Ids only — no trace content."
606
+ },
607
+ "duplicateOf": {
608
+ "type": [
609
+ "string",
610
+ "null"
611
+ ],
612
+ "description": "Existing artifact ref the proposal restates/overlaps, when duplication detection is on; else null."
613
+ }
614
+ }
615
+ },
616
+ "proposalActivated": {
617
+ "description": "RFC 0096 §D. Emitted on a successful `apply`. Content-free: ids / content-free references only — NEVER the installed artifact body. MUST NOT be emitted unless `capabilities.agents.proposals` is advertised.",
618
+ "type": "object",
619
+ "additionalProperties": false,
620
+ "required": [
621
+ "proposalId",
622
+ "kind",
623
+ "installedArtifactRef"
624
+ ],
625
+ "properties": {
626
+ "proposalId": {
627
+ "type": "string",
628
+ "minLength": 1
629
+ },
630
+ "kind": {
631
+ "type": "string",
632
+ "enum": [
633
+ "agent-pack",
634
+ "workflow-chain-pack",
635
+ "prompt-template",
636
+ "automation"
637
+ ]
638
+ },
639
+ "approvalId": {
640
+ "type": [
641
+ "string",
642
+ "null"
643
+ ],
644
+ "description": "RFC 0051 approval id when activation routed through an approval gate; null for direct-rbac."
645
+ },
646
+ "installedArtifactRef": {
647
+ "type": "string",
648
+ "minLength": 1,
649
+ "description": "Ref of the artifact installed on apply (RFC 0043)."
650
+ }
651
+ }
652
+ },
653
+ "goalEvaluated": {
654
+ "description": "RFC 0097 §D. Emitted after each judge check on a standing goal. Content-free: NO objective text. The verdict (`satisfied`/`confidence`) is non-deterministic judge output — it is RECORDED here and MUST NOT be recomputed on replay/fork (`replay.md`). MUST NOT be emitted unless `capabilities.agents.goals` is advertised.",
655
+ "type": "object",
656
+ "additionalProperties": false,
657
+ "required": [
658
+ "goalId",
659
+ "satisfied",
660
+ "runId",
661
+ "iterations"
662
+ ],
663
+ "properties": {
664
+ "goalId": {
665
+ "type": "string",
666
+ "minLength": 1
667
+ },
668
+ "satisfied": {
669
+ "type": "boolean",
670
+ "description": "The judge's verdict for this check."
671
+ },
672
+ "confidence": {
673
+ "type": "number",
674
+ "minimum": 0,
675
+ "maximum": 1,
676
+ "description": "Judge confidence in [0,1]."
677
+ },
678
+ "runId": {
679
+ "$ref": "ids.schema.json#/$defs/runId",
680
+ "description": "The run this verdict evaluated (RFC 0040 causation-compatible)."
681
+ },
682
+ "iterations": {
683
+ "type": "integer",
684
+ "minimum": 0,
685
+ "description": "Contributing iterations so far."
686
+ }
687
+ }
688
+ },
689
+ "goalClosed": {
690
+ "description": "RFC 0097 §D. Emitted when a standing goal stops continuation. Content-free. MUST NOT be emitted unless `capabilities.agents.goals` is advertised.",
691
+ "type": "object",
692
+ "additionalProperties": false,
693
+ "required": [
694
+ "goalId",
695
+ "finalState"
696
+ ],
697
+ "properties": {
698
+ "goalId": {
699
+ "type": "string",
700
+ "minLength": 1
701
+ },
702
+ "finalState": {
703
+ "type": "string",
704
+ "enum": [
705
+ "satisfied",
706
+ "escalated",
707
+ "abandoned",
708
+ "bound-exceeded"
709
+ ],
710
+ "description": "Terminal state the goal closed in."
711
+ }
712
+ }
713
+ },
714
+ "importApplied": {
715
+ "description": "RFC 0098 §D. Emitted when an estate import is applied. Content-free: counts + ref-only — NO item payloads, NO secret values (SECURITY invariant `export-bundle-no-credential-material`). MUST NOT be emitted unless `capabilities.portability` is advertised.",
716
+ "type": "object",
717
+ "additionalProperties": false,
718
+ "required": [
719
+ "bundleOrigin",
720
+ "counts"
721
+ ],
722
+ "properties": {
723
+ "bundleOrigin": {
724
+ "type": "string",
725
+ "minLength": 1,
726
+ "description": "The bundle's `source.origin` — informational only."
727
+ },
728
+ "counts": {
729
+ "type": "object",
730
+ "additionalProperties": false,
731
+ "description": "Per-action item tallies.",
732
+ "properties": {
733
+ "created": {
734
+ "type": "integer",
735
+ "minimum": 0
736
+ },
737
+ "updated": {
738
+ "type": "integer",
739
+ "minimum": 0
740
+ },
741
+ "skipped": {
742
+ "type": "integer",
743
+ "minimum": 0
744
+ },
745
+ "failed": {
746
+ "type": "integer",
747
+ "minimum": 0
748
+ }
749
+ }
750
+ },
751
+ "secretsToRebind": {
752
+ "type": "array",
753
+ "items": {
754
+ "type": "string"
755
+ },
756
+ "description": "Provider/ref ids whose secrets must be re-bound at the destination. Refs only — never secret values."
757
+ }
758
+ }
759
+ },
760
+ "connectorAuthorized": {
761
+ "description": "RFC 0047 — emitted when the host acquires (or re-authorizes) a third-party OAuth token on a user's behalf via the `host.oauth` flow. Redaction-safe: carries the credential REFERENCE (RFC 0046), never token material. MUST NOT be emitted unless `capabilities.oauth.supported: true`.",
762
+ "type": "object",
763
+ "additionalProperties": false,
764
+ "required": [
765
+ "provider",
766
+ "credentialRef"
767
+ ],
768
+ "properties": {
769
+ "provider": {
770
+ "type": "string",
771
+ "minLength": 1,
772
+ "description": "Provider id, matching an advertised `capabilities.oauth.providers[].id` (e.g. `slack`, `google`)."
773
+ },
774
+ "credentialRef": {
775
+ "type": "string",
776
+ "minLength": 1,
777
+ "description": "Opaque RFC 0046 credential reference where the acquired token is stored. NEVER the token itself."
778
+ },
779
+ "scopes": {
780
+ "type": "array",
781
+ "items": {
782
+ "type": "string"
783
+ },
784
+ "description": "Scopes granted for the acquired token."
785
+ }
786
+ }
787
+ },
788
+ "connectorAuthExpired": {
789
+ "description": "RFC 0047 — emitted when a stored OAuth token's refresh fails terminally (revoked/expired refresh token). Redaction-safe: no token material. MUST NOT be emitted unless `capabilities.oauth.supported: true`.",
790
+ "type": "object",
791
+ "additionalProperties": false,
792
+ "required": [
793
+ "provider",
794
+ "credentialRef"
795
+ ],
796
+ "properties": {
797
+ "provider": {
798
+ "type": "string",
799
+ "minLength": 1,
800
+ "description": "Provider id, matching an advertised `capabilities.oauth.providers[].id`."
801
+ },
802
+ "credentialRef": {
803
+ "type": "string",
804
+ "minLength": 1,
805
+ "description": "Opaque RFC 0046 credential reference for the expired token."
806
+ },
807
+ "reason": {
808
+ "type": "string",
809
+ "description": "Redaction-safe human-readable reason (e.g. `refresh_token_revoked`)."
810
+ }
811
+ }
812
+ },
813
+ "coreWorkflowChainEvent": {
814
+ "description": "RFC 0037 — emitted on every planner→worker handoff state-machine transition. Required when `capabilities.multiAgent.executionModel.supported: true`; MUST NOT be emitted otherwise. RFC 0040 §A extends with optional `causationHostId` (when `crossHostCausation.supported: true`): present + non-empty when the `causationId` points at an event on a different host; absent when the chained-event is on the same host (existing semantics).",
815
+ "type": "object",
816
+ "additionalProperties": false,
817
+ "required": [
818
+ "phase",
819
+ "workerId",
820
+ "parentRunId"
821
+ ],
822
+ "properties": {
823
+ "phase": {
824
+ "type": "string",
825
+ "enum": [
826
+ "dispatch.began",
827
+ "dispatch.succeeded",
828
+ "dispatch.failed",
829
+ "child.completed",
830
+ "child.failed",
831
+ "child.cancelled",
832
+ "output.harvested"
833
+ ],
834
+ "description": "Which handoff-state-machine transition this event records. See spec/v1/multi-agent-execution.md §'Handoff state machine'."
835
+ },
836
+ "workerId": {
837
+ "type": "string",
838
+ "minLength": 1,
839
+ "description": "The dispatched worker's workflowId — matches the entry in the supervisor's OrchestratorDecision.nextWorkerIds[]."
840
+ },
841
+ "parentRunId": {
842
+ "$ref": "ids.schema.json#/$defs/runId",
843
+ "description": "The orchestrator-driven parent run's runId."
844
+ },
845
+ "childRunId": {
846
+ "type": "string",
847
+ "minLength": 1,
848
+ "description": "The dispatched child run's runId. REQUIRED on phases `dispatch.succeeded` and beyond; absent on `dispatch.began` and `dispatch.failed`."
849
+ },
850
+ "harvestedKeys": {
851
+ "type": "array",
852
+ "items": {
853
+ "type": "string"
854
+ },
855
+ "description": "On phase `output.harvested`: which parent-variable keys were populated by the dispatch config's outputMapping per RFC 0022 §A. SHOULD be present; conformance asserts presence when outputMapping is non-empty."
856
+ },
857
+ "attestation": {
858
+ "type": "object",
859
+ "description": "RFC 0063 (when `capabilities.agents.subRunAttestation: true` AND the `core.subWorkflow` node sets `outputAttestation.checksum: true`). A content checksum over the child's harvested output object, computed BEFORE `outputMapping` is applied so the parent (or a downstream node) can verify integrity — host-independent because the recipe is RFC 8785 JCS canonicalization + SHA-256 (the `replay.md` recipe, RFC 0041), enabling verification of a child that ran on a different host (RFC 0040). Advisory: the host does NOT itself reject on checksum mismatch; that is parent policy.",
860
+ "additionalProperties": false,
861
+ "required": [
862
+ "checksum",
863
+ "algorithm"
864
+ ],
865
+ "properties": {
866
+ "checksum": {
867
+ "type": "string",
868
+ "minLength": 1,
869
+ "description": "Lowercase hex digest of the canonicalized harvested-output object. Content-free: a hash, never the outputs themselves."
870
+ },
871
+ "algorithm": {
872
+ "type": "string",
873
+ "enum": [
874
+ "sha256"
875
+ ],
876
+ "description": "Hash algorithm. `sha256` is the only v1 value; the enum reserves the axis for a future agility migration without a wire-shape break."
877
+ }
878
+ }
879
+ },
880
+ "error": {
881
+ "$ref": "#/$defs/_errorObject",
882
+ "description": "On phases `dispatch.failed` / `child.failed` / `child.cancelled`: the canonical error envelope."
883
+ },
884
+ "causationHostId": {
885
+ "type": "string",
886
+ "minLength": 1,
887
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` (top-level on RunEventDoc) points at an event on a DIFFERENT host; absent when the chained-event is on the SAME host (existing semantics). Value MUST equal the originating host's `capabilities.multiAgent.executionModel.crossHostCausation.hostId` advertisement. Hosts that don't advertise crossHostCausation MUST NOT emit this field."
888
+ }
889
+ }
890
+ },
891
+ "coreWorkflowChainConfidenceEscalated": {
892
+ "description": "RFC 0039 §A — emitted when a supervisor's OrchestratorDecision carries `confidence` below the active confidence floor (spec floor 0.5 OR operator-stricter `capabilities.multiAgent.executionModel.confidenceEscalationFloor`). Recorded BEFORE the host fires the matching clarify-or-escalate interrupt so the run event log carries the decision point even if the user later confirms the original decision. MUST NOT be emitted unless `capabilities.multiAgent.executionModel.version >= 2`.",
893
+ "type": "object",
894
+ "additionalProperties": false,
895
+ "required": [
896
+ "confidence",
897
+ "floor",
898
+ "escalationKind",
899
+ "parentRunId"
900
+ ],
901
+ "properties": {
902
+ "confidence": {
903
+ "type": "number",
904
+ "minimum": 0,
905
+ "maximum": 1,
906
+ "description": "The supervisor's stated confidence on the escalated decision, copied verbatim from `OrchestratorDecision.confidence`."
907
+ },
908
+ "floor": {
909
+ "type": "number",
910
+ "minimum": 0.5,
911
+ "maximum": 1,
912
+ "description": "The floor that triggered escalation — either the spec floor (0.5) when the host doesn't advertise a stricter `confidenceEscalationFloor`, or the host-advertised stricter value."
913
+ },
914
+ "escalationKind": {
915
+ "type": "string",
916
+ "enum": [
917
+ "clarify",
918
+ "escalate"
919
+ ],
920
+ "description": "Which interrupt-kind the host fired in response. `clarify` is preferred per RFC 0039 §A; `escalate` is permitted when the host doesn't expose a clarification UI."
921
+ },
922
+ "workerId": {
923
+ "type": "string",
924
+ "minLength": 1,
925
+ "description": "The decision's intended next-worker workflowId (when the escalated decision's kind is `next-worker`). OMITTED for `kind: 'terminate'` escalations — terminate decisions have no worker to name, so absent-field is the correct signal rather than empty-string."
926
+ },
927
+ "parentRunId": {
928
+ "$ref": "ids.schema.json#/$defs/runId",
929
+ "description": "The orchestrator-driven parent run's runId."
930
+ },
931
+ "originalDecision": {
932
+ "$ref": "orchestrator-decision.schema.json",
933
+ "description": "The OrchestratorDecision that triggered escalation, captured verbatim. The host's existing event-payload redaction harness (the same one enforcing SECURITY invariant `secret-leakage-eventlog-payload` per `conformance/src/scenarios/redaction.test.ts`) applies uniformly across all RunEventType payloads including this one — no per-event-type opt-in is required. The protocol-tier MUST-NOT for raw key material in persisted payloads is the canonical contract; this field inherits that protection."
934
+ },
935
+ "causationHostId": {
936
+ "type": "string",
937
+ "minLength": 1,
938
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host (existing semantics). Value MUST equal the originating host's `crossHostCausation.hostId` advertisement."
939
+ }
940
+ }
941
+ },
942
+ "_errorObject": {
943
+ "description": "Reusable error shape used by run.failed / node.failed / workflow.stalled / etc.",
944
+ "type": "object",
945
+ "required": [
946
+ "code",
947
+ "message"
948
+ ],
949
+ "properties": {
950
+ "code": {
951
+ "type": "string",
952
+ "minLength": 1
953
+ },
954
+ "message": {
955
+ "type": "string",
956
+ "minLength": 1
957
+ },
958
+ "details": {
959
+ "type": "object",
960
+ "additionalProperties": true
961
+ },
962
+ "retryable": {
963
+ "type": "boolean"
964
+ }
965
+ },
966
+ "additionalProperties": false
967
+ },
968
+ "_inputsObject": {
969
+ "type": "object",
970
+ "description": "Caller-supplied workflow inputs (from POST /v1/runs body).",
971
+ "additionalProperties": true
972
+ },
973
+ "_outputsObject": {
974
+ "type": "object",
975
+ "description": "Node output map. Keys are output port names; values are JSON.",
976
+ "additionalProperties": true
977
+ },
978
+ "runStarted": {
979
+ "type": "object",
980
+ "description": "Emitted once per run when execution begins.",
981
+ "required": [
982
+ "workflowId"
983
+ ],
984
+ "properties": {
985
+ "workflowId": {
986
+ "$ref": "ids.schema.json#/$defs/workflowId"
987
+ },
988
+ "inputs": {
989
+ "$ref": "#/$defs/_inputsObject"
990
+ },
991
+ "transport": {
992
+ "type": "string",
993
+ "enum": [
994
+ "rest",
995
+ "mcp",
996
+ "a2a",
997
+ "ui"
998
+ ]
999
+ },
1000
+ "engineVersion": {
1001
+ "type": "integer",
1002
+ "minimum": 0,
1003
+ "description": "v2: integer everywhere (RFC 0172 §B axis 3)."
1004
+ },
1005
+ "owner": {
1006
+ "type": "object",
1007
+ "additionalProperties": false,
1008
+ "required": [
1009
+ "tenant",
1010
+ "subject"
1011
+ ],
1012
+ "properties": {
1013
+ "tenant": {
1014
+ "$ref": "ids.schema.json#/$defs/tenantId"
1015
+ },
1016
+ "workspace": {
1017
+ "$ref": "ids.schema.json#/$defs/workspaceId"
1018
+ },
1019
+ "subject": {
1020
+ "$ref": "subject.schema.json"
1021
+ }
1022
+ },
1023
+ "description": "RFC 0170 §A.1 — the same block as RunSnapshot.owner."
1024
+ },
1025
+ "tags": {
1026
+ "type": "array",
1027
+ "items": {
1028
+ "type": "string"
1029
+ }
1030
+ },
1031
+ "metadata": {
1032
+ "type": "object",
1033
+ "additionalProperties": true
1034
+ }
1035
+ },
1036
+ "additionalProperties": false
1037
+ },
1038
+ "runCompleted": {
1039
+ "type": "object",
1040
+ "description": "Emitted once when the run reaches a successful terminal state. Closes the SSE stream.",
1041
+ "properties": {
1042
+ "outputs": {
1043
+ "$ref": "#/$defs/_outputsObject"
1044
+ },
1045
+ "durationMs": {
1046
+ "type": "integer",
1047
+ "minimum": 0
1048
+ }
1049
+ },
1050
+ "additionalProperties": false
1051
+ },
1052
+ "runFailed": {
1053
+ "type": "object",
1054
+ "description": "Emitted once when the run reaches a failed terminal state.",
1055
+ "required": [
1056
+ "error"
1057
+ ],
1058
+ "properties": {
1059
+ "error": {
1060
+ "$ref": "#/$defs/_errorObject"
1061
+ },
1062
+ "failedNodeId": {
1063
+ "type": "string"
1064
+ },
1065
+ "durationMs": {
1066
+ "type": "integer",
1067
+ "minimum": 0
1068
+ }
1069
+ },
1070
+ "additionalProperties": false
1071
+ },
1072
+ "runCancelled": {
1073
+ "type": "object",
1074
+ "description": "Emitted once when the run reaches the cancelled terminal state.",
1075
+ "properties": {
1076
+ "reason": {
1077
+ "type": "string",
1078
+ "description": "`v1_pin_unsupported` (RFC 0176 §B.1) is a registered reason."
1079
+ },
1080
+ "cancelledBy": {
1081
+ "type": "string",
1082
+ "description": "RFC 0176 §B.1 — `v2-cutover` when a v2 host cancels an inherited run whose pin it no longer implements."
1083
+ },
1084
+ "durationMs": {
1085
+ "type": "integer",
1086
+ "minimum": 0
1087
+ },
1088
+ "parentRunId": {
1089
+ "$ref": "ids.schema.json#/$defs/runId",
1090
+ "description": "When this cancellation was triggered by a parent-cancel cascade (`interrupt-profiles.md §openwop-interrupt-cascade-cancel`), the parent runId that initiated it. Pairs with `reason: 'parent-cancelled'`. Absent for direct cancellations."
1091
+ }
1092
+ },
1093
+ "additionalProperties": false
1094
+ },
1095
+ "runResuming": {
1096
+ "type": "object",
1097
+ "description": "Emitted when an explicit resume is dispatched (browser bootstrap or `:resume` callable).",
1098
+ "properties": {
1099
+ "fromStatus": {
1100
+ "type": "string"
1101
+ }
1102
+ },
1103
+ "additionalProperties": false
1104
+ },
1105
+ "runPaused": {
1106
+ "type": "object",
1107
+ "description": "Emitted when the run is paused (manual pause / cap.breached pause-and-checkpoint).",
1108
+ "properties": {
1109
+ "reason": {
1110
+ "type": "string"
1111
+ },
1112
+ "drainPolicy": {
1113
+ "type": "string",
1114
+ "enum": [
1115
+ "drain",
1116
+ "interrupt"
1117
+ ],
1118
+ "description": "v1 rest-endpoints.md MUST — the pause drain policy persisted on the event."
1119
+ }
1120
+ },
1121
+ "additionalProperties": false
1122
+ },
1123
+ "runResumed": {
1124
+ "type": "object",
1125
+ "description": "Emitted when the run resumes from `paused`.",
1126
+ "additionalProperties": true
1127
+ },
1128
+ "runRestoredFromSnapshot": {
1129
+ "type": "object",
1130
+ "description": "Emitted on cold-start when the engine rebuilds run state from event log.",
1131
+ "properties": {
1132
+ "snapshotSeq": {
1133
+ "type": "integer",
1134
+ "minimum": 0
1135
+ },
1136
+ "engineVersion": {
1137
+ "type": "integer",
1138
+ "minimum": 0,
1139
+ "description": "v2: integer everywhere (RFC 0172 §B axis 3)."
1140
+ }
1141
+ },
1142
+ "additionalProperties": false
1143
+ },
1144
+ "runDeadLettered": {
1145
+ "description": "RFC 0053 — emitted when a run/node exhausts its retry policy (RFC 0009) and is routed to the durable dead-letter sink. The run remains fork-eligible (RFC 0011) for `capabilities.deadLetter.retentionDays`. Redaction-safe: `reason` carries no credential material. MUST NOT be emitted unless `capabilities.deadLetter.supported: true`.",
1146
+ "type": "object",
1147
+ "additionalProperties": false,
1148
+ "required": [
1149
+ "runId",
1150
+ "reason",
1151
+ "attempts"
1152
+ ],
1153
+ "properties": {
1154
+ "runId": {
1155
+ "$ref": "ids.schema.json#/$defs/runId"
1156
+ },
1157
+ "nodeId": {
1158
+ "$ref": "ids.schema.json#/$defs/nodeId",
1159
+ "description": "The node whose retry exhaustion dead-lettered the run; absent for run-level failures."
1160
+ },
1161
+ "reason": {
1162
+ "type": "string",
1163
+ "minLength": 1,
1164
+ "description": "Redaction-safe terminal-failure reason."
1165
+ },
1166
+ "attempts": {
1167
+ "type": "integer",
1168
+ "minimum": 1,
1169
+ "description": "Total attempts made before dead-lettering."
1170
+ }
1171
+ }
1172
+ },
1173
+ "nodeStarted": {
1174
+ "type": "object",
1175
+ "description": "Emitted when a node begins execution.",
1176
+ "required": [
1177
+ "nodeId",
1178
+ "typeId"
1179
+ ],
1180
+ "properties": {
1181
+ "nodeId": {
1182
+ "$ref": "ids.schema.json#/$defs/nodeId"
1183
+ },
1184
+ "typeId": {
1185
+ "type": "string",
1186
+ "minLength": 1
1187
+ },
1188
+ "attempt": {
1189
+ "type": "integer",
1190
+ "minimum": 0,
1191
+ "description": "Zero-based retry counter."
1192
+ }
1193
+ },
1194
+ "additionalProperties": false
1195
+ },
1196
+ "nodeCompleted": {
1197
+ "type": "object",
1198
+ "description": "Emitted when a node successfully completes.",
1199
+ "required": [
1200
+ "nodeId"
1201
+ ],
1202
+ "properties": {
1203
+ "nodeId": {
1204
+ "$ref": "ids.schema.json#/$defs/nodeId"
1205
+ },
1206
+ "outputs": {
1207
+ "$ref": "#/$defs/_outputsObject"
1208
+ },
1209
+ "durationMs": {
1210
+ "type": "integer",
1211
+ "minimum": 0
1212
+ }
1213
+ },
1214
+ "additionalProperties": false
1215
+ },
1216
+ "nodeFailed": {
1217
+ "type": "object",
1218
+ "description": "Emitted on terminal node failure (after retries exhausted).",
1219
+ "required": [
1220
+ "nodeId",
1221
+ "error"
1222
+ ],
1223
+ "properties": {
1224
+ "nodeId": {
1225
+ "$ref": "ids.schema.json#/$defs/nodeId"
1226
+ },
1227
+ "error": {
1228
+ "$ref": "#/$defs/_errorObject"
1229
+ },
1230
+ "attempts": {
1231
+ "type": "integer",
1232
+ "minimum": 1
1233
+ }
1234
+ },
1235
+ "additionalProperties": false
1236
+ },
1237
+ "nodeSuspended": {
1238
+ "type": "object",
1239
+ "description": "Emitted when a node calls `ctx.interrupt(...)`. Carries the InterruptPayload (suspend-request.schema.json).",
1240
+ "required": [
1241
+ "nodeId",
1242
+ "interruptId"
1243
+ ],
1244
+ "properties": {
1245
+ "nodeId": {
1246
+ "$ref": "ids.schema.json#/$defs/nodeId"
1247
+ },
1248
+ "interruptId": {
1249
+ "$ref": "ids.schema.json#/$defs/interruptId"
1250
+ },
1251
+ "kind": {
1252
+ "type": "string",
1253
+ "enum": [
1254
+ "approval",
1255
+ "clarification",
1256
+ "external-event",
1257
+ "custom",
1258
+ "conversation.start",
1259
+ "conversation.exchange",
1260
+ "conversation.close",
1261
+ "low-confidence"
1262
+ ],
1263
+ "description": "RFC 0094 §E — the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1264
+ },
1265
+ "key": {
1266
+ "type": "string",
1267
+ "minLength": 1
1268
+ }
1269
+ },
1270
+ "additionalProperties": false
1271
+ },
1272
+ "nodeSuspendFailed": {
1273
+ "type": "object",
1274
+ "description": "Emitted when a suspension attempt fails (storage write error, signed-token issue).",
1275
+ "required": [
1276
+ "nodeId",
1277
+ "error"
1278
+ ],
1279
+ "properties": {
1280
+ "nodeId": {
1281
+ "$ref": "ids.schema.json#/$defs/nodeId"
1282
+ },
1283
+ "error": {
1284
+ "$ref": "#/$defs/_errorObject"
1285
+ }
1286
+ },
1287
+ "additionalProperties": false
1288
+ },
1289
+ "nodeResumed": {
1290
+ "type": "object",
1291
+ "description": "Emitted when a suspended node receives its resume value and continues.",
1292
+ "required": [
1293
+ "nodeId"
1294
+ ],
1295
+ "properties": {
1296
+ "nodeId": {
1297
+ "$ref": "ids.schema.json#/$defs/nodeId"
1298
+ },
1299
+ "interruptId": {
1300
+ "$ref": "ids.schema.json#/$defs/interruptId"
1301
+ },
1302
+ "resumeValue": {}
1303
+ },
1304
+ "additionalProperties": false
1305
+ },
1306
+ "nodeRetried": {
1307
+ "type": "object",
1308
+ "description": "Emitted on each retry attempt within a node's retry budget.",
1309
+ "required": [
1310
+ "nodeId",
1311
+ "attempt"
1312
+ ],
1313
+ "properties": {
1314
+ "nodeId": {
1315
+ "$ref": "ids.schema.json#/$defs/nodeId"
1316
+ },
1317
+ "attempt": {
1318
+ "type": "integer",
1319
+ "minimum": 1
1320
+ },
1321
+ "delayMs": {
1322
+ "type": "integer",
1323
+ "minimum": 0
1324
+ },
1325
+ "lastError": {
1326
+ "$ref": "#/$defs/_errorObject"
1327
+ }
1328
+ },
1329
+ "additionalProperties": false
1330
+ },
1331
+ "nodeSkipped": {
1332
+ "type": "object",
1333
+ "description": "Emitted when a node is skipped (edge condition failed, gate veto, conditional branch).",
1334
+ "required": [
1335
+ "nodeId"
1336
+ ],
1337
+ "properties": {
1338
+ "nodeId": {
1339
+ "$ref": "ids.schema.json#/$defs/nodeId"
1340
+ },
1341
+ "reason": {
1342
+ "type": "string"
1343
+ }
1344
+ },
1345
+ "additionalProperties": false
1346
+ },
1347
+ "nodeCancelled": {
1348
+ "type": "object",
1349
+ "description": "Emitted when an in-flight node is cancelled (run-level cancel or upstream failure cascade).",
1350
+ "required": [
1351
+ "nodeId"
1352
+ ],
1353
+ "properties": {
1354
+ "nodeId": {
1355
+ "$ref": "ids.schema.json#/$defs/nodeId"
1356
+ },
1357
+ "reason": {
1358
+ "type": "string"
1359
+ }
1360
+ },
1361
+ "additionalProperties": false
1362
+ },
1363
+ "interruptRequested": {
1364
+ "description": "Canonical HITL primitive — discriminated union over kind. Payload mirrors `suspend-request.schema.json` (InterruptPayload) plus engine-assigned identity fields.",
1365
+ "$ref": "https://openwop.dev/spec/v2/suspend-request.schema.json"
1366
+ },
1367
+ "interruptResolved": {
1368
+ "type": "object",
1369
+ "description": "Emitted when an interrupt is resolved (any kind).",
1370
+ "required": [
1371
+ "nodeId",
1372
+ "interruptId"
1373
+ ],
1374
+ "properties": {
1375
+ "nodeId": {
1376
+ "$ref": "ids.schema.json#/$defs/nodeId"
1377
+ },
1378
+ "interruptId": {
1379
+ "$ref": "ids.schema.json#/$defs/interruptId"
1380
+ },
1381
+ "kind": {
1382
+ "type": "string",
1383
+ "enum": [
1384
+ "approval",
1385
+ "clarification",
1386
+ "external-event",
1387
+ "custom",
1388
+ "conversation.start",
1389
+ "conversation.exchange",
1390
+ "conversation.close",
1391
+ "low-confidence"
1392
+ ],
1393
+ "description": "RFC 0094 §E — the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1394
+ },
1395
+ "resumeValue": {},
1396
+ "resolvedBy": {
1397
+ "$ref": "subject.schema.json",
1398
+ "description": "v1 interrupt.md MUST (`decidedBy` on approval.received / `resolvedBy` on interrupt.resolved) carried into v2 as the resolving Subject."
1399
+ },
1400
+ "decision": {
1401
+ "type": "string",
1402
+ "description": "The decision recorded for approval-kind interrupts (granted | rejected | overridden), carried from the v1 approval.* payloads."
1403
+ }
1404
+ },
1405
+ "additionalProperties": false
1406
+ },
1407
+ "channelWritten": {
1408
+ "$ref": "https://openwop.dev/spec/v2/channel-written-payload.schema.json"
1409
+ },
1410
+ "channelPresence": {
1411
+ "$ref": "https://openwop.dev/spec/v2/channel-presence-payload.schema.json"
1412
+ },
1413
+ "contextSummarized": {
1414
+ "type": "object",
1415
+ "description": "RFC 0111. Emitted when the host replaces older in-window orchestrator transcript turns with a host-produced summary to honor `multiAgent.executionModel.contextBudget.transcriptTokenBudget`. CONTENT-FREE: the summary text is NEVER inlined — `summaryRef` is an artifactId resolved via `GET /v1/runs/{runId}/artifacts/{artifactId}`. The summary is a NONDETERMINISTIC host output governed like an RFC 0041 envelope: on `:fork mode:replay` the host MUST reuse this recorded `summaryRef` and MUST NOT re-summarize (see multi-agent-execution.md §\"Context economy (RFC 0111)\"). `replacedTurns` lists the event ids the summary stands in for, so a replay engine reconstructs the exact transcript.",
1416
+ "required": [
1417
+ "iteration",
1418
+ "replacedTurns",
1419
+ "summaryRef",
1420
+ "tokenCounter",
1421
+ "tokensBefore",
1422
+ "tokensAfter"
1423
+ ],
1424
+ "properties": {
1425
+ "iteration": {
1426
+ "type": "integer",
1427
+ "minimum": 0,
1428
+ "description": "The orchestrator-loop iteration (the `runOrchestrator.decided.iteration` counter) whose transcript assembly triggered this summarization."
1429
+ },
1430
+ "replacedTurns": {
1431
+ "type": "array",
1432
+ "items": {
1433
+ "type": "string",
1434
+ "minLength": 1
1435
+ },
1436
+ "description": "Event ids (run event-log entries) the summary stands in for. A replay engine reconstructs the exact model-facing transcript by substituting the `summaryRef` artifact for this contiguous range."
1437
+ },
1438
+ "summaryRef": {
1439
+ "type": "string",
1440
+ "minLength": 1,
1441
+ "description": "ArtifactId of the persisted summary (read via `GET /v1/runs/{runId}/artifacts/{artifactId}`). The summary text is NOT on the wire. MUST be persisted/readable as-of the iteration's event-log index; a host that cannot serve it at the requested `fromSeq` MUST refuse the fork (mirrors `replay_memory_snapshot_unavailable`)."
1442
+ },
1443
+ "tokenCounter": {
1444
+ "type": "string",
1445
+ "enum": [
1446
+ "o200k_base",
1447
+ "cl100k_base",
1448
+ "chars",
1449
+ "host-defined"
1450
+ ],
1451
+ "description": "The unit `tokensBefore`/`tokensAfter` are denominated in. MUST equal the advertised `contextBudget.tokenCounter`."
1452
+ },
1453
+ "tokensBefore": {
1454
+ "type": "integer",
1455
+ "minimum": 0,
1456
+ "description": "Token count of the `replacedTurns` range before summarization, in `tokenCounter` units."
1457
+ },
1458
+ "tokensAfter": {
1459
+ "type": "integer",
1460
+ "minimum": 0,
1461
+ "description": "Token count of the summary that replaced the range, in `tokenCounter` units. Expected ≤ `tokensBefore`."
1462
+ }
1463
+ },
1464
+ "additionalProperties": false
1465
+ },
1466
+ "artifactCreated": {
1467
+ "type": "object",
1468
+ "description": "Emitted when a node produces a typed artifact (PRD, theme, plan, etc.).",
1469
+ "required": [
1470
+ "artifactId",
1471
+ "artifactType"
1472
+ ],
1473
+ "properties": {
1474
+ "artifactId": {
1475
+ "type": "string",
1476
+ "minLength": 1
1477
+ },
1478
+ "artifactType": {
1479
+ "type": "string",
1480
+ "minLength": 1
1481
+ },
1482
+ "nodeId": {
1483
+ "$ref": "ids.schema.json#/$defs/nodeId"
1484
+ },
1485
+ "version": {
1486
+ "type": "string"
1487
+ },
1488
+ "summary": {
1489
+ "type": "string"
1490
+ },
1491
+ "registered": {
1492
+ "type": "boolean",
1493
+ "description": "RFC 0071. True when `artifactType` resolves to a registered artifact type (pack- or host-registered) and the payload was validated against its schema; false for unregistered/host-local types accepted without schema validation. Optional; absent ⇒ treat as true, preserving pre-RFC-0071 semantics. See artifact-type-packs.md §\"Binding the existing artifact surfaces\"."
1494
+ },
1495
+ "registrationSource": {
1496
+ "type": "string",
1497
+ "enum": [
1498
+ "pack",
1499
+ "host"
1500
+ ],
1501
+ "description": "RFC 0075. Provenance of a registered type: `pack` (matches an installed artifact-type pack) or `host` (a host-native type the host validates against a host-known schema, independent of any pack — e.g. an AI host's built-in artifact types). Optional; meaningful only when `registered: true`. Absent ⇒ unspecified provenance (existing semantics)."
1502
+ }
1503
+ },
1504
+ "additionalProperties": false
1505
+ },
1506
+ "outputChunk": {
1507
+ "type": "object",
1508
+ "description": "Emitted for streaming output (e.g., LLM token chunks). Stream-mode `messages` consumers see these. RFC 0094 §D single-sources the `ai.message.chunk` payload here: bare {nodeId, runId, chunk, isLast} is the minimum compliant payload per stream-modes.md §messages (the prior {nodeId, chunk}-only required set was the defective restatement). Tiered metadata per stream-modes.md §messages (S2 closure): `meta` adds Tier 1 typed slots and a Tier 2 provider-pass-through escape hatch.",
1509
+ "required": [
1510
+ "nodeId",
1511
+ "runId",
1512
+ "chunk",
1513
+ "isLast"
1514
+ ],
1515
+ "properties": {
1516
+ "nodeId": {
1517
+ "$ref": "ids.schema.json#/$defs/nodeId"
1518
+ },
1519
+ "runId": {
1520
+ "$ref": "ids.schema.json#/$defs/runId",
1521
+ "description": "Run this chunk belongs to. Required so multiplexed consumers (mixed-mode streams, fan-in UIs) can route chunks without out-of-band context."
1522
+ },
1523
+ "chunk": {
1524
+ "type": "string"
1525
+ },
1526
+ "isLast": {
1527
+ "type": "boolean",
1528
+ "description": "True for the final chunk of a given AI node call. Required — both reference consumers rely on it for fold termination."
1529
+ },
1530
+ "channel": {
1531
+ "type": "string",
1532
+ "description": "Optional sub-stream identifier when a node emits multiple parallel streams."
1533
+ },
1534
+ "meta": {
1535
+ "$ref": "#/$defs/_chunkMeta"
1536
+ }
1537
+ },
1538
+ "additionalProperties": false
1539
+ },
1540
+ "_chunkMeta": {
1541
+ "type": "object",
1542
+ "description": "Tiered metadata for ai.message.chunk / outputChunk payloads. See stream-modes.md §messages.",
1543
+ "properties": {
1544
+ "finishReason": {
1545
+ "type": "string",
1546
+ "enum": [
1547
+ "stop",
1548
+ "length",
1549
+ "tool_calls",
1550
+ "content_filter"
1551
+ ],
1552
+ "description": "Tier 1: normalized termination reason. Set on the final chunk of a generation. Forward-compat: future values MAY be added; consumers MUST tolerate unknown values."
1553
+ },
1554
+ "logprobs": {
1555
+ "type": "array",
1556
+ "description": "Tier 1: per-token log-probability info. Shape mirrors OpenAI / Anthropic / Gemini conventions; servers SHOULD normalize to `[{token: string, logprob: number, topLogprobs?: [{token, logprob}]}]`."
1557
+ },
1558
+ "toolCalls": {
1559
+ "type": "array",
1560
+ "description": "Tier 1: structured tool / function calls emitted in this chunk. Each item: `{id, name, arguments}` — `arguments` is a string (JSON-encoded args, may be partial when streaming)."
1561
+ },
1562
+ "model": {
1563
+ "type": "string",
1564
+ "description": "Tier 1: model identifier the chunk was produced by (e.g., `claude-opus-4-7`, `gpt-5`). Useful when a workflow node fans out across multiple models."
1565
+ },
1566
+ "usage": {
1567
+ "type": "object",
1568
+ "description": "Tier 1: token-billing metadata. Pairs with O4 cost-attribution attributes (`openwop.cost.tokens.*`).",
1569
+ "properties": {
1570
+ "promptTokens": {
1571
+ "type": "integer",
1572
+ "minimum": 0
1573
+ },
1574
+ "completionTokens": {
1575
+ "type": "integer",
1576
+ "minimum": 0
1577
+ },
1578
+ "totalTokens": {
1579
+ "type": "integer",
1580
+ "minimum": 0
1581
+ }
1582
+ },
1583
+ "additionalProperties": false
1584
+ },
1585
+ "provider": {
1586
+ "type": "string",
1587
+ "description": "Tier 2: provider name when `providerExtensions` is present. Examples: `openai`, `anthropic`, `google`, `minimax`. Consumers MUST NOT branch on this for behavior — use Tier 1 fields. Provided for observability + debugging only."
1588
+ },
1589
+ "providerExtensions": {
1590
+ "type": "object",
1591
+ "description": "Tier 2: provider pass-through for fields the spec hasn't typed yet. Consumers using this opt into per-provider knowledge; spec evolution may move fields up into Tier 1 over time (additive — typed slot wins).",
1592
+ "additionalProperties": true
1593
+ }
1594
+ },
1595
+ "additionalProperties": false
1596
+ },
1597
+ "variableChanged": {
1598
+ "type": "object",
1599
+ "description": "Emitted on workflow-variable mutation (debug/values stream modes). NOT emitted for typed channels (those use channel.written).",
1600
+ "required": [
1601
+ "name"
1602
+ ],
1603
+ "properties": {
1604
+ "name": {
1605
+ "type": "string",
1606
+ "minLength": 1
1607
+ },
1608
+ "previous": {},
1609
+ "next": {},
1610
+ "nodeId": {
1611
+ "$ref": "ids.schema.json#/$defs/nodeId"
1612
+ }
1613
+ },
1614
+ "additionalProperties": false
1615
+ },
1616
+ "logAppended": {
1617
+ "type": "object",
1618
+ "description": "Emitted on `ctx.log.*` calls. Debug-stream-mode only.",
1619
+ "required": [
1620
+ "level",
1621
+ "message"
1622
+ ],
1623
+ "properties": {
1624
+ "level": {
1625
+ "type": "string",
1626
+ "enum": [
1627
+ "debug",
1628
+ "info",
1629
+ "warn",
1630
+ "error"
1631
+ ]
1632
+ },
1633
+ "message": {
1634
+ "type": "string"
1635
+ },
1636
+ "nodeId": {
1637
+ "$ref": "ids.schema.json#/$defs/nodeId"
1638
+ },
1639
+ "fields": {
1640
+ "type": "object",
1641
+ "additionalProperties": true
1642
+ }
1643
+ },
1644
+ "additionalProperties": false
1645
+ },
1646
+ "versionPinned": {
1647
+ "type": "object",
1648
+ "description": "Emitted via `ctx.getVersion(changeId)` per Temporal-style versioning. See version-negotiation.md.",
1649
+ "required": [
1650
+ "changeId",
1651
+ "version"
1652
+ ],
1653
+ "properties": {
1654
+ "changeId": {
1655
+ "type": "string",
1656
+ "minLength": 1
1657
+ },
1658
+ "version": {
1659
+ "type": "integer",
1660
+ "minimum": 0
1661
+ },
1662
+ "nodeId": {
1663
+ "$ref": "ids.schema.json#/$defs/nodeId"
1664
+ }
1665
+ },
1666
+ "additionalProperties": false
1667
+ },
1668
+ "workflowRestored": {
1669
+ "type": "object",
1670
+ "description": "Emitted when an in-flight run is recovered from the event log on a fresh engine boot.",
1671
+ "properties": {
1672
+ "fromSnapshotSeq": {
1673
+ "type": "integer",
1674
+ "minimum": 0
1675
+ },
1676
+ "engineVersion": {
1677
+ "type": "integer",
1678
+ "minimum": 0,
1679
+ "description": "v2: integer everywhere (RFC 0172 §B axis 3)."
1680
+ }
1681
+ },
1682
+ "additionalProperties": false
1683
+ },
1684
+ "workflowLoopbackLimit": {
1685
+ "type": "object",
1686
+ "description": "Emitted when a request-changes loop hits its `maxLoopbackIterations` cap.",
1687
+ "required": [
1688
+ "nodeId",
1689
+ "iterations"
1690
+ ],
1691
+ "properties": {
1692
+ "nodeId": {
1693
+ "$ref": "ids.schema.json#/$defs/nodeId"
1694
+ },
1695
+ "iterations": {
1696
+ "type": "integer",
1697
+ "minimum": 1
1698
+ },
1699
+ "limit": {
1700
+ "type": "integer",
1701
+ "minimum": 1
1702
+ }
1703
+ },
1704
+ "additionalProperties": false
1705
+ },
1706
+ "workflowStalled": {
1707
+ "type": "object",
1708
+ "description": "Emitted when the engine detects a stalled run (no progress for N seconds).",
1709
+ "properties": {
1710
+ "stalledForMs": {
1711
+ "type": "integer",
1712
+ "minimum": 0
1713
+ },
1714
+ "lastNodeId": {
1715
+ "type": "string"
1716
+ }
1717
+ },
1718
+ "additionalProperties": false
1719
+ },
1720
+ "capBreached": {
1721
+ "type": "object",
1722
+ "description": "Emitted when a CapabilityLimit is exceeded. Protocol-level limits use the engine kinds (clarificationRounds / schemaRounds / envelopesPerTurn / maxNodeExecutions). RFC 0008 §K WASM-runtime caps use the wasm-* kinds (memory ceiling, fuel exhaustion, execution-time wall-clock). RFC 0058 run-execution bounds use the run-scoped run-duration (wall-clock timeout; limit=resolvedMs, observed=elapsedMs) and loop-iterations (agent-loop ceiling; limit=resolvedMax, observed=iterationCount) kinds.",
1723
+ "required": [
1724
+ "kind",
1725
+ "limit",
1726
+ "observed"
1727
+ ],
1728
+ "properties": {
1729
+ "kind": {
1730
+ "type": "string",
1731
+ "enum": [
1732
+ "clarification",
1733
+ "schema",
1734
+ "envelopes",
1735
+ "node-executions",
1736
+ "wasm-memory",
1737
+ "wasm-fuel",
1738
+ "wasm-execution-time",
1739
+ "run-duration",
1740
+ "loop-iterations",
1741
+ "budget-tokens",
1742
+ "budget-cost",
1743
+ "budget-tool-calls",
1744
+ "budget-retries"
1745
+ ]
1746
+ },
1747
+ "limit": {
1748
+ "type": "number",
1749
+ "minimum": 0,
1750
+ "description": "The effective ceiling. A whole number for the engine/WASM/RFC 0058 integer kinds; a fractional value for budget-cost (dollars, matching budget.exhausted + maxCostUsd — RFC 0084 §D)."
1751
+ },
1752
+ "observed": {
1753
+ "type": "number",
1754
+ "minimum": 0,
1755
+ "description": "The observed value at breach. Same numeric domain as limit for the kind."
1756
+ },
1757
+ "nodeId": {
1758
+ "$ref": "ids.schema.json#/$defs/nodeId"
1759
+ }
1760
+ },
1761
+ "additionalProperties": false
1762
+ },
1763
+ "leaseLifecycle": {
1764
+ "type": "object",
1765
+ "description": "Shared payload for lease.acquired / lease.renewed / lease.lost.",
1766
+ "required": [
1767
+ "leaseId",
1768
+ "host"
1769
+ ],
1770
+ "properties": {
1771
+ "leaseId": {
1772
+ "type": "string",
1773
+ "minLength": 1
1774
+ },
1775
+ "host": {
1776
+ "type": "string",
1777
+ "enum": [
1778
+ "browser",
1779
+ "cloud"
1780
+ ]
1781
+ },
1782
+ "instanceId": {
1783
+ "type": "string"
1784
+ },
1785
+ "expiresAt": {
1786
+ "type": "string",
1787
+ "format": "date-time"
1788
+ },
1789
+ "previousHost": {
1790
+ "type": "string",
1791
+ "enum": [
1792
+ "browser",
1793
+ "cloud"
1794
+ ]
1795
+ }
1796
+ },
1797
+ "additionalProperties": false
1798
+ },
1799
+ "leaseHandedOff": {
1800
+ "type": "object",
1801
+ "description": "Emitted when a run's executing lease is transferred from one host to another (e.g., browser → cloud failover).",
1802
+ "required": [
1803
+ "leaseId",
1804
+ "fromHost",
1805
+ "toHost"
1806
+ ],
1807
+ "properties": {
1808
+ "leaseId": {
1809
+ "type": "string",
1810
+ "minLength": 1
1811
+ },
1812
+ "fromHost": {
1813
+ "type": "string",
1814
+ "enum": [
1815
+ "browser",
1816
+ "cloud"
1817
+ ]
1818
+ },
1819
+ "toHost": {
1820
+ "type": "string",
1821
+ "enum": [
1822
+ "browser",
1823
+ "cloud"
1824
+ ]
1825
+ },
1826
+ "reason": {
1827
+ "type": "string"
1828
+ }
1829
+ },
1830
+ "additionalProperties": false
1831
+ },
1832
+ "replayDivergedAtRefusal": {
1833
+ "type": "object",
1834
+ "description": "RFC 0041 §B — emitted by `:fork` mode `replay` when the replay's LLM call returns a refusal but the original run got a valid envelope (or vice-versa: the original refused, the replay succeeded). Distinct from the generic `replay.diverged` event (which covers structural output/missing/extra/type-mismatch divergence) to let operators audit safety-policy shifts without filtering through the generic divergence stream. When this event fires, the host MUST also fail the replay with `error.code: \"replay_diverged_at_refusal\"` per `spec/v1/rest-endpoints.md` §\"Common error codes\". Capability-gated on `capabilities.multiAgent.executionModel.replayDeterminism.refusalDivergenceEmission: true`; non-Phase-4 hosts MUST NOT emit this event.",
1835
+ "required": [
1836
+ "sourceRunId",
1837
+ "atSequence",
1838
+ "originalEnvelopeKind",
1839
+ "replayEnvelopeKind"
1840
+ ],
1841
+ "properties": {
1842
+ "sourceRunId": {
1843
+ "$ref": "ids.schema.json#/$defs/runId",
1844
+ "description": "The original run's runId (the source of the replay)."
1845
+ },
1846
+ "atSequence": {
1847
+ "type": "integer",
1848
+ "minimum": 0,
1849
+ "description": "Event-log index at which the refusal-divergence was detected (the index of the LLM call whose envelope shifted)."
1850
+ },
1851
+ "originalEventId": {
1852
+ "type": "string",
1853
+ "description": "Optional eventId of the original event whose envelope is being compared. SHOULD be set when the host has a stable identifier for the event; MAY be omitted when only the sequence index is known."
1854
+ },
1855
+ "nodeId": {
1856
+ "$ref": "ids.schema.json#/$defs/nodeId",
1857
+ "description": "ID of the node whose LLM call diverged. Operators use this to localize the safety-policy shift in the workflow definition."
1858
+ },
1859
+ "originalEnvelopeKind": {
1860
+ "type": "string",
1861
+ "enum": [
1862
+ "valid",
1863
+ "refusal"
1864
+ ],
1865
+ "description": "Whether the original run's LLM envelope was a valid response or a refusal."
1866
+ },
1867
+ "replayEnvelopeKind": {
1868
+ "type": "string",
1869
+ "enum": [
1870
+ "valid",
1871
+ "refusal"
1872
+ ],
1873
+ "description": "Whether the replay's LLM envelope was a valid response or a refusal. MUST differ from `originalEnvelopeKind` — otherwise there is no divergence to report."
1874
+ },
1875
+ "refusalReason": {
1876
+ "type": "string",
1877
+ "description": "Provider-supplied refusal reason when available (e.g., the model's `refusal` field on a chat-completion response). OPTIONAL; hosts MAY include for operator triage but MUST redact provider-specific identifiers per `SECURITY/threat-model-secret-leakage.md`."
1878
+ }
1879
+ },
1880
+ "additionalProperties": false
1881
+ },
1882
+ "replayDiverged": {
1883
+ "type": "object",
1884
+ "description": "Emitted by `:fork` when a replay re-execution produces a different output than the original at a given sequence. See replay.md §divergence detection. `divergencePoint` (RFC 0027 §F) is the canonical optional field for naming which event-emission diverged; the two fields are complementary, not mutually exclusive.",
1885
+ "required": [
1886
+ "sourceRunId",
1887
+ "atSequence"
1888
+ ],
1889
+ "properties": {
1890
+ "sourceRunId": {
1891
+ "$ref": "ids.schema.json#/$defs/runId"
1892
+ },
1893
+ "atSequence": {
1894
+ "type": "integer",
1895
+ "minimum": 0
1896
+ },
1897
+ "originalEventId": {
1898
+ "type": "string"
1899
+ },
1900
+ "divergenceKind": {
1901
+ "type": "string",
1902
+ "enum": [
1903
+ "output",
1904
+ "missing",
1905
+ "extra",
1906
+ "type-mismatch"
1907
+ ]
1908
+ },
1909
+ "divergencePoint": {
1910
+ "type": "string",
1911
+ "description": "RFC 0027 §F. Verbatim `RunEventType` enum string identifying which event-emission the replay diverged at (e.g., `\"prompt.composed\"` per RFC 0027, `\"agent.promptResolved\"` per RFC 0029, `\"envelope.retry.exhausted\"` / `\"envelope.recovery.applied\"` per RFC 0032). Set when divergence is detected on a specific cross-kind operational event's payload. When divergence is purely structural (output/missing/extra at the event-array level rather than within a typed payload), `divergenceKind` carries the shape and `divergencePoint` MAY be omitted. The two fields are complementary: a single `replay.diverged` event MAY carry both (e.g., `{ divergenceKind: \"output\", divergencePoint: \"prompt.composed\" }` reads as \"the `prompt.composed` event at sequence N had a different output on replay than the original\"). The field is defined by RFC 0027; values are contributed by consuming RFCs (0029 adds `agent.promptResolved`, 0032 adds the envelope-reliability event names)."
1912
+ }
1913
+ },
1914
+ "additionalProperties": false
1915
+ },
1916
+ "agentReasoned": {
1917
+ "type": "object",
1918
+ "description": "Multi-Agent Shift Phase 1. Emitted when an agent produces a reasoning trace (typically pre-tool-call, pre-decision, or pre-handoff). The reasoning text MAY be a summary or full trace depending on the run's resolved `RunOptions.configurable.reasoningVerbosity`. Replay-deterministic over the event log.",
1919
+ "required": [
1920
+ "agentId",
1921
+ "reasoning"
1922
+ ],
1923
+ "properties": {
1924
+ "agentId": {
1925
+ "$ref": "ids.schema.json#/$defs/agentId",
1926
+ "description": "AgentRef.agentId of the reasoning agent."
1927
+ },
1928
+ "reasoning": {
1929
+ "type": "string",
1930
+ "description": "Reasoning text. Bounded by `capabilities.agents.reasoning.tokenLimit` when verbosity is `summary` (default 512 tokens)."
1931
+ },
1932
+ "verbosity": {
1933
+ "type": "string",
1934
+ "enum": [
1935
+ "summary",
1936
+ "full",
1937
+ "off"
1938
+ ],
1939
+ "description": "Verbosity mode this trace was produced under. Hosts MAY emit `'off'` to record the suppression decision without payload content."
1940
+ },
1941
+ "causationHostId": {
1942
+ "type": "string",
1943
+ "minLength": 1,
1944
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
1945
+ }
1946
+ },
1947
+ "additionalProperties": false
1948
+ },
1949
+ "agentReasoningDelta": {
1950
+ "type": "object",
1951
+ "description": "RFC 0024. Incremental reasoning chunk for live-streaming UX. Emitted while a reasoning block is still open, BEFORE the corresponding `agent.reasoned` finalization. Consumers concatenate `delta` strings in arrival order to reconstruct the in-progress trace; the closing `agent.reasoned` event carries the FULL authoritative `reasoning`. Gated on `capabilities.agents.reasoning.streaming: true`. NOTE: `additionalProperties: true` mirrors the Phase-1 multi-agent-shift carve-out applied to the sibling `agentReasoned` schema — a deliberate forward-compat exception per RFC 0024 §Compatibility, not a precedent generalizable to other event payloads.",
1952
+ "required": [
1953
+ "agentId",
1954
+ "delta",
1955
+ "sequence"
1956
+ ],
1957
+ "properties": {
1958
+ "agentId": {
1959
+ "$ref": "ids.schema.json#/$defs/agentId",
1960
+ "description": "AgentRef.agentId of the reasoning agent. MUST match the eventual closing `agent.reasoned`."
1961
+ },
1962
+ "delta": {
1963
+ "type": "string",
1964
+ "description": "New reasoning content since the previous delta event in this block (or since block open, if `sequence` is 0)."
1965
+ },
1966
+ "sequence": {
1967
+ "type": "integer",
1968
+ "minimum": 0,
1969
+ "description": "Monotonically-increasing index within the current reasoning block. Starts at 0 for the first delta in a block; resets at each new block open. Consumers MAY use this to detect dropped events."
1970
+ },
1971
+ "verbosity": {
1972
+ "type": "string",
1973
+ "enum": [
1974
+ "summary",
1975
+ "full",
1976
+ "off"
1977
+ ],
1978
+ "description": "Verbosity mode the host resolved for this block. SHOULD match the verbosity reported on the closing `agent.reasoned`."
1979
+ }
1980
+ },
1981
+ "additionalProperties": false
1982
+ },
1983
+ "providerUsage": {
1984
+ "type": "object",
1985
+ "description": "RFC 0026. Per-call usage record emitted after every LLM provider invocation. Durably persisted in the run event log; consumed by replay, webhook subscribers, billing reconciliation. The OTel `openwop.cost.*` attribute group (per `observability.md §\"Cost attribution attributes\"`) is the observability sibling — this event type is the durable record. Replay determinism: `inputTokens` + `outputTokens` MUST replay identically; `costEstimateUsd` MAY be omitted on replay, and so MAY the RFC 0116 cost-only `cacheReadTokens`/`cacheWriteTokens` (they are NOT replay-asserted — a prompt-prefix cache hit vs miss MUST NOT change `inputTokens`/`outputTokens` or the recorded envelope). The payload MUST NOT carry credentialRefs, hashed credential identifiers, or prompt/response substrings per `SECURITY/threat-model-secret-leakage.md §SR-1` (enforced by SECURITY invariant `provider-usage-no-credential-leak`).",
1986
+ "required": [
1987
+ "provider",
1988
+ "model",
1989
+ "inputTokens",
1990
+ "outputTokens"
1991
+ ],
1992
+ "properties": {
1993
+ "provider": {
1994
+ "type": "string",
1995
+ "minLength": 1,
1996
+ "description": "Canonical provider id (lowercase ASCII, e.g. \"anthropic\", \"openai\", \"google\"). Same value as the `openwop.cost.provider` OTel attribute."
1997
+ },
1998
+ "model": {
1999
+ "type": "string",
2000
+ "minLength": 1,
2001
+ "description": "Provider-stamped model id as the model expects it. Same value used in the LLM cache-key recipe per `replay.md §A`."
2002
+ },
2003
+ "inputTokens": {
2004
+ "type": "integer",
2005
+ "minimum": 0,
2006
+ "description": "Input/prompt tokens billed for this call. Matches the provider response's input-token count verbatim."
2007
+ },
2008
+ "outputTokens": {
2009
+ "type": "integer",
2010
+ "minimum": 0,
2011
+ "description": "Output/completion tokens billed for this call. Matches the provider response's output-token count verbatim."
2012
+ },
2013
+ "totalTokens": {
2014
+ "type": "integer",
2015
+ "minimum": 0,
2016
+ "description": "Convenience sum (inputTokens + outputTokens). Consumers MAY compute themselves; emitters MAY include for readability."
2017
+ },
2018
+ "costEstimateUsd": {
2019
+ "type": "number",
2020
+ "minimum": 0,
2021
+ "description": "ADVISORY estimate in USD computed by the host's static rate table. MUST NOT be used for billing — real billing is external. Hosts SHOULD omit when no rate is known rather than emit 0."
2022
+ },
2023
+ "currency": {
2024
+ "type": "string",
2025
+ "pattern": "^[A-Z]{3}$",
2026
+ "description": "ISO 4217 code when `costEstimateUsd` is non-USD; the field name stays `costEstimateUsd` for back-compat but `currency` overrides the implied denomination."
2027
+ },
2028
+ "cacheHit": {
2029
+ "type": "boolean",
2030
+ "description": "True iff this call was served from the LLM response cache per `replay.md §\"LLM cache-key recipe\"`. When true, inputTokens/outputTokens reflect the ORIGINAL call's billed values; the cached invocation incurred zero new provider cost."
2031
+ },
2032
+ "cacheReadTokens": {
2033
+ "type": "integer",
2034
+ "minimum": 0,
2035
+ "description": "RFC 0116. Optional, cost-only. Provider-reported tokens served from the prompt-prefix context cache on this call — a cache HIT shows > 0. This is a cost hint, NOT a semantic input: it MAY be omitted on replay (NOT replay-asserted, like `costEstimateUsd`), and a hit-vs-miss difference MUST NOT change `inputTokens`/`outputTokens` or the recorded envelope (RFC 0116 replay-invariance MUST). MUST NOT carry prompt/response substrings per `SECURITY/threat-model-secret-leakage.md §SR-1`."
2036
+ },
2037
+ "cacheWriteTokens": {
2038
+ "type": "integer",
2039
+ "minimum": 0,
2040
+ "description": "RFC 0116. Optional, cost-only. Provider-reported tokens written to the prompt-prefix context cache on this call (a cache PRIME). MAY be omitted on replay (NOT replay-asserted). MUST NOT change `inputTokens`/`outputTokens` or the recorded envelope, and MUST NOT carry prompt/response substrings (SR-1)."
2041
+ },
2042
+ "nodeId": {
2043
+ "$ref": "ids.schema.json#/$defs/nodeId",
2044
+ "description": "The node id that initiated the provider call. Required for per-node cost attribution dashboards."
2045
+ },
2046
+ "traceId": {
2047
+ "$ref": "ids.schema.json#/$defs/traceId",
2048
+ "description": "OTel trace id linking this event to the matching `openwop.cost.*` span. Lets observability backends correlate event-log entries with traces."
2049
+ }
2050
+ },
2051
+ "additionalProperties": false
2052
+ },
2053
+ "promptComposed": {
2054
+ "type": "object",
2055
+ "description": "RFC 0027. Emitted once per (nodeId, kind) composition when a host resolves a PromptRef on a node and assembles its body for an LLM call. Gated on `capabilities.prompts.supported: true` AND `capabilities.prompts.observability !== 'off'`. Body fields (`systemPrompt`, `userPrompt`, `variableBindings`) are populated only under `observability: 'full'`; under `hashed` the event carries only `hash` + `variableHashes`. Replay-deterministic over `(refs, variableHashes, contentTrust)` per `spec/v1/prompts.md §\"Replay determinism\"`. Secret-source variable values MUST be replaced with `[REDACTED:<secretId>]` markers per SECURITY invariant `prompt-composed-secret-redaction`; untrusted-input segments MUST be wrapped with `<UNTRUSTED>...</UNTRUSTED>` markers per SECURITY invariant `prompt-composed-trust-marker`.",
2056
+ "required": [
2057
+ "nodeId",
2058
+ "refs",
2059
+ "kind",
2060
+ "hash"
2061
+ ],
2062
+ "properties": {
2063
+ "nodeId": {
2064
+ "$ref": "ids.schema.json#/$defs/nodeId",
2065
+ "description": "Lifted to top-level RunEventDoc.nodeId; mirrored here for self-contained payload validation."
2066
+ },
2067
+ "refs": {
2068
+ "type": "array",
2069
+ "items": {
2070
+ "type": "string",
2071
+ "pattern": "^prompt:[a-z0-9][a-z0-9._-]{0,127}(@\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?)?$"
2072
+ },
2073
+ "description": "Ordered list of PromptRef values (stringy form) that contributed to this composition: typically system, then user, then any few-shot or schema-hint additions. Object-form refs are projected to their stringy equivalent for stability."
2074
+ },
2075
+ "kind": {
2076
+ "type": "string",
2077
+ "enum": [
2078
+ "system+user",
2079
+ "system-only",
2080
+ "user-only",
2081
+ "agent-reasoning"
2082
+ ],
2083
+ "description": "Composition shape — what the host actually assembled. `system+user`: both system and user templates resolved. `system-only`: only a system template applied (e.g., agent intrinsic). `user-only`: only a user template applied. `agent-reasoning`: composition was emitted ahead of an agent reasoning trace per RFC 0024."
2084
+ },
2085
+ "hash": {
2086
+ "type": "string",
2087
+ "pattern": "^sha256:[0-9a-f]{64}$",
2088
+ "description": "SHA-256 of the composed body (post-substitution, post-redaction). Stable across replay. Always present, including under observability=hashed."
2089
+ },
2090
+ "composed": {
2091
+ "type": "string",
2092
+ "description": "Generic composed-body field. Present only when `capabilities.prompts.observability` is `full`. Populated for ALL four PromptKind values (system / user / few-shot / schema-hint) so consumers have a single body field to read — necessary for few-shot + schema-hint templates that don't fit the system/user split below. Same secret-redaction + trust-marker invariants apply as for the kind-specific fields. The kind-specific `systemPrompt` + `userPrompt` fields below remain populated for system/user kinds so existing consumers that key off them continue to work; both fields carry identical content for those kinds."
2093
+ },
2094
+ "systemPrompt": {
2095
+ "type": "string",
2096
+ "description": "Composed system prompt body. Present only when `capabilities.prompts.observability` is `full` AND template `kind: \"system\"`. Secret-sourced variable values MUST be replaced with `[REDACTED:<secretId>]` markers. Untrusted-content `<UNTRUSTED>...</UNTRUSTED>` markers MUST be preserved verbatim. Identical to `composed` when present."
2097
+ },
2098
+ "userPrompt": {
2099
+ "type": "string",
2100
+ "description": "Composed user prompt body. Same presence + redaction rules as `systemPrompt`."
2101
+ },
2102
+ "variableBindings": {
2103
+ "type": "object",
2104
+ "additionalProperties": true,
2105
+ "description": "Variable-name → bound-value map. Secret-source bindings MUST appear as `[REDACTED:<secretId>]`. Only present under `observability: 'full'`."
2106
+ },
2107
+ "variableHashes": {
2108
+ "type": "object",
2109
+ "additionalProperties": {
2110
+ "type": "string",
2111
+ "pattern": "^sha256:[0-9a-f]{64}$"
2112
+ },
2113
+ "description": "Variable-name → sha256(value) map. Always present (under both `hashed` and `full`). Enables replay-determinism checks without exposing values."
2114
+ },
2115
+ "contentTrust": {
2116
+ "type": "string",
2117
+ "enum": [
2118
+ "trusted",
2119
+ "untrusted"
2120
+ ],
2121
+ "description": "Aggregate trust marker. `untrusted` iff ANY contributing input was tagged untrusted per RFC 0020 §D / AIEnvelope.meta.contentTrust propagation. When `untrusted`, the composed bodies MUST contain `<UNTRUSTED>...</UNTRUSTED>` markers around the untrusted segments."
2122
+ },
2123
+ "causationHostId": {
2124
+ "type": "string",
2125
+ "minLength": 1,
2126
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2127
+ }
2128
+ },
2129
+ "additionalProperties": false
2130
+ },
2131
+ "agentPromptResolved": {
2132
+ "type": "object",
2133
+ "description": "RFC 0029 §B. Emitted once per (nodeId, kind) pair BEFORE the corresponding `prompt.composed` event (when emitted). Surfaces the four-layer resolution chain per `spec/v1/prompts.md` §\"Resolution chain (normative)\" so cross-host debuggers and multi-agent visualizers can render which PromptRef applied at this node and why. Gated on `capabilities.prompts.supported: true`; payload is durable in the event log and participates in replay. Carries refs (not bodies), so emission is safe regardless of `capabilities.prompts.observability` — the secret-redaction + trust-marker invariants on `prompt.composed` (RFC 0027 §G) don't apply here.",
2134
+ "required": [
2135
+ "nodeId",
2136
+ "kind",
2137
+ "chain",
2138
+ "resolved"
2139
+ ],
2140
+ "properties": {
2141
+ "nodeId": {
2142
+ "$ref": "ids.schema.json#/$defs/nodeId",
2143
+ "description": "Lifted to top-level RunEventDoc.nodeId; mirrored here for self-contained payload validation."
2144
+ },
2145
+ "kind": {
2146
+ "$ref": "./prompt-kind.schema.json"
2147
+ },
2148
+ "agentId": {
2149
+ "$ref": "ids.schema.json#/$defs/agentId",
2150
+ "description": "AgentManifest.agentId when the node has `config.agentId` set; omitted otherwise."
2151
+ },
2152
+ "chain": {
2153
+ "type": "array",
2154
+ "description": "Ordered traversal of the four normative resolution layers. Hosts MUST emit one entry per layer attempted; skipped layers produce an entry with `applied: false` and `reason: \"...\"` describing why (e.g., `\"agentId unresolved\"`, `\"no candidate at this layer\"`, `\"superseded by node-config layer\"`).",
2155
+ "items": {
2156
+ "type": "object",
2157
+ "additionalProperties": false,
2158
+ "required": [
2159
+ "layer",
2160
+ "applied"
2161
+ ],
2162
+ "properties": {
2163
+ "layer": {
2164
+ "type": "string",
2165
+ "enum": [
2166
+ "run-configurable",
2167
+ "node",
2168
+ "agent-intrinsic",
2169
+ "agent-overrides",
2170
+ "agent-library-default",
2171
+ "workflow-defaults",
2172
+ "host-defaults"
2173
+ ],
2174
+ "description": "Identifies which precedence layer this chain entry represents. The four normative layers per RFC 0029 §A are `node`, `agent-*`, `workflow-defaults`, `host-defaults`. `run-configurable` is reserved for the optional `RunOptions.configurable.promptOverrides` extension described in RFC 0029 §\"Alternatives considered\" #5; hosts that honor that extension MUST emit a chain entry with this layer value above the `node` entry."
2175
+ },
2176
+ "source": {
2177
+ "type": "string",
2178
+ "description": "The PromptRef stringy form this layer would have applied (e.g., `prompt:writer@1.0.0`). Object-form refs are projected to their stringy equivalent for stability. Present only when this layer had a candidate."
2179
+ },
2180
+ "applied": {
2181
+ "type": "boolean",
2182
+ "description": "True for exactly one entry in the chain — the layer whose ref was selected. False for layers that yielded null OR were skipped after a higher-precedence layer already applied."
2183
+ },
2184
+ "reason": {
2185
+ "type": "string",
2186
+ "description": "Non-normative human-readable explanation. Hosts MAY omit; clients MUST tolerate absence."
2187
+ }
2188
+ }
2189
+ }
2190
+ },
2191
+ "resolved": {
2192
+ "type": [
2193
+ "string",
2194
+ "null"
2195
+ ],
2196
+ "description": "The winning PromptRef in stringy form (`prompt:templateId@version`), or null if no layer yielded a candidate. Mirrors the `chain[].source` whose `applied: true` when present."
2197
+ },
2198
+ "causationHostId": {
2199
+ "type": "string",
2200
+ "minLength": 1,
2201
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2202
+ }
2203
+ },
2204
+ "additionalProperties": false
2205
+ },
2206
+ "modelCapabilitySubstituted": {
2207
+ "type": "object",
2208
+ "additionalProperties": false,
2209
+ "description": "RFC 0031 §D. Emitted when a host substitutes the active model with a NodeModule's declared `fallbackModel` because the active model lacks one or more of the `requiredModelCapabilities`. MUST event per RFC 0031 §B step 3. The `fallbackProvider` + `fallbackModel` pair MAY be redacted as all-or-nothing `\"[REDACTED]\"` when workspace policy treats multi-vendor posture as confidential per SECURITY invariant `model-capability-substituted-no-credential-disclosure`. The other fields are not redactable — `originalProvider` is already public via `RunOptions.configurable.ai.provider`, and `nodeId` / `missingCapabilities` carry no provider-possession information.",
2210
+ "required": [
2211
+ "nodeId",
2212
+ "originalProvider",
2213
+ "originalModel",
2214
+ "fallbackProvider",
2215
+ "fallbackModel",
2216
+ "missingCapabilities"
2217
+ ],
2218
+ "properties": {
2219
+ "nodeId": {
2220
+ "$ref": "ids.schema.json#/$defs/nodeId",
2221
+ "description": "The node whose dispatch triggered the substitution."
2222
+ },
2223
+ "originalProvider": {
2224
+ "type": "string",
2225
+ "description": "Provider id of the active model the host was about to use."
2226
+ },
2227
+ "originalModel": {
2228
+ "type": "string",
2229
+ "description": "Model id of the active model."
2230
+ },
2231
+ "fallbackProvider": {
2232
+ "type": "string",
2233
+ "description": "Provider id of the substitute model from `NodeModule.fallbackModel.provider`, or `\"[REDACTED]\"` when the host's workspace policy redacts multi-vendor posture."
2234
+ },
2235
+ "fallbackModel": {
2236
+ "type": "string",
2237
+ "description": "Model id of the substitute model from `NodeModule.fallbackModel.model`, or `\"[REDACTED]\"` when redacted (always paired all-or-nothing with `fallbackProvider`)."
2238
+ },
2239
+ "missingCapabilities": {
2240
+ "type": "array",
2241
+ "items": {
2242
+ "type": "string"
2243
+ },
2244
+ "uniqueItems": true,
2245
+ "description": "Subset of `NodeModule.requiredModelCapabilities` that the active model did not satisfy."
2246
+ }
2247
+ }
2248
+ },
2249
+ "modelCapabilityInsufficient": {
2250
+ "type": "object",
2251
+ "additionalProperties": false,
2252
+ "description": "RFC 0031 §D. Emitted when a host refuses to dispatch a NodeModule because the active model lacks declared `requiredModelCapabilities` AND no viable fallback is available (no `fallbackModel` declared, OR the host cannot authenticate to the fallback provider). MUST event per RFC 0031 §B step 4. Pairs with `RunSnapshot.error.code = \"capability_not_provided\"` per `capabilities.md` §\"Unsupported capability — refusal contract\". Recursive fallback is NOT permitted (RFC 0031 §\"Unresolved questions\" #3): if a host attempts substitution and the fallback itself fails, the host MUST emit this event with `fallbackAttempted: true` and refuse, not chain to another fallback.",
2253
+ "required": [
2254
+ "nodeId",
2255
+ "provider",
2256
+ "model",
2257
+ "missingCapabilities"
2258
+ ],
2259
+ "properties": {
2260
+ "nodeId": {
2261
+ "$ref": "ids.schema.json#/$defs/nodeId",
2262
+ "description": "The node whose dispatch was refused."
2263
+ },
2264
+ "provider": {
2265
+ "type": "string",
2266
+ "description": "Provider id of the active model the host attempted to use."
2267
+ },
2268
+ "model": {
2269
+ "type": "string",
2270
+ "description": "Model id of the active model."
2271
+ },
2272
+ "missingCapabilities": {
2273
+ "type": "array",
2274
+ "items": {
2275
+ "type": "string"
2276
+ },
2277
+ "uniqueItems": true,
2278
+ "description": "Subset of `NodeModule.requiredModelCapabilities` that the active model did not satisfy."
2279
+ },
2280
+ "fallbackAttempted": {
2281
+ "type": "boolean",
2282
+ "default": false,
2283
+ "description": "True if the host attempted to authenticate to a declared `fallbackModel` and that attempt failed (e.g., no credential resolvable, or the fallback provider was outside `capabilities.aiProviders.supported`). False if no `fallbackModel` was declared on the NodeModule."
2284
+ }
2285
+ }
2286
+ },
2287
+ "envelopeRetryAttempted": {
2288
+ "type": "object",
2289
+ "additionalProperties": false,
2290
+ "description": "RFC 0032 §B.1. Emitted when a host retries an envelope emission after a parse or validation failure on a prior attempt. The first attempt does NOT emit this event; the second attempt emits with `attempt: 2`, etc. SHOULD-tier — hosts that don't implement retry don't emit; hosts that DO retry on validation failure SHOULD emit per attempt past the first.",
2291
+ "required": [
2292
+ "nodeId",
2293
+ "attempt",
2294
+ "reason"
2295
+ ],
2296
+ "properties": {
2297
+ "nodeId": {
2298
+ "$ref": "ids.schema.json#/$defs/nodeId",
2299
+ "description": "The node whose envelope emission is being retried."
2300
+ },
2301
+ "attempt": {
2302
+ "type": "integer",
2303
+ "minimum": 1,
2304
+ "maximum": 16,
2305
+ "description": "1-indexed attempt counter. The first attempt does NOT emit this event; the second attempt emits with `attempt: 2`, etc."
2306
+ },
2307
+ "reason": {
2308
+ "type": "string",
2309
+ "anyOf": [
2310
+ {
2311
+ "enum": [
2312
+ "schema-violation",
2313
+ "truncation",
2314
+ "type-drift",
2315
+ "type-mismatch",
2316
+ "refusal",
2317
+ "parse-error",
2318
+ "unknown"
2319
+ ]
2320
+ },
2321
+ {
2322
+ "pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
2323
+ }
2324
+ ],
2325
+ "description": "Why the prior attempt failed. Spec-reserved values: `schema-violation` (model emitted wrong-shape JSON; corrective fragment + retry per RFC 0033 §C), `truncation` (stop_reason: max_tokens; budget-double + retry per RFC 0033 §B), `type-drift` (envelope `type` discriminator drifted from what was advertised mid-run), `type-mismatch` (a typed payload field was emitted with the wrong runtime type — e.g., string where number was declared), `refusal` (provider safety-stop; NO retry per RFC 0032 §B.3), `parse-error` (response was not extractable as JSON even after lenient parsing), `unknown` (host could not classify). Host-private extensions MUST prefix with `x-host-<host>-` per `host-extensions.md` §\"Canonical-prefix table\"; matches the RFC 0031 §B `requiredModelCapabilities` precedent."
2326
+ },
2327
+ "previousError": {
2328
+ "type": [
2329
+ "string",
2330
+ "null"
2331
+ ],
2332
+ "description": "Diagnostic text from the failing attempt. MUST NOT contain prompt or response substring excerpts; hosts SHOULD limit to validator output (e.g., \"required field 'steps' missing\"). Subject to SR-1 redaction per `ai-envelope.md` §\"Redaction (SR-1 carry-forward)\"."
2333
+ }
2334
+ }
2335
+ },
2336
+ "envelopeRetryExhausted": {
2337
+ "type": "object",
2338
+ "additionalProperties": false,
2339
+ "description": "RFC 0032 §B.2. Emitted when a host has exhausted its retry budget and is about to surface a terminal envelope failure to the node. MUST-tier — alternative is silent terminal failure with no event surface, leaving conformance suites unable to assert correct give-up behavior. Hosts that don't retry MUST still emit this event when an envelope attempt terminally fails (with `totalAttempts: 1`). Pairs with `cap.breached` when the failure mode is schema-violation or truncation per RFC 0033 §B + §C.",
2340
+ "required": [
2341
+ "nodeId",
2342
+ "totalAttempts",
2343
+ "finalReason"
2344
+ ],
2345
+ "properties": {
2346
+ "nodeId": {
2347
+ "$ref": "ids.schema.json#/$defs/nodeId"
2348
+ },
2349
+ "totalAttempts": {
2350
+ "type": "integer",
2351
+ "minimum": 1
2352
+ },
2353
+ "finalReason": {
2354
+ "type": "string",
2355
+ "anyOf": [
2356
+ {
2357
+ "enum": [
2358
+ "schema-violation",
2359
+ "truncation",
2360
+ "type-drift",
2361
+ "type-mismatch",
2362
+ "refusal",
2363
+ "parse-error",
2364
+ "unknown"
2365
+ ]
2366
+ },
2367
+ {
2368
+ "pattern": "^x-host-[a-z][a-z0-9-]*-[a-z][a-z0-9-]*$"
2369
+ }
2370
+ ],
2371
+ "description": "Same value set as `envelope.retry.attempted.reason` (§B.1). Spec-reserved closed enum plus `x-host-<host>-` extensions."
2372
+ },
2373
+ "finalError": {
2374
+ "type": [
2375
+ "string",
2376
+ "null"
2377
+ ],
2378
+ "description": "Diagnostic text from the final attempt. Same redaction discipline as `envelope.retry.attempted.previousError`."
2379
+ }
2380
+ }
2381
+ },
2382
+ "envelopeRefusal": {
2383
+ "type": "object",
2384
+ "additionalProperties": false,
2385
+ "description": "RFC 0032 §B.3. Emitted when the underlying LLM provider returns an explicit refusal (e.g., OpenAI `message.refusal`, Anthropic safety-stop, Gemini safety-block). MUST-tier. Hosts MUST NOT retry on refusal — retrying refusal with prompt mutation creates a circumvention concern (the host automatically searches for a prompt the model will accept, evading the safety filter's intent) per RFC 0032 §B.3 + RFC 0033 §D. The node MUST fail with `error.code = \"envelope_refusal\"` per RFC 0033 §F (renamed from `envelope_refused_by_provider` per the 2026-05-21 RFC adoption-feedback amendment).",
2386
+ "required": [
2387
+ "nodeId",
2388
+ "provider",
2389
+ "model"
2390
+ ],
2391
+ "properties": {
2392
+ "nodeId": {
2393
+ "$ref": "ids.schema.json#/$defs/nodeId"
2394
+ },
2395
+ "provider": {
2396
+ "type": "string"
2397
+ },
2398
+ "model": {
2399
+ "type": "string"
2400
+ },
2401
+ "refusalText": {
2402
+ "type": [
2403
+ "string",
2404
+ "null"
2405
+ ],
2406
+ "description": "Provider-returned refusal message, if any. MUST be passed through the host's BYOK redaction harness AND prompt-content redaction pipeline before emission (per SECURITY invariant `envelope-refusal-no-prompt-leak`). Provider safety-refusal messages can echo offending prompt substrings; emitting them verbatim would create a side channel for prompt-injection-attack telemetry exfiltration AND for SR-1 secret-leak. Replay consumers MUST tolerate `null` even when the original was non-null (host redaction policies legitimately tighten over time)."
2407
+ },
2408
+ "safetyCategory": {
2409
+ "type": [
2410
+ "string",
2411
+ "null"
2412
+ ],
2413
+ "description": "Provider-specific safety category if available (e.g., Anthropic `harmful-content`, Gemini `SAFETY_BLOCK_HARASSMENT`, OpenAI `policy_violation`). Verbatim from provider; no normalization."
2414
+ }
2415
+ }
2416
+ },
2417
+ "envelopeTruncated": {
2418
+ "type": "object",
2419
+ "additionalProperties": false,
2420
+ "description": "RFC 0032 §B.4. Emitted when the LLM emission was cut off before the envelope was complete (typically `stop_reason: \"max_tokens\"`). SHOULD-tier — hosts that distinguish truncation from schema-violation per RFC 0033 §A MUST emit this event when truncation occurs. Hosts that conflate truncation with schema-violation (legacy behavior) MAY omit; they then fail RFC 0033 conformance.",
2421
+ "required": [
2422
+ "nodeId",
2423
+ "provider",
2424
+ "model",
2425
+ "stopReason"
2426
+ ],
2427
+ "properties": {
2428
+ "nodeId": {
2429
+ "$ref": "ids.schema.json#/$defs/nodeId"
2430
+ },
2431
+ "provider": {
2432
+ "type": "string"
2433
+ },
2434
+ "model": {
2435
+ "type": "string"
2436
+ },
2437
+ "stopReason": {
2438
+ "type": "string",
2439
+ "enum": [
2440
+ "max_tokens",
2441
+ "length",
2442
+ "stop_sequence",
2443
+ "unknown"
2444
+ ],
2445
+ "description": "Provider-normalized stop reason. `max_tokens` covers OpenAI `length` + Anthropic `max_tokens`; `length` preserved as a separate value for hosts that distinguish provider-side `length` (model self-determined length cap) from `max_tokens` (host-side budget cap)."
2446
+ },
2447
+ "partialPayloadAvailable": {
2448
+ "type": "boolean",
2449
+ "default": false,
2450
+ "description": "True if the host recovered a partial envelope before truncation. Hosts MAY use this signal to route to a recovery path (e.g., budget-doubled retry per RFC 0033 §B)."
2451
+ },
2452
+ "outputTokenCount": {
2453
+ "type": [
2454
+ "integer",
2455
+ "null"
2456
+ ],
2457
+ "minimum": 0,
2458
+ "description": "Tokens emitted before truncation. Sourced from the provider response's usage block. MUST replay identically."
2459
+ }
2460
+ }
2461
+ },
2462
+ "envelopeNlToFormatEngaged": {
2463
+ "type": "object",
2464
+ "additionalProperties": false,
2465
+ "description": "RFC 0032 §B.5. Emitted when the host has escalated to a two-call NL-to-Format fallback after retry exhaustion (per Tam et al., arXiv 2408.02442 mitigation strategy: free-form reasoning in the first call → schema coercion in the second call). MAY-tier — NL-to-Format is one of many possible recovery strategies; hosts that don't implement it don't advertise it.",
2466
+ "required": [
2467
+ "nodeId",
2468
+ "originalEnvelopeType"
2469
+ ],
2470
+ "properties": {
2471
+ "nodeId": {
2472
+ "$ref": "ids.schema.json#/$defs/nodeId"
2473
+ },
2474
+ "originalEnvelopeType": {
2475
+ "type": "string",
2476
+ "description": "The envelope kind the original attempt was trying to emit."
2477
+ },
2478
+ "fallbackCalls": {
2479
+ "type": "integer",
2480
+ "minimum": 1,
2481
+ "default": 1,
2482
+ "description": "Number of secondary LLM calls used to reformat free-form output into the envelope's schema."
2483
+ }
2484
+ }
2485
+ },
2486
+ "envelopeRecoveryApplied": {
2487
+ "type": "object",
2488
+ "additionalProperties": false,
2489
+ "description": "RFC 0032 §B.6. Emitted when lenient parsing recovered a malformed envelope (e.g., JSON repair via `jsonrepair`, markdown fence stripping, last-balanced-object extraction). Recovery is internal to the parsing step, BEFORE validation; recovery does NOT consume a retry attempt per RFC 0033 §D. MAY-tier — lenient parsing is a host-discretion recovery path. The event payload MUST NOT carry the recovered envelope content or any substring from the model's pre-recovery output per SECURITY invariant `envelope-recovery-no-content-leak`; only the recovery path identifier and the optional `byteOffset` are emitted. The recovered content rides on the subsequent envelope acceptance + downstream `RunEventDoc`, NOT on this event.",
2490
+ "required": [
2491
+ "nodeId",
2492
+ "path"
2493
+ ],
2494
+ "properties": {
2495
+ "nodeId": {
2496
+ "$ref": "ids.schema.json#/$defs/nodeId"
2497
+ },
2498
+ "path": {
2499
+ "type": "string",
2500
+ "enum": [
2501
+ "direct",
2502
+ "jsonrepair",
2503
+ "markdown-fence",
2504
+ "brace-walker",
2505
+ "custom"
2506
+ ],
2507
+ "description": "Which recovery path succeeded. `direct` is reserved for the no-recovery-needed path and is informational; hosts MAY omit emission when `path: \"direct\"`. MUST replay identically (deterministic parsing → deterministic recovery outcome)."
2508
+ },
2509
+ "byteOffset": {
2510
+ "type": [
2511
+ "integer",
2512
+ "null"
2513
+ ],
2514
+ "minimum": 0,
2515
+ "description": "Byte position where recovery succeeded. Useful for debugging which fraction of the model's output was salvageable."
2516
+ }
2517
+ }
2518
+ },
2519
+ "agentToolCalled": {
2520
+ "type": "object",
2521
+ "description": "Multi-Agent Shift Phase 1. Emitted when an agent invokes a tool. Pairs with `agent.toolReturned` via shared `callId`.",
2522
+ "required": [
2523
+ "agentId",
2524
+ "toolName",
2525
+ "callId"
2526
+ ],
2527
+ "properties": {
2528
+ "agentId": {
2529
+ "$ref": "ids.schema.json#/$defs/agentId"
2530
+ },
2531
+ "toolName": {
2532
+ "type": "string",
2533
+ "minLength": 1,
2534
+ "description": "Tool identifier (typically a node-pack typeId or function name)."
2535
+ },
2536
+ "callId": {
2537
+ "type": "string",
2538
+ "minLength": 1,
2539
+ "description": "Unique correlation id linking this call to the subsequent `agent.toolReturned`. Hosts SHOULD use UUIDs or content-addressable hashes."
2540
+ },
2541
+ "inputs": {
2542
+ "description": "Tool inputs. Shape is tool-specific; consumers MUST NOT assume an object."
2543
+ },
2544
+ "argsHash": {
2545
+ "type": "string",
2546
+ "description": "RFC 0064 (when `capabilities.toolHooks.prePostEvents`). SHA-256 over RFC 8785 JCS-canonicalized args with resolved secrets already redacted (SR-1) — the SIEM-safe, content-free alternative to `inputs`. Raw key material MUST NOT enter the hash input."
2547
+ },
2548
+ "principal": {
2549
+ "type": "string",
2550
+ "description": "RFC 0064. RFC 0048 principal id the call is attributed to (`core.system` for non-agent host egress)."
2551
+ },
2552
+ "transport": {
2553
+ "type": "string",
2554
+ "enum": [
2555
+ "mcp",
2556
+ "http",
2557
+ "native"
2558
+ ],
2559
+ "description": "RFC 0064. How the tool was reached."
2560
+ },
2561
+ "causationHostId": {
2562
+ "type": "string",
2563
+ "minLength": 1,
2564
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2565
+ }
2566
+ },
2567
+ "additionalProperties": false
2568
+ },
2569
+ "agentToolReturned": {
2570
+ "type": "object",
2571
+ "description": "Multi-Agent Shift Phase 1. Emitted when a tool invocation completes (success or failure). Pairs with `agent.toolCalled` via `callId`.",
2572
+ "required": [
2573
+ "agentId",
2574
+ "toolName",
2575
+ "callId"
2576
+ ],
2577
+ "properties": {
2578
+ "agentId": {
2579
+ "$ref": "ids.schema.json#/$defs/agentId"
2580
+ },
2581
+ "toolName": {
2582
+ "type": "string",
2583
+ "minLength": 1
2584
+ },
2585
+ "callId": {
2586
+ "type": "string",
2587
+ "minLength": 1
2588
+ },
2589
+ "outcome": {
2590
+ "description": "Tool result. Discriminated by host on success vs error; payload shape is tool-specific."
2591
+ },
2592
+ "error": {
2593
+ "$ref": "#/$defs/_errorObject",
2594
+ "description": "Set on tool-execution failure. Mutually exclusive with `outcome`."
2595
+ },
2596
+ "status": {
2597
+ "type": "string",
2598
+ "enum": [
2599
+ "ok",
2600
+ "error",
2601
+ "forbidden",
2602
+ "rate_limited"
2603
+ ],
2604
+ "description": "RFC 0064 (when `capabilities.toolHooks.prePostEvents`). Tool-hooks outcome. `forbidden`/`rate_limited` mean the tool was never invoked (per-tool authz / rate-limit gate)."
2605
+ },
2606
+ "durationMs": {
2607
+ "type": "integer",
2608
+ "minimum": 0,
2609
+ "description": "RFC 0064. Wall-clock tool duration; recorded in the event and re-emitted verbatim on replay/`:fork` (MUST NOT be recomputed from a clock, per `replay.md`). Absent when the call never started (`forbidden`/`rate_limited`)."
2610
+ },
2611
+ "causationHostId": {
2612
+ "type": "string",
2613
+ "minLength": 1,
2614
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2615
+ }
2616
+ },
2617
+ "additionalProperties": false
2618
+ },
2619
+ "agentHandoff": {
2620
+ "type": "object",
2621
+ "description": "Multi-Agent Shift Phase 1. Emitted when control transfers from one agent to another mid-run (e.g., orchestrator → worker, worker → worker via `core.dispatch`). Pairs with the receiving agent's subsequent `agent.decided` / `agent.toolCalled` / `node.started`.",
2622
+ "required": [
2623
+ "fromAgentId",
2624
+ "toAgentId"
2625
+ ],
2626
+ "properties": {
2627
+ "fromAgentId": {
2628
+ "type": "string",
2629
+ "minLength": 3,
2630
+ "maxLength": 256,
2631
+ "description": "Agent surrendering control."
2632
+ },
2633
+ "toAgentId": {
2634
+ "type": "string",
2635
+ "minLength": 3,
2636
+ "maxLength": 256,
2637
+ "description": "Agent receiving control."
2638
+ },
2639
+ "reason": {
2640
+ "type": "string",
2641
+ "description": "Optional handoff rationale (e.g., 'specialist routing', 'escalation', 'dispatch-loop-iteration')."
2642
+ },
2643
+ "causationHostId": {
2644
+ "type": "string",
2645
+ "minLength": 1,
2646
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2647
+ }
2648
+ },
2649
+ "additionalProperties": false
2650
+ },
2651
+ "agentDecided": {
2652
+ "type": "object",
2653
+ "description": "Multi-Agent Shift Phase 1. Emitted when an agent produces a typed decision (routing, classification, judgement). Carries optional `confidence` in `[0, 1]`; when below the run's resolved `escalationThreshold` (default 0.7), hosts MUST suspend with `node.suspended { reason: 'low-confidence' }` per the confidence-escalation contract.",
2654
+ "required": [
2655
+ "agentId",
2656
+ "decision"
2657
+ ],
2658
+ "properties": {
2659
+ "agentId": {
2660
+ "$ref": "ids.schema.json#/$defs/agentId"
2661
+ },
2662
+ "decision": {
2663
+ "description": "Typed decision payload. Shape is decision-specific; consumers MUST NOT assume an object."
2664
+ },
2665
+ "confidence": {
2666
+ "type": "number",
2667
+ "minimum": 0,
2668
+ "maximum": 1,
2669
+ "description": "Optional confidence in `[0, 1]`. Below the threshold → escalate via `node.suspended { reason: 'low-confidence' }`. Absent values are treated as 'no signal' — no escalation."
2670
+ },
2671
+ "causationHostId": {
2672
+ "type": "string",
2673
+ "minLength": 1,
2674
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2675
+ }
2676
+ },
2677
+ "additionalProperties": false
2678
+ },
2679
+ "agentVerified": {
2680
+ "type": "object",
2681
+ "description": "RFC 0090 (`multiAgent.executionModel.version >= 6`). A critic agent's independent verdict over a prior result, emitted before the result is committed/merged. Content-free: names the target + verdict + (optional) criteria KEYS, never the verified content (SECURITY invariant `verifier-no-content-leak`). A `fail` verdict on a `verifier.gating: true` host MUST block the merge/terminate; `revise` SHOULD route back to another actor turn (bounded by `maxLoopIterations`, RFC 0058).",
2682
+ "required": [
2683
+ "agentId",
2684
+ "target",
2685
+ "verdict"
2686
+ ],
2687
+ "properties": {
2688
+ "agentId": {
2689
+ "$ref": "ids.schema.json#/$defs/agentId",
2690
+ "description": "AgentRef.agentId of the verifying (critic) agent. SHOULD differ from the agent whose work is checked; a host MAY allow self-verification but MUST keep verifier identity inspectable."
2691
+ },
2692
+ "target": {
2693
+ "type": "string",
2694
+ "minLength": 1,
2695
+ "description": "Opaque reference to what was checked — the eventId of the verified `agent.decided`, a child runId, or a tool callId. Chains the verdict to its subject."
2696
+ },
2697
+ "verdict": {
2698
+ "type": "string",
2699
+ "enum": [
2700
+ "pass",
2701
+ "fail",
2702
+ "revise"
2703
+ ],
2704
+ "description": "`pass`: acceptable, MAY commit/terminate. `fail`: rejected; a `verifier.gating` host MUST NOT commit it. `revise`: needs another actor turn; SHOULD route back, not terminate."
2705
+ },
2706
+ "criteria": {
2707
+ "type": "array",
2708
+ "items": {
2709
+ "type": "string",
2710
+ "minLength": 1
2711
+ },
2712
+ "uniqueItems": true,
2713
+ "description": "Optional closed list of the criteria KEYS evaluated (e.g. `[\"schema-valid\",\"grounded\"]`). Keys only — never per-criterion verdict text — for SIEM safety."
2714
+ },
2715
+ "confidence": {
2716
+ "type": "number",
2717
+ "minimum": 0,
2718
+ "maximum": 1,
2719
+ "description": "Optional verifier confidence in `[0,1]` — the critic's confidence in its OWN verdict, distinct from the actor's `agent.decided.confidence`. MAY drive the RFC 0039 escalation contract."
2720
+ },
2721
+ "causationHostId": {
2722
+ "type": "string",
2723
+ "minLength": 1,
2724
+ "description": "RFC 0040 §A — cross-host causation pointer when the verified target lives on a different host."
2725
+ }
2726
+ },
2727
+ "additionalProperties": false
2728
+ },
2729
+ "runOrchestratorDecided": {
2730
+ "type": "object",
2731
+ "description": "Multi-Agent Shift Phase 5. Emitted exactly once per orchestrator decision by a `core.orchestrator.supervisor` node (or host-extension equivalent). Carries the deciding agent's identity and the typed `OrchestratorDecision` (see `orchestrator-decision.schema.json`). The envelope's top-level `nodeId` carries the supervisor node-id; the payload does NOT duplicate it.",
2732
+ "required": [
2733
+ "agentId",
2734
+ "decision"
2735
+ ],
2736
+ "properties": {
2737
+ "agentId": {
2738
+ "$ref": "ids.schema.json#/$defs/agentId",
2739
+ "description": "AgentRef.agentId of the orchestrator. MUST equal `RunSnapshot.runOrchestrator.agentId` for the run's lifetime — orchestrator identity is set at first decision and does not change."
2740
+ },
2741
+ "decision": {
2742
+ "$ref": "orchestrator-decision.schema.json"
2743
+ },
2744
+ "iteration": {
2745
+ "type": "integer",
2746
+ "minimum": 1,
2747
+ "description": "RFC 0061 (`multiAgent.executionModel.version >= 5`). 1-based, monotonic count of orchestrator turns in this run — the observable loop-iteration counter that `maxLoopIterations` (RFC 0058) bounds; a breach emits `cap.breached { kind: 'loop-iterations', observed: <this+1> }`. A `version >= 5` host MUST set it on every `runOrchestrator.decided`, incrementing by exactly 1 per turn and surviving a stateful HITL resume unchanged. Recorded in the event and re-emitted verbatim on replay/`:fork`, never recomputed (`replay.md`). Omitted by hosts on `version < 5`."
2748
+ },
2749
+ "causationHostId": {
2750
+ "type": "string",
2751
+ "minLength": 1,
2752
+ "description": "RFC 0040 §A — optional cross-host causation pointer. Present + non-empty when this event's `causationId` points at an event on a DIFFERENT host; absent when same-host. MUST equal the originating host's `crossHostCausation.hostId`."
2753
+ }
2754
+ },
2755
+ "additionalProperties": false
2756
+ },
2757
+ "nodeDispatched": {
2758
+ "type": "object",
2759
+ "description": "Emitted by `core.dispatch` (RFC 0007 §D + RFC 0022 §A) for each child workflow spawned by a `next-worker` OrchestratorDecision. The envelope's top-level `nodeId` carries the dispatching `core.dispatch` node's id; the payload names the spawned child run + its terminal status at the moment of emission. Lets observers reconstruct the parent → child linkage without scanning the runs table.",
2760
+ "required": [
2761
+ "childRunId",
2762
+ "childWorkflowId"
2763
+ ],
2764
+ "properties": {
2765
+ "childRunId": {
2766
+ "type": "string",
2767
+ "minLength": 1,
2768
+ "description": "RunId of the spawned child run."
2769
+ },
2770
+ "childWorkflowId": {
2771
+ "type": "string",
2772
+ "minLength": 1,
2773
+ "description": "WorkflowId of the spawned child."
2774
+ },
2775
+ "childStatus": {
2776
+ "type": "string",
2777
+ "description": "Status of the child run at the moment the dispatch step returned (typically `completed`, `failed`, `cancelled`, or one of the `waiting-*` states when the child suspended)."
2778
+ }
2779
+ },
2780
+ "additionalProperties": false
2781
+ },
2782
+ "dispatchFanOut": {
2783
+ "type": "object",
2784
+ "description": "RFC 0118. Emitted by `core.dispatch` when a `fanOutPolicy: 'parallel'` wave BEGINS, so the parent stays observable while children run concurrently. The envelope's `nodeId` carries the dispatching `core.dispatch` node id; `causationId` is set to the consumed `runOrchestrator.decided` event so replay reconstructs decision → fan-out. Emitted ONLY on the parallel path.",
2785
+ "required": [
2786
+ "fanOutPolicy",
2787
+ "childCount"
2788
+ ],
2789
+ "properties": {
2790
+ "fanOutPolicy": {
2791
+ "const": "parallel",
2792
+ "description": "Always `\"parallel\"` — this event is emitted only on the parallel fan-out path."
2793
+ },
2794
+ "childCount": {
2795
+ "type": "integer",
2796
+ "minimum": 2,
2797
+ "description": "Number of children dispatched in this fan-out (`nextWorkerIds.length`; > 1 by construction)."
2798
+ },
2799
+ "maxConcurrency": {
2800
+ "type": "integer",
2801
+ "minimum": 1,
2802
+ "description": "Effective concurrency ceiling for the wave (`min(config.maxConcurrency ?? ∞, capabilities.dispatch.maxFanOut ?? ∞)`), when bounded."
2803
+ },
2804
+ "joinMode": {
2805
+ "type": "string",
2806
+ "enum": [
2807
+ "wait-all",
2808
+ "quorum",
2809
+ "first",
2810
+ "race"
2811
+ ],
2812
+ "description": "The `joinPolicy.mode` governing this fan-out."
2813
+ }
2814
+ },
2815
+ "additionalProperties": false
2816
+ },
2817
+ "dispatchJoin": {
2818
+ "type": "object",
2819
+ "description": "RFC 0118. Emitted by `core.dispatch` when a `fanOutPolicy: 'parallel'` join is SATISFIED (or fails). The envelope's `nodeId` carries the dispatching node id; `causationId` matches the paired `core.dispatch.fanOut`. `mergeOrder` is the canonical replay-deterministic record of the output-merge tiebreak: a replay MUST re-apply `outputMapping` in `mergeOrder` (the parent host's observed wall-clock terminal order), NOT in `nextWorkerIds` order.",
2820
+ "required": [
2821
+ "joinOutcome",
2822
+ "completedCount",
2823
+ "failedCount",
2824
+ "mergeOrder"
2825
+ ],
2826
+ "properties": {
2827
+ "joinOutcome": {
2828
+ "type": "string",
2829
+ "enum": [
2830
+ "satisfied",
2831
+ "failed",
2832
+ "partial"
2833
+ ],
2834
+ "description": "`'satisfied'` — `mode` met and `onChildFailure` did not fail the node. `'failed'` — `onChildFailure: 'fail-fast'` tripped, or `mode` could not be satisfied (e.g. quorum unreachable); the dispatch node fails. `'partial'` — `mode` satisfied but ≥1 child is non-`completed` under `collect`/`absorb`; the node SUCCEEDS."
2835
+ },
2836
+ "completedCount": {
2837
+ "type": "integer",
2838
+ "minimum": 0,
2839
+ "description": "Number of children that reached `completed`."
2840
+ },
2841
+ "failedCount": {
2842
+ "type": "integer",
2843
+ "minimum": 0,
2844
+ "description": "Number of children that reached `failed`."
2845
+ },
2846
+ "cancelledCount": {
2847
+ "type": "integer",
2848
+ "minimum": 0,
2849
+ "description": "Number of children cancelled (e.g. in-flight when `quorum`/`first`/`race`/`fail-fast` short-circuited the join)."
2850
+ },
2851
+ "mergeOrder": {
2852
+ "type": "array",
2853
+ "items": {
2854
+ "type": "string"
2855
+ },
2856
+ "description": "`childRunId`s in the parent host's observed wall-clock terminal order — the replay-deterministic tiebreak for colliding `outputMapping` keys. Recorded at terminal-fold time; never recomputed from child timestamps."
2857
+ }
2858
+ },
2859
+ "additionalProperties": false
2860
+ },
2861
+ "conversationOpened": {
2862
+ "type": "object",
2863
+ "description": "Multi-Agent Shift Phase 4. Emitted when a `core.conversationGate` (or host-extension equivalent) opens a new multi-turn conversation context. Pairs with the closing `conversation.closed` via shared `conversationId`.",
2864
+ "required": [
2865
+ "conversationId"
2866
+ ],
2867
+ "properties": {
2868
+ "conversationId": {
2869
+ "type": "string",
2870
+ "minLength": 1,
2871
+ "maxLength": 256,
2872
+ "description": "Opaque conversation identifier. Tenant-unique invariant: hosts MUST ensure no two distinct conversations in the same tenant share an id. Cross-host portability not normative."
2873
+ },
2874
+ "openedBy": {
2875
+ "type": "string",
2876
+ "description": "Optional `AgentRef.agentId` of the agent that opened the conversation."
2877
+ }
2878
+ },
2879
+ "additionalProperties": false
2880
+ },
2881
+ "conversationExchanged": {
2882
+ "type": "object",
2883
+ "description": "Multi-Agent Shift Phase 4. Emitted when a single turn completes within an open conversation (`core.conversationGate.exchange`). Carries the validated outcome of the suspend/resume cycle.",
2884
+ "required": [
2885
+ "conversationId",
2886
+ "turnIndex"
2887
+ ],
2888
+ "properties": {
2889
+ "conversationId": {
2890
+ "type": "string",
2891
+ "minLength": 1,
2892
+ "maxLength": 256
2893
+ },
2894
+ "turnIndex": {
2895
+ "type": "integer",
2896
+ "minimum": 0,
2897
+ "description": "0-indexed turn within this conversation. Strictly monotonic."
2898
+ },
2899
+ "outcome": {
2900
+ "description": "Validated turn outcome per the per-turn schema declared in `core.conversationGate` config."
2901
+ }
2902
+ },
2903
+ "additionalProperties": false
2904
+ },
2905
+ "conversationClosed": {
2906
+ "type": "object",
2907
+ "description": "Multi-Agent Shift Phase 4. Emitted when a conversation context terminates (`core.conversationGate.close`). Final event in the conversation's lifecycle; no further `conversation.exchanged` events MAY follow for the same `conversationId` in this run.",
2908
+ "required": [
2909
+ "conversationId"
2910
+ ],
2911
+ "properties": {
2912
+ "conversationId": {
2913
+ "type": "string",
2914
+ "minLength": 1,
2915
+ "maxLength": 256
2916
+ },
2917
+ "reason": {
2918
+ "type": "string",
2919
+ "description": "Optional close reason (e.g., 'goal-reached', 'max-turns', 'user-cancelled')."
2920
+ },
2921
+ "turnCount": {
2922
+ "type": "integer",
2923
+ "minimum": 0,
2924
+ "description": "Total turns completed in this conversation (number of `conversation.exchanged` events emitted)."
2925
+ }
2926
+ },
2927
+ "additionalProperties": false
2928
+ },
2929
+ "memoryCompacted": {
2930
+ "type": "object",
2931
+ "description": "RFC 0012 (Memory Compaction Profile). Emitted by a host advertising `capabilities.memory.compaction.supported: true` each time a compaction run completes, regardless of trigger. `outputId` MUST be readable via `MemoryAdapter.get(memoryRef, outputId)` until normal TTL eviction. SR-1 carry-forward (RFC 0012 §D) applies: the host MUST route compacted entry content through the same BYOK redaction harness applied to a fresh `put`.",
2932
+ "required": [
2933
+ "memoryRef",
2934
+ "outputId",
2935
+ "sourceCount",
2936
+ "trigger",
2937
+ "byteSize"
2938
+ ],
2939
+ "properties": {
2940
+ "memoryRef": {
2941
+ "type": "string",
2942
+ "minLength": 1,
2943
+ "description": "Opaque MemoryAdapter handle per RFC 0004 §C. Bounds compaction to a single memory scope."
2944
+ },
2945
+ "outputId": {
2946
+ "type": "string",
2947
+ "minLength": 1,
2948
+ "description": "Id of the new MemoryEntry created by compaction."
2949
+ },
2950
+ "sourceIds": {
2951
+ "type": "array",
2952
+ "items": {
2953
+ "type": "string",
2954
+ "minLength": 1
2955
+ },
2956
+ "description": "Ids of entries collapsed into outputId. Hosts MAY omit when sourceCount > 100; the `compacted-from:<runId>` tag convention (RFC 0012 §C) becomes the authoritative provenance signal. When present, MUST be exhaustive within the array (no 'and N more' semantics)."
2957
+ },
2958
+ "sourceCount": {
2959
+ "type": "integer",
2960
+ "minimum": 1,
2961
+ "description": "Total source entries collapsed, including any not enumerated in `sourceIds`."
2962
+ },
2963
+ "trigger": {
2964
+ "type": "string",
2965
+ "enum": [
2966
+ "host-managed",
2967
+ "client-requested",
2968
+ "both"
2969
+ ],
2970
+ "description": "Matches `capabilities.memory.compaction.trigger`; indicates which trigger path drove this run. v1.x normates only `host-managed`."
2971
+ },
2972
+ "byteSize": {
2973
+ "type": "integer",
2974
+ "minimum": 0,
2975
+ "description": "Byte size of the resulting MemoryEntry.content."
2976
+ },
2977
+ "distillation": {
2978
+ "type": "object",
2979
+ "description": "RFC 0062 (when `capabilities.memory.distillation.supported: true`). Present when this compaction is part of a budgeted distillation run (a scheduled or on-demand 'dream'). Absent for a plain RFC 0012 compaction. Carries the token-budget accounting + whether the memory index was refreshed — not a parallel `memory.distilled` event.",
2980
+ "additionalProperties": false,
2981
+ "required": [
2982
+ "tokenBudget",
2983
+ "tokensUsed"
2984
+ ],
2985
+ "properties": {
2986
+ "tokenBudget": {
2987
+ "type": "integer",
2988
+ "minimum": 1,
2989
+ "description": "Effective per-run budget honored (≤ advertised `maxTokenBudget`), counted against the advertised `tokenizerName`."
2990
+ },
2991
+ "tokensUsed": {
2992
+ "type": "integer",
2993
+ "minimum": 0,
2994
+ "description": "Total input+output tokens the distillation consumed, best-effort-honest per the advertised tokenizer (±10% tolerance). MUST be ≤ `tokenBudget` on a successful run."
2995
+ },
2996
+ "indexUpdated": {
2997
+ "type": "boolean",
2998
+ "description": "Whether this run refreshed the memory-index workspace file (`MEMORY-INDEX.json`, RFC 0059). When `true`, a `workspace.updated` event was also emitted for that path."
2999
+ }
3000
+ }
3001
+ }
3002
+ },
3003
+ "additionalProperties": false
3004
+ },
3005
+ "memoryWritten": {
3006
+ "type": "object",
3007
+ "description": "RFC 0057. Emitted by a host advertising `capabilities.memory.attribution.emitsWriteEvents: true` for each memory write a run makes, attributing it to the node (and agent, when known) that caused it. Content-free: identifiers + non-secret tags only — the entry content is served by the read-side (`MemoryAdapter.get`), already SR-1-redacted. On replay the event is re-read from the log, never regenerated (the host MUST NOT mint a new `memoryId` or timestamp at replay time). SECURITY invariants `memory-attribution-no-content` + `memory-attribution-tenant-scoped` apply.",
3008
+ "required": [
3009
+ "memoryRef",
3010
+ "memoryId"
3011
+ ],
3012
+ "properties": {
3013
+ "memoryRef": {
3014
+ "type": "string",
3015
+ "minLength": 1,
3016
+ "description": "Opaque MemoryAdapter handle (RFC 0004 §C) the entry was written under; resolvable via the read-side."
3017
+ },
3018
+ "memoryId": {
3019
+ "type": "string",
3020
+ "minLength": 1,
3021
+ "description": "Host-issued, stable entry id; correlates to `MemoryAdapter.get(memoryRef, memoryId)`."
3022
+ },
3023
+ "nodeId": {
3024
+ "$ref": "ids.schema.json#/$defs/nodeId",
3025
+ "description": "SHOULD — the node whose execution caused the write. Omitted only for writes with no node attribution (e.g. host session-end auto-memory)."
3026
+ },
3027
+ "agentId": {
3028
+ "$ref": "ids.schema.json#/$defs/agentId",
3029
+ "description": "MAY — the agent identity (AgentRef per RFC 0002) behind the write, when known."
3030
+ },
3031
+ "tags": {
3032
+ "type": "array",
3033
+ "items": {
3034
+ "type": "string"
3035
+ },
3036
+ "description": "MAY — the entry's non-secret labels. MUST NOT carry secret material (the no-content invariant covers payload bodies)."
3037
+ }
3038
+ },
3039
+ "additionalProperties": false
3040
+ },
3041
+ "agentMemoryConsolidated": {
3042
+ "type": "object",
3043
+ "description": "RFC 0068 (`Draft`). Emitted by a host advertising `capabilities.agents.memoryConsolidation.supported: true` after a background consolidation pass over LONG-TERM memory (merge/dedup/supersede/strengthen). Content-free: identifiers + counts only — entry content is served by the SR-1-redacted read-side (`MemoryAdapter.get`). On replay the event is re-read from the log, never regenerated. Distinct from RFC 0062 `memory.compacted` (token-budgeted distillation of transactional memory). SR-1 carry-forward (RFC 0004) + CTI-1 apply to the consolidated entries.",
3044
+ "required": [
3045
+ "memoryRef",
3046
+ "inputCount",
3047
+ "outputCount"
3048
+ ],
3049
+ "properties": {
3050
+ "memoryRef": {
3051
+ "type": "string",
3052
+ "minLength": 1,
3053
+ "description": "Opaque MemoryAdapter handle (RFC 0004 §C) the consolidation pass operated over. Bounds the pass to a single memory scope (CTI-1)."
3054
+ },
3055
+ "inputCount": {
3056
+ "type": "integer",
3057
+ "minimum": 0,
3058
+ "description": "Long-term entries considered by the pass."
3059
+ },
3060
+ "outputCount": {
3061
+ "type": "integer",
3062
+ "minimum": 0,
3063
+ "description": "Long-term entries remaining after the pass. MUST be <= inputCount for a pass that only merges/dedups; a strengthen-only pass MAY leave outputCount == inputCount."
3064
+ },
3065
+ "mergedIds": {
3066
+ "type": "array",
3067
+ "items": {
3068
+ "type": "string",
3069
+ "minLength": 1
3070
+ },
3071
+ "description": "MAY — ids of entries collapsed/superseded by the pass. Hosts MAY omit when inputCount is large; consumers MUST tolerate absence."
3072
+ },
3073
+ "trigger": {
3074
+ "type": "string",
3075
+ "enum": [
3076
+ "host-managed",
3077
+ "scheduled",
3078
+ "on-demand"
3079
+ ],
3080
+ "description": "MAY — which initiation path drove this pass (mirrors `agents.memoryConsolidation.schedule`)."
3081
+ }
3082
+ },
3083
+ "additionalProperties": false
3084
+ },
3085
+ "commitmentFired": {
3086
+ "type": "object",
3087
+ "description": "RFC 0068 (`Draft`). Emitted by a host advertising `capabilities.agents.commitments.supported: true` when an inferred standing commitment fires. Content-free: identifiers + condition kind only — the intention text lives in SR-1-redacted memory (`MemoryAdapter.get(memoryRef, memoryId)`). The fired arm composes RFC 0052 (time) or RFC 0060 (predicate). On replay the event is re-read from the log, never regenerated (the host MUST NOT re-infer or re-fire a commitment at replay time). CTI-1: the commitment, its memory provenance, and any run it enqueues MUST share the source memory's tenant.",
3088
+ "required": [
3089
+ "commitmentId",
3090
+ "memoryRef",
3091
+ "condition"
3092
+ ],
3093
+ "properties": {
3094
+ "commitmentId": {
3095
+ "type": "string",
3096
+ "minLength": 1,
3097
+ "description": "Host-issued, stable id for the inferred commitment. Correlates repeated observability across re-evaluations of the same commitment."
3098
+ },
3099
+ "memoryRef": {
3100
+ "type": "string",
3101
+ "minLength": 1,
3102
+ "description": "Opaque MemoryAdapter handle of the memory scope the commitment was inferred from (provenance + CTI-1 tenant binding)."
3103
+ },
3104
+ "memoryId": {
3105
+ "type": "string",
3106
+ "minLength": 1,
3107
+ "description": "MAY — id of the source `MemoryEntry` the commitment was inferred from, when a single entry is attributable. Resolvable via `MemoryAdapter.get`; content is read SR-1-redacted from the read-side."
3108
+ },
3109
+ "condition": {
3110
+ "type": "string",
3111
+ "enum": [
3112
+ "time",
3113
+ "predicate"
3114
+ ],
3115
+ "description": "Which fire-condition kind triggered. `time` composes RFC 0052; `predicate` composes RFC 0060."
3116
+ },
3117
+ "enqueuedRunId": {
3118
+ "type": "string",
3119
+ "minLength": 1,
3120
+ "description": "MAY — id of the run the fired commitment enqueued, when the host initiates one. Absent when the commitment fires as a notification without a run."
3121
+ }
3122
+ },
3123
+ "additionalProperties": false
3124
+ },
3125
+ "agentInvocationStarted": {
3126
+ "type": "object",
3127
+ "description": "RFC 0077. Emitted by a host advertising `capabilities.agents.liveRuntime.supported: true` as the FIRST agent-scoped event of a live manifest invocation, bracketing the existing `agent.*` family with `agent.invocation.completed`. Content-free: identifiers + selection metadata only — prompt/task content is served by the run's normal projection, never on this event. A recorded-fact event per `replay.md` §\"Recorded-fact events\": on replay it is re-emitted from the log and the host MUST NOT regenerate its `invocationId` (or any identifier). Distinct from the deterministic RFC 0070 sample floor.",
3128
+ "required": [
3129
+ "invocationId",
3130
+ "agentId",
3131
+ "source"
3132
+ ],
3133
+ "properties": {
3134
+ "invocationId": {
3135
+ "type": "string",
3136
+ "minLength": 1,
3137
+ "description": "Host-defined id correlating this agent invocation within its run, UNIQUE-WITHIN-RUN (not a mandated global id-space). Distinct from `runId` — one run MAY dispatch several invocations (multiple agent nodes, or a handoff chain) — but a host MAY derive it from an existing per-node-execution receipt id (e.g. `runId:nodeId:seq`) or mint a UUID; a single-invocation run MAY reuse `runId`. Recorded-fact: re-read from the log on replay, never regenerated (`replay.md` §\"Recorded-fact events\"). Correlates to the matching `agent.invocation.completed`."
3138
+ },
3139
+ "agentId": {
3140
+ "$ref": "ids.schema.json#/$defs/agentId",
3141
+ "description": "The manifest agentId being invoked (matches `AgentManifest.agentId`)."
3142
+ },
3143
+ "source": {
3144
+ "type": "string",
3145
+ "enum": [
3146
+ "workflow-node",
3147
+ "run-api",
3148
+ "chat-mention"
3149
+ ],
3150
+ "description": "Which entry point launched the invocation. All sources emit this identical family."
3151
+ },
3152
+ "modelClass": {
3153
+ "type": "string",
3154
+ "description": "MAY — the manifest's abstract `modelClass`. Always populatable at start."
3155
+ },
3156
+ "resolvedModel": {
3157
+ "type": "string",
3158
+ "description": "MAY — the concrete model the host selected. OPTIONAL: modelClass→concrete resolution MAY happen downstream (with capability-gated fallback substitution), so a dispatch-time start event genuinely may not know it; a host MAY also omit for deployment-privacy."
3159
+ },
3160
+ "resolvedProvider": {
3161
+ "type": "string",
3162
+ "description": "MAY — the concrete provider the host routed to (aligns with `capabilities.aiProviders.supported` / RFC 0067 `authModes`). OPTIONAL, same rationale as `resolvedModel`."
3163
+ },
3164
+ "resolvedAgentVersion": {
3165
+ "type": "string",
3166
+ "description": "MAY — RFC 0082 §B. When this invocation's `AgentRef` bound a `channel` (rather than an exact `version`), the concrete agent-definition version the host pinned per-(run, agentId, channel) at first resolution. A RECORDED FACT: re-read from the log on replay and NEVER re-resolved against a moved channel (the whole event is recorded-fact). Absent when the ref used an exact `version` or host-default resolution."
3167
+ },
3168
+ "resolvedChannel": {
3169
+ "type": "string",
3170
+ "description": "MAY — RFC 0082 §B. The named `channel` the `AgentRef` bound (mirrors `AgentRef.channel`), for which `resolvedAgentVersion` is the pinned resolution. Content-free label; present only when the ref bound a channel."
3171
+ },
3172
+ "toolSurfaceCount": {
3173
+ "type": "integer",
3174
+ "minimum": 0,
3175
+ "description": "MAY — number of tools in the constructed surface after `toolAllowlist` filtering. Content-free count, not the tool ids."
3176
+ },
3177
+ "memoryBound": {
3178
+ "type": "boolean",
3179
+ "description": "MAY — whether a long-term memory backend was bound for the invocation."
3180
+ }
3181
+ },
3182
+ "additionalProperties": false
3183
+ },
3184
+ "agentInvocationCompleted": {
3185
+ "type": "object",
3186
+ "description": "RFC 0077. Emitted by a host advertising `capabilities.agents.liveRuntime.supported: true` as the LAST agent-scoped event of a live manifest invocation (after the terminal `agent.decided`). Content-free: identifiers + outcome metadata only — the result body is served by the run's normal projection. A recorded-fact event per `replay.md` §\"Recorded-fact events\": re-read from the log on replay, never regenerated.",
3187
+ "required": [
3188
+ "invocationId",
3189
+ "agentId",
3190
+ "outcome"
3191
+ ],
3192
+ "properties": {
3193
+ "invocationId": {
3194
+ "type": "string",
3195
+ "minLength": 1,
3196
+ "description": "Correlates to the `agent.invocation.started` `invocationId`. Recorded-fact: never regenerated on replay."
3197
+ },
3198
+ "agentId": {
3199
+ "$ref": "ids.schema.json#/$defs/agentId",
3200
+ "description": "The manifest agentId."
3201
+ },
3202
+ "outcome": {
3203
+ "type": "string",
3204
+ "enum": [
3205
+ "completed",
3206
+ "handed-off",
3207
+ "escalated",
3208
+ "refused",
3209
+ "failed"
3210
+ ],
3211
+ "description": "Terminal disposition. `completed`: produced a (schema-valid, if enforced) terminal result. `handed-off`: control passed to another agent (`agent.handoff`). `escalated`: confidence escalation fired (RFC 0002 §F). `refused`: the model refused (RFC 0032 refusal envelope) — never a silent substitution. `failed`: an error terminated the invocation."
3212
+ },
3213
+ "schemaValidated": {
3214
+ "type": "boolean",
3215
+ "description": "MAY — whether the terminal result was validated against `handoff.returnSchemaRef` (true only when `liveRuntime.structuredOutput` is advertised and a `returnSchemaRef` exists)."
3216
+ },
3217
+ "confidence": {
3218
+ "type": "number",
3219
+ "minimum": 0,
3220
+ "maximum": 1,
3221
+ "description": "MAY — the terminal `agent.decided` confidence, mirrored for convenience. Content-free scalar."
3222
+ },
3223
+ "enqueuedRunId": {
3224
+ "type": "string",
3225
+ "minLength": 1,
3226
+ "description": "MAY — id of a follow-on run the invocation enqueued (e.g. a sub-run), when applicable."
3227
+ }
3228
+ },
3229
+ "additionalProperties": false
3230
+ },
3231
+ "workspaceUpdated": {
3232
+ "description": "RFC 0059. Emitted by a host advertising `capabilities.workspace.supported: true` on each successful `PUT`/`DELETE` of a workspace file, attributing the change to the file `path` + resulting `version`. Content-free: carries the path + version only — the file body is served by the read-side (`GET /v1/host/workspace/files/{path}`), already SR-1-redacted (RFC 0059 §E WSR-1). On replay the event is re-read from the log, never regenerated. MUST NOT be emitted unless `capabilities.workspace.supported: true`. The proposed SECURITY invariant `workspace-cross-tenant-isolation` (WCT-1) applies to the read-side that resolves these paths.",
3233
+ "type": "object",
3234
+ "additionalProperties": false,
3235
+ "required": [
3236
+ "path",
3237
+ "version"
3238
+ ],
3239
+ "properties": {
3240
+ "path": {
3241
+ "type": "string",
3242
+ "minLength": 1,
3243
+ "description": "Workspace-relative path of the file that changed (matches `workspace-file.schema.json#path`)."
3244
+ },
3245
+ "version": {
3246
+ "type": "integer",
3247
+ "minimum": 1,
3248
+ "description": "The file's resulting monotonic version after the write. On delete, the tombstone version when `versioned: true`."
3249
+ }
3250
+ }
3251
+ },
3252
+ "evalStarted": {
3253
+ "type": "object",
3254
+ "description": "RFC 0081 §C. Emitted ONCE at the start of an eval run (a `mode: \"eval\"` run, RFC 0081 §B) by a host advertising `capabilities.agents.evalSuite.supported: true`. Content-free: suite provenance + counts only. A recorded-fact event per `replay.md` §\"Recorded-fact events\".",
3255
+ "required": [
3256
+ "suiteId",
3257
+ "suiteVersion",
3258
+ "taskCount",
3259
+ "modes"
3260
+ ],
3261
+ "properties": {
3262
+ "suiteId": {
3263
+ "type": "string",
3264
+ "minLength": 1,
3265
+ "description": "The `agent-eval-suite.schema.json#suiteId` being run."
3266
+ },
3267
+ "suiteVersion": {
3268
+ "type": "string",
3269
+ "minLength": 1,
3270
+ "description": "The pinned suite SemVer."
3271
+ },
3272
+ "taskCount": {
3273
+ "type": "integer",
3274
+ "minimum": 0,
3275
+ "description": "Number of tasks the run will execute."
3276
+ },
3277
+ "modes": {
3278
+ "type": "array",
3279
+ "uniqueItems": true,
3280
+ "items": {
3281
+ "type": "string",
3282
+ "enum": [
3283
+ "golden",
3284
+ "rubric",
3285
+ "adversarial",
3286
+ "regression",
3287
+ "live-shadow"
3288
+ ]
3289
+ },
3290
+ "description": "The eval modes this run exercises (RFC 0081 §D)."
3291
+ },
3292
+ "baselineRunId": {
3293
+ "type": "string",
3294
+ "minLength": 1,
3295
+ "description": "MAY — for `regression` mode, the prior eval run this run is scored against."
3296
+ }
3297
+ },
3298
+ "additionalProperties": false
3299
+ },
3300
+ "evalScored": {
3301
+ "type": "object",
3302
+ "description": "RFC 0081 §C. Emitted ONCE PER TASK, after that task's terminal `agent.decided`, so a streaming consumer sees results land incrementally. Content-free: the task id + scalars + counts ONLY — NEVER the task output, rubric prose, or model completion (SECURITY invariant `eval-summary-no-content-leak`). A recorded-fact event.",
3303
+ "required": [
3304
+ "taskId",
3305
+ "score",
3306
+ "passed"
3307
+ ],
3308
+ "properties": {
3309
+ "taskId": {
3310
+ "type": "string",
3311
+ "minLength": 1,
3312
+ "description": "The `agent-eval-suite` task id."
3313
+ },
3314
+ "score": {
3315
+ "type": "number",
3316
+ "minimum": 0,
3317
+ "maximum": 1,
3318
+ "description": "Task score (0.0–1.0)."
3319
+ },
3320
+ "passed": {
3321
+ "type": "boolean",
3322
+ "description": "Whether the task met its bar."
3323
+ },
3324
+ "costUsd": {
3325
+ "type": "number",
3326
+ "minimum": 0,
3327
+ "description": "MAY — task cost (scalar; summed from RFC 0026 `provider.usage`). NEVER a pricing breakdown."
3328
+ },
3329
+ "latencyMs": {
3330
+ "type": "integer",
3331
+ "minimum": 0,
3332
+ "description": "MAY — task wall-clock latency."
3333
+ },
3334
+ "schemaValid": {
3335
+ "type": "boolean",
3336
+ "description": "MAY — whether the output validated against `handoff.returnSchemaRef`."
3337
+ },
3338
+ "safetyFindingCount": {
3339
+ "type": "integer",
3340
+ "minimum": 0,
3341
+ "description": "MAY — count of safety findings for the task (the redaction-safe descriptors live on `EvalSummary`; the event carries the count only)."
3342
+ }
3343
+ },
3344
+ "additionalProperties": false
3345
+ },
3346
+ "evalCompleted": {
3347
+ "type": "object",
3348
+ "description": "RFC 0081 §C. Emitted ONCE, after all tasks and before `run.completed`. Content-free: aggregate scalars only. A recorded-fact event. The full scorecard is the run's output (`eval-summary.schema.json`), served by `GET /v1/runs/{runId}/eval-summary`.",
3349
+ "required": [
3350
+ "aggregateScore",
3351
+ "passed",
3352
+ "taskCount",
3353
+ "passedCount"
3354
+ ],
3355
+ "properties": {
3356
+ "aggregateScore": {
3357
+ "type": "number",
3358
+ "minimum": 0,
3359
+ "maximum": 1,
3360
+ "description": "The suite-level score (0.0–1.0)."
3361
+ },
3362
+ "passed": {
3363
+ "type": "boolean",
3364
+ "description": "Whether the run cleared the suite thresholds — the flag an RFC 0082 deployment gate MAY require."
3365
+ },
3366
+ "taskCount": {
3367
+ "type": "integer",
3368
+ "minimum": 0,
3369
+ "description": "Tasks executed."
3370
+ },
3371
+ "passedCount": {
3372
+ "type": "integer",
3373
+ "minimum": 0,
3374
+ "description": "Tasks that individually passed."
3375
+ },
3376
+ "regressionVsBaseline": {
3377
+ "type": "number",
3378
+ "minimum": -1,
3379
+ "maximum": 1,
3380
+ "description": "MAY — for `regression` mode, `aggregateScore` minus the baseline's (negative ⇒ regression)."
3381
+ }
3382
+ },
3383
+ "additionalProperties": false
3384
+ },
3385
+ "toolSessionOpened": {
3386
+ "type": "object",
3387
+ "description": "RFC 0078 §D. Emitted when the host opens a multi-step tool session, bracketing one or more RFC 0064 `agent.toolCalled`/`agent.toolReturned` call events. Content-free: identifiers only — never tool arguments, results, or credential material (SR-1). Emitted only when `capabilities.toolCatalog.sessionLifecycle: true`.",
3388
+ "required": [
3389
+ "sessionId",
3390
+ "toolId"
3391
+ ],
3392
+ "properties": {
3393
+ "sessionId": {
3394
+ "type": "string",
3395
+ "minLength": 1,
3396
+ "description": "Host-unique id correlating the opened/closed pair + the bracketed call events."
3397
+ },
3398
+ "toolId": {
3399
+ "type": "string",
3400
+ "minLength": 1,
3401
+ "description": "The `ToolDescriptor.toolId` the session is for (`<scope>:<tool-id>`)."
3402
+ }
3403
+ },
3404
+ "additionalProperties": false
3405
+ },
3406
+ "toolSessionClosed": {
3407
+ "type": "object",
3408
+ "description": "RFC 0078 §D. Emitted when the host closes a multi-step tool session opened by `tool.session.opened`. Content-free: identifiers + a closed-enum outcome only — never tool arguments, results, or credential material (SR-1).",
3409
+ "required": [
3410
+ "sessionId",
3411
+ "toolId",
3412
+ "outcome"
3413
+ ],
3414
+ "properties": {
3415
+ "sessionId": {
3416
+ "type": "string",
3417
+ "minLength": 1,
3418
+ "description": "Matches the `tool.session.opened` `sessionId`."
3419
+ },
3420
+ "toolId": {
3421
+ "type": "string",
3422
+ "minLength": 1,
3423
+ "description": "The `ToolDescriptor.toolId` the session was for."
3424
+ },
3425
+ "outcome": {
3426
+ "type": "string",
3427
+ "enum": [
3428
+ "completed",
3429
+ "failed",
3430
+ "cancelled"
3431
+ ],
3432
+ "description": "Terminal disposition of the session. Content-free — no failure detail/result on the payload."
3433
+ }
3434
+ },
3435
+ "additionalProperties": false
3436
+ },
3437
+ "egressDecided": {
3438
+ "type": "object",
3439
+ "description": "RFC 0079 §B. Emitted when a host evaluates a credentialed egress (via `ctx.http.safeFetch` / a tool) against credential provenance + the SSRF guard. Content-free: identifiers + decision only — no credential value, no request/response body (SR-1). On replay re-read from the log, never regenerated (the decision is a recorded fact). Emitted only when `capabilities.httpClient.egressPolicy.supported: true`.",
3440
+ "required": [
3441
+ "decision",
3442
+ "destination"
3443
+ ],
3444
+ "properties": {
3445
+ "decision": {
3446
+ "type": "string",
3447
+ "enum": [
3448
+ "allowed",
3449
+ "denied",
3450
+ "downgraded",
3451
+ "approval-required"
3452
+ ],
3453
+ "description": "`allowed`: egress proceeds with the credential; `denied`: blocked (out-of-audience / expired / SSRF / unevaluable provenance — fail-closed); `downgraded`: proceeds WITHOUT the credential (anonymous egress, when host policy permits); `approval-required`: suspended pending an RFC 0051 approval interrupt."
3454
+ },
3455
+ "destination": {
3456
+ "type": "string",
3457
+ "minLength": 1,
3458
+ "description": "The egress destination **host/authority ONLY** (`api.stripe.com`) — NOT a path, query, or full URL (SR-1: a path/query can carry secrets; the host MUST strip them for this canonical content-free event). A host whose internal audit retains the path keeps that on its vendor `x-host-*` variant, never here."
3459
+ },
3460
+ "credentialId": {
3461
+ "type": "string",
3462
+ "minLength": 1,
3463
+ "description": "MAY — the provenance `credentialId` considered (absent for an anonymous / denied-pre-credential egress)."
3464
+ },
3465
+ "reason": {
3466
+ "type": "string",
3467
+ "enum": [
3468
+ "ok",
3469
+ "out-of-audience",
3470
+ "expired",
3471
+ "ssrf-blocked",
3472
+ "provenance-unevaluable",
3473
+ "scope-denied",
3474
+ "policy-denied"
3475
+ ],
3476
+ "description": "MAY — a machine-stable reason code (a CLOSED enum — a free-form reason is a leak vector that would let a host spill the blocked URL/host/header into it, defeating `egress-decision-no-secret-leak`). The load-bearing field is `decision`."
3477
+ },
3478
+ "auditCorrelationId": {
3479
+ "type": "string",
3480
+ "minLength": 1,
3481
+ "description": "MAY — correlates to the provenance descriptor + host audit log."
3482
+ }
3483
+ },
3484
+ "additionalProperties": false
3485
+ },
3486
+ "triggerSubscriptionStateChanged": {
3487
+ "type": "object",
3488
+ "description": "RFC 0083 §C. Emitted when a trigger subscription changes state (the §B four-state machine). Content-free: identifiers + states only — no inbound payload, headers, or credential material (SR-1). Emitted only when `capabilities.triggerBridge.supported: true`.",
3489
+ "required": [
3490
+ "subscriptionId",
3491
+ "source",
3492
+ "fromState",
3493
+ "toState"
3494
+ ],
3495
+ "properties": {
3496
+ "subscriptionId": {
3497
+ "$ref": "ids.schema.json#/$defs/subscriptionId",
3498
+ "description": "The TriggerSubscription this state change is for."
3499
+ },
3500
+ "source": {
3501
+ "type": "string",
3502
+ "enum": [
3503
+ "webhook",
3504
+ "schedule",
3505
+ "queue",
3506
+ "email",
3507
+ "form",
3508
+ "stream",
3509
+ "change"
3510
+ ],
3511
+ "description": "The subscription source."
3512
+ },
3513
+ "fromState": {
3514
+ "type": "string",
3515
+ "enum": [
3516
+ "active",
3517
+ "paused",
3518
+ "failed",
3519
+ "dead-lettered"
3520
+ ],
3521
+ "description": "Prior state."
3522
+ },
3523
+ "toState": {
3524
+ "type": "string",
3525
+ "enum": [
3526
+ "active",
3527
+ "paused",
3528
+ "failed",
3529
+ "dead-lettered"
3530
+ ],
3531
+ "description": "New state."
3532
+ },
3533
+ "reason": {
3534
+ "type": "string",
3535
+ "enum": [
3536
+ "retry-exhausted",
3537
+ "operator-paused",
3538
+ "signature-invalid",
3539
+ "backpressure",
3540
+ "source-removed",
3541
+ "provenance-unevaluable"
3542
+ ],
3543
+ "description": "MAY — a machine-stable reason code (a CLOSED enum — a free-form reason is a leak vector that would let a host spill an inbound URL/host/header into it). The load-bearing field is `toState`."
3544
+ }
3545
+ },
3546
+ "additionalProperties": false
3547
+ },
3548
+ "triggerDeliveryAttempted": {
3549
+ "type": "object",
3550
+ "description": "RFC 0083 §C. Emitted on each inbound-delivery attempt against an active subscription. Content-free: the subscription id, the dedup key, the attempt counter, the outcome, and the resulting runId only — NEVER the inbound body, headers, or credential material (SR-1).",
3551
+ "required": [
3552
+ "subscriptionId",
3553
+ "dedupKey",
3554
+ "attempt",
3555
+ "outcome"
3556
+ ],
3557
+ "properties": {
3558
+ "subscriptionId": {
3559
+ "$ref": "ids.schema.json#/$defs/subscriptionId",
3560
+ "description": "The TriggerSubscription the delivery is for."
3561
+ },
3562
+ "dedupKey": {
3563
+ "type": "string",
3564
+ "minLength": 1,
3565
+ "description": "The de-duplication key (§C-1). MUST be a **host-opaque** stable key (e.g. `hash(subscriptionId + inbound-event-id)`); it MUST NOT embed inbound body / path / header content in cleartext (SR-1 — a key like `POST /webhook/orders/12345?token=…` would leak). A repeat within retention is a no-op returning the prior runId."
3566
+ },
3567
+ "attempt": {
3568
+ "type": "integer",
3569
+ "minimum": 1,
3570
+ "description": "1-based attempt counter."
3571
+ },
3572
+ "outcome": {
3573
+ "type": "string",
3574
+ "enum": [
3575
+ "delivered",
3576
+ "retrying",
3577
+ "dead-lettered"
3578
+ ],
3579
+ "description": "`delivered`: the run started; `retrying`: failed, will retry per policy; `dead-lettered`: retries exhausted, routed to the RFC 0053 sink (no run)."
3580
+ },
3581
+ "runId": {
3582
+ "$ref": "ids.schema.json#/$defs/runId",
3583
+ "description": "MAY — the run started by a `delivered` outcome (the run's `run.started` carries this delivery's id as `causationId`, RFC 0040). Absent for `retrying` / `dead-lettered`."
3584
+ }
3585
+ },
3586
+ "additionalProperties": false
3587
+ },
3588
+ "budgetReserved": {
3589
+ "type": "object",
3590
+ "description": "RFC 0084 §C. Emitted once at run start with the resolved effective budget (`min` across run/workflow/agent/project scopes, clamped to the host ceiling). A recorded fact — replay re-reads it, never re-resolves (§B). Content-free: dimension ceilings + scope only, no pricing breakdown (SR-1, `budget-no-pricing-leak`).",
3591
+ "required": [
3592
+ "effectiveBudget",
3593
+ "scope"
3594
+ ],
3595
+ "properties": {
3596
+ "effectiveBudget": {
3597
+ "type": "object",
3598
+ "additionalProperties": false,
3599
+ "description": "The resolved per-dimension ceilings (a subset of the BudgetPolicy dimensions).",
3600
+ "properties": {
3601
+ "maxTokens": {
3602
+ "type": "integer",
3603
+ "minimum": 0
3604
+ },
3605
+ "maxCostUsd": {
3606
+ "type": "number",
3607
+ "minimum": 0
3608
+ },
3609
+ "maxToolCalls": {
3610
+ "type": "integer",
3611
+ "minimum": 0
3612
+ },
3613
+ "maxRetries": {
3614
+ "type": "integer",
3615
+ "minimum": 0
3616
+ }
3617
+ }
3618
+ },
3619
+ "scope": {
3620
+ "type": "string",
3621
+ "enum": [
3622
+ "run",
3623
+ "workflow",
3624
+ "agent",
3625
+ "project"
3626
+ ],
3627
+ "description": "The binding scope the effective budget resolved from (§B)."
3628
+ }
3629
+ },
3630
+ "additionalProperties": false
3631
+ },
3632
+ "budgetConsumed": {
3633
+ "type": "object",
3634
+ "description": "RFC 0084 §C. A running projection of spend, derived from the existing events (`provider.usage` tokens/cost, `agent.toolCalled`, `node.retried`) — NOT a new measurement (no double-counting). The host MAY coalesce. Content-free: dimension name + integers only, no pricing breakdown / rate card (SR-1).",
3635
+ "required": [
3636
+ "dimension",
3637
+ "consumed",
3638
+ "limit"
3639
+ ],
3640
+ "properties": {
3641
+ "dimension": {
3642
+ "type": "string",
3643
+ "enum": [
3644
+ "tokens",
3645
+ "cost",
3646
+ "toolCalls",
3647
+ "retries"
3648
+ ],
3649
+ "description": "Which budget dimension this projection is for."
3650
+ },
3651
+ "consumed": {
3652
+ "type": "number",
3653
+ "minimum": 0,
3654
+ "description": "Amount consumed so far (tokens/calls/retries are integers; cost is a number in the host's `costEstimateUsd` units)."
3655
+ },
3656
+ "limit": {
3657
+ "type": "number",
3658
+ "minimum": 0,
3659
+ "description": "The effective ceiling for the dimension."
3660
+ },
3661
+ "remaining": {
3662
+ "type": "number",
3663
+ "description": "MAY — `limit - consumed`."
3664
+ }
3665
+ },
3666
+ "additionalProperties": false
3667
+ },
3668
+ "budgetThresholdCrossed": {
3669
+ "type": "object",
3670
+ "description": "RFC 0084 §C. Emitted once per dimension when consumption crosses `thresholdPercent`. Content-free.",
3671
+ "required": [
3672
+ "dimension",
3673
+ "consumed",
3674
+ "limit",
3675
+ "percent"
3676
+ ],
3677
+ "properties": {
3678
+ "dimension": {
3679
+ "type": "string",
3680
+ "enum": [
3681
+ "tokens",
3682
+ "cost",
3683
+ "toolCalls",
3684
+ "retries"
3685
+ ]
3686
+ },
3687
+ "consumed": {
3688
+ "type": "number",
3689
+ "minimum": 0
3690
+ },
3691
+ "limit": {
3692
+ "type": "number",
3693
+ "minimum": 0
3694
+ },
3695
+ "percent": {
3696
+ "type": "number",
3697
+ "minimum": 0,
3698
+ "maximum": 100,
3699
+ "description": "The percent-of-limit threshold crossed."
3700
+ }
3701
+ },
3702
+ "additionalProperties": false
3703
+ },
3704
+ "budgetExhausted": {
3705
+ "type": "object",
3706
+ "description": "RFC 0084 §C. Emitted when a dimension hits its limit. For a hard dimension this is followed by `cap.breached{kind:\"budget-*\"}` → `run.failed{budget_exhausted}` (or, with `onExhaustion:\"interrupt\"`, an approval interrupt). Content-free.",
3707
+ "required": [
3708
+ "dimension",
3709
+ "consumed",
3710
+ "limit"
3711
+ ],
3712
+ "properties": {
3713
+ "dimension": {
3714
+ "type": "string",
3715
+ "enum": [
3716
+ "tokens",
3717
+ "cost",
3718
+ "toolCalls",
3719
+ "retries"
3720
+ ]
3721
+ },
3722
+ "consumed": {
3723
+ "type": "number",
3724
+ "minimum": 0
3725
+ },
3726
+ "limit": {
3727
+ "type": "number",
3728
+ "minimum": 0
3729
+ }
3730
+ },
3731
+ "additionalProperties": false
3732
+ },
3733
+ "deploymentPromoted": {
3734
+ "type": "object",
3735
+ "description": "RFC 0082 §D. Emitted on the deployment-management run when a version is promoted into a new lifecycle state (the §E contract: authorized via RFC 0049 `deploy:*`, gated via RFC 0051 `approvalGate`, eval-verified via RFC 0081 when `requiredEval` is configured). Content-free: ids / state / scalars / content-free references only — NEVER a manifest body, prompt, or credential (SECURITY invariant `deployment-event-no-content-leak`; `additionalProperties:false` enforces it). A recorded-fact event per `replay.md` §\"Recorded-fact events\". Audit-logged with the acting principal (`auth.md`).",
3736
+ "additionalProperties": false,
3737
+ "required": [
3738
+ "agentId",
3739
+ "toVersion",
3740
+ "toState"
3741
+ ],
3742
+ "properties": {
3743
+ "agentId": {
3744
+ "$ref": "ids.schema.json#/$defs/agentId",
3745
+ "description": "The promoted agent's id."
3746
+ },
3747
+ "fromVersion": {
3748
+ "type": "string",
3749
+ "minLength": 1,
3750
+ "description": "MAY — the version previously occupying the target channel/state (absent on a first promotion)."
3751
+ },
3752
+ "toVersion": {
3753
+ "type": "string",
3754
+ "minLength": 1,
3755
+ "description": "The version promoted."
3756
+ },
3757
+ "toState": {
3758
+ "type": "string",
3759
+ "enum": [
3760
+ "draft",
3761
+ "test",
3762
+ "staged",
3763
+ "active",
3764
+ "paused",
3765
+ "deprecated",
3766
+ "rolled-back"
3767
+ ],
3768
+ "description": "The lifecycle state entered."
3769
+ },
3770
+ "channel": {
3771
+ "type": "string",
3772
+ "minLength": 1,
3773
+ "description": "MAY — the named channel this promotion targets (when promoting to a channel)."
3774
+ },
3775
+ "canaryPercent": {
3776
+ "type": "integer",
3777
+ "minimum": 0,
3778
+ "maximum": 100,
3779
+ "description": "MAY — the canary traffic share assigned (when promoting `active` at < 100)."
3780
+ },
3781
+ "evalRunId": {
3782
+ "type": "string",
3783
+ "minLength": 1,
3784
+ "description": "MAY — the RFC 0081 eval run whose `EvalSummary.passed` gated this promotion (the §E evidence)."
3785
+ },
3786
+ "approvalGateId": {
3787
+ "type": "string",
3788
+ "minLength": 1,
3789
+ "description": "MAY — the RFC 0051 approvalGate that authorized this promotion."
3790
+ }
3791
+ }
3792
+ },
3793
+ "deploymentRolledBack": {
3794
+ "type": "object",
3795
+ "description": "RFC 0082 §D. Emitted when an `active` version is rolled back and a prior version restored to `active`. Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3796
+ "additionalProperties": false,
3797
+ "required": [
3798
+ "agentId",
3799
+ "fromVersion",
3800
+ "toVersion",
3801
+ "rollbackPointer"
3802
+ ],
3803
+ "properties": {
3804
+ "agentId": {
3805
+ "$ref": "ids.schema.json#/$defs/agentId",
3806
+ "description": "The agent's id."
3807
+ },
3808
+ "fromVersion": {
3809
+ "type": "string",
3810
+ "minLength": 1,
3811
+ "description": "The version that was rolled back (left `active`)."
3812
+ },
3813
+ "toVersion": {
3814
+ "type": "string",
3815
+ "minLength": 1,
3816
+ "description": "The version restored to `active`."
3817
+ },
3818
+ "rollbackPointer": {
3819
+ "type": "string",
3820
+ "minLength": 1,
3821
+ "description": "The recovery target the rolled-back record points to (= `toVersion`)."
3822
+ },
3823
+ "reason": {
3824
+ "type": "string",
3825
+ "minLength": 1,
3826
+ "description": "MAY — a short redaction-safe rollback reason label (NOT free-text content; same posture as `run.dead_lettered.reason`)."
3827
+ }
3828
+ }
3829
+ },
3830
+ "deploymentCanaryAdjusted": {
3831
+ "type": "object",
3832
+ "description": "RFC 0082 §D. Emitted when an `active` version's canary traffic share changes. Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3833
+ "additionalProperties": false,
3834
+ "required": [
3835
+ "agentId",
3836
+ "version",
3837
+ "fromPercent",
3838
+ "toPercent"
3839
+ ],
3840
+ "properties": {
3841
+ "agentId": {
3842
+ "$ref": "ids.schema.json#/$defs/agentId",
3843
+ "description": "The agent's id."
3844
+ },
3845
+ "version": {
3846
+ "type": "string",
3847
+ "minLength": 1,
3848
+ "description": "The version whose canary share changed."
3849
+ },
3850
+ "fromPercent": {
3851
+ "type": "integer",
3852
+ "minimum": 0,
3853
+ "maximum": 100,
3854
+ "description": "The prior canary percent."
3855
+ },
3856
+ "toPercent": {
3857
+ "type": "integer",
3858
+ "minimum": 0,
3859
+ "maximum": 100,
3860
+ "description": "The new canary percent."
3861
+ }
3862
+ }
3863
+ },
3864
+ "deploymentStateChanged": {
3865
+ "type": "object",
3866
+ "description": "RFC 0082 §D. Emitted on any non-promotion lifecycle transition (pause / resume / deprecate). Content-free (`deployment-event-no-content-leak`). Recorded-fact; audit-logged.",
3867
+ "additionalProperties": false,
3868
+ "required": [
3869
+ "agentId",
3870
+ "version",
3871
+ "fromState",
3872
+ "toState"
3873
+ ],
3874
+ "properties": {
3875
+ "agentId": {
3876
+ "$ref": "ids.schema.json#/$defs/agentId",
3877
+ "description": "The agent's id."
3878
+ },
3879
+ "version": {
3880
+ "type": "string",
3881
+ "minLength": 1,
3882
+ "description": "The version whose state changed."
3883
+ },
3884
+ "fromState": {
3885
+ "type": "string",
3886
+ "enum": [
3887
+ "draft",
3888
+ "test",
3889
+ "staged",
3890
+ "active",
3891
+ "paused",
3892
+ "deprecated",
3893
+ "rolled-back"
3894
+ ],
3895
+ "description": "The prior state."
3896
+ },
3897
+ "toState": {
3898
+ "type": "string",
3899
+ "enum": [
3900
+ "draft",
3901
+ "test",
3902
+ "staged",
3903
+ "active",
3904
+ "paused",
3905
+ "deprecated",
3906
+ "rolled-back"
3907
+ ],
3908
+ "description": "The new state."
3909
+ }
3910
+ }
3911
+ },
3912
+ "rosterRunInitiated": {
3913
+ "type": "object",
3914
+ "description": "RFC 0086 §C. Emitted once, immediately after `run.started` and before any agent invocation, when a trigger (RFC 0052 schedule / RFC 0083 durable work item) fires a workflow in a roster member's portfolio — attributing the run to the standing agent. Content-free (`roster-attribution-no-content`): ids + persona + trigger source ONLY — never the work-item body, prompt, or credential material (SR-1). A recorded-fact event (replay.md §'Recorded-fact events'): re-emitted from the log on replay, identifiers never regenerated, so the run stays attributed to the same member even if the entry was since renamed or deleted.",
3915
+ "additionalProperties": false,
3916
+ "required": [
3917
+ "rosterId",
3918
+ "persona",
3919
+ "agentId",
3920
+ "workflowId",
3921
+ "triggerSource"
3922
+ ],
3923
+ "properties": {
3924
+ "rosterId": {
3925
+ "type": "string",
3926
+ "minLength": 1,
3927
+ "description": "The standing agent instance the run is attributed to (a `host:<id>` AgentRef agentId)."
3928
+ },
3929
+ "persona": {
3930
+ "type": "string",
3931
+ "minLength": 1,
3932
+ "description": "The member's human display name (e.g. \"Sally\")."
3933
+ },
3934
+ "agentId": {
3935
+ "$ref": "ids.schema.json#/$defs/agentId",
3936
+ "description": "The manifest agentId the member instantiates (`agentRef.agentId`)."
3937
+ },
3938
+ "workflowId": {
3939
+ "$ref": "ids.schema.json#/$defs/workflowId",
3940
+ "description": "The portfolio workflow this run executes."
3941
+ },
3942
+ "triggerSource": {
3943
+ "type": "string",
3944
+ "minLength": 1,
3945
+ "description": "What fired the run: an RFC 0083 source (`schedule`/`webhook`/`queue`/`email`/`form`) or a host-extension source name (e.g. a vendor Kanban bridge)."
3946
+ },
3947
+ "triggerSubscriptionId": {
3948
+ "type": "string",
3949
+ "minLength": 1,
3950
+ "description": "MAY. The RFC 0083 trigger-subscription id when the fire came through the durable trigger bridge, so trigger → run → roster is traceable via /ancestry (RFC 0040)."
3951
+ }
3952
+ }
3953
+ },
3954
+ "compensationRequested": {
3955
+ "type": "object",
3956
+ "additionalProperties": false,
3957
+ "description": "RFC 0151 §D — plan persisted, before the first inverse action. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) — these land in the durable log, the least revocable place a credential can reach.",
3958
+ "properties": {
3959
+ "compensationId": {
3960
+ "type": "string",
3961
+ "minLength": 1
3962
+ },
3963
+ "nodeId": {
3964
+ "$ref": "ids.schema.json#/$defs/nodeId"
3965
+ },
3966
+ "effectId": {
3967
+ "$ref": "ids.schema.json#/$defs/effectId"
3968
+ },
3969
+ "attempt": {
3970
+ "type": "integer",
3971
+ "minimum": 0
3972
+ },
3973
+ "orderingModel": {
3974
+ "enum": [
3975
+ "reverse-completion",
3976
+ "dependency-graph"
3977
+ ]
3978
+ }
3979
+ }
3980
+ },
3981
+ "compensationStarted": {
3982
+ "type": "object",
3983
+ "additionalProperties": false,
3984
+ "description": "RFC 0151 §D — first inverse action started. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) — these land in the durable log, the least revocable place a credential can reach.",
3985
+ "properties": {
3986
+ "compensationId": {
3987
+ "type": "string",
3988
+ "minLength": 1
3989
+ },
3990
+ "nodeId": {
3991
+ "$ref": "ids.schema.json#/$defs/nodeId"
3992
+ },
3993
+ "effectId": {
3994
+ "$ref": "ids.schema.json#/$defs/effectId"
3995
+ },
3996
+ "attempt": {
3997
+ "type": "integer",
3998
+ "minimum": 0
3999
+ },
4000
+ "orderingModel": {
4001
+ "enum": [
4002
+ "reverse-completion",
4003
+ "dependency-graph"
4004
+ ]
4005
+ }
4006
+ }
4007
+ },
4008
+ "compensationCompleted": {
4009
+ "type": "object",
4010
+ "additionalProperties": false,
4011
+ "description": "RFC 0151 §D — every inverse action succeeded. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) — these land in the durable log, the least revocable place a credential can reach.",
4012
+ "properties": {
4013
+ "compensationId": {
4014
+ "type": "string",
4015
+ "minLength": 1
4016
+ },
4017
+ "nodeId": {
4018
+ "$ref": "ids.schema.json#/$defs/nodeId"
4019
+ },
4020
+ "effectId": {
4021
+ "$ref": "ids.schema.json#/$defs/effectId"
4022
+ },
4023
+ "attempt": {
4024
+ "type": "integer",
4025
+ "minimum": 0
4026
+ },
4027
+ "orderingModel": {
4028
+ "enum": [
4029
+ "reverse-completion",
4030
+ "dependency-graph"
4031
+ ]
4032
+ }
4033
+ }
4034
+ },
4035
+ "compensationFailed": {
4036
+ "type": "object",
4037
+ "additionalProperties": false,
4038
+ "description": "RFC 0151 §D — an inverse action exhausted its retries. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) — these land in the durable log, the least revocable place a credential can reach.",
4039
+ "properties": {
4040
+ "compensationId": {
4041
+ "type": "string",
4042
+ "minLength": 1
4043
+ },
4044
+ "nodeId": {
4045
+ "$ref": "ids.schema.json#/$defs/nodeId"
4046
+ },
4047
+ "effectId": {
4048
+ "$ref": "ids.schema.json#/$defs/effectId"
4049
+ },
4050
+ "attempt": {
4051
+ "type": "integer",
4052
+ "minimum": 0
4053
+ },
4054
+ "orderingModel": {
4055
+ "enum": [
4056
+ "reverse-completion",
4057
+ "dependency-graph"
4058
+ ]
4059
+ },
4060
+ "reason": {
4061
+ "enum": [
4062
+ "retries-exhausted",
4063
+ "approval-denied",
4064
+ "authority-denied",
4065
+ "dead-lettered",
4066
+ "operator-terminated"
4067
+ ],
4068
+ "description": "Closed reason vocabulary. An open string here would invite a provider error body."
4069
+ }
4070
+ }
4071
+ },
4072
+ "compensationPaused": {
4073
+ "type": "object",
4074
+ "additionalProperties": false,
4075
+ "description": "RFC 0151 §D — paused for authorized intervention. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) — these land in the durable log, the least revocable place a credential can reach.",
4076
+ "properties": {
4077
+ "compensationId": {
4078
+ "type": "string",
4079
+ "minLength": 1
4080
+ },
4081
+ "nodeId": {
4082
+ "$ref": "ids.schema.json#/$defs/nodeId"
4083
+ },
4084
+ "effectId": {
4085
+ "$ref": "ids.schema.json#/$defs/effectId"
4086
+ },
4087
+ "attempt": {
4088
+ "type": "integer",
4089
+ "minimum": 0
4090
+ },
4091
+ "orderingModel": {
4092
+ "enum": [
4093
+ "reverse-completion",
4094
+ "dependency-graph"
4095
+ ]
4096
+ },
4097
+ "reason": {
4098
+ "enum": [
4099
+ "retries-exhausted",
4100
+ "approval-denied",
4101
+ "authority-denied",
4102
+ "dead-lettered",
4103
+ "operator-terminated"
4104
+ ],
4105
+ "description": "Closed reason vocabulary. An open string here would invite a provider error body."
4106
+ }
4107
+ }
4108
+ },
4109
+ "compensationManualInterventionRequired": {
4110
+ "type": "object",
4111
+ "additionalProperties": false,
4112
+ "description": "RFC 0151 §D — operator action required. Content-free: opaque node/effect IDs, attempt, ordering model, and closed reason codes. Provider bodies and credentials MUST NOT appear (§D/§G) — these land in the durable log, the least revocable place a credential can reach.",
4113
+ "properties": {
4114
+ "compensationId": {
4115
+ "type": "string",
4116
+ "minLength": 1
4117
+ },
4118
+ "nodeId": {
4119
+ "$ref": "ids.schema.json#/$defs/nodeId"
4120
+ },
4121
+ "effectId": {
4122
+ "$ref": "ids.schema.json#/$defs/effectId"
4123
+ },
4124
+ "attempt": {
4125
+ "type": "integer",
4126
+ "minimum": 0
4127
+ },
4128
+ "orderingModel": {
4129
+ "enum": [
4130
+ "reverse-completion",
4131
+ "dependency-graph"
4132
+ ]
4133
+ },
4134
+ "reason": {
4135
+ "enum": [
4136
+ "retries-exhausted",
4137
+ "approval-denied",
4138
+ "authority-denied",
4139
+ "dead-lettered",
4140
+ "operator-terminated"
4141
+ ],
4142
+ "description": "Closed reason vocabulary. An open string here would invite a provider error body."
4143
+ }
4144
+ }
4145
+ },
4146
+ "approvalRequested": {
4147
+ "$ref": "#/$defs/interruptRequested",
4148
+ "description": "RFC 0171 §A.4 E4 — sub-typing is $ref composition, not duplication: the legacy approvalRequested shape (deprecation row legacy-interrupt-payloads) is the unified interruptRequested payload; the event type is kept, its payload is not a second shape."
4149
+ },
4150
+ "clarificationRequested": {
4151
+ "$ref": "#/$defs/interruptRequested",
4152
+ "description": "RFC 0171 §A.4 E4 — sub-typing is $ref composition, not duplication: the legacy clarificationRequested shape (deprecation row legacy-interrupt-payloads) is the unified interruptRequested payload; the event type is kept, its payload is not a second shape."
4153
+ },
4154
+ "approvalReceived": {
4155
+ "$ref": "#/$defs/interruptResolved",
4156
+ "description": "RFC 0171 §A.4 E4 — sub-typing is $ref composition, not duplication: the legacy approvalReceived shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4157
+ },
4158
+ "approvalGranted": {
4159
+ "$ref": "#/$defs/interruptResolved",
4160
+ "description": "RFC 0171 §A.4 E4 — sub-typing is $ref composition, not duplication: the legacy approvalGranted shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4161
+ },
4162
+ "approvalRejected": {
4163
+ "$ref": "#/$defs/interruptResolved",
4164
+ "description": "RFC 0171 §A.4 E4 — sub-typing is $ref composition, not duplication: the legacy approvalRejected shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4165
+ },
4166
+ "approvalOverridden": {
4167
+ "$ref": "#/$defs/interruptResolved",
4168
+ "description": "RFC 0171 §A.4 E4 — sub-typing is $ref composition, not duplication: the legacy approvalOverridden shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4169
+ },
4170
+ "clarificationResolved": {
4171
+ "$ref": "#/$defs/interruptResolved",
4172
+ "description": "RFC 0171 §A.4 E4 — sub-typing is $ref composition, not duplication: the legacy clarificationResolved shape (deprecation row legacy-interrupt-payloads) is the unified interruptResolved payload; the event type is kept, its payload is not a second shape."
4173
+ },
4174
+ "negotiationDecided": {
4175
+ "type": "object",
4176
+ "additionalProperties": false,
4177
+ "required": [
4178
+ "protocol",
4179
+ "outcome",
4180
+ "at"
4181
+ ],
4182
+ "properties": {
4183
+ "protocol": {
4184
+ "type": "string",
4185
+ "enum": [
4186
+ "a2a",
4187
+ "mcp"
4188
+ ]
4189
+ },
4190
+ "outcome": {
4191
+ "type": "string",
4192
+ "enum": [
4193
+ "accepted",
4194
+ "refused"
4195
+ ]
4196
+ },
4197
+ "version": {
4198
+ "type": "string",
4199
+ "description": "The version or revision decided (absent when refused below the floor)."
4200
+ },
4201
+ "floor": {
4202
+ "type": "string"
4203
+ },
4204
+ "peerDigest": {
4205
+ "type": "string",
4206
+ "pattern": "^[0-9a-f]{64}$",
4207
+ "description": "SHA-256 of the peer origin; never the origin in clear (RFC 0175 §D.3)."
4208
+ },
4209
+ "reason": {
4210
+ "type": "string",
4211
+ "enum": [
4212
+ "below-floor",
4213
+ "unauthenticated",
4214
+ "unsupported",
4215
+ "ok"
4216
+ ]
4217
+ },
4218
+ "at": {
4219
+ "type": "string",
4220
+ "format": "date-time"
4221
+ }
4222
+ },
4223
+ "description": "RFC 0175 §D.3 — the content-free negotiation audit event."
4224
+ }
4225
+ },
4226
+ "additionalProperties": false,
4227
+ "_typeIndex": {
4228
+ "description": "NORMATIVE (RFC 0171 §A.4): v2 event type → $defs key, generated from spec/v2/event-codemap.json.",
4229
+ "type": "object",
4230
+ "additionalProperties": false,
4231
+ "properties": {
4232
+ "run.started": {
4233
+ "$ref": "#/$defs/runStarted"
4234
+ },
4235
+ "run.completed": {
4236
+ "$ref": "#/$defs/runCompleted"
4237
+ },
4238
+ "run.failed": {
4239
+ "$ref": "#/$defs/runFailed"
4240
+ },
4241
+ "run.cancelled": {
4242
+ "$ref": "#/$defs/runCancelled"
4243
+ },
4244
+ "run.resume-started": {
4245
+ "$ref": "#/$defs/runResuming"
4246
+ },
4247
+ "run.paused": {
4248
+ "$ref": "#/$defs/runPaused"
4249
+ },
4250
+ "run.resumed": {
4251
+ "$ref": "#/$defs/runResumed"
4252
+ },
4253
+ "run.restored-from-snapshot": {
4254
+ "$ref": "#/$defs/runRestoredFromSnapshot"
4255
+ },
4256
+ "run.dead-lettered": {
4257
+ "$ref": "#/$defs/runDeadLettered"
4258
+ },
4259
+ "node.started": {
4260
+ "$ref": "#/$defs/nodeStarted"
4261
+ },
4262
+ "node.completed": {
4263
+ "$ref": "#/$defs/nodeCompleted"
4264
+ },
4265
+ "node.failed": {
4266
+ "$ref": "#/$defs/nodeFailed"
4267
+ },
4268
+ "node.suspended": {
4269
+ "$ref": "#/$defs/nodeSuspended"
4270
+ },
4271
+ "node.suspend-failed": {
4272
+ "$ref": "#/$defs/nodeSuspendFailed"
4273
+ },
4274
+ "node.resumed": {
4275
+ "$ref": "#/$defs/nodeResumed"
4276
+ },
4277
+ "node.retried": {
4278
+ "$ref": "#/$defs/nodeRetried"
4279
+ },
4280
+ "node.skipped": {
4281
+ "$ref": "#/$defs/nodeSkipped"
4282
+ },
4283
+ "node.cancelled": {
4284
+ "$ref": "#/$defs/nodeCancelled"
4285
+ },
4286
+ "approval.requested": {
4287
+ "$ref": "#/$defs/approvalRequested"
4288
+ },
4289
+ "approval.received": {
4290
+ "$ref": "#/$defs/approvalReceived"
4291
+ },
4292
+ "approval.granted": {
4293
+ "$ref": "#/$defs/approvalGranted"
4294
+ },
4295
+ "approval.rejected": {
4296
+ "$ref": "#/$defs/approvalRejected"
4297
+ },
4298
+ "approval.overridden": {
4299
+ "$ref": "#/$defs/approvalOverridden"
4300
+ },
4301
+ "clarification.requested": {
4302
+ "$ref": "#/$defs/clarificationRequested"
4303
+ },
4304
+ "clarification.resolved": {
4305
+ "$ref": "#/$defs/clarificationResolved"
4306
+ },
4307
+ "interrupt.requested": {
4308
+ "$ref": "#/$defs/interruptRequested"
4309
+ },
4310
+ "interrupt.resolved": {
4311
+ "$ref": "#/$defs/interruptResolved"
4312
+ },
4313
+ "channel.written": {
4314
+ "$ref": "#/$defs/channelWritten"
4315
+ },
4316
+ "channel.presence": {
4317
+ "$ref": "#/$defs/channelPresence"
4318
+ },
4319
+ "context.summarized": {
4320
+ "$ref": "#/$defs/contextSummarized"
4321
+ },
4322
+ "artifact.created": {
4323
+ "$ref": "#/$defs/artifactCreated"
4324
+ },
4325
+ "output.chunk": {
4326
+ "$ref": "#/$defs/outputChunk"
4327
+ },
4328
+ "variable.changed": {
4329
+ "$ref": "#/$defs/variableChanged"
4330
+ },
4331
+ "log.appended": {
4332
+ "$ref": "#/$defs/logAppended"
4333
+ },
4334
+ "version.pinned": {
4335
+ "$ref": "#/$defs/versionPinned"
4336
+ },
4337
+ "workflow.restored": {
4338
+ "$ref": "#/$defs/workflowRestored"
4339
+ },
4340
+ "workflow.loopback-limit": {
4341
+ "$ref": "#/$defs/workflowLoopbackLimit"
4342
+ },
4343
+ "workflow.stalled": {
4344
+ "$ref": "#/$defs/workflowStalled"
4345
+ },
4346
+ "cap.breached": {
4347
+ "$ref": "#/$defs/capBreached"
4348
+ },
4349
+ "lease.acquired": {
4350
+ "$ref": "#/$defs/leaseLifecycle"
4351
+ },
4352
+ "lease.renewed": {
4353
+ "$ref": "#/$defs/leaseLifecycle"
4354
+ },
4355
+ "lease.lost": {
4356
+ "$ref": "#/$defs/leaseLifecycle"
4357
+ },
4358
+ "lease.handed-off": {
4359
+ "$ref": "#/$defs/leaseHandedOff"
4360
+ },
4361
+ "replay.diverged": {
4362
+ "$ref": "#/$defs/replayDiverged"
4363
+ },
4364
+ "replay.diverged-at-refusal": {
4365
+ "$ref": "#/$defs/replayDivergedAtRefusal"
4366
+ },
4367
+ "agent.reasoned": {
4368
+ "$ref": "#/$defs/agentReasoned"
4369
+ },
4370
+ "agent.reasoning-delta": {
4371
+ "$ref": "#/$defs/agentReasoningDelta"
4372
+ },
4373
+ "provider.usage": {
4374
+ "$ref": "#/$defs/providerUsage"
4375
+ },
4376
+ "prompt.composed": {
4377
+ "$ref": "#/$defs/promptComposed"
4378
+ },
4379
+ "agent.prompt-resolved": {
4380
+ "$ref": "#/$defs/agentPromptResolved"
4381
+ },
4382
+ "model.capability-substituted": {
4383
+ "$ref": "#/$defs/modelCapabilitySubstituted"
4384
+ },
4385
+ "model.capability-insufficient": {
4386
+ "$ref": "#/$defs/modelCapabilityInsufficient"
4387
+ },
4388
+ "envelope.retry-attempted": {
4389
+ "$ref": "#/$defs/envelopeRetryAttempted"
4390
+ },
4391
+ "envelope.retry-exhausted": {
4392
+ "$ref": "#/$defs/envelopeRetryExhausted"
4393
+ },
4394
+ "envelope.refusal": {
4395
+ "$ref": "#/$defs/envelopeRefusal"
4396
+ },
4397
+ "envelope.truncated": {
4398
+ "$ref": "#/$defs/envelopeTruncated"
4399
+ },
4400
+ "envelope.nl-to-format-engaged": {
4401
+ "$ref": "#/$defs/envelopeNlToFormatEngaged"
4402
+ },
4403
+ "envelope.recovery-applied": {
4404
+ "$ref": "#/$defs/envelopeRecoveryApplied"
4405
+ },
4406
+ "agent.tool-called": {
4407
+ "$ref": "#/$defs/agentToolCalled"
4408
+ },
4409
+ "agent.tool-returned": {
4410
+ "$ref": "#/$defs/agentToolReturned"
4411
+ },
4412
+ "agent.handoff": {
4413
+ "$ref": "#/$defs/agentHandoff"
4414
+ },
4415
+ "agent.decided": {
4416
+ "$ref": "#/$defs/agentDecided"
4417
+ },
4418
+ "agent.verified": {
4419
+ "$ref": "#/$defs/agentVerified"
4420
+ },
4421
+ "agent.invocation-started": {
4422
+ "$ref": "#/$defs/agentInvocationStarted"
4423
+ },
4424
+ "agent.invocation-completed": {
4425
+ "$ref": "#/$defs/agentInvocationCompleted"
4426
+ },
4427
+ "eval.started": {
4428
+ "$ref": "#/$defs/evalStarted"
4429
+ },
4430
+ "eval.scored": {
4431
+ "$ref": "#/$defs/evalScored"
4432
+ },
4433
+ "eval.completed": {
4434
+ "$ref": "#/$defs/evalCompleted"
4435
+ },
4436
+ "deployment.promoted": {
4437
+ "$ref": "#/$defs/deploymentPromoted"
4438
+ },
4439
+ "deployment.rolled-back": {
4440
+ "$ref": "#/$defs/deploymentRolledBack"
4441
+ },
4442
+ "deployment.canary-adjusted": {
4443
+ "$ref": "#/$defs/deploymentCanaryAdjusted"
4444
+ },
4445
+ "deployment.state-changed": {
4446
+ "$ref": "#/$defs/deploymentStateChanged"
4447
+ },
4448
+ "roster.run-initiated": {
4449
+ "$ref": "#/$defs/rosterRunInitiated"
4450
+ },
4451
+ "tool.session-opened": {
4452
+ "$ref": "#/$defs/toolSessionOpened"
4453
+ },
4454
+ "tool.session-closed": {
4455
+ "$ref": "#/$defs/toolSessionClosed"
4456
+ },
4457
+ "egress.decided": {
4458
+ "$ref": "#/$defs/egressDecided"
4459
+ },
4460
+ "trigger.subscription-state-changed": {
4461
+ "$ref": "#/$defs/triggerSubscriptionStateChanged"
4462
+ },
4463
+ "trigger.delivery-attempted": {
4464
+ "$ref": "#/$defs/triggerDeliveryAttempted"
4465
+ },
4466
+ "budget.reserved": {
4467
+ "$ref": "#/$defs/budgetReserved"
4468
+ },
4469
+ "budget.consumed": {
4470
+ "$ref": "#/$defs/budgetConsumed"
4471
+ },
4472
+ "budget.threshold-crossed": {
4473
+ "$ref": "#/$defs/budgetThresholdCrossed"
4474
+ },
4475
+ "budget.exhausted": {
4476
+ "$ref": "#/$defs/budgetExhausted"
4477
+ },
4478
+ "orchestrator.decided": {
4479
+ "$ref": "#/$defs/runOrchestratorDecided"
4480
+ },
4481
+ "node.dispatched": {
4482
+ "$ref": "#/$defs/nodeDispatched"
4483
+ },
4484
+ "dispatch.fanned-out": {
4485
+ "$ref": "#/$defs/dispatchFanOut"
4486
+ },
4487
+ "dispatch.joined": {
4488
+ "$ref": "#/$defs/dispatchJoin"
4489
+ },
4490
+ "conversation.opened": {
4491
+ "$ref": "#/$defs/conversationOpened"
4492
+ },
4493
+ "conversation.exchanged": {
4494
+ "$ref": "#/$defs/conversationExchanged"
4495
+ },
4496
+ "conversation.closed": {
4497
+ "$ref": "#/$defs/conversationClosed"
4498
+ },
4499
+ "memory.compacted": {
4500
+ "$ref": "#/$defs/memoryCompacted"
4501
+ },
4502
+ "memory.written": {
4503
+ "$ref": "#/$defs/memoryWritten"
4504
+ },
4505
+ "agent.memory-consolidated": {
4506
+ "$ref": "#/$defs/agentMemoryConsolidated"
4507
+ },
4508
+ "commitment.fired": {
4509
+ "$ref": "#/$defs/commitmentFired"
4510
+ },
4511
+ "workspace.updated": {
4512
+ "$ref": "#/$defs/workspaceUpdated"
4513
+ },
4514
+ "workflow-chain.event": {
4515
+ "$ref": "#/$defs/coreWorkflowChainEvent"
4516
+ },
4517
+ "workflow-chain.confidence-escalated": {
4518
+ "$ref": "#/$defs/coreWorkflowChainConfidenceEscalated"
4519
+ },
4520
+ "connector.authorized": {
4521
+ "$ref": "#/$defs/connectorAuthorized"
4522
+ },
4523
+ "connector.auth-expired": {
4524
+ "$ref": "#/$defs/connectorAuthExpired"
4525
+ },
4526
+ "authorization.decided": {
4527
+ "$ref": "#/$defs/authorizationDecided"
4528
+ },
4529
+ "proposal.created": {
4530
+ "$ref": "#/$defs/proposalCreated"
4531
+ },
4532
+ "proposal.activated": {
4533
+ "$ref": "#/$defs/proposalActivated"
4534
+ },
4535
+ "goal.evaluated": {
4536
+ "$ref": "#/$defs/goalEvaluated"
4537
+ },
4538
+ "goal.closed": {
4539
+ "$ref": "#/$defs/goalClosed"
4540
+ },
4541
+ "import.applied": {
4542
+ "$ref": "#/$defs/importApplied"
4543
+ },
4544
+ "voice.speech-start": {
4545
+ "$ref": "#/$defs/voiceSpeechStart"
4546
+ },
4547
+ "voice.transcript": {
4548
+ "$ref": "#/$defs/voiceTranscript"
4549
+ },
4550
+ "voice.endpoint-candidate": {
4551
+ "$ref": "#/$defs/voiceEndpointCandidate"
4552
+ },
4553
+ "voice.turn-commit": {
4554
+ "$ref": "#/$defs/voiceTurnCommit"
4555
+ },
4556
+ "voice.synthesis-chunk": {
4557
+ "$ref": "#/$defs/voiceSynthesisChunk"
4558
+ },
4559
+ "voice.barge-in": {
4560
+ "$ref": "#/$defs/voiceBargeIn"
4561
+ },
4562
+ "voice.cancelled": {
4563
+ "$ref": "#/$defs/voiceCancelled"
4564
+ },
4565
+ "compensation.requested": {
4566
+ "$ref": "#/$defs/compensationRequested"
4567
+ },
4568
+ "compensation.started": {
4569
+ "$ref": "#/$defs/compensationStarted"
4570
+ },
4571
+ "compensation.completed": {
4572
+ "$ref": "#/$defs/compensationCompleted"
4573
+ },
4574
+ "compensation.failed": {
4575
+ "$ref": "#/$defs/compensationFailed"
4576
+ },
4577
+ "compensation.paused": {
4578
+ "$ref": "#/$defs/compensationPaused"
4579
+ },
4580
+ "compensation.manual-intervention-required": {
4581
+ "$ref": "#/$defs/compensationManualInterventionRequired"
4582
+ },
4583
+ "negotiation.decided": {
4584
+ "$ref": "#/$defs/negotiationDecided"
4585
+ }
4586
+ }
4587
+ }
4588
+ }