@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,211 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/run-event.schema.json",
4
+ "title": "RunEventDoc",
5
+ "description": "Persisted event document in the run's append-only event log. Source of truth for run state via projection fold. Canonical OpenWOP v1 event envelope.",
6
+ "type": "object",
7
+ "required": [
8
+ "eventId",
9
+ "runId",
10
+ "type",
11
+ "payload",
12
+ "timestamp",
13
+ "sequence"
14
+ ],
15
+ "properties": {
16
+ "eventId": {
17
+ "type": "string",
18
+ "description": "Globally unique ID for this event. Generated by appendAtomic before write; consumers MUST treat as opaque.",
19
+ "minLength": 1,
20
+ "maxLength": 128
21
+ },
22
+ "runId": {
23
+ "type": "string",
24
+ "description": "Run this event belongs to.",
25
+ "minLength": 1,
26
+ "maxLength": 128
27
+ },
28
+ "nodeId": {
29
+ "type": "string",
30
+ "description": "Set for node-scoped events (node.*, approval.*, clarification.*). Lifted to top-level so projection code can key per-node state machines without payload type coercion.",
31
+ "minLength": 1,
32
+ "maxLength": 128
33
+ },
34
+ "type": {
35
+ "description": "Event-type discriminator. RFC 0094 \u00a7C: either a protocol-owned type from the authoritative `RunEventType` catalog, or a correctly-prefixed vendor-extension event per `host-extensions.md` \u00a7\"Vendor-prefixed namespaces\" (dotted name whose first segment is the vendor's short identifier or reverse-DNS label \u2014 e.g. `acme.canvas.published` \u2014 and is NOT a protocol-owned/registry-reserved prefix). Aligns the schema with `COMPATIBILITY.md` (\"Clients MUST ignore unknown event types\") and `version-negotiation.md` (readers ignore unknown).",
36
+ "anyOf": [
37
+ {
38
+ "$ref": "#/$defs/RunEventType"
39
+ },
40
+ {
41
+ "type": "string",
42
+ "pattern": "^(?!(?:openwop|core|community|vendor|private|local)\\.)[a-z][a-zA-Z0-9_-]*(\\.[a-zA-Z0-9_-]+)+$",
43
+ "description": "Vendor-extension event type: two or more dot-separated segments; the leading segment is the vendor prefix and MUST NOT be one of the protocol-owned / registry-reserved prefixes (`openwop.*`, `core.*`, `community.*`, `vendor.*`, `private.*`, `local.*`) per `host-extensions.md` \u00a7\"Canonical prefixes\"."
44
+ }
45
+ ]
46
+ },
47
+ "payload": {
48
+ "description": "Event-type-specific payload. Servers MAY validate against per-type schemas; this top-level schema accepts any JSON value.",
49
+ "type": [
50
+ "object",
51
+ "array",
52
+ "string",
53
+ "number",
54
+ "boolean",
55
+ "null"
56
+ ]
57
+ },
58
+ "timestamp": {
59
+ "type": "string",
60
+ "format": "date-time",
61
+ "description": "ISO 8601 timestamp. IO adapters normalize between this canonical form and platform-specific representations (e.g., Firestore Timestamp)."
62
+ },
63
+ "sequence": {
64
+ "type": "integer",
65
+ "minimum": 0,
66
+ "description": "Monotonic per-run sequence. First event is 0; assigned atomically by appendAtomic."
67
+ },
68
+ "schemaVersion": {
69
+ "type": "integer",
70
+ "minimum": 0,
71
+ "description": "Per-event schema version. Bumped when an individual event type's payload contract changes. Distinct from per-run eventLogSchemaVersion (which describes the subcollection contract). Reader behavior is tolerant \u2014 unknown future versions fold best-effort."
72
+ },
73
+ "engineVersion": {
74
+ "type": "string",
75
+ "description": "Engine version that produced this event. Used by P4 versioning for compatibility checks."
76
+ },
77
+ "causationId": {
78
+ "type": "string",
79
+ "description": "Optional ID of the event that caused this one (e.g., node.completed caused by approval.received). Lets projections build causal chains without inferring from timing.",
80
+ "minLength": 1,
81
+ "maxLength": 128
82
+ }
83
+ },
84
+ "$comment": "RFC 0094 \u00a7G + COMPATIBILITY.md \u00a7\"Schema closure\": RunEventDoc is a SERVER-EMITTED shape, so it is open (`additionalProperties: true`) \u2014 v1.x hosts may add optional fields additively without breaking schema-validating clients. Client-submitted shapes stay closed at their outermost composition.",
85
+ "additionalProperties": true,
86
+ "$defs": {
87
+ "RunEventType": {
88
+ "type": "string",
89
+ "description": "Discriminator for event payload shape. Dotted naming convention. New variants extend the union \u2014 readers MUST NOT throw on unknown types (forward-compat: fold best-effort, ignore unknowns). RFC 0151 \u00a7D adds the six content-free `compensation.*` events. They are added to this CLOSED enum because without them a conforming host cannot emit them at all: the RFC named the events, the enum did not contain them, and any host following \u00a7D would have produced run events that fail schema validation. Payloads carry opaque node/effect IDs, attempt, ordering model, and closed reason codes \u2014 never provider bodies or credentials (\u00a7D/\u00a7G).",
90
+ "enum": [
91
+ "run.started",
92
+ "run.completed",
93
+ "run.failed",
94
+ "run.cancelled",
95
+ "run.resuming",
96
+ "run.paused",
97
+ "run.resumed",
98
+ "run.restored-from-snapshot",
99
+ "run.dead_lettered",
100
+ "node.started",
101
+ "node.completed",
102
+ "node.failed",
103
+ "node.suspended",
104
+ "node.suspend-failed",
105
+ "node.resumed",
106
+ "node.retried",
107
+ "node.skipped",
108
+ "node.cancelled",
109
+ "approval.requested",
110
+ "approval.received",
111
+ "approval.granted",
112
+ "approval.rejected",
113
+ "approval.overridden",
114
+ "clarification.requested",
115
+ "clarification.resolved",
116
+ "interrupt.requested",
117
+ "interrupt.resolved",
118
+ "channel.written",
119
+ "channel.presence",
120
+ "context.summarized",
121
+ "artifact.created",
122
+ "output.chunk",
123
+ "variable.changed",
124
+ "log.appended",
125
+ "version.pinned",
126
+ "workflow.restored",
127
+ "workflow.loopback-limit",
128
+ "workflow.stalled",
129
+ "cap.breached",
130
+ "lease.acquired",
131
+ "lease.renewed",
132
+ "lease.lost",
133
+ "lease.handed-off",
134
+ "replay.diverged",
135
+ "replay.divergedAtRefusal",
136
+ "agent.reasoned",
137
+ "agent.reasoning.delta",
138
+ "provider.usage",
139
+ "prompt.composed",
140
+ "agent.promptResolved",
141
+ "model.capability.substituted",
142
+ "model.capability.insufficient",
143
+ "envelope.retry.attempted",
144
+ "envelope.retry.exhausted",
145
+ "envelope.refusal",
146
+ "envelope.truncated",
147
+ "envelope.nlToFormat.engaged",
148
+ "envelope.recovery.applied",
149
+ "agent.toolCalled",
150
+ "agent.toolReturned",
151
+ "agent.handoff",
152
+ "agent.decided",
153
+ "agent.verified",
154
+ "agent.invocation.started",
155
+ "agent.invocation.completed",
156
+ "eval.started",
157
+ "eval.scored",
158
+ "eval.completed",
159
+ "deployment.promoted",
160
+ "deployment.rolled-back",
161
+ "deployment.canary.adjusted",
162
+ "deployment.state.changed",
163
+ "roster.run.initiated",
164
+ "tool.session.opened",
165
+ "tool.session.closed",
166
+ "egress.decided",
167
+ "trigger.subscription.state.changed",
168
+ "trigger.delivery.attempted",
169
+ "budget.reserved",
170
+ "budget.consumed",
171
+ "budget.threshold.crossed",
172
+ "budget.exhausted",
173
+ "runOrchestrator.decided",
174
+ "node.dispatched",
175
+ "core.dispatch.fanOut",
176
+ "core.dispatch.join",
177
+ "conversation.opened",
178
+ "conversation.exchanged",
179
+ "conversation.closed",
180
+ "memory.compacted",
181
+ "memory.written",
182
+ "agent.memory.consolidated",
183
+ "commitment.fired",
184
+ "workspace.updated",
185
+ "core.workflowChain.event",
186
+ "core.workflowChain.confidence-escalated",
187
+ "connector.authorized",
188
+ "connector.auth_expired",
189
+ "authorization.decided",
190
+ "proposal.created",
191
+ "proposal.activated",
192
+ "goal.evaluated",
193
+ "goal.closed",
194
+ "import.applied",
195
+ "voice.speech_start",
196
+ "voice.transcript",
197
+ "voice.endpoint_candidate",
198
+ "voice.turn_commit",
199
+ "voice.synthesis_chunk",
200
+ "voice.barge_in",
201
+ "voice.cancelled",
202
+ "compensation.requested",
203
+ "compensation.started",
204
+ "compensation.completed",
205
+ "compensation.failed",
206
+ "compensation.paused",
207
+ "compensation.manual_intervention_required"
208
+ ]
209
+ }
210
+ }
211
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/run-options.schema.json",
4
+ "title": "RunOptions",
5
+ "description": "Per-run parameter overlay supplied by the caller in `POST /v1/runs`. See `run-options.md` for full semantics. Reserved keys are typed; unknown keys in `configurable` pass through to the engine. RFC 0094 §A: this schema is OPEN at its own root (no `additionalProperties: false`) because it participates in the composed `createRun` request body in `api/openapi.yaml`; the closure (`unevaluatedProperties: false`) lives at that composition site, the only place JSON Schema 2020-12 can express closure over an `allOf`.",
6
+ "type": "object",
7
+ "properties": {
8
+ "configurable": {
9
+ "$ref": "#/$defs/Configurable",
10
+ "description": "Per-run overrides that affect runtime behavior without forking the workflow definition."
11
+ },
12
+ "tags": {
13
+ "type": "array",
14
+ "items": { "type": "string", "minLength": 1, "maxLength": 256 },
15
+ "maxItems": 100,
16
+ "uniqueItems": false,
17
+ "description": "Free-form caller tags for filtering/correlation. Server SHOULD enforce maxItems=100 and per-tag maxLength=256."
18
+ },
19
+ "metadata": {
20
+ "type": "object",
21
+ "description": "Free-form caller metadata. Persisted on the run doc; surfaces back via `RunSnapshot.metadata`. Server MAY enforce a serialized-size limit (recommended: 50KB)."
22
+ }
23
+ },
24
+ "$defs": {
25
+ "Configurable": {
26
+ "type": "object",
27
+ "description": "Reserved keys are typed below; unknown keys pass through verbatim. Implementations declare which keys they consume via `Capabilities.configurable` when advertised.",
28
+ "properties": {
29
+ "recursionLimit": {
30
+ "type": "integer",
31
+ "minimum": 1,
32
+ "description": "Override the per-run node-execution ceiling. Server clamps to `Capabilities.limits.maxNodeExecutions`."
33
+ },
34
+ "model": {
35
+ "type": "string",
36
+ "minLength": 1,
37
+ "description": "Override the AI model for nodes that consume `ctx.config.configurable.model`. Examples: `gpt-4`, `claude-opus-4-7`, `gemini-2.5-pro`."
38
+ },
39
+ "temperature": {
40
+ "type": "number",
41
+ "minimum": 0,
42
+ "maximum": 2,
43
+ "description": "Override AI temperature. Server SHOULD enforce 0..2 range."
44
+ },
45
+ "maxTokens": {
46
+ "type": "integer",
47
+ "minimum": 1,
48
+ "description": "Override AI max-tokens cap."
49
+ },
50
+ "promptOverrides": {
51
+ "type": "object",
52
+ "additionalProperties": { "type": "string" },
53
+ "description": "Per-prompt-ID variant override. Map of canonical prompt ID -> override text."
54
+ },
55
+ "mockProvider": {
56
+ "$ref": "#/$defs/MockProvider"
57
+ }
58
+ },
59
+ "additionalProperties": true
60
+ },
61
+ "MockProvider": {
62
+ "type": "object",
63
+ "description": "Routes AI activity calls through a deterministic mock provider instead of real LLM APIs. Test-keys-only — server returns 403 mock_provider_forbidden on production keys. See run-options.md §Mock provider extension (closes F1).",
64
+ "required": ["id"],
65
+ "properties": {
66
+ "id": {
67
+ "type": "string",
68
+ "description": "Selects a mock provider from the server's catalog (advertised via `Capabilities.testing.mockProviders`). The spec-canonical baseline `stream-text` MUST be supported for OpenWOP v1.0 conformance; other providers (`tool-calls`, `error`, `usage-only`) are recommended but not required.",
69
+ "minLength": 1,
70
+ "maxLength": 128
71
+ },
72
+ "config": {
73
+ "type": "object",
74
+ "description": "Per-provider parameter shape. Each provider documents its own keys; see run-options.md §Canonical mock provider catalog. Common shapes (informative — not enforced at this schema level since providers are pluggable):\n\n - stream-text: { tokens: string[], delayMsPerToken?: integer, finishReason?: string, usage?: object, model?: string }\n - tool-calls: { toolCalls: object[], delayMsPerToken?: integer }\n - error: { code: string, message: string, retryable?: boolean, failAfterMs?: integer }\n - usage-only: { usage: object }"
75
+ }
76
+ },
77
+ "additionalProperties": false
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/run-orchestrator-decided-event.schema.json",
4
+ "title": "RunOrchestratorDecidedPayload",
5
+ "description": "Payload for the `runOrchestrator.decided` RunEvent. Emitted exactly once per orchestrator decision by a `core.orchestrator.supervisor` node (or a host-extension equivalent that advertises orchestration). Carries the deciding agent's identity and the typed decision (orchestrator-decision.schema.json). The event envelope's top-level `nodeId` field carries the supervisor node-id; the payload does NOT duplicate it. See RFC 0006 §E for ordering invariants CO-1/CO-2/CO-3.",
6
+ "type": "object",
7
+ "required": ["agentId", "decision"],
8
+ "properties": {
9
+ "agentId": {
10
+ "type": "string",
11
+ "minLength": 3,
12
+ "maxLength": 256,
13
+ "description": "AgentRef.agentId of the orchestrator that emitted this decision. MUST equal `RunSnapshot.runOrchestrator.agentId` for the run's lifetime — the orchestrator identity is set at the first decision and does not change."
14
+ },
15
+ "decision": {
16
+ "$ref": "https://openwop.dev/spec/v1/orchestrator-decision.schema.json"
17
+ }
18
+ },
19
+ "additionalProperties": false
20
+ }
@@ -0,0 +1,148 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/run-snapshot.schema.json",
4
+ "title": "RunSnapshot",
5
+ "description": "Projected run state returned by `GET /v1/runs/{runId}`. Source is the run's append-only event log (run-event.schema.json) folded through the `RunProjection`. Forward-compat tolerant: readers MUST ignore unknown fields rather than reject.",
6
+ "type": "object",
7
+ "required": ["runId", "workflowId", "status"],
8
+ "properties": {
9
+ "runId": {
10
+ "type": "string",
11
+ "description": "Globally unique run identifier.",
12
+ "minLength": 1,
13
+ "maxLength": 128
14
+ },
15
+ "workflowId": {
16
+ "type": "string",
17
+ "description": "ID of the workflow this run executes.",
18
+ "minLength": 1
19
+ },
20
+ "status": {
21
+ "type": "string",
22
+ "enum": [
23
+ "pending",
24
+ "running",
25
+ "paused",
26
+ "waiting-approval",
27
+ "waiting-input",
28
+ "waiting-external",
29
+ "completed",
30
+ "failed",
31
+ "cancelling",
32
+ "cancelled"
33
+ ],
34
+ "description": "Current run state. `waiting-external` MUST be used when the suspended interrupt's `kind` is `external-event` per `interrupt-profiles.md §openwop-interrupt-external-event` — distinguishes external-event waits from HITL waits at the wire level. `cancelling` (RFC 0094 §B) is the transitional state between a cancel request being accepted and the terminal `cancelled` — `rest-endpoints.md` and the OpenAPI cancel responses already document the transition; a snapshot read during the cancel cascade carries it. Forward-compat: future statuses MAY be added; readers SHOULD treat unknown values as terminal-unknown rather than throw."
35
+ },
36
+ "compensationStatus": {
37
+ "type": "string",
38
+ "enum": ["none", "pending", "running", "completed", "partial", "failed", "manual"],
39
+ "description": "RFC 0151 §D — the run's compensation (unwind) rollup, kept separate from `status` on purpose: `status` is the FORWARD execution state and a closed union exported by the SDK, so RFC 0151 forbids reinterpreting it (there is deliberately no `compensating` run status). OPTIONAL and capability-gated — a host that does not advertise `capabilities.compensation` MUST omit this field; a host that advertises it MUST include it on every snapshot, `none` when no compensation was ever requested for the run. Presence is therefore a wire witness of the advert, and a `none` cannot be read as \"unwind is monitored here\" from a host that would never unwind. Values are the deterministic fold of the six `compensation.*` events over the persisted plan, defined normatively in `spec/v1/compensation.md §\"Run rollup: compensationStatus\"`: `none` (no `compensation.requested`), `pending` (requested, no `started`), `running` (started, plan active — a §E approval pause does NOT change it; the run's own `status: waiting-approval` carries the wait), `completed` (every inverse action completed), `partial` (plan inactive; some completed and some did not — reported, never rounded), `failed` (plan inactive; none completed), `manual` (`manual_intervention_required` recorded and unresolved; takes precedence over `partial`/`failed` while unresolved). Content-free by construction. Resolves RFC 0151 UQ3: `RunSnapshot` (`GET /v1/runs/{runId}`) is the sole owner; debug bundles and the AsyncAPI `run.snapshot` reuse it by `$ref`."
40
+ },
41
+ "owner": {
42
+ "type": "object",
43
+ "description": "RFC 0048. The identity triple that owns this run. Redaction-safe — `principal` is an opaque identifier, never PII or credential material. Optional: single-tenant hosts omit it. A principal scoped to one `workspace` MUST NOT read a run owned by another (`run_forbidden`).",
44
+ "required": ["tenant"],
45
+ "properties": {
46
+ "tenant": { "type": "string", "minLength": 1, "description": "Top-level isolation boundary." },
47
+ "workspace": { "type": "string", "minLength": 1, "description": "Optional sub-tenant within the tenant (RFC 0048 workspace)." },
48
+ "principal": { "type": "string", "minLength": 1, "description": "Acting identity (user or agent) — opaque id, never PII." },
49
+ "subject": {
50
+ "$ref": "subject.schema.json",
51
+ "description": "RFC 0165 \u00a7B. OPTIONAL issuer-scoped Subject record for the acting identity. When present: `subject.tenant` MUST equal `tenant`, `subject.subjectId` MUST equal `principal` when both are present, `subject.kind` MUST equal `principalKind` when both are present. A host that emits it on new runs synthesizes `issuer: \"urn:openwop:legacy\"` for runs that predate emission (\u00a7B.3) and copies it verbatim onto forks (\u00a7B.4)."
52
+ },
53
+ "principalKind": {
54
+ "type": "string",
55
+ "enum": ["user", "agent", "anonymous"],
56
+ "description": "RFC 0132. The kind of the acting principal. OPTIONAL and EXPLICIT — absent ⇒ unconstrained (today's RFC 0048 behavior; a host that does not distinguish kinds omits it). `anonymous` ⇒ the RFC 0132 §A anonymous-actor rules and the §C default-deny per-surface grant bind: the `principal` id MUST be opaque, origin-bound, ephemeral, non-cross-linkable, non-PII, and never inherit a role or a default-on tool baseline. A host that advertises `capabilities.anonymousActor` and dispatches through a public surface MUST set `anonymous` on the resulting run. Resolves RFC 0048 §Unresolved-Q1 for the anonymous case."
57
+ }
58
+ },
59
+ "additionalProperties": false
60
+ },
61
+ "currentNodeId": {
62
+ "type": "string",
63
+ "description": "Set when the run is suspended at a specific node (`waiting-approval` / `waiting-input` / `waiting-external`) — identifies which node holds the interrupt."
64
+ },
65
+ "startedAt": { "type": "string", "format": "date-time" },
66
+ "completedAt": { "type": "string", "format": "date-time" },
67
+ "agent": {
68
+ "$ref": "agent-ref.schema.json",
69
+ "description": "Optional run-level agent identity (Multi-Agent Shift Phase 1). When the run is driven by a single agent, this field carries that agent's `AgentRef`. In supervisor-orchestrated runs (Phase 5), this field rotates as workers hand off — it always carries the active worker for the current node. See `runOrchestrator` for the run-lifetime supervisor identity. Absent for runs with no agent provenance (legacy single-actor host)."
70
+ },
71
+ "runOrchestrator": {
72
+ "$ref": "agent-ref.schema.json",
73
+ "description": "Optional orchestrator-supervisor identity (Multi-Agent Shift Phase 5). When set, this agent owns dispatch decisions across the run's lifetime; `runOrchestrator.decided` events emitted during the run carry this agent's `agentId`. Distinct from `agent` — `agent` rotates with each worker; `runOrchestrator` is set at run start (or first `core.orchestrator.supervisor` node) and MUST NOT change for the run's lifetime. In single-agent runs (no supervisor), this field is absent; in supervisor runs both fields MAY co-exist."
74
+ },
75
+ "nodeStates": {
76
+ "type": "object",
77
+ "description": "Per-node state map. Keys are nodeIds; values are implementation-shaped state objects. Spec doesn't constrain the inner shape — see version-negotiation.md §node-states."
78
+ },
79
+ "variables": {
80
+ "type": "object",
81
+ "description": "Workflow-level variables (caller-supplied inputs + per-node outputs that survive the projection)."
82
+ },
83
+ "channels": {
84
+ "type": "object",
85
+ "description": "Optional typed state channels (see channels-and-reducers.md). Present when the workflow declares channel-aware mode."
86
+ },
87
+ "error": {
88
+ "type": "object",
89
+ "description": "Set on terminal `failed`. Structured so consumers can route on code without parsing message text.",
90
+ "required": ["code", "message"],
91
+ "properties": {
92
+ "code": { "type": "string", "minLength": 1 },
93
+ "message": { "type": "string", "minLength": 1 },
94
+ "details": { "type": "object" }
95
+ },
96
+ "additionalProperties": false
97
+ },
98
+ "engineVersion": {
99
+ "type": "string",
100
+ "description": "Engine version the run was started under. Used by the projection for forward-compat folds."
101
+ },
102
+ "eventLogSchemaVersion": {
103
+ "type": "integer",
104
+ "minimum": 0,
105
+ "description": "Per-run event-log subcollection schema version. See version-negotiation.md."
106
+ },
107
+ "tags": {
108
+ "type": "array",
109
+ "items": { "type": "string", "maxLength": 256 },
110
+ "maxItems": 100,
111
+ "description": "Caller-supplied tags from `RunOptions.tags`."
112
+ },
113
+ "metadata": {
114
+ "type": "object",
115
+ "description": "Caller-supplied metadata from `RunOptions.metadata`."
116
+ },
117
+ "configurable": {
118
+ "type": "object",
119
+ "description": "Per-run overlay from `RunOptions.configurable` (see run-options.md). Reserved keys: `recursionLimit`, `model`, `temperature`, `maxTokens`, `promptOverrides`."
120
+ },
121
+ "metrics": {
122
+ "type": "object",
123
+ "description": "Aggregate run-level metrics. Forward-compat: readers MUST tolerate missing/unknown fields. Fields are populated lazily as the engine emits them — absence does NOT mean zero. Implementation-specific fields (e.g., legacy `cost: number` estimates) MAY appear alongside the spec-canonical fields below.",
124
+ "properties": {
125
+ "openwopCost": {
126
+ "type": "object",
127
+ "description": "Spec-canonical cost rollup aggregated from per-node `recordCost()` calls. Keys mirror the `openwop.cost.*` OTel attribute allowlist (see `observability.md` §Cost attribution). Named `openwopCost` rather than `cost` because some implementations carry a legacy `metrics.cost: number` estimate that predates the typed rollup; using a distinct name avoids collision. Multi-provider runs report `provider`/`model` of the LAST contributing call; SDKs that need per-call detail SHOULD subscribe to OTel spans instead of reading this rollup.",
128
+ "properties": {
129
+ "usd": { "type": "number", "minimum": 0, "description": "Total USD cost across all node-level recordCost emissions." },
130
+ "tokens": {
131
+ "type": "object",
132
+ "properties": {
133
+ "input": { "type": "integer", "minimum": 0 },
134
+ "output": { "type": "integer", "minimum": 0 }
135
+ },
136
+ "additionalProperties": false
137
+ },
138
+ "model": { "type": "string", "description": "Model identifier of the most recent recordCost emission (e.g., `claude-opus-4-7`). For multi-model runs, surfaces the last value." },
139
+ "provider": { "type": "string", "description": "Normalized provider name (e.g., `anthropic`, `openai`, `gemini`)." },
140
+ "duration_ms": { "type": "integer", "minimum": 0, "description": "Sum of per-call durations across all recordCost emissions in this run." }
141
+ },
142
+ "additionalProperties": false
143
+ }
144
+ }
145
+ }
146
+ },
147
+ "additionalProperties": true
148
+ }
@@ -0,0 +1,109 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/security-advisory.schema.json",
4
+ "title": "SecurityAdvisory",
5
+ "description": "Registry-owned security advisory for a published OpenWOP pack version. Sourced from registry/security/advisories.json. Every entry MUST be reviewed + merged via maintainer PR; the CI check-advisories gate refuses to deploy if any active advisory targets a pack version that is not already yanked.",
6
+ "type": "object",
7
+ "required": ["id", "publishedAt", "severity", "summary", "affected"],
8
+ "properties": {
9
+ "id": {
10
+ "type": "string",
11
+ "description": "Stable advisory identifier. Format: `OPENWOP-YYYY-NNNN` (sequential, assigned by maintainers at PR merge time). MAY also include an aliased CVE ID via `cveIds[]`.",
12
+ "pattern": "^OPENWOP-[0-9]{4}-[0-9]{4}$"
13
+ },
14
+ "cveIds": {
15
+ "type": "array",
16
+ "description": "Aliased CVE identifiers if a CVE was reserved through Mitre or a CNA. Listed in cve.mitre.org format.",
17
+ "items": {
18
+ "type": "string",
19
+ "pattern": "^CVE-[0-9]{4}-[0-9]+$"
20
+ },
21
+ "uniqueItems": true
22
+ },
23
+ "publishedAt": {
24
+ "type": "string",
25
+ "format": "date",
26
+ "description": "Date the advisory was first published (ISO 8601 yyyy-mm-dd). Frozen at merge time; do not update on revision."
27
+ },
28
+ "updatedAt": {
29
+ "type": "string",
30
+ "format": "date",
31
+ "description": "Date of last advisory update. Bump when severity, affected, or fixedIn changes."
32
+ },
33
+ "severity": {
34
+ "type": "string",
35
+ "enum": ["critical", "high", "medium", "low"],
36
+ "description": "Severity per the rubric in docs/runbooks/INCIDENT-RESPONSE.md. critical=S0 (yank immediately), high=S1, medium=S2, low=S3."
37
+ },
38
+ "cvssV4Score": {
39
+ "type": "number",
40
+ "minimum": 0,
41
+ "maximum": 10,
42
+ "description": "Optional CVSS 4.0 base score. Informational; severity field is the authoritative classification."
43
+ },
44
+ "summary": {
45
+ "type": "string",
46
+ "description": "One-line human-readable summary of the vulnerability. Surfaces in tooling output.",
47
+ "minLength": 1,
48
+ "maxLength": 200
49
+ },
50
+ "details": {
51
+ "type": "string",
52
+ "description": "Long-form description: vulnerability mechanism, attack vector, impact, recommended consumer action. May reference external URLs via advisoryUrl."
53
+ },
54
+ "advisoryUrl": {
55
+ "type": "string",
56
+ "format": "uri",
57
+ "description": "External advisory link (e.g., GitHub Security Advisory, vendor security page, CVE detail page)."
58
+ },
59
+ "affected": {
60
+ "type": "array",
61
+ "description": "Pack versions impacted by this advisory. Each entry pins a pack name + a SemVer range. The check-advisories CI gate cross-references this list against every published version and fails if any non-yanked version matches.",
62
+ "minItems": 1,
63
+ "items": {
64
+ "type": "object",
65
+ "required": ["packName", "versions"],
66
+ "properties": {
67
+ "packName": {
68
+ "type": "string",
69
+ "description": "Pack name (e.g., `vendor.myndhyve.ai`). MUST exist under registry/v1/packs/.",
70
+ "pattern": "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
71
+ },
72
+ "versions": {
73
+ "type": "string",
74
+ "description": "SemVer range using node-semver syntax (`<1.0.0`, `>=1.0.0 <1.0.3`, `1.0.0 || 1.0.1`). Matched against published version numbers via the check-advisories gate."
75
+ },
76
+ "fixedIn": {
77
+ "type": "string",
78
+ "description": "Earliest version that contains the fix. Consumers MUST upgrade to >= this version. Absent if no fix is available yet (defense-only).",
79
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$"
80
+ },
81
+ "fixedInRef": {
82
+ "type": "string",
83
+ "description": "PR or commit reference where the fix landed (e.g., `openwop/openwop#42`). Helps consumers audit the patch."
84
+ }
85
+ },
86
+ "additionalProperties": false
87
+ }
88
+ },
89
+ "credits": {
90
+ "type": "array",
91
+ "description": "Acknowledged reporters or researchers.",
92
+ "items": {
93
+ "type": "object",
94
+ "required": ["name"],
95
+ "properties": {
96
+ "name": { "type": "string", "minLength": 1 },
97
+ "url": { "type": "string", "format": "uri" },
98
+ "role": {
99
+ "type": "string",
100
+ "enum": ["finder", "reporter", "analyst", "coordinator", "remediation-developer"],
101
+ "description": "Per CSAF role vocabulary. Defaults to `finder` when not specified."
102
+ }
103
+ },
104
+ "additionalProperties": false
105
+ }
106
+ }
107
+ },
108
+ "additionalProperties": false
109
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/self-hosted-runner-dispatch-frame.schema.json",
4
+ "title": "SelfHostedRunnerDispatchFrame",
5
+ "description": "RFC 0122 §Registration + channel. A single model/tool DISPATCH STEP the host routes to a registered runner over the runner↔host channel (`self-hosted-runner.md`). The host is the sole orchestration/persistence/replay authority; this frame carries ONE step's inputs, never a whole run. `inputs` is opaque model/tool input (messages, tool arguments) and MUST NOT contain runner-credential material — the runner holds its own credential locally (SECURITY invariant `runner-credential-non-transit`). `seq` is the per-runner monotonic DISPATCH cursor, a DISTINCT sequence from the run event-log `sequence` (they MUST NOT be conflated); a reconnecting runner resumes via `Last-Event-ID` at this cursor and the host drops any redelivered `{runId, stepId}` whose result is already persisted (at-most-once).",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["runId", "stepId", "seq", "kind", "inputs"],
9
+ "properties": {
10
+ "runId": {
11
+ "type": "string",
12
+ "minLength": 1,
13
+ "description": "The backing OpenWOP run this dispatch belongs to. Host-owned run identity."
14
+ },
15
+ "stepId": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "description": "The dispatch step within the run. The `{runId, stepId}` pair is the at-most-once idempotency key: a runner MUST return the result under the same pair, and the host MUST drop (not re-dispatch) a redelivered `{runId, stepId}` whose result is already persisted."
19
+ },
20
+ "seq": {
21
+ "type": "integer",
22
+ "minimum": 0,
23
+ "description": "The per-runner monotonic dispatch cursor for the channel. DISTINCT from the run event-log `sequence` (MUST NOT be conflated — conflating them breaks resume dedup). A reconnecting runner resumes via the SSE `Last-Event-ID` at this cursor so a dispatch is never redelivered past it (`stream-modes.md §Resumption`)."
24
+ },
25
+ "kind": {
26
+ "type": "string",
27
+ "enum": ["model", "tool"],
28
+ "description": "Whether this step dispatches a model call (`model`) or a tool call (`tool`). A host MAY advertise only a subset via `selfHostedRunner.dispatchKinds` and route only those kinds to runners."
29
+ },
30
+ "provider": {
31
+ "type": "string",
32
+ "minLength": 1,
33
+ "description": "REQUIRED when `kind == 'model'`. The model provider id the runner dispatches to under its locally-held credential (e.g. a subscription CLI login, a private endpoint). Never a host-held credential."
34
+ },
35
+ "model": {
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "description": "REQUIRED when `kind == 'model'`. The model id to run."
39
+ },
40
+ "tool": {
41
+ "type": "string",
42
+ "minLength": 1,
43
+ "description": "REQUIRED when `kind == 'tool'`. The tool the runner executes locally."
44
+ },
45
+ "inputs": {
46
+ "type": "object",
47
+ "description": "Opaque model/tool inputs for this step (messages, tool arguments). MUST NOT contain runner-credential material (`runner-credential-non-transit`). The host sends inputs and receives outputs; the credential stays on the runner."
48
+ }
49
+ },
50
+ "allOf": [
51
+ {
52
+ "if": { "properties": { "kind": { "const": "model" } } },
53
+ "then": { "required": ["provider", "model"] }
54
+ },
55
+ {
56
+ "if": { "properties": { "kind": { "const": "tool" } } },
57
+ "then": { "required": ["tool"] }
58
+ }
59
+ ],
60
+ "examples": [
61
+ {
62
+ "runId": "run_x",
63
+ "stepId": "step_3",
64
+ "seq": 12,
65
+ "kind": "model",
66
+ "provider": "anthropic",
67
+ "model": "claude-opus-4-8",
68
+ "inputs": { "messages": [{ "role": "user", "content": "summarize the attached notes" }] }
69
+ },
70
+ {
71
+ "runId": "run_y",
72
+ "stepId": "step_1",
73
+ "seq": 0,
74
+ "kind": "tool",
75
+ "tool": "local.shell.readFile",
76
+ "inputs": { "path": "/home/user/notes.txt" }
77
+ }
78
+ ]
79
+ }