@openwop/spec-artifacts 2.35.1 → 2.36.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 (101) hide show
  1. package/CORPUS-STAMP.json +103 -89
  2. package/api/openapi.yaml +325 -4
  3. package/api/seams-v2.yaml +342 -1
  4. package/api/v2/asyncapi.yaml +1 -1
  5. package/api/v2/openapi.yaml +564 -8
  6. package/package.json +1 -1
  7. package/schemas/a2a-task-state.schema.json +3 -3
  8. package/schemas/artifact-type-pack-manifest.schema.json +3 -3
  9. package/schemas/capabilities.schema.json +34 -1
  10. package/schemas/connection-pack-manifest.schema.json +14 -0
  11. package/schemas/debug-bundle.schema.json +20 -0
  12. package/schemas/dispatch-config.schema.json +1 -1
  13. package/schemas/localized-content-language-settings.schema.json +3 -3
  14. package/schemas/localized-content-page.schema.json +2 -2
  15. package/schemas/localized-content-section.schema.json +3 -3
  16. package/schemas/run-event-payloads.schema.json +4 -2
  17. package/schemas/suspend-request.schema.json +61 -4
  18. package/schemas/v2/a2a-task-state.schema.json +10 -9
  19. package/schemas/v2/agent-deployment-transition.schema.json +4 -4
  20. package/schemas/v2/agent-deployment.schema.json +7 -7
  21. package/schemas/v2/agent-eval-suite.schema.json +10 -10
  22. package/schemas/v2/agent-inventory-response.schema.json +8 -2
  23. package/schemas/v2/artifact-type-pack-manifest.schema.json +3 -3
  24. package/schemas/v2/artifact.schema.json +84 -0
  25. package/schemas/v2/capabilities.schema.json +82 -8
  26. package/schemas/v2/certification-bundle.schema.json +1 -1
  27. package/schemas/v2/channel-presence-payload.schema.json +3 -3
  28. package/schemas/v2/connection-pack-manifest.schema.json +14 -0
  29. package/schemas/v2/conversation-event.schema.json +9 -2
  30. package/schemas/v2/conversation-turn.schema.json +19 -12
  31. package/schemas/v2/dispatch-config.schema.json +1 -1
  32. package/schemas/v2/envelopes/ui.a2ui-surface.schema.json +920 -22
  33. package/schemas/v2/error-envelope.schema.json +11 -1
  34. package/schemas/v2/eval-summary.schema.json +1 -2
  35. package/schemas/v2/goal.schema.json +4 -4
  36. package/schemas/v2/localized-content-language-settings.schema.json +3 -3
  37. package/schemas/v2/localized-content-page.schema.json +2 -2
  38. package/schemas/v2/localized-content-section.schema.json +3 -3
  39. package/schemas/v2/node-pack-manifest.schema.json +105 -0
  40. package/schemas/v2/part.schema.json +81 -0
  41. package/schemas/v2/proposal.schema.json +6 -6
  42. package/schemas/v2/run-event-payloads.schema.json +5 -3
  43. package/schemas/v2/self-hosted-runner-dispatch-frame.schema.json +2 -2
  44. package/schemas/v2/self-hosted-runner-result-frame.schema.json +1 -1
  45. package/schemas/v2/suspend-request.schema.json +251 -6
  46. package/schemas/v2/tool-descriptor.schema.json +246 -2
  47. package/schemas/v2/trigger-event.schema.json +1 -2
  48. package/schemas/v2/trigger-subscription.schema.json +1 -2
  49. package/schemas/v2/webhook-verification.schema.json +22 -0
  50. package/schemas/v2/workflow-definition.schema.json +25 -25
  51. package/spec/v1/alias-detectors.json +13 -1
  52. package/spec/v1/core-standard-manifest.json +2 -2
  53. package/spec/v1/deprecations.json +45 -1
  54. package/spec/v1/deprecations.schema.json +119 -4
  55. package/spec/v1/gaps.json +1925 -4
  56. package/spec/v2/README.md +5 -2
  57. package/spec/v2/core/capabilities.md +13 -26
  58. package/spec/v2/core/conformance.md +5 -8
  59. package/spec/v2/core/connection-packs.md +1 -1
  60. package/spec/v2/core/conversation.md +1 -1
  61. package/spec/v2/core/errors.md +8 -3
  62. package/spec/v2/core/events.md +8 -20
  63. package/spec/v2/core/form-content-packs.md +2 -2
  64. package/spec/v2/core/headers.md +5 -4
  65. package/spec/v2/core/host-services.md +6 -2
  66. package/spec/v2/core/idempotency.md +1 -1
  67. package/spec/v2/core/identity.md +23 -12
  68. package/spec/v2/core/interop.md +34 -4
  69. package/spec/v2/core/interrupt.md +6 -3
  70. package/spec/v2/core/node-pack-runtimes.md +20 -0
  71. package/spec/v2/core/oauth.md +32 -0
  72. package/spec/v2/core/overview.md +19 -6
  73. package/spec/v2/core/packs.md +4 -6
  74. package/spec/v2/core/persistence.md +20 -55
  75. package/spec/v2/core/replay.md +5 -11
  76. package/spec/v2/core/runs.md +9 -8
  77. package/spec/v2/core/security-defaults.md +18 -20
  78. package/spec/v2/core/tool-catalog.md +22 -0
  79. package/spec/v2/core/versioning.md +10 -28
  80. package/spec/v2/core/webhooks.md +16 -4
  81. package/spec/v2/core/workflow-chain-packs.md +1 -1
  82. package/spec/v2/corrections.json +32 -0
  83. package/spec/v2/corrections.schema.json +49 -0
  84. package/spec/v2/declaration.json +18 -13
  85. package/spec/v2/declaration.schema.json +3 -1
  86. package/spec/v2/errors.json +46 -1
  87. package/spec/v2/ext/a2uiSurface/README.md +131 -17
  88. package/spec/v2/ext/dataIntegration/README.md +5 -0
  89. package/spec/v2/facets/a2a.schema.json +4 -0
  90. package/spec/v2/facets/auth.schema.json +24 -0
  91. package/spec/v2/facets/mcp.schema.json +4 -0
  92. package/spec/v2/facets/oauth.schema.json +70 -0
  93. package/spec/v2/facets/webhooks.schema.json +23 -2
  94. package/spec/v2/id-field-bindings.json +2 -0
  95. package/spec/v2/interop-map.json +639 -0
  96. package/spec/v2/interop-map.schema.json +458 -0
  97. package/spec/v2/migrations.json +7 -0
  98. package/spec/v2/migrations.schema.json +58 -0
  99. package/spec/v2/path-manifest.json +6 -1
  100. package/spec/v2/release.json +3 -3
  101. package/spec/v2/surface-baseline.json +7981 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/spec-artifacts",
