@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,134 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/ai-envelope.schema.json",
4
+ "title": "AIEnvelope",
5
+ "description": "Canonical inbound wire format for a typed, structured emission produced by an LLM during workflow execution. Distinct from `RunEventDoc` (which is the outbound run event log envelope). Per `spec/v1/ai-envelope.md`. The top-level shape is closed (`additionalProperties: false`); the `payload` shape is selected by the `type` discriminator and validated against a per-kind schema at `schemas/envelopes/{type}.schema.json` (universals) or a host-published vendor location. Hosts advertise the kind catalog via `Capabilities.supportedEnvelopes` and the per-kind active version via `Capabilities.schemaVersions`. Status: FINAL v1.1 (promoted 2026-05-18 via RFC 0021).",
6
+ "type": "object",
7
+ "required": ["type", "envelopeId", "correlationId", "payload", "meta"],
8
+ "properties": {
9
+ "type": {
10
+ "type": "string",
11
+ "minLength": 1,
12
+ "maxLength": 256,
13
+ "description": "Discriminator for payload shape, kind routing, and Envelope Contract gate. Universal kinds (always allowed): `clarification.request`, `schema.request`, `schema.response`, `error`. Vendor kinds MUST be namespaced per `spec/v1/host-extensions.md` (e.g., `vendor.myndhyve.prd.create`). Pre-v1.x unnamespaced kinds (`prd.create`, `theme.create`, `tasks.create`) MAY appear in `Capabilities.supportedEnvelopes` for backward compatibility; v1.x hosts SHOULD prefer the namespaced form."
14
+ },
15
+ "schemaVersion": {
16
+ "type": "integer",
17
+ "minimum": 0,
18
+ "description": "Per-kind schema version. Absent → treat as 0. Matched against `Capabilities.schemaVersions[type]`. When the emitted version is lower than the advertised floor, engines under `envelopeStrictness: 'warn'` (default) MUST attempt validation against the advertised version and log `envelope_schema_version_drift`; engines under `envelopeStrictness: 'strict'` MUST refuse with `unknown_schema_version`. When higher than advertised, engines MUST refuse regardless of strictness."
19
+ },
20
+ "envelopeId": {
21
+ "type": "string",
22
+ "minLength": 1,
23
+ "maxLength": 128,
24
+ "description": "Globally unique envelope id. Generated by the engine if absent on receipt; consumers MUST treat as opaque. Distinct from `correlationId` (which is the dedup/replay key)."
25
+ },
26
+ "correlationId": {
27
+ "type": "string",
28
+ "minLength": 1,
29
+ "maxLength": 128,
30
+ "description": "Caller-stable identifier for dedup, replay short-circuit, and causal chaining. Two envelopes in the same run with the same `correlationId` MUST be treated as a re-emission (engine returns the cached outcome). Same-`correlationId` envelopes with different `type` values MUST be refused with `envelope_correlation_conflict`. The engine propagates `correlationId` onto resulting `RunEventDoc.causationId`. Recommended construction: `${runId}:${nodeId}:${turnIndex}:${kindHash}`."
31
+ },
32
+ "nodeId": {
33
+ "type": "string",
34
+ "minLength": 1,
35
+ "maxLength": 128,
36
+ "description": "Set when the emitting node is identifiable. Lifted to top-level for per-node projection without payload coercion (mirrors `RunEventDoc.nodeId`). Engines MAY populate from execution context when absent."
37
+ },
38
+ "payload": {
39
+ "description": "Discriminated payload. Shape selected by `type`. Validated against the per-kind schema at `schemas/envelopes/{type}.schema.json` (universals) or a host-published vendor schema. Top-level accepts any JSON value because per-kind schemas vary; strict validation is per-kind, not at this layer.",
40
+ "type": ["object", "array", "string", "number", "boolean", "null"]
41
+ },
42
+ "meta": {
43
+ "$ref": "#/$defs/EnvelopeMeta"
44
+ },
45
+ "partial": {
46
+ "$ref": "#/$defs/PartialInfo"
47
+ }
48
+ },
49
+ "additionalProperties": false,
50
+ "$defs": {
51
+ "EnvelopeMeta": {
52
+ "type": "object",
53
+ "required": ["source", "ts"],
54
+ "properties": {
55
+ "source": {
56
+ "type": "string",
57
+ "enum": ["ai-generation", "user", "system"],
58
+ "description": "Provenance of this emission. `ai-generation` — LLM emitted this in a node turn. `user` — relayed from a user action (form fill, approval gate). `system` — engine-synthesized (e.g., resume value normalization). Gates approval-flow re-routing per `ai-envelope.md` §\"Source attribution\" (LLM-generated mutations route through approval gates; user-supplied mutations bypass them when the user is already authenticated)."
59
+ },
60
+ "contentTrust": {
61
+ "type": "string",
62
+ "enum": ["trusted", "untrusted"],
63
+ "description": "Trust tag mirroring `RunEventDoc.contentTrust`. Hosts MUST set `untrusted` when the payload origin is an MCP tool result per `mcp-integration.md` or an A2A inbound message per `a2a-integration.md`. The engine MUST propagate this onto any `RunEventDoc` emitted as a consequence of the envelope. Approval gates MUST refuse to advance on `untrusted` envelopes (refusal code `untrusted_content_blocks_approval`)."
64
+ },
65
+ "ts": {
66
+ "type": "string",
67
+ "format": "date-time",
68
+ "description": "ISO 8601 UTC timestamp of emission."
69
+ },
70
+ "traceparent": {
71
+ "type": "string",
72
+ "description": "Optional W3C trace-context value (`traceparent` header format) for distributed tracing propagation. Engines that export OTel spans for envelope acceptance SHOULD honor this value as the parent span when present."
73
+ },
74
+ "label": {
75
+ "type": "string",
76
+ "maxLength": 256,
77
+ "description": "Optional human-readable label for ops dashboards (e.g., `\"Draft PRD #2\"`). Never used for routing; never persisted into event payloads in a security-relevant way. (in-flight)"
78
+ },
79
+ "rendering": {
80
+ "type": "object",
81
+ "description": "RFC 0055. Optional hint for how a consumer SHOULD render this envelope's payload. Non-normative w.r.t. payload validation; a consumer that doesn't recognize the hint (or a `display` value) MUST fall back to its default rendering (text / raw JSON). Carries no secret material (SR-1 applies as for the rest of `meta`).",
82
+ "properties": {
83
+ "display": {
84
+ "type": "string",
85
+ "enum": ["markdown", "code", "card", "image", "audio", "file"],
86
+ "description": "Renderer family the producer suggests."
87
+ },
88
+ "mimeType": {
89
+ "type": "string",
90
+ "description": "IANA media type when `display` is `image`/`audio`/`file`."
91
+ },
92
+ "lang": {
93
+ "type": "string",
94
+ "description": "Language tag when `display` is `code` (e.g. `ts`, `python`)."
95
+ },
96
+ "alt": {
97
+ "type": "string",
98
+ "description": "Text alternative for accessibility when `display` is `image`/`audio`/`file`. SHOULD be present for those families."
99
+ },
100
+ "title": {
101
+ "type": "string",
102
+ "description": "Optional caption / card header."
103
+ }
104
+ },
105
+ "additionalProperties": false
106
+ }
107
+ },
108
+ "additionalProperties": false,
109
+ "description": "Wire metadata. See `spec/v1/ai-envelope.md` §EnvelopeMeta."
110
+ },
111
+ "PartialInfo": {
112
+ "type": "object",
113
+ "required": ["isPartial", "index", "total"],
114
+ "properties": {
115
+ "isPartial": {
116
+ "type": "boolean",
117
+ "description": "True for all chunks of a partial emission EXCEPT the final one. The final chunk carries `isPartial: false` and signals reassembly completion. (in-flight)"
118
+ },
119
+ "index": {
120
+ "type": "integer",
121
+ "minimum": 0,
122
+ "description": "0-indexed chunk position. (in-flight)"
123
+ },
124
+ "total": {
125
+ "type": "integer",
126
+ "minimum": -1,
127
+ "description": "Total expected chunks. -1 when unknown (streaming without precount). (in-flight)"
128
+ }
129
+ },
130
+ "additionalProperties": false,
131
+ "description": "Present when the envelope is one fragment of a streamed emission. Cross-transport reassembly is open (see gap E1 in `ai-envelope.md`)."
132
+ }
133
+ }
134
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/annotation-create.schema.json",
4
+ "title": "AnnotationCreate",
5
+ "description": "RFC 0056. Request body for `POST /v1/runs/{runId}/annotations`. The host assigns `annotationId` + `createdAt`, derives `actor.principalRef` from the authenticated principal, and binds `target.runId` to the path `runId` — so the client supplies only the target anchor (event/node), the signal, and an optional note. The response is a full `annotation.schema.json`.",
6
+ "type": "object",
7
+ "required": ["signal"],
8
+ "properties": {
9
+ "target": {
10
+ "type": "object",
11
+ "description": "Optional finer-grained anchor within the run. `runId` is taken from the path and MUST NOT be supplied here.",
12
+ "properties": {
13
+ "eventId": { "type": "string", "description": "Anchor the annotation to one RunEvent." },
14
+ "nodeId": { "type": "string", "description": "Anchor the annotation to one node." }
15
+ },
16
+ "additionalProperties": false
17
+ },
18
+ "signal": {
19
+ "type": "object",
20
+ "required": ["kind"],
21
+ "properties": {
22
+ "kind": { "type": "string", "enum": ["rating", "correction", "label", "flag"] },
23
+ "rating": { "type": "integer", "minimum": 1, "maximum": 5, "description": "Required iff `kind` is `rating`." },
24
+ "label": { "type": "string", "description": "Required iff `kind` is `label`." },
25
+ "correction": { "type": "string", "description": "Corrected text/value iff `kind` is `correction`. Untrusted user content." }
26
+ },
27
+ "additionalProperties": false,
28
+ "allOf": [
29
+ { "if": { "properties": { "kind": { "const": "rating" } } }, "then": { "required": ["rating"] } },
30
+ { "if": { "properties": { "kind": { "const": "label" } } }, "then": { "required": ["label"] } },
31
+ { "if": { "properties": { "kind": { "const": "correction" } } }, "then": { "required": ["correction"] } }
32
+ ]
33
+ },
34
+ "note": { "type": "string", "description": "Optional free-text reviewer note. Untrusted user content." }
35
+ },
36
+ "additionalProperties": false
37
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/annotation.schema.json",
4
+ "title": "Annotation",
5
+ "description": "RFC 0056. A non-blocking human/agent quality signal attached to a run, event, or node — a side-resource, NOT a replayable run-event-log entry. Recorded via `POST /v1/runs/{runId}/annotations`, listed via `GET`, and surfaced live via the `run.annotated` SSE notification. `signal.correction` and `note` are untrusted user content (SECURITY invariant `annotation-content-redaction`).",
6
+ "type": "object",
7
+ "required": ["annotationId", "target", "signal", "actor", "createdAt"],
8
+ "properties": {
9
+ "annotationId": {
10
+ "type": "string",
11
+ "minLength": 1,
12
+ "description": "Host-assigned unique identifier for this annotation."
13
+ },
14
+ "target": {
15
+ "type": "object",
16
+ "required": ["runId"],
17
+ "properties": {
18
+ "runId": { "type": "string", "minLength": 1 },
19
+ "eventId": { "type": "string", "description": "Optional — anchors the annotation to one RunEvent." },
20
+ "nodeId": { "type": "string", "description": "Optional — anchors the annotation to one node." }
21
+ },
22
+ "additionalProperties": false
23
+ },
24
+ "signal": {
25
+ "type": "object",
26
+ "required": ["kind"],
27
+ "properties": {
28
+ "kind": { "type": "string", "enum": ["rating", "correction", "label", "flag"] },
29
+ "rating": { "type": "integer", "minimum": 1, "maximum": 5, "description": "Required iff `kind` is `rating`." },
30
+ "label": { "type": "string", "description": "Required iff `kind` is `label`." },
31
+ "correction": { "type": "string", "description": "Corrected text/value iff `kind` is `correction`. Untrusted user content." }
32
+ },
33
+ "additionalProperties": false,
34
+ "allOf": [
35
+ { "if": { "properties": { "kind": { "const": "rating" } } }, "then": { "required": ["rating"] } },
36
+ { "if": { "properties": { "kind": { "const": "label" } } }, "then": { "required": ["label"] } },
37
+ { "if": { "properties": { "kind": { "const": "correction" } } }, "then": { "required": ["correction"] } }
38
+ ]
39
+ },
40
+ "actor": {
41
+ "type": "object",
42
+ "required": ["principalRef"],
43
+ "properties": {
44
+ "principalRef": {
45
+ "type": "string",
46
+ "minLength": 1,
47
+ "description": "Opaque principal identifier — a principal per RFC 0048 (Draft, referenced non-normatively) or an AgentRef per RFC 0002 when a supervisor agent annotates. String-typed so RFC 0056 does not depend on RFC 0048 reaching Accepted."
48
+ }
49
+ },
50
+ "additionalProperties": false
51
+ },
52
+ "note": { "type": "string", "description": "Optional free-text reviewer note. Untrusted user content." },
53
+ "createdAt": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp the host recorded the annotation." }
54
+ },
55
+ "additionalProperties": false
56
+ }
@@ -0,0 +1,244 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/artifact-type-pack-manifest.schema.json",
4
+ "title": "ArtifactTypePackManifest",
5
+ "description": "Manifest for a published OpenWOP artifact-type pack — `pack.json` at the pack root with `kind: \"artifact-type\"`. Peer to `node-pack-manifest.schema.json` (RFC 0003), `workflow-chain-pack-manifest.schema.json` (RFC 0013), and `prompt-pack-manifest.schema.json` (RFC 0028); disjoint from all three via the `kind` discriminator. See `spec/v1/artifact-type-packs.md` for the canonical contract and RFC 0071 for the rationale.\n\nArtifact-type packs distribute typed artifact definitions — the JSON Schema, rendering hint, lifecycle, and export-format hints for the rich outputs workflow nodes produce — via the same signed-tarball + Ed25519 + SRI pipeline that already serves node, workflow-chain, and prompt packs. When a host installs an artifact-type pack and advertises `host.artifactTypes: { supported: true }`, it validates produced artifacts of the declared `artifactTypeId`s against their `schemaRef` before emitting `artifact.created`.",
6
+ "type": "object",
7
+ "required": [
8
+ "name",
9
+ "version",
10
+ "kind",
11
+ "engines",
12
+ "artifactTypes"
13
+ ],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "kind": {
17
+ "type": "string",
18
+ "const": "artifact-type",
19
+ "description": "Pack kind discriminator. MUST be the literal string `\"artifact-type\"`. Manifests carrying any other `kind` value validate against a different pack-manifest schema."
20
+ },
21
+ "name": {
22
+ "type": "string",
23
+ "description": "Reverse-DNS pack name per `node-packs.md` §Naming. Reserved scopes are identical (`core.*` / `vendor.<org>.*` / `community.<author>.*` / `private.<host>.*`). Mirror of `prompt-pack-manifest.schema.json#/properties/name`.",
24
+ "pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
25
+ "minLength": 1,
26
+ "maxLength": 256
27
+ },
28
+ "version": {
29
+ "type": "string",
30
+ "description": "Pack-level SemVer 2.0.0.",
31
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
32
+ },
33
+ "description": {
34
+ "type": "string",
35
+ "maxLength": 1024
36
+ },
37
+ "author": {
38
+ "type": "string"
39
+ },
40
+ "license": {
41
+ "type": "string",
42
+ "description": "SPDX license identifier (e.g., `Apache-2.0`, `MIT`)."
43
+ },
44
+ "homepage": {
45
+ "type": "string",
46
+ "format": "uri"
47
+ },
48
+ "repository": {
49
+ "type": "string",
50
+ "format": "uri"
51
+ },
52
+ "keywords": {
53
+ "type": "array",
54
+ "items": {
55
+ "type": "string",
56
+ "maxLength": 64
57
+ },
58
+ "maxItems": 50
59
+ },
60
+ "engines": {
61
+ "type": "object",
62
+ "required": [
63
+ "openwop"
64
+ ],
65
+ "properties": {
66
+ "openwop": {
67
+ "type": "string",
68
+ "description": "Semver range — which openwop protocol versions this pack works against. Example: `>=1.1 <2.0.0`."
69
+ }
70
+ },
71
+ "additionalProperties": true
72
+ },
73
+ "dependencies": {
74
+ "type": "object",
75
+ "additionalProperties": {
76
+ "type": "string"
77
+ },
78
+ "description": "Other packs this pack depends on. Map of pack name → semver range. Resolved transitively at workflow-register time."
79
+ },
80
+ "peerDependencies": {
81
+ "type": "object",
82
+ "additionalProperties": {
83
+ "type": "string"
84
+ },
85
+ "description": "Engine-supplied capabilities the pack consumes (e.g., `{ \"host.artifactTypes\": \"supported\" }`). Resolved against the host's advertised capabilities at register time."
86
+ },
87
+ "artifactTypes": {
88
+ "type": "array",
89
+ "minItems": 1,
90
+ "items": {
91
+ "$ref": "#/$defs/ArtifactType"
92
+ },
93
+ "description": "Typed artifact definitions this pack contributes. Each MUST have a unique `artifactTypeId` within the pack."
94
+ },
95
+ "signing": {
96
+ "$ref": "#/$defs/Signing"
97
+ }
98
+ },
99
+ "$defs": {
100
+ "ArtifactType": {
101
+ "type": "object",
102
+ "required": [
103
+ "artifactTypeId",
104
+ "schemaRef"
105
+ ],
106
+ "additionalProperties": false,
107
+ "properties": {
108
+ "artifactTypeId": {
109
+ "type": "string",
110
+ "description": "Reverse-DNS artifact-type identifier. Same pattern and reserved scopes as a pack `name`. This is the value `WorkflowNode.artifactType`, `nodes[].artifact.typeId`, and `artifact.created.artifactType` reference. Third parties MUST NOT publish under `core.*`.",
111
+ "pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
112
+ "minLength": 1,
113
+ "maxLength": 256
114
+ },
115
+ "schemaRef": {
116
+ "type": "string",
117
+ "minLength": 1,
118
+ "description": "Path inside the pack tarball to the artifact's JSON Schema (Draft 2020-12). The target schema MUST set `additionalProperties: false` at its top level and declare an `$id` under `{HostBase}/schemas/artifacts/{artifactTypeId}.schema.json`, mirroring the envelope convention in `ai-envelope.md` §\"Canonical schema location\"."
119
+ },
120
+ "schemaVersion": {
121
+ "type": "integer",
122
+ "minimum": 0,
123
+ "description": "Non-negative integer artifact-schema version, parallel to the per-kind integer in `capabilities.schemaVersions`. Absent ⇒ treated as 0. Bumped when the artifact schema changes shape. A version *declaration*, not a validation guarantee (RFC 0075 / P1-2)."
124
+ },
125
+ "validation": {
126
+ "type": "string",
127
+ "enum": [
128
+ "open",
129
+ "closed"
130
+ ],
131
+ "description": "RFC 0075. Strictness contract of the artifact's `schemaRef` schema. `closed` ⇒ closed-world (`additionalProperties: false`); a consumer MAY rely on the absence of unknown fields. `open` (recommended for AI/LLM-produced artifacts) ⇒ the schema tolerates extra fields to absorb model drift; consumers MUST ignore unknown fields per COMPATIBILITY.md §2.1. Absent ⇒ `open` (the forward-compatible default). The `additionalProperties:false` requirement on `schemaRef` was relaxed MUST → SHOULD by RFC 0075: a closed-world artifact contract contradicts the protocol's own forward-compat mandate and the first AI-native adopter cannot meet it."
132
+ },
133
+ "displayName": {
134
+ "type": "string",
135
+ "description": "Human-readable label for artifact-management UIs. Non-normative."
136
+ },
137
+ "rendering": {
138
+ "$ref": "#/$defs/RenderingHint"
139
+ },
140
+ "exportFormats": {
141
+ "type": "array",
142
+ "items": {
143
+ "type": "string",
144
+ "minLength": 1,
145
+ "maxLength": 64,
146
+ "pattern": "^([a-z][a-z0-9]*|vendor\\.[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*|x-[a-z][a-z0-9-]*)$"
147
+ },
148
+ "uniqueItems": true,
149
+ "description": "Export-format identifiers (hints) a renderer MAY offer. Spec-reserved core identifiers carry interoperable meaning (the lowercase file-extension / common name): `pdf`, `pptx`, `docx`, `xlsx`, `md`, `html`, `txt`, `csv`, `json`, `png`, `svg`, `jpeg`, `step`, `stl`, `dxf`. Domain-specific formats outside the core set MUST be `vendor.<org>.<format>`- or `x-<format>`-prefixed (mirrors the `requiredModelCapabilities` reserved-core + extension idiom). Advisory: this spec assigns no byte-level production semantics to any identifier — it standardizes the identifier so two hosts agree what `pptx` names, not how the bytes are produced."
150
+ },
151
+ "syncOn": {
152
+ "type": "string",
153
+ "enum": [
154
+ "completion",
155
+ "approval",
156
+ "manual"
157
+ ],
158
+ "description": "When the host registers the artifact as durable. Mirrors `node-pack-manifest.schema.json#/$defs/PackNode/properties/artifact/properties/syncOn`. Default `completion`."
159
+ },
160
+ "supportsCheckpoint": {
161
+ "type": "boolean",
162
+ "description": "True if the artifact participates in checkpoint/resume. Mirrors the `PackNode.artifact.supportsCheckpoint` field."
163
+ },
164
+ "versionable": {
165
+ "type": "boolean",
166
+ "description": "True if the host SHOULD retain prior versions of the artifact. Non-normative storage hint."
167
+ },
168
+ "diffable": {
169
+ "type": "boolean",
170
+ "description": "True if the artifact's schema supports structural diffing (informs run-diff tooling per rest-endpoints.md §:diff). Non-normative."
171
+ }
172
+ },
173
+ "patternProperties": {
174
+ "^(x-|vendor\\.)": {
175
+ "description": "Vendor / host extension escape hatch (RFC 0138). A property matching `^(x-|vendor\\.)` is a HOST EXTENSION: its semantics are unspecified by this protocol, and a consumer that does not recognize one MUST ignore it rather than reject the pack. Resolves the contradiction in `host-extensions.md` §\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque — a field that `additionalProperties: false` previously made impossible to carry. SECURITY: an extension value is PACK-AUTHORED, therefore untrusted; \"ignore\" means ignore. See `node-packs.md` §\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
176
+ }
177
+ }
178
+ },
179
+ "RenderingHint": {
180
+ "type": "object",
181
+ "additionalProperties": false,
182
+ "description": "Advisory rendering hint. Reuses the closed vocabulary defined in ai-envelope.md §\"Rendering hints\" (RFC 0055). Advisory only — consumers MUST degrade gracefully and MUST NOT treat this as a validation input. The `card` display value is reserved for envelopes and is excluded here (durable artifacts are not transient chat cards).",
183
+ "properties": {
184
+ "display": {
185
+ "type": "string",
186
+ "enum": [
187
+ "markdown",
188
+ "code",
189
+ "image",
190
+ "audio",
191
+ "file"
192
+ ],
193
+ "description": "How a consumer SHOULD render the artifact when it recognizes the value."
194
+ },
195
+ "mimeType": {
196
+ "type": "string",
197
+ "maxLength": 255
198
+ },
199
+ "lang": {
200
+ "type": "string",
201
+ "maxLength": 64,
202
+ "description": "Language hint for `display: code`."
203
+ },
204
+ "alt": {
205
+ "type": "string",
206
+ "maxLength": 1024,
207
+ "description": "Accessibility text for image/audio/file."
208
+ },
209
+ "title": {
210
+ "type": "string",
211
+ "maxLength": 255
212
+ }
213
+ }
214
+ },
215
+ "Signing": {
216
+ "type": "object",
217
+ "description": "Optional signing metadata. See node-packs.md §signing.",
218
+ "additionalProperties": false,
219
+ "properties": {
220
+ "publicKeyRef": {
221
+ "type": "string",
222
+ "description": "Path inside the tarball to the Ed25519 public key (PEM-encoded)."
223
+ },
224
+ "signatureRef": {
225
+ "type": "string",
226
+ "description": "Path to the detached signature over `pack.json`."
227
+ },
228
+ "method": {
229
+ "type": "string",
230
+ "enum": [
231
+ "manual",
232
+ "sigstore"
233
+ ],
234
+ "description": "Signing method. `manual` uses publicKeyRef + signatureRef; `sigstore` uses a Sigstore bundle at `pack.json.sigstore`."
235
+ }
236
+ }
237
+ }
238
+ },
239
+ "patternProperties": {
240
+ "^(x-|vendor\\.)": {
241
+ "description": "Vendor / host extension escape hatch (RFC 0138). A property matching `^(x-|vendor\\.)` is a HOST EXTENSION: its semantics are unspecified by this protocol, and a consumer that does not recognize one MUST ignore it rather than reject the pack. Resolves the contradiction in `host-extensions.md` §\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque — a field that `additionalProperties: false` previously made impossible to carry. SECURITY: an extension value is PACK-AUTHORED, therefore untrusted; \"ignore\" means ignore. See `node-packs.md` §\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
242
+ }
243
+ }
244
+ }
@@ -0,0 +1,90 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/audit-verify-result.schema.json",
4
+ "title": "AuditVerifyResult",
5
+ "description": "Response payload from `GET /v1/audit/verify` per spec/v1/auth-profiles.md §`openwop-audit-log-integrity` §4 'Verification endpoint'. Hosts advertising the audit-log-integrity profile MUST return this shape on the verify endpoint when called with a valid `audit:read`-scoped credential. The shape carries the verifier's chain-validity verdict, the in-range signed checkpoints, and any anomaly records the verifier detected while re-walking the hash chain.",
6
+ "type": "object",
7
+ "required": ["fromSeq", "toSeq", "chainValid", "checkpoints", "anomalies"],
8
+ "properties": {
9
+ "fromSeq": {
10
+ "type": "integer",
11
+ "minimum": 0,
12
+ "description": "Echo of the caller's `fromSeq` query parameter. The verifier MUST re-walk entries [fromSeq, toSeq] inclusive."
13
+ },
14
+ "toSeq": {
15
+ "type": "integer",
16
+ "minimum": 0,
17
+ "description": "Echo of the caller's `toSeq` query parameter. MUST be >= fromSeq."
18
+ },
19
+ "chainValid": {
20
+ "type": "boolean",
21
+ "description": "True when every entry's `prevHash` matches the SHA-256 of the prior entry's RFC 8785 JCS canonicalization AND every signed checkpoint in `checkpoints[]` verifies against the host's advertised `auditLogIntegrity.checkpointPublicKey`. False when ANY break or invalid signature is detected; `anomalies[]` enumerates the breaks."
22
+ },
23
+ "checkpointsValid": {
24
+ "type": "boolean",
25
+ "description": "OPTIONAL companion bit: true when every checkpoint signature in `checkpoints[]` verifies. Distinguishes 'chain broken but checkpoints OK' from 'checkpoints forged but chain intact'. Hosts MAY omit when `chainValid` already conveys the verdict; clients that distinguish the two failure modes SHOULD prefer hosts that surface this bit explicitly."
26
+ },
27
+ "checkpoints": {
28
+ "type": "array",
29
+ "description": "Signed checkpoints emitted within [fromSeq, toSeq]. Order: ascending by `atSequence`. Empty array MUST appear when no checkpoint was emitted in the window (not omitted).",
30
+ "items": { "$ref": "#/$defs/Checkpoint" }
31
+ },
32
+ "anomalies": {
33
+ "type": "array",
34
+ "description": "One entry per detected hash-chain break in [fromSeq, toSeq]. Empty array MUST appear when chainValid is true (not omitted).",
35
+ "items": { "$ref": "#/$defs/Anomaly" }
36
+ }
37
+ },
38
+ "additionalProperties": false,
39
+ "$defs": {
40
+ "Checkpoint": {
41
+ "type": "object",
42
+ "required": ["checkpoint", "atSequence", "merkleRoot", "signature"],
43
+ "properties": {
44
+ "checkpoint": {
45
+ "type": "string",
46
+ "minLength": 1,
47
+ "maxLength": 256,
48
+ "description": "Host-issued checkpoint id. Globally unique within the host's audit log."
49
+ },
50
+ "atSequence": {
51
+ "type": "integer",
52
+ "minimum": 0,
53
+ "description": "Audit-log sequence number at which the checkpoint was minted. Inclusive — the entry at this sequence is covered by the checkpoint's merkleRoot."
54
+ },
55
+ "merkleRoot": {
56
+ "type": "string",
57
+ "minLength": 1,
58
+ "description": "Hex-encoded SHA-256 Merkle root over the canonicalized entries 0..atSequence inclusive. Verifiers re-compute and compare; mismatch implies chain mutation between two checkpoints."
59
+ },
60
+ "signature": {
61
+ "type": "string",
62
+ "minLength": 1,
63
+ "description": "Base64-encoded Ed25519 signature over the checkpoint's canonical JSON (excluding the `signature` field itself), produced with the host's advertised `auditLogIntegrity.checkpointPublicKey`."
64
+ }
65
+ },
66
+ "additionalProperties": false
67
+ },
68
+ "Anomaly": {
69
+ "type": "object",
70
+ "required": ["atSeq", "expectedPrevHash", "actualPrevHash"],
71
+ "properties": {
72
+ "atSeq": {
73
+ "type": "integer",
74
+ "minimum": 0,
75
+ "description": "Sequence number of the entry whose `prevHash` failed verification."
76
+ },
77
+ "expectedPrevHash": {
78
+ "type": "string",
79
+ "minLength": 1,
80
+ "description": "Hex-encoded SHA-256 the verifier computed from the prior entry's RFC 8785 JCS canonicalization."
81
+ },
82
+ "actualPrevHash": {
83
+ "type": "string",
84
+ "description": "The `prevHash` value the audit-log entry actually carries. Empty string when the field is missing (a structural anomaly distinct from a hash mismatch)."
85
+ }
86
+ },
87
+ "additionalProperties": false
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openwop.dev/spec/v1/budget-policy.schema.json",
4
+ "title": "BudgetPolicy",
5
+ "description": "RFC 0084 §A. The reserved `budget` run-options key (on `RunOptions.configurable`) — an enforceable per-run SPEND policy. Wall-time + loop-iterations are deliberately NOT here: those are RFC 0058's `runTimeoutMs` / `maxLoopIterations` (the §E orthogonality seam). 0084 governs spend; 0058 governs execution bounds; they share only the `cap.breached` overflow event. Every dimension is optional; an absent dimension is unbounded (host default).",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "maxTokens": { "type": "integer", "minimum": 1, "description": "Total input+output tokens across all `provider.usage` (RFC 0026) in the run." },
10
+ "maxCostUsd": { "type": "number", "minimum": 0, "description": "Total cost summed from `provider.usage` `costEstimateUsd` (host-defined pricing per RFC 0026)." },
11
+ "maxToolCalls": { "type": "integer", "minimum": 1, "description": "Total `agent.toolCalled` events in the run." },
12
+ "maxRetries": { "type": "integer", "minimum": 0, "description": "Ceiling over the cumulative RFC 0009 retry count (node + envelope retries); the run fails when cumulative retries hit it. NOT a separate retry mechanism (RFC 0084 §UQ4)." },
13
+ "modelAllow": { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "description": "Optional allowlist (glob over provider model ids, e.g. `claude-*`). A run resolving to a model outside the allowlist is refused with `budget_model_denied` before the call." },
14
+ "modelDeny": { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "description": "Optional denylist. `modelDeny` wins on conflict with `modelAllow` (fail-closed)." },
15
+ "thresholdPercent": { "type": "number", "minimum": 0, "maximum": 100, "description": "Emit `budget.threshold.crossed` once per dimension at this percent of the dimension's limit." },
16
+ "onExhaustion": { "type": "string", "enum": ["fail", "interrupt"], "description": "`fail` (default): `cap.breached{kind:\"budget-*\"}` → `run.failed{budget_exhausted}`. `interrupt`: raise an RFC 0051 approval interrupt so a human MAY extend the budget." }
17
+ }
18
+ }