@openwop/spec-artifacts 2.0.0-rc.37 → 2.0.0-rc.6
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.
- package/CORPUS-STAMP.json +32 -34
- package/api/seams-v2.yaml +1 -1
- package/api/v2/asyncapi.yaml +1 -1
- package/api/v2/openapi.yaml +10 -9
- package/package.json +5 -18
- package/schemas/capabilities.schema.json +1 -40
- package/schemas/certification-bundle-v2.schema.json +27 -119
- package/schemas/run-snapshot.schema.json +33 -103
- package/schemas/v2/agent-deployment-transition.schema.json +6 -5
- package/schemas/v2/agent-deployment.schema.json +9 -8
- package/schemas/v2/agent-eval-suite.schema.json +12 -11
- package/schemas/v2/artifact-type-pack-manifest.schema.json +18 -22
- package/schemas/v2/capabilities.schema.json +0 -39
- package/schemas/v2/certification-bundle.schema.json +1 -1
- package/schemas/v2/chat-card-pack-manifest.schema.json +15 -19
- package/schemas/v2/debug-bundle.schema.json +6 -6
- package/schemas/v2/eval-summary.schema.json +10 -17
- package/schemas/v2/goal.schema.json +5 -5
- package/schemas/v2/ids.schema.json +22 -120
- package/schemas/v2/node-pack-manifest.schema.json +31 -27
- package/schemas/v2/proposal.schema.json +8 -7
- package/schemas/v2/run-event-payloads.schema.json +242 -246
- package/schemas/v2/run-event.schema.json +126 -2
- package/schemas/v2/run-snapshot.schema.json +13 -34
- package/schemas/v2/workflow-chain-pack-manifest.schema.json +45 -41
- package/schemas/v2/workflow-definition.schema.json +36 -31
- package/spec/v1/core-standard-manifest.json +2 -2
- package/spec/v1/deprecations.json +67 -79
- package/spec/v1/deprecations.schema.json +7 -23
- package/spec/v1/extensions.json +2 -3
- package/spec/v2/declaration.json +0 -7
- package/spec/v2/release.json +2 -2
- package/schemas/v2/webhook-delivery.schema.json +0 -26
- package/spec/v2/id-field-bindings.json +0 -104
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/workflow-chain-pack-manifest.schema.json",
|
|
4
4
|
"title": "WorkflowChainPackManifest",
|
|
5
|
-
"description": "Manifest for a published OpenWOP workflow-chain pack
|
|
5
|
+
"description": "Manifest for a published OpenWOP workflow-chain pack — `pack.json` at the pack root with `kind: \"workflow-chain\"`. Distinct from node-pack-manifest.schema.json. See workflow-chain-packs.md for the canonical contract and RFC 0013 for the rationale. Chain packs are workflow-edit-time abstractions: a host editor expands each declared chain inline into the parent workflow at author time, so the dispatching runtime sees only concrete `core.*` (or published-vendor) typeIds.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": [
|
|
8
8
|
"name",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"properties": {
|
|
15
15
|
"name": {
|
|
16
16
|
"type": "string",
|
|
17
|
-
"description": "Reverse-DNS pack name per node-packs.md
|
|
17
|
+
"description": "Reverse-DNS pack name per node-packs.md §Naming. Reserved scopes are identical (`core.*` / `vendor.<org>.*` / `community.<author>.*` / `private.<host>.*` / `local.*`).",
|
|
18
18
|
"pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
|
|
19
19
|
"minLength": 1,
|
|
20
20
|
"maxLength": 256
|
|
@@ -64,18 +64,18 @@
|
|
|
64
64
|
"properties": {
|
|
65
65
|
"openwop": {
|
|
66
66
|
"type": "string",
|
|
67
|
-
"description": "Semver range
|
|
67
|
+
"description": "Semver range — which openwop protocol versions this pack works against."
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
70
|
"additionalProperties": false,
|
|
71
|
-
"$comment": "Open by design
|
|
71
|
+
"$comment": "Open by design — packs MAY advertise extra engine constraints (`node`, `python`, etc.) that consumer hosts ignore but operator tooling consumes. Mirrors the shape used in node-pack-manifest.schema.json."
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"type": "object",
|
|
75
75
|
"additionalProperties": {
|
|
76
76
|
"type": "string"
|
|
77
77
|
},
|
|
78
|
-
"description": "Other node packs whose typeIds this pack's chains reference. Map of pack name
|
|
78
|
+
"description": "Other node packs whose typeIds this pack's chains reference. Map of pack name → semver range. The host editor uses this map at expansion time to verify referenced typeIds resolve."
|
|
79
79
|
},
|
|
80
80
|
"chains": {
|
|
81
81
|
"type": "array",
|
|
@@ -101,11 +101,11 @@
|
|
|
101
101
|
"parameters",
|
|
102
102
|
"dag"
|
|
103
103
|
],
|
|
104
|
-
"description": "A single workflow-chain entry
|
|
104
|
+
"description": "A single workflow-chain entry — a pre-configured DAG fragment + parameter schema that the host editor expands inline at author time. See workflow-chain-packs.md §Chain entry shape.",
|
|
105
105
|
"properties": {
|
|
106
106
|
"chainId": {
|
|
107
107
|
"$ref": "ids.schema.json#/$defs/chainId",
|
|
108
|
-
"description": "Canonical chain id
|
|
108
|
+
"description": "Canonical chain id — namespaced like a node typeId (reverse-DNS pattern). The pack's `name` prefix is recommended (e.g., pack `vendor.acme.editor-presets` exposing `vendor.acme.generatePRD`)."
|
|
109
109
|
},
|
|
110
110
|
"version": {
|
|
111
111
|
"type": "string",
|
|
@@ -123,13 +123,13 @@
|
|
|
123
123
|
},
|
|
124
124
|
"internal": {
|
|
125
125
|
"type": "boolean",
|
|
126
|
-
"description": "RFC 0135
|
|
126
|
+
"description": "RFC 0135 — when true, this chain is a composition-only fragment (typically an RFC 0133 sub-chain child): hosts MUST omit it from default template-gallery/picker listings while keeping it loadable, resolvable by id, composable, and expandable exactly like any other chain. Presentational/discovery semantics only — NOT an authorization boundary (a host MUST NOT treat it as access control). Absent ⇒ false (listed). See workflow-chain-packs.md §\"Chain visibility (RFC 0135)\"."
|
|
127
127
|
},
|
|
128
128
|
"parameters": {
|
|
129
129
|
"type": "object",
|
|
130
|
-
"description": "JSON Schema 2020-12 fragment describing the parameter values the host editor MUST collect from the author at drop time. Authors-supplied values are validated against this schema before expansion proceeds; invalid input MUST be rejected with `chain_parameter_invalid`. RECOGNIZED EXTENSION KEY (RFC 0124 / WCP4): a property MAY carry `x-openwop-sensitive: true` to declare the parameter secret-class. A host that recognizes it MUST NOT expansion-time-freeze that parameter (plaintext secret-at-rest leak, SR-1) and MUST NOT materialize it as a plaintext `source:\"variable\"` binding (the value would land in the run-scoped bag / `RunSnapshot.variables`
|
|
130
|
+
"description": "JSON Schema 2020-12 fragment describing the parameter values the host editor MUST collect from the author at drop time. Authors-supplied values are validated against this schema before expansion proceeds; invalid input MUST be rejected with `chain_parameter_invalid`. RECOGNIZED EXTENSION KEY (RFC 0124 / WCP4): a property MAY carry `x-openwop-sensitive: true` to declare the parameter secret-class. A host that recognizes it MUST NOT expansion-time-freeze that parameter (plaintext secret-at-rest leak, SR-1) and MUST NOT materialize it as a plaintext `source:\"variable\"` binding (the value would land in the run-scoped bag / `RunSnapshot.variables` — the same SR-1 leak one layer down). Instead, per the 2026-07-04 §Security amendment: it is deferrable ONLY in a prompt-body position, where it MUST be materialized as a `source:\"secret\"` `PromptVariable` (BYOK-resolved via `capabilities.secrets`, redacted to `[REDACTED:<secretId>]` in `prompt.composed`, never bagged); in ANY other position (whole-value `node.inputs`, embedded non-prompt `config`, or a host lacking deferred / `secrets` support) it MUST fail closed with `sensitive_param_not_deferrable` (422). Per-run supply is a `credentialRef` secret reference, never plaintext. See `workflow-chain-packs.md` §\"Deferred-parameter expansion\" / RFC 0124 §Security.",
|
|
131
131
|
"additionalProperties": true,
|
|
132
|
-
"$comment": "Open by design
|
|
132
|
+
"$comment": "Open by design — this field IS a JSON Schema document, so it must accept any of the 30+ JSON Schema 2020-12 keywords (`type`, `properties`, `required`, `oneOf`, `allOf`, etc.). Strict closure would require importing the JSON Schema meta-schema."
|
|
133
133
|
},
|
|
134
134
|
"dag": {
|
|
135
135
|
"$ref": "#/$defs/WorkflowDefinitionFragment"
|
|
@@ -160,18 +160,18 @@
|
|
|
160
160
|
"items": {
|
|
161
161
|
"$ref": "#/$defs/SubChainRef"
|
|
162
162
|
},
|
|
163
|
-
"description": "RFC 0133
|
|
163
|
+
"description": "RFC 0133 §1.1. OPTIONAL. Child chains this chain composes at RUN TIME. Each entry names a chain (a sibling `chainId` in this pack, or an externally published chain) that a node references via `config.subChainRef`. Unlike RFC 0013's author-time inline splice, a referenced sub-chain is co-instantiated as its own registered workflow and dispatched by the parent as a child run (both parent and child stay owned + builder-editable). A host without runtime child dispatch MUST refuse instantiation with `sub_chain_unsupported` (422) rather than flatten. Requires `capabilities.workflowChainPacks.subChains.supported: true`. See `workflow-chain-packs.md` §\"Sub-chain composition (RFC 0133)\"."
|
|
164
164
|
},
|
|
165
165
|
"producedVariables": {
|
|
166
166
|
"type": "array",
|
|
167
167
|
"items": {
|
|
168
168
|
"$ref": "#/$defs/ProducedVariable"
|
|
169
169
|
},
|
|
170
|
-
"description": "RFC 0133
|
|
170
|
+
"description": "RFC 0133 §2.2. OPTIONAL. Run-scoped values a node writes to the executor's variable bag during the run and downstream nodes read by name via a `{ type:\"variable\", variableName }` input binding — where the value is NOT an author-time `parameter` and rides no typed output port. Prefer edges (a typed `sourceOutput`→`targetInput` hand-off) wherever a node exposes a value on a port; `producedVariables` is only for values written to the run bag with no typed port. On expansion the host emits these into `WorkflowDefinition.variables[]` as run-scoped entries (name + type, no value). Any `{ type:\"variable\" }` read of an UNDECLARED name (not here and not a materialized parameter) is a `variable_undeclared` manifest error. See `workflow-chain-packs.md` §\"Produced (run-scoped) variables (RFC 0133)\"."
|
|
171
171
|
},
|
|
172
172
|
"compensation": {
|
|
173
173
|
"type": "object",
|
|
174
|
-
"description": "RFC 0157 (RFC 0013 revision
|
|
174
|
+
"description": "RFC 0157 (RFC 0013 revision × RFC 0151 §B) — the chain-level compensation POLICY, MIRROR of `compensation-policy.schema.json` (copied inline; a conformance leg asserts equality apart from this description). On expansion it becomes the registered definition's `settings.compensation`: if the parent has none, the host MUST copy it; if the parent already carries one that is not deep-equal, expansion MUST fail `chain_compensation_policy_conflict` — a merged policy nobody wrote is exactly the guess-at-a-contract failure the policy exists to prevent. Absent ⇒ the chain expresses no policy and inherits the parent's (or none).",
|
|
175
175
|
"additionalProperties": false,
|
|
176
176
|
"required": [
|
|
177
177
|
"triggers"
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
"profileVersion": {
|
|
181
181
|
"type": "string",
|
|
182
182
|
"pattern": "^[1-9][0-9]*$",
|
|
183
|
-
"description": "The RFC 0151 profile version this policy was authored against. OPTIONAL; when present it MUST equal the host's advertised `capabilities.compensation.profileVersion` or registration fails, because `profileVersion` is part of the inverse-action identity (
|
|
183
|
+
"description": "The RFC 0151 profile version this policy was authored against. OPTIONAL; when present it MUST equal the host's advertised `capabilities.compensation.profileVersion` or registration fails, because `profileVersion` is part of the inverse-action identity (§C) and a workflow authored under one ordering rule MUST NOT mint identities under another."
|
|
184
184
|
},
|
|
185
185
|
"orderingModel": {
|
|
186
186
|
"type": "string",
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
"dependency-graph"
|
|
190
190
|
],
|
|
191
191
|
"default": "reverse-completion",
|
|
192
|
-
"description": "RFC 0151
|
|
192
|
+
"description": "RFC 0151 §A/§C. `reverse-completion` (default) orders inverse actions by descending durable forward-completion sequence; `dependency-graph` MUST be a DAG and preserve reverse dependency order. The value MUST be one of the host's advertised `capabilities.compensation.orderingModels[]`; a host MUST refuse the workflow at registration otherwise, so an unwind never discovers at failure time that its ordering rule is unimplemented."
|
|
193
193
|
},
|
|
194
194
|
"triggers": {
|
|
195
195
|
"type": "array",
|
|
@@ -204,12 +204,12 @@
|
|
|
204
204
|
"operator-request"
|
|
205
205
|
]
|
|
206
206
|
},
|
|
207
|
-
"description": "Which events start an unwind. REQUIRED and closed
|
|
207
|
+
"description": "Which events start an unwind. REQUIRED and closed — a policy that names no trigger is not a policy, and an open string here would let a host and an author disagree about a word. `node-failure`: a node reaches terminal failure after its own RFC 0009 retry policy and the run cannot continue. `run-cancel`: an RFC 0094 cancel is accepted while committed effects exist. `cap-breach`: an RFC 0058 / RFC 0084 `cap.breached` hard stop. `operator-request`: an authorized operator explicitly requests an unwind (§E) — MUST be authorized per RFC 0049, binding tenant, principal, action, and plan version. A trigger not listed here does NOT start an unwind; the run ends with its committed effects in place and `compensationStatus: none`, which is the honest shape — no generic rollback is inferred from an undeclared trigger (RFC 0151 §Compatibility)."
|
|
208
208
|
},
|
|
209
209
|
"retry": {
|
|
210
210
|
"type": "object",
|
|
211
211
|
"additionalProperties": false,
|
|
212
|
-
"description": "Defaults for inverse actions whose node-level `compensation.retry` is absent. A node's own bounds always win. Retries reuse the inverse action's stable identity (
|
|
212
|
+
"description": "Defaults for inverse actions whose node-level `compensation.retry` is absent. A node's own bounds always win. Retries reuse the inverse action's stable identity (§C) — never a fresh one, or a transient refund failure mints a second refund.",
|
|
213
213
|
"properties": {
|
|
214
214
|
"maxAttempts": {
|
|
215
215
|
"type": "integer",
|
|
@@ -233,7 +233,7 @@
|
|
|
233
233
|
"manual-intervention"
|
|
234
234
|
],
|
|
235
235
|
"default": "record-outcome",
|
|
236
|
-
"description": "RFC 0151
|
|
236
|
+
"description": "RFC 0151 §E — what the host does when an inverse action exhausts its retries. Either way the run MUST route to RFC 0053 dead-letter handling and the run's `compensationStatus` follows the §D fold (`partial` or `failed`). `record-outcome` (default): record the failure and continue unwinding the remaining actions. `manual-intervention`: additionally emit `compensation.manual_intervention_required` and stop issuing further inverse actions until an authorized operator retries, skips with recorded justification, substitutes a registered action, or terminates as uncompensated — the rollup reads `manual` while that is unresolved. Requires `capabilities.compensation.manualIntervention: true`; a host that does not advertise it MUST refuse a policy that selects it."
|
|
237
237
|
},
|
|
238
238
|
"approvalScope": {
|
|
239
239
|
"type": "string",
|
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
"all"
|
|
243
243
|
],
|
|
244
244
|
"default": "declared",
|
|
245
|
-
"description": "RFC 0151
|
|
245
|
+
"description": "RFC 0151 §E. `declared` (default): only inverse actions whose node sets `compensation.requiresApproval: true` create an RFC 0051 approval interrupt. `all`: every inverse action does, regardless of the node's declaration. This value can only ESCALATE — there is no `none`, because a policy MUST NOT strip an approval a node declared for itself (RFC 0147 R9: an inverse action can itself be harmful)."
|
|
246
246
|
},
|
|
247
247
|
"onParentCancel": {
|
|
248
248
|
"type": "string",
|
|
@@ -252,7 +252,7 @@
|
|
|
252
252
|
"manual"
|
|
253
253
|
],
|
|
254
254
|
"default": "continue",
|
|
255
|
-
"description": "RFC 0151
|
|
255
|
+
"description": "RFC 0151 §C — cancellation of the parent run MUST NOT silently abandon an active compensation. `continue`: the unwind runs to its terminal rollup. `pause`: emit `compensation.paused` and hold for authorized intervention (the run's own `status` carries the wait). `manual`: emit `compensation.manual_intervention_required` and stop; rollup reads `manual`. `pause`/`manual` require `capabilities.compensation.manualIntervention: true`."
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
}
|
|
@@ -260,7 +260,7 @@
|
|
|
260
260
|
"additionalProperties": false,
|
|
261
261
|
"patternProperties": {
|
|
262
262
|
"^(openwop-|x-|vendor\\.)": {
|
|
263
|
-
"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`
|
|
263
|
+
"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."
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
266
|
},
|
|
@@ -269,7 +269,7 @@
|
|
|
269
269
|
"required": [
|
|
270
270
|
"ref"
|
|
271
271
|
],
|
|
272
|
-
"description": "RFC 0133
|
|
272
|
+
"description": "RFC 0133 §1.1. A reference to a child chain the parent composes. `ref` is EITHER a string naming a SIBLING `chainId` in this pack's `chains[]`, OR an object naming an externally published chain (resolved + signature-verified like any pack dependency). A sibling `ref` that matches no `chainId`, or an external `ref` that fails resolution/verification, is `sub_chain_unresolved`. A chain that transitively composes itself is `sub_chain_cycle`.",
|
|
273
273
|
"properties": {
|
|
274
274
|
"ref": {
|
|
275
275
|
"oneOf": [
|
|
@@ -299,7 +299,7 @@
|
|
|
299
299
|
},
|
|
300
300
|
"version": {
|
|
301
301
|
"type": "string",
|
|
302
|
-
"description": "Semver range for the external chain. Co-registration SHOULD pin the resolved version into the parent's ownership record for reproducibility (RFC 0133
|
|
302
|
+
"description": "Semver range for the external chain. Co-registration SHOULD pin the resolved version into the parent's ownership record for reproducibility (RFC 0133 §Unresolved #1, resolved: pin)."
|
|
303
303
|
}
|
|
304
304
|
},
|
|
305
305
|
"additionalProperties": false
|
|
@@ -316,7 +316,7 @@
|
|
|
316
316
|
"producedBy",
|
|
317
317
|
"type"
|
|
318
318
|
],
|
|
319
|
-
"description": "RFC 0133
|
|
319
|
+
"description": "RFC 0133 §2.2. A run-scoped variable a chain declares: written by one node and read by others via a `{ type:\"variable\", variableName }` input binding. Run-scoped — carries NO author-time value (that is what `parameters` are for); the manifest distinguishes the two.",
|
|
320
320
|
"properties": {
|
|
321
321
|
"name": {
|
|
322
322
|
"type": "string",
|
|
@@ -369,7 +369,7 @@
|
|
|
369
369
|
"required": [
|
|
370
370
|
"nodes"
|
|
371
371
|
],
|
|
372
|
-
"description": "Subset of workflow-definition.schema.json. `id`/`name`/`version`/`triggers`/`settings`/`metadata` MUST be omitted (host generates per-expansion); `variables` is replaced by the chain's top-level `parameters`. See workflow-chain-packs.md
|
|
372
|
+
"description": "Subset of workflow-definition.schema.json. `id`/`name`/`version`/`triggers`/`settings`/`metadata` MUST be omitted (host generates per-expansion); `variables` is replaced by the chain's top-level `parameters`. See workflow-chain-packs.md §WorkflowDefinitionFragment.",
|
|
373
373
|
"properties": {
|
|
374
374
|
"nodes": {
|
|
375
375
|
"type": "array",
|
|
@@ -403,7 +403,10 @@
|
|
|
403
403
|
"description": "Node id, unique within the fragment. Hosts MUST rewrite these to globally-unique ids at expansion time."
|
|
404
404
|
},
|
|
405
405
|
"typeId": {
|
|
406
|
-
"
|
|
406
|
+
"type": "string",
|
|
407
|
+
"pattern": "^[a-z][a-zA-Z0-9._-]*$",
|
|
408
|
+
"minLength": 1,
|
|
409
|
+
"maxLength": 256
|
|
407
410
|
},
|
|
408
411
|
"name": {
|
|
409
412
|
"type": "string"
|
|
@@ -422,7 +425,7 @@
|
|
|
422
425
|
},
|
|
423
426
|
"config": {
|
|
424
427
|
"type": "object",
|
|
425
|
-
"description": "Node config
|
|
428
|
+
"description": "Node config — host-validated against the referenced typeId's config schema. String fields MAY contain `{{params.<name>}}` placeholders that the host MUST substitute at expansion time. RFC 0133: a `core.subWorkflow` / `core.dispatch` (child-run) node MAY carry `subChainRef: string` — a declared `subChains[].ref` (sibling `chainId` or external ref) the host rewrites to the minted child `workflowId` at co-expansion time (§1.3 step 3). A concrete `config.workflowId` inside a fragment remains INVALID — a chain MUST NOT pin a host-specific workflow id (the `not` guard below enforces it).",
|
|
426
429
|
"additionalProperties": false,
|
|
427
430
|
"not": {
|
|
428
431
|
"required": [
|
|
@@ -433,32 +436,33 @@
|
|
|
433
436
|
"subChainRef": {
|
|
434
437
|
"type": "string",
|
|
435
438
|
"pattern": "^[a-z][a-zA-Z0-9._-]*$",
|
|
436
|
-
"description": "RFC 0133
|
|
439
|
+
"description": "RFC 0133 §1.2. A declared `subChains[].ref` this node dispatches as a child run. The host rewrites it to the minted child `config.workflowId` at co-expansion time. MUST match a `subChains[].ref` (sibling `chainId` or external ref's `chainId`), else `sub_chain_unresolved`."
|
|
437
440
|
}
|
|
438
441
|
},
|
|
439
|
-
"$comment": "Open by design
|
|
442
|
+
"$comment": "Open by design — node config shapes are per-typeId and only known to the host at expansion time when the referenced typeId's config schema is resolved. Cross-typeId enforcement happens at the expansion step, not at manifest-validation time. The `not: { required: ['workflowId'] }` guard is the ONE closed constraint: RFC 0133 forbids pinning a concrete host-specific workflow id inside a portable chain fragment (use `subChainRef` instead)."
|
|
440
443
|
},
|
|
441
444
|
"inputs": {
|
|
442
445
|
"type": "object",
|
|
443
446
|
"description": "Per-port input wiring. String values MAY contain `{{params.<name>}}` placeholders.",
|
|
444
447
|
"additionalProperties": true,
|
|
445
|
-
"$comment": "Open by design
|
|
448
|
+
"$comment": "Open by design — port shapes are per-typeId, same reasoning as `config` above."
|
|
446
449
|
},
|
|
447
450
|
"compensation": {
|
|
448
451
|
"type": "object",
|
|
449
|
-
"description": "RFC 0157 (RFC 0013 revision
|
|
452
|
+
"description": "RFC 0157 (RFC 0013 revision × RFC 0151 §B) — MIRROR of `workflow-definition.schema.json#/$defs/WorkflowNode/properties/compensation`, copied inline so this manifest stays self-contained (no cross-file `$ref`); a conformance leg asserts the two stay byte-equal apart from this description. The inverse action for this fragment node. `nodeTypeId` MUST resolve at expansion (step 3) exactly as `typeId` does — `chain_unresolvable_typeid`; `inputMapping` strings MAY carry `{{params.<name>}}` and MUST be substituted at expansion (step 5); node-id references inside `inputMapping` MUST be rewritten with the expansion prefix (step 6). Survives expansion verbatim into the registered `WorkflowNode.compensation`.",
|
|
450
453
|
"additionalProperties": false,
|
|
451
454
|
"required": [
|
|
452
455
|
"nodeTypeId"
|
|
453
456
|
],
|
|
454
457
|
"properties": {
|
|
455
458
|
"nodeTypeId": {
|
|
456
|
-
"
|
|
459
|
+
"type": "string",
|
|
460
|
+
"minLength": 1,
|
|
457
461
|
"description": "Node type implementing the inverse action. MUST resolve at registration time."
|
|
458
462
|
},
|
|
459
463
|
"inputMapping": {
|
|
460
464
|
"type": "object",
|
|
461
|
-
"description": "Derived from recorded facts only
|
|
465
|
+
"description": "Derived from recorded facts only — node outputs and run inputs already in the event log.",
|
|
462
466
|
"additionalProperties": true
|
|
463
467
|
},
|
|
464
468
|
"retry": {
|
|
@@ -477,17 +481,17 @@
|
|
|
477
481
|
},
|
|
478
482
|
"requiresApproval": {
|
|
479
483
|
"type": "boolean",
|
|
480
|
-
"description": "RFC 0151
|
|
484
|
+
"description": "RFC 0151 §C — an inverse action can itself be harmful (RFC 0147 R9), so it may be gated behind the same approval surface as a forward effect."
|
|
481
485
|
},
|
|
482
486
|
"waiveRequiresApproval": {
|
|
483
487
|
"type": "boolean",
|
|
484
|
-
"description": "RFC 0151
|
|
488
|
+
"description": "RFC 0151 §B/§E (S36, 2026-08-17) — OPTIONAL. When true, ABANDONING this inverse action (§E `skip with justification` or `terminate as uncompensated`) requires an RFC 0051 approval to have resolved `approved` first — if a human must authorize RUNNING an inverse, a human must authorize deciding it will NEVER run. DEFAULT = the obligation's EFFECTIVE `requiresApproval` (after the policy's `approvalScope` escalation, §B) — NOT false — so the field is purely additive: no existing document changes meaning. Stamped onto the obligation at MINT time like `requiresApproval` (a mid-flight redefinition cannot change who had to authorize). Does NOT apply to `substitute` (still an attempt to undo; a substitution is a new planVersion whose own `requiresApproval` governs it). No policy-level counterpart: because the default inherits the effective value, an `approvalScope` escalation escalates waives with it."
|
|
485
489
|
}
|
|
486
490
|
}
|
|
487
491
|
},
|
|
488
492
|
"irreversibleEffect": {
|
|
489
493
|
"type": "boolean",
|
|
490
|
-
"description": "RFC 0151
|
|
494
|
+
"description": "RFC 0151 §B UQ4 (resolved 2026-08-16), mirrored into chain fragments per RFC 0157 — the fragment author states that this node's committed effect HAS NO INVERSE. Mutually exclusive with `compensation` (host MUST reject both at pack install / chain expansion); expansion copies it onto the expanded `WorkflowNode` unchanged. See `workflow-definition.schema.json` `WorkflowNode.irreversibleEffect`."
|
|
491
495
|
}
|
|
492
496
|
},
|
|
493
497
|
"additionalProperties": false,
|
|
@@ -526,7 +530,7 @@
|
|
|
526
530
|
},
|
|
527
531
|
"condition": {
|
|
528
532
|
"$ref": "#/$defs/EdgeCondition",
|
|
529
|
-
"description": "Optional edge condition
|
|
533
|
+
"description": "Optional edge condition — the SAME shape as a top-level workflow edge's condition (workflow-definition.schema.json §EdgeCondition). When present, the edge contributes to the target only if the condition holds against the source node's output, letting a chain express content routing (router/switch/conditional branches). Safety-fix (RFC 0013 amendment 2026-07-03): the field was previously typed `string`, contradicting this description; no chain used the string form (hosts dropped the field at expansion), so correcting it to the object shape breaks no conformant behavior."
|
|
530
534
|
},
|
|
531
535
|
"triggerRule": {
|
|
532
536
|
"type": "string",
|
|
@@ -538,14 +542,14 @@
|
|
|
538
542
|
"any_failed"
|
|
539
543
|
],
|
|
540
544
|
"default": "all_success",
|
|
541
|
-
"description": "Optional fan-in / error-routing rule
|
|
545
|
+
"description": "Optional fan-in / error-routing rule — the SAME shape and enum as a top-level workflow edge's `triggerRule` (workflow-definition.schema.json §WorkflowEdge). Governs how the target node fires given its incoming edges: `all_success` (default — every incoming edge's source succeeded), `any_success`, `all_complete` (fire when all sources have finished regardless of success — best-effort completion), `none_failed`, `any_failed`. Additive (RFC 0125): omitting it is identical to `all_success`, the implicit prior behavior. Mirrors the RFC 0013 2026-07-03 `condition` amendment's WorkflowEdge→FragmentEdge move. Expansion MUST carry this value onto the resulting `WorkflowEdge` so the scheduler honors it (see `workflow-chain-packs.md` §\"Expansion semantics\")."
|
|
542
546
|
}
|
|
543
547
|
},
|
|
544
548
|
"additionalProperties": false
|
|
545
549
|
},
|
|
546
550
|
"EdgeCondition": {
|
|
547
551
|
"type": "object",
|
|
548
|
-
"description": "Edge condition
|
|
552
|
+
"description": "Edge condition — identical to workflow-definition.schema.json §EdgeCondition (RFC 0013 §edges: 'same shape as a top-level workflow definition'). Inlined here so the manifest schema is self-contained for pack-loader validators. RFC 0134 added `truthy`/`falsy` (kept in sync with the top-level def).",
|
|
549
553
|
"properties": {
|
|
550
554
|
"type": {
|
|
551
555
|
"type": "string",
|
|
@@ -576,7 +580,7 @@
|
|
|
576
580
|
},
|
|
577
581
|
"Signing": {
|
|
578
582
|
"type": "object",
|
|
579
|
-
"description": "Optional signing metadata. Reuses node-packs.md
|
|
583
|
+
"description": "Optional signing metadata. Reuses node-packs.md §signing unchanged.",
|
|
580
584
|
"properties": {
|
|
581
585
|
"publicKeyRef": {
|
|
582
586
|
"type": "string",
|
|
@@ -599,7 +603,7 @@
|
|
|
599
603
|
},
|
|
600
604
|
"patternProperties": {
|
|
601
605
|
"^(openwop-|x-|vendor\\.)": {
|
|
602
|
-
"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`
|
|
606
|
+
"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."
|
|
603
607
|
}
|
|
604
608
|
},
|
|
605
609
|
"x-openwop-seeded-from": "v1"
|