3
- "version": "2.35.1",
3
+ "version": "2.36.0",
4
4
  "description": "The OpenWOP machine-readable contract: api/ (OpenAPI, AsyncAPI, the seams profile), schemas/ (v1 and v2 JSON Schemas), the spec/v1 and spec/v2 registries (errors, event codemap, declaration, deprecations, migrations, gaps) and CORPUS-STAMP.json — published from the openwop/openwop corpus tag; the peer dependency @openwop/openwop-conformance digest-checks at start (RFC 0168 §D.2).",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -24,12 +24,12 @@
24
24
  "state": {
25
25
  "type": "string",
26
26
  "enum": ["submitted", "working", "input-required", "auth-required", "completed", "failed", "canceled", "rejected"],
27
- "description": "The A2A 0.3 JSON-RPC wire form (lowercase-hyphen — a2a-integration.md §'Wire-shape spelling drift'). Projected from `run.status` per a2a-integration.md §'State projection (forward)': pending→submitted, running→working, paused→working, waiting-approval/waiting-input→input-required, completed→completed, failed→failed, cancelled→canceled. `auth-required` is carried for reverse-direction fidelity only; the forward projection never sets it (openwop has no native auth interrupt — a2a-integration.md drift point #3)."
27
+ "description": "The canonical stored vocabulary: lowercase-hyphen, the spelling A2A 0.3's JSON-RPC binding uses (a2a-integration.md §'Wire-shape spelling drift'). An A2A 1.0 interface renders it as `TASK_STATE_*` at the boundary through the a2a-integration.md §D.4 bijection; the stored form does not change. Projected from `run.status` per a2a-integration.md §'State projection (forward)' and §D.4: pending→submitted; running, paused and cancelling (RFC 0094, until terminal)→working; waiting-approval, waiting-input and waiting-external→input-required; completed→completed; failed→failed; cancelled→canceled. `auth-required` is set by the forward projection only for a run suspended on a `credential` interrupt (RFC 0199 §D.1; a2a-integration.md drift point #3 is retired for the forward direction) and is otherwise carried for reverse-direction fidelity."
28
28
  },
29
29
  "interruptKind": {
30
30
  "type": "string",
31
- "enum": ["approval", "clarification"],
32
- "description": "Present iff `state == 'input-required'`. Disambiguates a2a-integration.md drift point #2 (both approval + clarification project to INPUT_REQUIRED) — carried in `Task.metadata.openwop.interrupt.kind`, the `metadata.openwop.*` shape the doc's Future-work asks to codify."
31
+ "enum": ["approval", "clarification", "credential"],
32
+ "description": "Present iff `state` is `input-required` or `auth-required`; `credential` ⇔ `auth-required` in the forward direction (RFC 0199 §D.1) — a rule stated in the prose of a2a-integration.md §'The durable Task projection record'; this schema does not enforce it (the field is not in `required` and there is no conditional). Disambiguates a2a-integration.md drift point #2 (approval and clarification both project to INPUT_REQUIRED) — carried in `Task.metadata.openwop.interrupt.kind`, the `metadata.openwop.*` shape the doc's Future-work asks to codify. The enum names only `approval`, `clarification` and `credential`: a `waiting-external` run, which also projects to input-required, has no value here, and its kind is disambiguated by the `metadata.openwop.interrupt.kind` carrier alone."
33
33
  },
34
34
  "updatedAt": {
35
35
  "type": "string",
@@ -142,11 +142,11 @@
142
142
  "items": {
143
143
  "type": "string",
144
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-]*)$"
145
+ "maxLength": 255,
146
+ "pattern": "^([a-z][a-z0-9]*|vendor\\.[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*|x-[a-z][a-z0-9-]*|[a-z0-9][a-z0-9!#$&^_.+-]{0,126}/[a-z0-9][a-z0-9!#$&^_.+-]{0,126})$"
147
147
  },
148
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."
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). An entry MAY instead be a lowercase RFC 6838 media type (`type/subtype`, no parameters; RFC 0205 §C); each reserved alias names exactly one media type per artifact-type-packs.md §\"Export-format aliases\", and a consumer MUST treat the two spellings as one format. 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
150
  },
151
151
  "syncOn": {
152
152
  "type": "string",
@@ -877,6 +877,10 @@
877
877
  "uniqueItems": true,
878
878
  "description": "OAuth 2.0 grant types the host performs on a node's behalf."
879
879
  },
880
+ "credentialInterrupt": {
881
+ "type": "boolean",
882
+ "description": "RFC 0199 §C. The host suspends a node on a `credential` interrupt instead of failing it when no credential resolves or refresh fails terminally. Absent ⇒ RFC 0047 §C.3 (fail the node with `connector_auth_expired`)."
883
+ },
880
884
  "providers": {
881
885
  "type": "array",
882
886
  "description": "Provider catalog the host can acquire tokens for. A connector node's `auth.provider` MUST match an `id` here.",
@@ -907,6 +911,19 @@
907
911
  "type": "string"
908
912
  },
909
913
  "description": "Scopes this provider exposes."
914
+ },
915
+ "issuer": {
916
+ "type": "string",
917
+ "format": "uri",
918
+ "description": "RFC 0199 §A.4. The provider's authorization-server issuer identifier (RFC 8414 / RFC 9207). Absent ⇒ the host uses a provider-unique redirect URI (RFC 9700 §4.4.2.2)."
919
+ },
920
+ "pkce": {
921
+ "type": "string",
922
+ "enum": [
923
+ "S256",
924
+ "unsupported"
925
+ ],
926
+ "description": "RFC 0199 §A.1. Absent or `S256` ⇒ the host sends PKCE S256. `unsupported` ⇒ the host sends no PKCE for this provider; such a provider cannot back an MCP reach (§B.2)."
910
927
  }
911
928
  },
912
929
  "additionalProperties": false
@@ -2741,11 +2758,27 @@
2741
2758
  "type": "string"
2742
2759
  },
2743
2760
  "uniqueItems": true,
2744
- "description": "HMAC signature algorithm ids the host supports (e.g. `v1`)."
2761
+ "description": "HMAC signature algorithm ids the host supports (e.g. `v1`). `standard-webhooks-1` (RFC 0201) names the Standard Webhooks 1.0.0 companion scheme a subscriber opts into per subscription; it is listed only beside `v1`."
2745
2762
  },
2746
2763
  "durable": {
2747
2764
  "type": "boolean",
2748
2765
  "description": "RFC 0083 §A — OPTIONAL opt-in. `true` ⇒ webhook delivery is durable (a trigger-bridge source); absent/`false` ⇒ the best-effort `webhooks.md` contract, unchanged. The best-effort default is NOT relaxed."
2766
+ },
2767
+ "secretRotation": {
2768
+ "type": "object",
2769
+ "additionalProperties": false,
2770
+ "required": [
2771
+ "overlapSeconds"
2772
+ ],
2773
+ "description": "RFC 0201 §E — zero-downtime secret rotation for subscriptions opted into `standard-webhooks-1`. Advertised only by a host that serves `POST /v1/webhooks/{webhookId}/rotate-secret`.",
2774
+ "properties": {
2775
+ "overlapSeconds": {
2776
+ "type": "integer",
2777
+ "minimum": 60,
2778
+ "maximum": 604800,
2779
+ "description": "How long after a rotation `webhook-signature` carries an entry under the previous secret beside the new one."
2780
+ }
2781
+ }
2749
2782
  }
2750
2783
  }
2751
2784
  },
@@ -218,6 +218,20 @@
218
218
  "instanceUrlTemplate": {
219
219
  "type": "string",
220
220
  "description": "For per-account-host providers (Snowflake/NetSuite/ServiceNow): a template the host fills per connection, e.g. `https://{account}.snowflakecomputing.com`. Its presence signals the provider cannot use a single global OAuth app."
221
+ },
222
+ "issuer": {
223
+ "type": "string",
224
+ "format": "uri",
225
+ "pattern": "^https://",
226
+ "description": "RFC 0199 §A.4/§B.3. The authorization server's issuer identifier. Fixed and manifest-declared, like `endpoints`. OPTIONAL in the schema; a host MUST NOT authorize a `reach.mcp` + `oauth2` provider whose manifest omits it (refused `connection_auth_metadata_mismatch` before any authorization URL is issued)."
227
+ },
228
+ "pkce": {
229
+ "type": "string",
230
+ "enum": [
231
+ "S256",
232
+ "unsupported"
233
+ ],
234
+ "description": "RFC 0199 §A.1. Absent or `S256` ⇒ the host sends PKCE S256. `unsupported` ⇒ no PKCE; a host MUST NOT authorize such a provider when it is reached as an MCP server (§B.2)."
221
235
  }
222
236
  }
223
237
  },
@@ -122,7 +122,27 @@
122
122
  "required": ["name"],
123
123
  "properties": {
124
124
  "name": { "type": "string", "minLength": 1 },
125
+ "traceId": {
126
+ "type": "string",
127
+ "pattern": "^[0-9a-f]{32}$",
128
+ "not": { "const": "00000000000000000000000000000000" },
129
+ "description": "RFC 0207 §C — W3C Trace Context / OTLP 16-byte trace id (32 lowercase hex) of the trace this span belongs to. SHOULD be present when the span was recorded in a trace; when present it MUST equal that trace's id."
130
+ },
125
131
  "spanId": { "type": "string" },
132
+ "kind": {
133
+ "enum": ["internal", "server", "client", "producer", "consumer"],
134
+ "description": "RFC 0207 §C — OTLP SPAN_KIND_* 1–5, lowercased. Absent means unspecified."
135
+ },
136
+ "status": {
137
+ "type": "object",
138
+ "required": ["code"],
139
+ "properties": {
140
+ "code": { "enum": ["unset", "ok", "error"] },
141
+ "message": { "type": "string" }
142
+ },
143
+ "additionalProperties": false,
144
+ "description": "RFC 0207 §C — OTLP Status (STATUS_CODE_* 0–2). message is redacted like every attribute."
145
+ },
126
146
  "parentSpanId": {
127
147
  "oneOf": [{ "type": "string" }, { "type": "null" }]
128
148
  },
@@ -16,7 +16,7 @@
16
16
  "type": "string",
17
17
  "enum": ["child-run"],
18
18
  "default": "child-run",
19
- "description": "How `kind: 'next-worker'` is dispatched. v1.x normates only `'child-run'` — each `nextWorkerIds[i]` resolves to a workflow id and is dispatched as a child run via the existing `core.subWorkflow` machinery. Same-run DAG navigation is OUT OF SCOPE for v1.x (deferred to RFC 0013 / v1.3+). Hosts MAY add vendor-extension dispatch models under `vendor.<host>.<model>`; conformance scenarios validate `'child-run'` only."
19
+ "description": "How `kind: 'next-worker'` is dispatched. v1.x normates only `'child-run'` — each `nextWorkerIds[i]` resolves to a workflow id and is dispatched as a child run via the existing `core.subWorkflow` machinery. Same-run DAG navigation is OUT OF SCOPE for v1.x (deferred to RFC 0013 / v1.3+). The enum is closed: any other value, including a `vendor.<host>.<model>` name, fails validation against this schema, so a host cannot add a dispatch model without an additive schema change. Conformance scenarios validate `'child-run'` only."
20
20
  },
21
21
  "fanOutPolicy": {
22
22
  "type": "string",
@@ -9,13 +9,13 @@
9
9
  "properties": {
10
10
  "baseLocale": {
11
11
  "type": "string",
12
- "pattern": "^[a-z]{2}(-[A-Z]{2})?$",
12
+ "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$",
13
13
  "description": "The locale section `data` is authored in. MUST equal `capabilities.i18n.defaultLocale`."
14
14
  },
15
15
  "supportedLocales": {
16
16
  "type": "array",
17
- "description": "BCP-47 tags the tenant authors content translations for. MUST NOT contain `baseLocale`.",
18
- "items": { "type": "string", "pattern": "^[a-z]{2}(-[A-Z]{2})?$" },
17
+ "description": "Case-canonical BCP 47 tags (RFC 0206 §A) the tenant authors content translations for. MUST NOT contain `baseLocale`.",
18
+ "items": { "type": "string", "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$" },
19
19
  "uniqueItems": true
20
20
  },
21
21
  "autoTranslateOnPublish": {
@@ -45,7 +45,7 @@
45
45
  "additionalProperties": false,
46
46
  "required": ["locale", "href"],
47
47
  "properties": {
48
- "locale": { "type": "string", "pattern": "^[a-z]{2}(-[A-Z]{2})?$" },
48
+ "locale": { "type": "string", "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$" },
49
49
  "href": { "type": "string", "format": "uri" }
50
50
  }
51
51
  }
@@ -53,7 +53,7 @@
53
53
  "ogLocaleAlternates": {
54
54
  "type": "array",
55
55
  "description": "og:locale:alternate values.",
56
- "items": { "type": "string", "pattern": "^[a-z]{2}(-[A-Z]{2})?$" },
56
+ "items": { "type": "string", "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$" },
57
57
  "uniqueItems": true
58
58
  }
59
59
  }
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openwop.dev/spec/v1/localized-content-section.schema.json",
4
4
  "title": "LocalizedContentSection",
5
- "description": "RFC 0103 (spec/v1/localized-content.md §B). One section record of an authored content page. A section is ONE record carrying a base `data` payload (authored in the host's `content.baseLocale`) plus a sparse `localizations` map of partial per-locale field overrides — never one record per locale. The negotiated locale's resolved body is computed by the normative per-section field merge (exact-locale → language-family → base `data`, shallow overlay; §C). Body field shapes inside `data`/`localizations` are open and host/section-type-defined; this schema closes the envelope, not the body.",
5
+ "description": "RFC 0103 (spec/v1/localized-content.md §B). One section record of an authored content page. A section is ONE record carrying a base `data` payload (authored in the host's `content.baseLocale`) plus a sparse `localizations` map of partial per-locale field overrides — never one record per locale. The negotiated locale's resolved body is computed by the normative per-section field merge (exact-locale → script-family (RFC 0206) → language-family → base `data`, shallow overlay; §C). Body field shapes inside `data`/`localizations` are open and host/section-type-defined; this schema closes the envelope, not the body.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "required": ["sectionId", "sectionType", "data", "localizations", "status", "enabled", "order"],
@@ -24,9 +24,9 @@
24
24
  },
25
25
  "localizations": {
26
26
  "type": "object",
27
- "description": "Sparse map of per-locale partial field overrides. MAY be empty (`{}`). Each key is a BCP-47 tag matching `^[a-z]{2}(-[A-Z]{2})?$` and MUST NOT equal `content.baseLocale` (the base locale is carried by `data`). Each value is a partial overlay of `data` fields; missing fields fall through to `data` (per-section merge §C).",
27
+ "description": "Sparse map of per-locale partial field overrides. MAY be empty (`{}`). Each key is a case-canonical BCP 47 tag (language, optional script, optional region; RFC 0206 §A) matching `^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$` and MUST NOT equal `content.baseLocale` (the base locale is carried by `data`). Each value is a partial overlay of `data` fields; missing fields fall through to `data` (per-section merge §C).",
28
28
  "propertyNames": {
29
- "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
29
+ "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$"
30
30
  },
31
31
  "additionalProperties": {
32
32
  "type": "object",
@@ -1263,7 +1263,8 @@
1263
1263
  "conversation.start",
1264
1264
  "conversation.exchange",
1265
1265
  "conversation.close",
1266
- "low-confidence"
1266
+ "low-confidence",
1267
+ "credential"
1267
1268
  ],
1268
1269
  "description": "RFC 0094 \u00a7E \u2014 the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1269
1270
  },
@@ -1673,7 +1674,8 @@
1673
1674
  "conversation.start",
1674
1675
  "conversation.exchange",
1675
1676
  "conversation.close",
1676
- "low-confidence"
1677
+ "low-confidence",
1678
+ "credential"
1677
1679
  ],
1678
1680
  "description": "RFC 0094 \u00a7E \u2014 the full kind union `interrupt.md` defines (mirrors suspend-request.schema.json). Conversation kinds are gated on the conversation capability per capabilities.md."
1679
1681
  },
@@ -8,8 +8,8 @@
8
8
  "properties": {
9
9
  "kind": {
10
10
  "type": "string",
11
- "enum": ["approval", "clarification", "external-event", "custom", "conversation.start", "conversation.exchange", "conversation.close", "low-confidence"],
12
- "description": "Discriminator for resume-time routing + UI rendering + observability. Multi-Agent Shift Phase 4 adds `conversation.start` / `conversation.exchange` / `conversation.close` for multi-turn user interjections (see ConversationStartData / ConversationExchangeData / ConversationCloseData below). Phase 1 adds `low-confidence` for the confidence-escalation contract (orchestrator-supervisor suspends below threshold; see LowConfidenceData)."
11
+ "enum": ["approval", "clarification", "external-event", "custom", "conversation.start", "conversation.exchange", "conversation.close", "low-confidence", "credential"],
12
+ "description": "Discriminator for resume-time routing + UI rendering + observability. Multi-Agent Shift Phase 4 adds `conversation.start` / `conversation.exchange` / `conversation.close` for multi-turn user interjections (see ConversationStartData / ConversationExchangeData / ConversationCloseData below). Phase 1 adds `low-confidence` for the confidence-escalation contract (orchestrator-supervisor suspends below threshold; see LowConfidenceData). RFC 0199 adds `credential` (see CredentialData), gated on `oauth.credentialInterrupt`."
13
13
  },
14
14
  "key": {
15
15
  "type": "string",
@@ -27,7 +27,8 @@
27
27
  "description": "Optional auto-reject after this duration. Engine throws InterruptTimeoutError when exceeded."
28
28
  },
29
29
  "data": {
30
- "oneOf": [
30
+ "description": "Discriminated payload data. The union below lists every per-kind shape; the root `allOf` binds each `kind` to exactly one of them (`interrupt.md` §Per-kind payloads). `anyOf`, not `oneOf`: the shapes are not mutually exclusive by content — a minimal `conversation.start` and `conversation.close` payload are both `{ conversationId }` — so `kind`, not the data, is the discriminator. Before 2.36.0 this was an unbound `oneOf`, which rejected those two minimal payloads and accepted a payload whose `data` matched a different kind's shape (COMPATIBILITY.md §3, 2026-09-22).",
31
+ "anyOf": [
31
32
  { "$ref": "#/$defs/ApprovalData" },
32
33
  { "$ref": "#/$defs/ClarificationData" },
33
34
  { "$ref": "#/$defs/ExternalEventData" },
@@ -35,11 +36,24 @@
35
36
  { "$ref": "#/$defs/ConversationStartData" },
36
37
  { "$ref": "#/$defs/ConversationExchangeData" },
37
38
  { "$ref": "#/$defs/ConversationCloseData" },
38
- { "$ref": "#/$defs/LowConfidenceData" }
39
+ { "$ref": "#/$defs/LowConfidenceData" },
40
+ { "$ref": "#/$defs/CredentialData" }
39
41
  ]
40
42
  }
41
43
  },
42
44
  "additionalProperties": false,
45
+ "$comment": "Binds `data` to `kind`: one if/then per kind, so every kind accepts exactly its own per-kind shape and a payload whose `data` belongs to another kind fails.",
46
+ "allOf": [
47
+ { "if": { "properties": { "kind": { "const": "approval" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/ApprovalData" } } } },
48
+ { "if": { "properties": { "kind": { "const": "clarification" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/ClarificationData" } } } },
49
+ { "if": { "properties": { "kind": { "const": "external-event" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/ExternalEventData" } } } },
50
+ { "if": { "properties": { "kind": { "const": "custom" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/CustomData" } } } },
51
+ { "if": { "properties": { "kind": { "const": "conversation.start" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/ConversationStartData" } } } },
52
+ { "if": { "properties": { "kind": { "const": "conversation.exchange" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/ConversationExchangeData" } } } },
53
+ { "if": { "properties": { "kind": { "const": "conversation.close" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/ConversationCloseData" } } } },
54
+ { "if": { "properties": { "kind": { "const": "low-confidence" } }, "required": ["kind"] }, "then": { "properties": { "data": { "$ref": "#/$defs/LowConfidenceData" } } } },
55
+ { "if": { "properties": { "kind": { "const": "credential" } }, "required": ["kind"] }, "then": {"required": ["resumeSchema"], "properties": {"data": {"$ref": "#/$defs/CredentialData"}, "resumeSchema": {"const": {"type": "object", "additionalProperties": false, "required": ["outcome"], "properties": {"outcome": {"enum": ["authorized", "declined"]}}}}}} }
56
+ ],
43
57
  "$defs": {
44
58
  "ApprovalData": {
45
59
  "type": "object",
@@ -202,6 +216,49 @@
202
216
  "decision": { "description": "Optional sketch of the decision the agent WOULD have emitted at threshold-or-above. Lets operators see the un-ratified choice. Shape mirrors `OrchestratorDecision` or the agent's domain-specific decision type." }
203
217
  },
204
218
  "additionalProperties": false
219
+ },
220
+ "CredentialData": {
221
+ "type": "object",
222
+ "description": "Payload for kind='credential' (RFC 0199 §C.3). Closed: it names the provider, scopes and reason and carries the host-owned `connectUrl`; it NEVER carries credential material, the interrupt's token, or any value that resolves the interrupt. Gated on `oauth.credentialInterrupt`.",
223
+ "required": [
224
+ "provider",
225
+ "scopes",
226
+ "reason",
227
+ "connectUrl"
228
+ ],
229
+ "properties": {
230
+ "provider": {
231
+ "type": "string",
232
+ "minLength": 1,
233
+ "description": "An advertised `oauth.providers[].id`."
234
+ },
235
+ "scopes": {
236
+ "type": "array",
237
+ "items": {
238
+ "type": "string",
239
+ "minLength": 1
240
+ },
241
+ "uniqueItems": true
242
+ },
243
+ "reason": {
244
+ "enum": [
245
+ "missing",
246
+ "expired",
247
+ "insufficient_scope"
248
+ ]
249
+ },
250
+ "connectUrl": {
251
+ "type": "string",
252
+ "format": "uri",
253
+ "pattern": "^https://",
254
+ "description": "Host-owned https URL on the host's own origin that begins the authorization-code grant for the interrupt's initiating Subject. MUST NOT be pre-authenticated and MUST NOT embed the interrupt token."
255
+ },
256
+ "credentialRef": {
257
+ "$ref": "credential-reference.schema.json",
258
+ "description": "The reference being re-authorized; never material."
259
+ }
260
+ },
261
+ "additionalProperties": false
205
262
  }
206
263
  }
207
264
  }
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openwop.dev/spec/v2/a2a-task-state.schema.json",
4
4
  "title": "A2ATaskState",
5
- "description": "RFC 0100 \u00a72. The durable, persisted projection of an A2A `Task` an OpenWOP host keeps per backing run when it advertises `capabilities.a2a.durableTasks: true` \u2014 durable for the run's whole lifecycle (surviving caller disconnect, host restart within retention, and HITL pauses) so `tasks/get` returns live state after a disconnect. It is the persisted form of the `a2a-integration.md` \u00a7\"State projection (forward)\" mapping, NOT a new mapping. Content-free of run inputs/outputs/artifacts/credential material (SR-1 / `a2a-integration.md` trust boundary) \u2014 artifacts project to A2A `Artifact`s over the A2A transport, not into this record.",
5
+ "description": "RFC 0100 §2. The durable, persisted projection of an A2A `Task` an OpenWOP host keeps per backing run when it advertises `capabilities.a2a.durableTasks: true` — durable for the run's whole lifecycle (surviving caller disconnect, host restart within retention, and HITL pauses) so `tasks/get` returns live state after a disconnect. It is the persisted form of the `a2a-integration.md` §\"State projection (forward)\" mapping, NOT a new mapping. Content-free of run inputs/outputs/artifacts/credential material (SR-1 / `a2a-integration.md` trust boundary) — artifacts project to A2A `Artifact`s over the A2A transport, not into this record.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "required": [
@@ -15,7 +15,7 @@
15
15
  "taskId": {
16
16
  "type": "string",
17
17
  "minLength": 1,
18
- "description": "The A2A Task.id. MUST equal the backing OpenWOP `runId` (a2a-integration.md \u00a72 \u2014 'the returned runId becomes the A2A Task.id')."
18
+ "description": "The A2A Task.id. MUST equal the backing OpenWOP `runId` (a2a-integration.md §2 — 'the returned runId becomes the A2A Task.id')."
19
19
  },
20
20
  "runId": {
21
21
  "$ref": "ids.schema.json#/$defs/runId",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "contextId": {
25
25
  "type": "string",
26
- "description": "The A2A context_id (carried as the run tag `a2a:ctx_*` per a2a-integration.md \u00a72)."
26
+ "description": "The A2A context_id (carried as the run tag `a2a:ctx_*` per a2a-integration.md §2)."
27
27
  },
28
28
  "state": {
29
29
  "type": "string",
@@ -37,15 +37,16 @@
37
37
  "canceled",
38
38
  "rejected"
39
39
  ],
40
- "description": "The A2A 0.3 JSON-RPC wire form (lowercase-hyphen \u2014 a2a-integration.md \u00a7'Wire-shape spelling drift'). Projected from `run.status` per a2a-integration.md \u00a7'State projection (forward)': pending\u2192submitted, running\u2192working, paused\u2192working, waiting-approval/waiting-input\u2192input-required, completed\u2192completed, failed\u2192failed, cancelled\u2192canceled. `auth-required` is carried for reverse-direction fidelity only; the forward projection never sets it (openwop has no native auth interrupt \u2014 a2a-integration.md drift point #3)."
40
+ "description": "The canonical stored vocabulary: lowercase-hyphen, the spelling A2A 0.3's JSON-RPC binding uses (a2a-integration.md §'Wire-shape spelling drift'). An A2A 1.0 interface renders it as `TASK_STATE_*` at the boundary through the a2a-integration.md §D.4 bijection; the stored form does not change. Projected from `run.status` per a2a-integration.md §'State projection (forward)' and §D.4: pending→submitted; running, paused and cancelling (RFC 0094, until terminal)→working; waiting-approval, waiting-input and waiting-external→input-required; completed→completed; failed→failed; cancelled→canceled. `auth-required` is set by the forward projection only for a run suspended on a `credential` interrupt (RFC 0199 §D.1; a2a-integration.md drift point #3 is retired for the forward direction) and is otherwise carried for reverse-direction fidelity."
41
41
  },
42
42
  "interruptKind": {
43
43
  "type": "string",
44
44
  "enum": [
45
45
  "approval",
46
- "clarification"
46
+ "clarification",
47
+ "credential"
47
48
  ],
48
- "description": "Present iff `state == 'input-required'`. Disambiguates a2a-integration.md drift point #2 (both approval + clarification project to INPUT_REQUIRED) \u2014 carried in `Task.metadata.openwop.interrupt.kind`, the `metadata.openwop.*` shape the doc's Future-work asks to codify."
49
+ "description": "Present iff `state` is `input-required` or `auth-required`; `credential` ⇔ `auth-required` in the forward direction (RFC 0199 §D.1) — a rule stated in the prose of a2a-integration.md §'The durable Task projection record'; this schema does not enforce it (the field is not in `required` and there is no conditional). Disambiguates a2a-integration.md drift point #2 (approval and clarification both project to INPUT_REQUIRED) — carried in `Task.metadata.openwop.interrupt.kind`, the `metadata.openwop.*` shape the doc's Future-work asks to codify. The enum names only `approval`, `clarification` and `credential`: a `waiting-external` run, which also projects to input-required, has no value here, and its kind is disambiguated by the `metadata.openwop.interrupt.kind` carrier alone."
49
50
  },
50
51
  "updatedAt": {
51
52
  "type": "string",
@@ -63,17 +64,17 @@
63
64
  "required": [
64
65
  "url"
65
66
  ],
66
- "description": "RFC 0100 \u00a74. A caller-registered A2A push-notification config for this Task.",
67
+ "description": "RFC 0100 §4. A caller-registered A2A push-notification config for this Task.",
67
68
  "properties": {
68
69
  "url": {
69
70
  "type": "string",
70
71
  "format": "uri",
71
- "description": "Caller-registered push target. The host MUST validate it through the RFC 0093 webhook-egress SSRF guard before any push (no private/loopback/link-local target) \u2014 SECURITY invariant `a2a-push-egress-ssrf`."
72
+ "description": "Caller-registered push target. The host MUST validate it through the RFC 0093 webhook-egress SSRF guard before any push (no private/loopback/link-local target) — SECURITY invariant `a2a-push-egress-ssrf`."
72
73
  },
73
74
  "tokenFingerprint": {
74
75
  "type": "string",
75
76
  "maxLength": 32,
76
- "description": "MAY \u2014 a truncated/salted digest of the caller's push-auth token (NEVER the raw token; same SR-1 rule as RFC 0083's `secretFingerprint`). The A2A push HMAC details (A2A \u00a74.3.3) stay inside the A2A layer per a2a-integration.md."
77
+ "description": "MAY — a truncated/salted digest of the caller's push-auth token (NEVER the raw token; same SR-1 rule as RFC 0083's `secretFingerprint`). The A2A push HMAC details (A2A §4.3.3) stay inside the A2A layer per a2a-integration.md."
77
78
  }
78
79
  }
79
80
  }
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openwop.dev/spec/v2/agent-deployment-transition.schema.json",
4
4
  "title": "AgentDeploymentTransition",
5
- "description": "RFC 0082 \u00a7E. The request body of POST /agents/{agentId}/deployments \u2014 a deployment state-transition request. The host authorizes it fail-closed against the RFC 0049 `deploy:*` scope, runs any configured RFC 0051 approvalGate, enforces the RFC 0081 eval evidence when the gate requires it, and on success emits the matching `deployment.*` event and returns the updated `agent-deployment.schema.json` record. Carries no manifest body or credential material (SR-1).",
5
+ "description": "RFC 0082 §E. The request body of POST /agents/{agentId}/deployments — a deployment state-transition request. The host authorizes it fail-closed against the RFC 0049 `deploy:*` scope, runs any configured RFC 0051 approvalGate, enforces the RFC 0081 eval evidence when the gate requires it, and on success emits the matching `deployment.*` event and returns the updated `agent-deployment.schema.json` record. Carries no manifest body or credential material (SR-1).",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "required": [
@@ -24,7 +24,7 @@
24
24
  "rollback",
25
25
  "adjust-canary"
26
26
  ],
27
- "description": "The lifecycle operation. `promote`: advance toward production (draft\u2192test\u2192staged\u2192active) into `toState`. `pause`: active\u2192paused. `deprecate`: active\u2192deprecated. `rollback`: active\u2192rolled-back, restoring a prior version. `adjust-canary`: change the active version's `canaryPercent`. Legal transitions + the seven-state machine are normative in `agent-deployment.md` \u00a7C."
27
+ "description": "The lifecycle operation. `promote`: advance toward production (draft→test→staged→active) into `toState`. `pause`: active→paused. `deprecate`: active→deprecated. `rollback`: active→rolled-back, restoring a prior version. `adjust-canary`: change the active version's `canaryPercent`. Legal transitions + the seven-state machine are normative in `agent-deployment.md` §C."
28
28
  },
29
29
  "toState": {
30
30
  "type": "string",
@@ -43,7 +43,7 @@
43
43
  "type": "string",
44
44
  "minLength": 1,
45
45
  "maxLength": 64,
46
- "description": "MAY. The named deployment channel this transition targets (e.g. `stable`). The version becomes resolvable by `AgentRef.channel` = this value (RFC 0082 \u00a7A/\u00a7B)."
46
+ "description": "MAY. The named deployment channel this transition targets (e.g. `stable`). The version becomes resolvable by `AgentRef.channel` = this value (RFC 0082 §A/§B)."
47
47
  },
48
48
  "canaryPercent": {
49
49
  "type": "integer",
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "evalRunId": {
55
55
  "$ref": "ids.schema.json#/$defs/runId",
56
- "description": "MAY. The RFC 0081 eval run whose `EvalSummary.passed` the gate verifies before emitting `deployment.promoted` (the \u00a7E evidence). Required when the target `approvalGate` is configured with `requiredEval`; an unmet eval gate is rejected with `eval_gate_unmet`."
56
+ "description": "MAY. The RFC 0081 eval run whose `EvalSummary.passed` the gate verifies before emitting `deployment.promoted` (the §E evidence). Required when the target `approvalGate` is configured with `requiredEval`; an unmet eval gate is rejected with `eval_gate_unmet`."
57
57
  },
58
58
  "reason": {
59
59
  "type": "string",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openwop.dev/spec/v2/agent-deployment.schema.json",
4
4
  "title": "AgentDeployment",
5
- "description": "RFC 0082 \u00a7C. A per-(agentId, version) deployment record: the host-runtime lifecycle state of one version of a manifest agent (RFC 0003/0070), distinct from the immutable AgentManifest (which is the pack-distribution descriptor) and from the registry's published semver tags (which version EXISTS, not which version SERVES). Holds the deployment `state`, the named `channels` that resolve to this version, the canary traffic share, the rollback pointer, and the provenance (`evalRunId`/`approvalGateId`) of the last transition. Content-free of any manifest body or credential material (SR-1). The record itself is host-internal; this schema is the canonical wire shape a host exposes via GET /agents/{agentId}/deployments (the endpoint lands at Active \u2192 Accepted per RFC 0082 \u00a7Conformance).",
5
+ "description": "RFC 0082 §C. A per-(agentId, version) deployment record: the host-runtime lifecycle state of one version of a manifest agent (RFC 0003/0070), distinct from the immutable AgentManifest (which is the pack-distribution descriptor) and from the registry's published semver tags (which version EXISTS, not which version SERVES). Holds the deployment `state`, the named `channels` that resolve to this version, the canary traffic share, the rollback pointer, and the provenance (`evalRunId`/`approvalGateId`) of the last transition. Content-free of any manifest body or credential material (SR-1). The record itself is host-internal; this schema is the canonical wire shape a host exposes via GET /agents/{agentId}/deployments (the endpoint lands at Active → Accepted per RFC 0082 §Conformance).",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "required": [
@@ -18,7 +18,7 @@
18
18
  "version": {
19
19
  "type": "string",
20
20
  "maxLength": 64,
21
- "description": "The concrete agent-definition version this record governs (matches `AgentManifest.version`). A deployment record is per-(agentId, version); a `@channel` reference resolves to exactly one such version per the RFC 0082 \u00a7B pin."
21
+ "description": "The concrete agent-definition version this record governs (matches `AgentManifest.version`). A deployment record is per-(agentId, version); a `@channel` reference resolves to exactly one such version per the RFC 0082 §B pin."
22
22
  },
23
23
  "state": {
24
24
  "type": "string",
@@ -31,13 +31,13 @@
31
31
  "deprecated",
32
32
  "rolled-back"
33
33
  ],
34
- "description": "RFC 0082 \u00a7C lifecycle state. `draft`: authored, not yet evaluated. `test`: undergoing eval (RFC 0081). `staged`: eval-passed, awaiting production promotion. `active`: serving (optionally at `canaryPercent < 100`). `paused`: temporarily withdrawn, recoverable. `deprecated`: sunset \u2014 no new traffic, existing pins honored. `rolled-back`: superseded; `rollbackPointer` names the version that replaced it. Legal transitions: draft\u2192test\u2192staged\u2192active (promotion); active\u2194paused (operational); active\u2192deprecated (terminal); active\u2192rolled-back (recovery, with `rollbackPointer`)."
34
+ "description": "RFC 0082 §C lifecycle state. `draft`: authored, not yet evaluated. `test`: undergoing eval (RFC 0081). `staged`: eval-passed, awaiting production promotion. `active`: serving (optionally at `canaryPercent < 100`). `paused`: temporarily withdrawn, recoverable. `deprecated`: sunset — no new traffic, existing pins honored. `rolled-back`: superseded; `rollbackPointer` names the version that replaced it. Legal transitions: draft→test→staged→active (promotion); active↔paused (operational); active→deprecated (terminal); active→rolled-back (recovery, with `rollbackPointer`)."
35
35
  },
36
36
  "canaryPercent": {
37
37
  "type": "integer",
38
38
  "minimum": 0,
39
39
  "maximum": 100,
40
- "description": "MAY. For an `active` version, the share (0\u2013100) of channel traffic the \u00a7B pin draw assigns to THIS version; the remainder goes to the prior `active` version on the same channel. Absent \u21d2 100 (full traffic). A host advertising `agents.deployment.canary: false` MUST reject any value < 100. The per-run draw outcome is the recorded-fact `resolvedAgentVersion` (RFC 0082 \u00a7B) \u2014 never re-rolled on replay."
40
+ "description": "MAY. For an `active` version, the share (0–100) of channel traffic the §B pin draw assigns to THIS version; the remainder goes to the prior `active` version on the same channel. Absent ⇒ 100 (full traffic). A host advertising `agents.deployment.canary: false` MUST reject any value < 100. The per-run draw outcome is the recorded-fact `resolvedAgentVersion` (RFC 0082 §B) — never re-rolled on replay."
41
41
  },
42
42
  "rollbackPointer": {
43
43
  "type": "string",
@@ -51,16 +51,16 @@
51
51
  "type": "string",
52
52
  "minLength": 1
53
53
  },
54
- "description": "MAY. The named deployment channels (e.g. `stable`, `canary`) that resolve to this version. A version MAY be on more than one channel (RFC 0082 UQ#4 \u2014 a promoted-to-`stable` version is also resolvable by the reserved `latest` channel = highest active semver). Channel names are host-advertised in `capabilities.agents.deployment.channels`."
54
+ "description": "MAY. The named deployment channels (e.g. `stable`, `canary`) that resolve to this version. A version MAY be on more than one channel (RFC 0082 UQ#4 — a promoted-to-`stable` version is also resolvable by the reserved `latest` channel = highest active semver). Channel names are host-advertised in `capabilities.agents.deployment.channels`."
55
55
  },
56
56
  "evalRunId": {
57
57
  "$ref": "ids.schema.json#/$defs/runId",
58
- "description": "MAY. The RFC 0081 eval run whose `EvalSummary.passed` gated the last promotion into this state (the \u00a7E evidence). Content-free reference, not the eval body."
58
+ "description": "MAY. The RFC 0081 eval run whose `EvalSummary.passed` gated the last promotion into this state (the §E evidence). Content-free reference, not the eval body."
59
59
  },
60
60
  "approvalGateId": {
61
61
  "type": "string",
62
62
  "minLength": 1,
63
- "description": "MAY. The RFC 0051 `approvalGate` that authorized the last transition (the \u00a7E human gate). Content-free reference."
63
+ "description": "MAY. The RFC 0051 `approvalGate` that authorized the last transition (the §E human gate). Content-free reference."
64
64
  }
65
65
  },
66
66
  "x-openwop-seeded-from": "v1"