@openwop/spec-artifacts 2.0.0-rc.29 → 2.0.0-rc.31
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 +23 -21
- package/api/seams-v2.yaml +1 -1
- package/api/v2/asyncapi.yaml +1 -1
- package/api/v2/openapi.yaml +1 -1
- package/package.json +1 -1
- package/schemas/v2/agent-deployment-transition.schema.json +5 -6
- package/schemas/v2/agent-deployment.schema.json +8 -9
- package/schemas/v2/agent-eval-suite.schema.json +11 -12
- package/schemas/v2/artifact-type-pack-manifest.schema.json +22 -18
- package/schemas/v2/certification-bundle.schema.json +1 -1
- package/schemas/v2/chat-card-pack-manifest.schema.json +19 -15
- package/schemas/v2/debug-bundle.schema.json +6 -6
- package/schemas/v2/eval-summary.schema.json +9 -10
- package/schemas/v2/ids.schema.json +8 -7
- package/schemas/v2/node-pack-manifest.schema.json +27 -31
- package/schemas/v2/run-event-payloads.schema.json +240 -239
- package/schemas/v2/run-snapshot.schema.json +17 -17
- package/schemas/v2/webhook-delivery.schema.json +27 -0
- package/schemas/v2/workflow-chain-pack-manifest.schema.json +41 -45
- package/schemas/v2/workflow-definition.schema.json +30 -35
- package/spec/v1/core-standard-manifest.json +2 -2
- package/spec/v2/id-field-bindings.json +96 -0
- package/spec/v2/release.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/chat-card-pack-manifest.schema.json",
|
|
4
4
|
"title": "ChatCardPackManifest",
|
|
5
|
-
"description": "Manifest for a published OpenWOP AI chat card pack
|
|
5
|
+
"description": "Manifest for a published OpenWOP AI chat card pack \u2014 `pack.json` at the pack root with `kind: \"card\"`. Peer to the node / workflow-chain / prompt / artifact-type pack manifests; disjoint via the `kind` discriminator. See `spec/v1/chat-card-packs.md` for the canonical contract and RFC 0071 Phase 2 for the rationale.\n\nA chat card pack distributes AI step cards: each card binds a prompt template (with typed input slots) to a typed output artifact. When a host advertises `host.chat.cardPacks: supported` and a registered card is invoked, the host substitutes inputs into the prompt, routes the call through `ctx.aiEnvelope.generate`, and (when `outputArtifactType` is set) validates the result against the referenced artifact-type pack's schema before emitting `artifact.created`.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": [
|
|
8
8
|
"name",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"name": {
|
|
22
22
|
"type": "string",
|
|
23
|
-
"description": "Reverse-DNS pack name per `node-packs.md`
|
|
23
|
+
"description": "Reverse-DNS pack name per `node-packs.md` \u00a7Naming. Reserved scopes are identical (`core.*` / `vendor.<org>.*` / `community.<author>.*` / `private.<host>.*`).",
|
|
24
24
|
"pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
|
|
25
25
|
"minLength": 1,
|
|
26
26
|
"maxLength": 256
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"properties": {
|
|
66
66
|
"openwop": {
|
|
67
67
|
"type": "string",
|
|
68
|
-
"description": "Semver range
|
|
68
|
+
"description": "Semver range \u2014 which openwop protocol versions this pack works against."
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
71
|
"additionalProperties": false
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"additionalProperties": {
|
|
76
76
|
"type": "string"
|
|
77
77
|
},
|
|
78
|
-
"description": "Other packs this pack depends on (e.g., the artifact-type pack declaring this card's `outputArtifactType`). Map of pack name
|
|
78
|
+
"description": "Other packs this pack depends on (e.g., the artifact-type pack declaring this card's `outputArtifactType`). Map of pack name \u2192 semver range."
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
81
|
"type": "object",
|
|
@@ -106,16 +106,20 @@
|
|
|
106
106
|
"additionalProperties": false,
|
|
107
107
|
"properties": {
|
|
108
108
|
"cardTypeId": {
|
|
109
|
-
"
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
"allOf": [
|
|
110
|
+
{
|
|
111
|
+
"$ref": "ids.schema.json#/$defs/typeId"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$"
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"description": "Reverse-DNS card identifier. Same pattern and reserved scopes as a pack `name`. The value `WorkflowNode.cardType` / `ctx.chat.emitCard` MAY reference. Third parties MUST NOT publish under `core.*`."
|
|
114
118
|
},
|
|
115
119
|
"schemaVersion": {
|
|
116
120
|
"type": "integer",
|
|
117
121
|
"minimum": 0,
|
|
118
|
-
"description": "Non-negative integer card-schema version (the envelope/artifact integer-version axis). Absent
|
|
122
|
+
"description": "Non-negative integer card-schema version (the envelope/artifact integer-version axis). Absent \u21d2 treated as 0."
|
|
119
123
|
},
|
|
120
124
|
"prompt": {
|
|
121
125
|
"$ref": "#/$defs/PromptSpec"
|
|
@@ -150,7 +154,7 @@
|
|
|
150
154
|
},
|
|
151
155
|
"patternProperties": {
|
|
152
156
|
"^(openwop-|x-|vendor\\.)": {
|
|
153
|
-
"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`
|
|
157
|
+
"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` \u00a7\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque \u2014 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` \u00a7\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
160
|
},
|
|
@@ -177,7 +181,7 @@
|
|
|
177
181
|
"additionalProperties": {
|
|
178
182
|
"type": "string"
|
|
179
183
|
},
|
|
180
|
-
"description": "Map of `{{placeholder}}` name
|
|
184
|
+
"description": "Map of `{{placeholder}}` name \u2192 input path (e.g. `\"spec\": \"inputs.spec\"`)."
|
|
181
185
|
},
|
|
182
186
|
"temperature": {
|
|
183
187
|
"type": "number",
|
|
@@ -205,7 +209,7 @@
|
|
|
205
209
|
},
|
|
206
210
|
"type": {
|
|
207
211
|
"type": "string",
|
|
208
|
-
"description": "Closed portable subset OR a `vendor.<org>.<kind>` / `x-<kind>` host extension other hosts ignore. The portable subset (G9, resolved 2026-05-27 against MyndHyve's `CardFieldType`): `text`, `longtext`, `number`, `boolean`, `select`, `multiselect`, `file`, `artifact-ref`. MyndHyve maps `textarea
|
|
212
|
+
"description": "Closed portable subset OR a `vendor.<org>.<kind>` / `x-<kind>` host extension other hosts ignore. The portable subset (G9, resolved 2026-05-27 against MyndHyve's `CardFieldType`): `text`, `longtext`, `number`, `boolean`, `select`, `multiselect`, `file`, `artifact-ref`. MyndHyve maps `textarea`\u2192`longtext` and `toggle`\u2192`boolean`; its product-specific kinds (`canvas-reference`, `collection-reference`, `color`) are host extensions (`vendor.myndhyve.*`), not portable.",
|
|
209
213
|
"pattern": "^(text|longtext|number|boolean|select|multiselect|file|artifact-ref|vendor\\.[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*|x-[a-z][a-z0-9-]*)$"
|
|
210
214
|
},
|
|
211
215
|
"label": {
|
|
@@ -226,7 +230,7 @@
|
|
|
226
230
|
},
|
|
227
231
|
"Signing": {
|
|
228
232
|
"type": "object",
|
|
229
|
-
"description": "Optional signing metadata. See node-packs.md
|
|
233
|
+
"description": "Optional signing metadata. See node-packs.md \u00a7signing.",
|
|
230
234
|
"additionalProperties": false,
|
|
231
235
|
"properties": {
|
|
232
236
|
"publicKeyRef": {
|
|
@@ -247,7 +251,7 @@
|
|
|
247
251
|
},
|
|
248
252
|
"patternProperties": {
|
|
249
253
|
"^(openwop-|x-|vendor\\.)": {
|
|
250
|
-
"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`
|
|
254
|
+
"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` \u00a7\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque \u2014 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` \u00a7\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
251
255
|
}
|
|
252
256
|
},
|
|
253
257
|
"x-openwop-seeded-from": "v1"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/debug-bundle.schema.json",
|
|
4
4
|
"title": "RunDebugBundle",
|
|
5
|
-
"description": "Portable JSON export of a single run's diagnostic state. See spec/v1/debug-bundle.md. Additive over v1 per COMPATIBILITY.md
|
|
5
|
+
"description": "Portable JSON export of a single run's diagnostic state. See spec/v1/debug-bundle.md. Additive over v1 per COMPATIBILITY.md \u00a72.1: optional endpoint; hosts MAY omit.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": [
|
|
8
8
|
"bundleVersion",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"properties": {
|
|
17
17
|
"bundleVersion": {
|
|
18
18
|
"const": "2",
|
|
19
|
-
"description": "RFC 0172
|
|
19
|
+
"description": "RFC 0172 \u00a7B axis 10 \u2014 one const family; this bundle is \"2\" in v2."
|
|
20
20
|
},
|
|
21
21
|
"generatedAt": {
|
|
22
22
|
"type": "string",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"run": {
|
|
49
49
|
"type": "object",
|
|
50
|
-
"description": "Run snapshot
|
|
50
|
+
"description": "Run snapshot \u2014 same shape as GET /v1/runs/{runId}. See run-snapshot.schema.json.",
|
|
51
51
|
"required": [
|
|
52
52
|
"runId",
|
|
53
53
|
"workflowId",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"currentNodeId": {
|
|
122
122
|
"oneOf": [
|
|
123
123
|
{
|
|
124
|
-
"
|
|
124
|
+
"$ref": "ids.schema.json#/$defs/nodeId"
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
"type": "null"
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"nodeId": {
|
|
168
168
|
"oneOf": [
|
|
169
169
|
{
|
|
170
|
-
"
|
|
170
|
+
"$ref": "ids.schema.json#/$defs/nodeId"
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
"type": "null"
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
"parentSpanId": {
|
|
199
199
|
"oneOf": [
|
|
200
200
|
{
|
|
201
|
-
"
|
|
201
|
+
"$ref": "ids.schema.json#/$defs/spanId"
|
|
202
202
|
},
|
|
203
203
|
{
|
|
204
204
|
"type": "null"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/eval-summary.schema.json",
|
|
4
4
|
"title": "EvalSummary",
|
|
5
|
-
"description": "RFC 0081
|
|
5
|
+
"description": "RFC 0081 \u00a7C. The terminal scorecard of an eval run (the `mode: \"eval\"` projection over `POST /v1/runs`, RFC 0081 \u00a7B): the aggregate + per-task scores, cost, latency, schema-validity, and safety findings, plus the suite provenance and (for `regression` mode) the score delta vs a baseline. Set as the eval run's output and served by `GET /v1/runs/{runId}/eval-summary`. SECURITY invariant `eval-summary-no-content-leak`: the summary carries scores, ids, counts, and redaction-safe safety descriptors only \u2014 NEVER task output bodies, rubric prose, model completions, prompts, or credential material (SR-1). A consumer reads the run's normal projection for any body.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": [
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"type": "number",
|
|
42
42
|
"minimum": 0,
|
|
43
43
|
"maximum": 1,
|
|
44
|
-
"description": "The suite-level score (0.0
|
|
44
|
+
"description": "The suite-level score (0.0\u20131.0): the aggregation (host-defined, typically the mean) of per-task scores."
|
|
45
45
|
},
|
|
46
46
|
"passed": {
|
|
47
47
|
"type": "boolean",
|
|
48
|
-
"description": "Whether the run cleared the suite's `thresholds` (RFC 0081
|
|
48
|
+
"description": "Whether the run cleared the suite's `thresholds` (RFC 0081 \u00a7A) \u2014 `aggregateScore >= passScore` AND, when declared, `totalCostUsd <= maxCostUsd` AND the p95 latency bar. The load-bearing flag an RFC 0082 deployment gate may require (`requiredEval`)."
|
|
49
49
|
},
|
|
50
50
|
"taskCount": {
|
|
51
51
|
"type": "integer",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"totalCostUsd": {
|
|
61
61
|
"type": "number",
|
|
62
62
|
"minimum": 0,
|
|
63
|
-
"description": "MAY. Total cost of the run, summed from the per-task RFC 0026 `provider.usage` events (the scalar only
|
|
63
|
+
"description": "MAY. Total cost of the run, summed from the per-task RFC 0026 `provider.usage` events (the scalar only \u2014 never a pricing breakdown or rate card; `eval-summary-no-content-leak`)."
|
|
64
64
|
},
|
|
65
65
|
"tasks": {
|
|
66
66
|
"type": "array",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"type": "number",
|
|
84
84
|
"minimum": 0,
|
|
85
85
|
"maximum": 1,
|
|
86
|
-
"description": "Task score (0.0
|
|
86
|
+
"description": "Task score (0.0\u20131.0)."
|
|
87
87
|
},
|
|
88
88
|
"passed": {
|
|
89
89
|
"type": "boolean",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
},
|
|
106
106
|
"safetyFindings": {
|
|
107
107
|
"type": "array",
|
|
108
|
-
"description": "MAY. Redaction-safe safety findings (primarily `adversarial` mode). Each is a `{kind, severity}` descriptor
|
|
108
|
+
"description": "MAY. Redaction-safe safety findings (primarily `adversarial` mode). Each is a `{kind, severity}` descriptor \u2014 NO excerpted content, prompt, or completion text (`eval-summary-no-content-leak`).",
|
|
109
109
|
"items": {
|
|
110
110
|
"type": "object",
|
|
111
111
|
"additionalProperties": false,
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"kind": {
|
|
118
118
|
"type": "string",
|
|
119
119
|
"minLength": 1,
|
|
120
|
-
"description": "Finding category (e.g. `jailbreak`, `pii-leak`, `unsafe-tool-call`)
|
|
120
|
+
"description": "Finding category (e.g. `jailbreak`, `pii-leak`, `unsafe-tool-call`) \u2014 a category label, not excerpted content."
|
|
121
121
|
},
|
|
122
122
|
"severity": {
|
|
123
123
|
"type": "string",
|
|
@@ -145,15 +145,14 @@
|
|
|
145
145
|
],
|
|
146
146
|
"properties": {
|
|
147
147
|
"baselineRunId": {
|
|
148
|
-
"
|
|
149
|
-
"minLength": 1,
|
|
148
|
+
"$ref": "ids.schema.json#/$defs/runId",
|
|
150
149
|
"description": "The prior eval run this run is compared against."
|
|
151
150
|
},
|
|
152
151
|
"scoreDelta": {
|
|
153
152
|
"type": "number",
|
|
154
153
|
"minimum": -1,
|
|
155
154
|
"maximum": 1,
|
|
156
|
-
"description": "`aggregateScore` minus the baseline's (negative
|
|
155
|
+
"description": "`aggregateScore` minus the baseline's (negative \u21d2 regression)."
|
|
157
156
|
},
|
|
158
157
|
"diffRef": {
|
|
159
158
|
"type": "string",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/ids.schema.json",
|
|
4
|
-
"title": "OpenWOP v2 identifier grammars (RFC 0170
|
|
4
|
+
"title": "OpenWOP v2 identifier grammars (RFC 0170 \u00a7D.1)",
|
|
5
5
|
"description": "One $defs entry per id kind. Every id field in every v2 schema, OpenAPI parameter and response body $refs its kind. `minted` records who mints the id: host (opaque, checkable: `^[A-Za-z0-9._~-]{16,128}$` after any tenant segment), author (a workflow/pack author chooses it; the v1 grammar stands), registry (the pack registry mints it). Tenant-bound kinds (runId, interruptId, subscriptionId, deliveryId, effectId) carry the tenant segment: a host MUST reject an id whose tenant segment is not the caller's.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"opaque": {
|
|
10
10
|
"type": "string",
|
|
11
11
|
"pattern": "^[A-Za-z0-9._~-]{16,128}$",
|
|
12
|
-
"description": "Host-minted opaque token: no `@`, no whitespace, no `/`; 16
|
|
12
|
+
"description": "Host-minted opaque token: no `@`, no whitespace, no `/`; 16\u2013128 characters."
|
|
13
13
|
},
|
|
14
14
|
"tenantId": {
|
|
15
15
|
"type": "string",
|
|
16
16
|
"pattern": "^(anon:)?[A-Za-z0-9._~-]{1,128}$",
|
|
17
17
|
"x-openwop-minted": "host",
|
|
18
|
-
"description": "A tenant identifier. The optional `anon:` prefix is the ONLY colon admitted, and it exists because RFC 0132 anonymous tenants are `anon:<hash>` while RFC 0170
|
|
18
|
+
"description": "A tenant identifier. The optional `anon:` prefix is the ONLY colon admitted, and it exists because RFC 0132 anonymous tenants are `anon:<hash>` while RFC 0170 \u00a7A.5 makes the anonymous surface first-class \u2014 without it a conforming host can serve an anonymous run with neither a valid `owner.tenant` nor a valid tenant-bound `runId`. `:` is a legal path character (RFC 3986 pchar), so this stays safe inside the `<tenantId>/<opaque>` run-id form. The alternative \u2014 renaming anonymous tenants at the cut \u2014 was rejected: it is a write to historical identity, which is the one thing the v2 migration does not do."
|
|
19
19
|
},
|
|
20
20
|
"workspaceId": {
|
|
21
21
|
"type": "string",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"subjectId": {
|
|
26
26
|
"type": "string",
|
|
27
27
|
"pattern": "^[^\\s/]{1,256}$",
|
|
28
|
-
"description": "Issuer-scoped, stable, opaque (RFC 0170
|
|
28
|
+
"description": "Issuer-scoped, stable, opaque (RFC 0170 \u00a7A); the issuer's grammar, never PII.",
|
|
29
29
|
"x-openwop-minted": "host"
|
|
30
30
|
},
|
|
31
31
|
"runId": {
|
|
@@ -120,9 +120,10 @@
|
|
|
120
120
|
},
|
|
121
121
|
"typeId": {
|
|
122
122
|
"type": "string",
|
|
123
|
-
"pattern": "^[a-z][a-z0-
|
|
124
|
-
"description": "A node type id (`core.ai.callPrompt`); the RFC 0107 grammar.",
|
|
125
|
-
"x-openwop-minted": "author"
|
|
123
|
+
"pattern": "^[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
|
|
124
|
+
"description": "A node type id (`core.ai.callPrompt`); the RFC 0107 grammar. Underscore is admitted because node-pack-manifest.schema.json's `name` pattern admits it and a pack's node type ids are DERIVED from its name \u2014 a pack legally named `vendor.acme.my_tools` must be able to declare `vendor.acme.my_tools.echo`. Without the underscore this kind rejected type ids that a legal pack name generates, which is a constraint that cannot express a legitimate value. maxLength is present because this was the ONLY kind whose pattern left length unbounded \u2014 every other $def bounds it inside the pattern ({1,128}, {16,128}). 256 is taken from the bound node-pack-manifest already carried locally, so this relocates it rather than inventing one, and binding those properties to this kind no longer drops it.",
|
|
125
|
+
"x-openwop-minted": "author",
|
|
126
|
+
"maxLength": 256
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/node-pack-manifest.schema.json",
|
|
4
4
|
"title": "NodePackManifest",
|
|
5
|
-
"description": "Manifest for a published OpenWOP node pack
|
|
5
|
+
"description": "Manifest for a published OpenWOP node pack \u2014 `pack.json` at the pack root. Language-neutral. See node-packs.md for the canonical contract.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": [
|
|
8
8
|
"engines",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"kind": {
|
|
40
40
|
"type": "string",
|
|
41
41
|
"const": "node",
|
|
42
|
-
"description": "Pack kind discriminator. For node packs (the default and original kind) `kind` is either omitted entirely OR set to the literal string `\"node\"`. Manifests carrying `kind: \"workflow-chain\"` validate against `workflow-chain-pack-manifest.schema.json` instead
|
|
42
|
+
"description": "Pack kind discriminator. For node packs (the default and original kind) `kind` is either omitted entirely OR set to the literal string `\"node\"`. Manifests carrying `kind: \"workflow-chain\"` validate against `workflow-chain-pack-manifest.schema.json` instead \u2014 see workflow-chain-packs.md and RFC 0013."
|
|
43
43
|
},
|
|
44
44
|
"name": {
|
|
45
45
|
"type": "string",
|
|
46
|
-
"description": "Reverse-DNS pack name. Reserved scopes: `core.*` (spec-canonical), `vendor.<org>.*` (vendor-published), `community.<author>.*` (individual), `private.<host>.*` (host-internal
|
|
46
|
+
"description": "Reverse-DNS pack name. Reserved scopes: `core.*` (spec-canonical), `vendor.<org>.*` (vendor-published), `community.<author>.*` (individual), `private.<host>.*` (host-internal \u2014 MUST NOT appear in `packs.openwop.dev`). `local.*` is for in-repo unpublished packs and MUST NOT appear in any registry. See node-packs.md \u00a7Naming for the full reservation table.",
|
|
47
47
|
"pattern": "^(core|vendor|community|private)\\.[a-z][a-z0-9_-]*(\\.[a-z][a-zA-Z0-9_-]*)+$",
|
|
48
48
|
"minLength": 1,
|
|
49
49
|
"maxLength": 256
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"openwop": {
|
|
91
91
|
"type": "string",
|
|
92
92
|
"pattern": "^>=\\d+(\\.\\d+){0,2} <\\d+\\.0\\.0$",
|
|
93
|
-
"description": "RFC 0177
|
|
93
|
+
"description": "RFC 0177 \u00a7A.1 \u2014 explicit upper bound required."
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
},
|
|
@@ -99,18 +99,18 @@
|
|
|
99
99
|
"additionalProperties": {
|
|
100
100
|
"type": "string"
|
|
101
101
|
},
|
|
102
|
-
"description": "Other node packs this pack depends on. Map of pack name
|
|
102
|
+
"description": "Other node packs this pack depends on. Map of pack name \u2192 semver range. Engine resolves transitively at workflow-register time."
|
|
103
103
|
},
|
|
104
104
|
"peerDependencies": {
|
|
105
105
|
"type": "object",
|
|
106
106
|
"additionalProperties": {
|
|
107
107
|
"type": "string"
|
|
108
108
|
},
|
|
109
|
-
"description": "Engine-supplied capabilities the pack consumes (e.g., a particular AI provider extension). Resolved against `Capabilities` at register time. Each entry is REQUIRED by default
|
|
109
|
+
"description": "Engine-supplied capabilities the pack consumes (e.g., a particular AI provider extension). Resolved against `Capabilities` at register time. Each entry is REQUIRED by default \u2014 an unmet entry fails install with `pack_peer_dependency_missing` \u2014 unless marked optional in `peerDependenciesMeta` (RFC 0072 \u00a7C)."
|
|
110
110
|
},
|
|
111
111
|
"peerDependenciesMeta": {
|
|
112
112
|
"type": "object",
|
|
113
|
-
"description": "Per-peer-dependency metadata (RFC 0072
|
|
113
|
+
"description": "Per-peer-dependency metadata (RFC 0072 \u00a7C). Keys mirror `peerDependencies` keys. Marking an entry `optional: true` makes it degrade-if-unmet instead of refuse-if-unmet: a host that does not satisfy it MUST install the pack with that capability inert AND surface it in the affected agents' inventory `degraded[]` (RFC 0072 \u00a7A); it MUST NOT silently ignore the declared dependency. Default (absent entry) is required. Packs published before RFC 0072 validate unchanged.",
|
|
114
114
|
"additionalProperties": {
|
|
115
115
|
"type": "object",
|
|
116
116
|
"additionalProperties": false,
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"type": "string",
|
|
129
129
|
"pattern": "^[a-z][A-Za-z0-9]*$"
|
|
130
130
|
},
|
|
131
|
-
"description": "Facets of the peer family the pack needs (packs.md
|
|
131
|
+
"description": "Facets of the peer family the pack needs (packs.md \u00a7Peer dependencies; RFC 0177 \u00a7B.1). Each MUST be a facet the declaration file lists for that family; the family key alone means the family's presence."
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -138,14 +138,14 @@
|
|
|
138
138
|
"items": {
|
|
139
139
|
"$ref": "#/$defs/PackNode"
|
|
140
140
|
},
|
|
141
|
-
"description": "Node typeIds the pack contributes. Each MUST have a unique `typeId` within the pack. A pack MAY omit `nodes` entirely if it ships only `agents[]`
|
|
141
|
+
"description": "Node typeIds the pack contributes. Each MUST have a unique `typeId` within the pack. A pack MAY omit `nodes` entirely if it ships only `agents[]` \u2014 the top-level `anyOf` constraint requires at least one of `nodes` or `agents` to be non-empty."
|
|
142
142
|
},
|
|
143
143
|
"agents": {
|
|
144
144
|
"type": "array",
|
|
145
145
|
"items": {
|
|
146
146
|
"$ref": "agent-manifest.schema.json"
|
|
147
147
|
},
|
|
148
|
-
"description": "Optional agent manifests shipped alongside this pack. Each entry is an AgentManifest (see agent-manifest.schema.json + RFC 0003
|
|
148
|
+
"description": "Optional agent manifests shipped alongside this pack. Each entry is an AgentManifest (see agent-manifest.schema.json + RFC 0003 \u00a7`agents[]` extension). Pure-agent packs MUST set `runtime.language: 'remote'` \u2014 agents are interpreted by the host, not bundled as executable artifacts. Mixed packs (nodes + agents) declare the runtime that loads the node implementations; agents remain host-interpreted."
|
|
149
149
|
},
|
|
150
150
|
"runtime": {
|
|
151
151
|
"$ref": "#/$defs/Runtime"
|
|
@@ -169,15 +169,12 @@
|
|
|
169
169
|
],
|
|
170
170
|
"properties": {
|
|
171
171
|
"typeId": {
|
|
172
|
-
"
|
|
173
|
-
"description": "Canonical node type ID. MUST match the same pattern as `WorkflowNode.typeId` in workflow-definition.schema.json. The pack's `name` prefix is recommended (e.g., a pack `vendor.acme.salesforce-tools` exposing `vendor.acme.salesforce.upsert`)."
|
|
174
|
-
"pattern": "^[a-z][a-zA-Z0-9._-]*$",
|
|
175
|
-
"minLength": 1,
|
|
176
|
-
"maxLength": 256
|
|
172
|
+
"$ref": "ids.schema.json#/$defs/typeId",
|
|
173
|
+
"description": "Canonical node type ID. MUST match the same pattern as `WorkflowNode.typeId` in workflow-definition.schema.json. The pack's `name` prefix is recommended (e.g., a pack `vendor.acme.salesforce-tools` exposing `vendor.acme.salesforce.upsert`)."
|
|
177
174
|
},
|
|
178
175
|
"version": {
|
|
179
176
|
"type": "string",
|
|
180
|
-
"description": "Per-node semver. MAY differ from the pack's overall version
|
|
177
|
+
"description": "Per-node semver. MAY differ from the pack's overall version \u2014 useful when a single pack ships multiple nodes that evolve independently."
|
|
181
178
|
},
|
|
182
179
|
"label": {
|
|
183
180
|
"type": "string",
|
|
@@ -236,7 +233,7 @@
|
|
|
236
233
|
"sensitive": {
|
|
237
234
|
"type": "boolean",
|
|
238
235
|
"default": false,
|
|
239
|
-
"description": "When true, the engine masks this output port's value in `node.completed` event payloads. Use when a NodeModule ALWAYS handles sensitive data (e.g., a Salesforce upsert always touches PII). Workflows MAY override per-instance via `WorkflowNode.outputSensitivity`. See observability.md
|
|
236
|
+
"description": "When true, the engine masks this output port's value in `node.completed` event payloads. Use when a NodeModule ALWAYS handles sensitive data (e.g., a Salesforce upsert always touches PII). Workflows MAY override per-instance via `WorkflowNode.outputSensitivity`. See observability.md \u00a7Privacy classification (closes O5)."
|
|
240
237
|
}
|
|
241
238
|
},
|
|
242
239
|
"additionalProperties": false
|
|
@@ -251,7 +248,7 @@
|
|
|
251
248
|
"type": "object",
|
|
252
249
|
"properties": {
|
|
253
250
|
"typeId": {
|
|
254
|
-
"
|
|
251
|
+
"$ref": "ids.schema.json#/$defs/typeId"
|
|
255
252
|
},
|
|
256
253
|
"syncOn": {
|
|
257
254
|
"type": "string",
|
|
@@ -305,7 +302,7 @@
|
|
|
305
302
|
},
|
|
306
303
|
"uniqueItems": true,
|
|
307
304
|
"maxItems": 32,
|
|
308
|
-
"description": "RFC 0031
|
|
305
|
+
"description": "RFC 0031 \u00a7B. Model capabilities this NodeModule requires the active model to advertise in `capabilities.modelCapabilities.advertised[]`. Distinct from `requires`, which gates on HOST capabilities (`capabilities.runtimeCapabilities[]`) \u2014 this field gates on MODEL capabilities. Spec-reserved identifiers: `structured-output`, `discriminator-enum`, `long-context`, `reasoning` (model-native thinking-tokens), `function-calling`. Host-private extensions MUST prefix with `x-host-<host>-` per `host-extensions.md` \u00a7\"Canonical-prefix table\". Empty array (or absent field) means no model-capability requirements. When the active model does not satisfy the declared set, the host MUST follow the dispatch flow in RFC 0031 \u00a7B: substitute to `fallbackModel` (emit `model.capability.substituted`) or refuse (emit `model.capability.insufficient` + terminate with `capability_not_provided`)."
|
|
309
306
|
},
|
|
310
307
|
"fallbackModel": {
|
|
311
308
|
"type": "object",
|
|
@@ -314,7 +311,7 @@
|
|
|
314
311
|
"provider",
|
|
315
312
|
"model"
|
|
316
313
|
],
|
|
317
|
-
"description": "RFC 0031
|
|
314
|
+
"description": "RFC 0031 \u00a7B. Substitute model coordinates the host MAY use if the active model lacks the declared `requiredModelCapabilities`. When the host substitutes, it MUST emit `model.capability.substituted` per RFC 0031 \u00a7D. Absent means no substitution permitted; the host MUST refuse to dispatch with `capability_not_provided` when capabilities are unmet. The fallback is single-shot \u2014 if the fallback itself fails capability checks or authentication, the host emits `model.capability.insufficient` with `fallbackAttempted: true` and refuses (no recursive fallback chains per RFC 0031 \u00a7\"Unresolved questions\" #3).",
|
|
318
315
|
"properties": {
|
|
319
316
|
"provider": {
|
|
320
317
|
"type": "string",
|
|
@@ -332,7 +329,7 @@
|
|
|
332
329
|
"additionalProperties": false,
|
|
333
330
|
"patternProperties": {
|
|
334
331
|
"^(openwop-|x-|vendor\\.)": {
|
|
335
|
-
"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`
|
|
332
|
+
"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` \u00a7\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque \u2014 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` \u00a7\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
336
333
|
}
|
|
337
334
|
}
|
|
338
335
|
},
|
|
@@ -478,7 +475,7 @@
|
|
|
478
475
|
"id",
|
|
479
476
|
"displayName"
|
|
480
477
|
],
|
|
481
|
-
"description": "RFC 0045. Declares this pack a named connector
|
|
478
|
+
"description": "RFC 0045. Declares this pack a named connector \u2014 a typed integration exposing actions (and reusing the existing trigger model). Optional; packs without it remain plain node packs. Actions are normal side-effectful nodes from this pack's `nodes[]` annotated with scheduler hints; the connector block adds metadata, not a new execution kind.",
|
|
482
479
|
"properties": {
|
|
483
480
|
"id": {
|
|
484
481
|
"type": "string",
|
|
@@ -504,8 +501,7 @@
|
|
|
504
501
|
],
|
|
505
502
|
"properties": {
|
|
506
503
|
"typeId": {
|
|
507
|
-
"
|
|
508
|
-
"minLength": 1,
|
|
504
|
+
"$ref": "ids.schema.json#/$defs/typeId",
|
|
509
505
|
"description": "MUST match a `nodes[].typeId` in this manifest."
|
|
510
506
|
},
|
|
511
507
|
"displayName": {
|
|
@@ -514,7 +510,7 @@
|
|
|
514
510
|
},
|
|
515
511
|
"idempotent": {
|
|
516
512
|
"type": "boolean",
|
|
517
|
-
"description": "Action is safe to auto-retry without an idempotency key. Absent/false
|
|
513
|
+
"description": "Action is safe to auto-retry without an idempotency key. Absent/false \u21d2 the host MUST NOT auto-retry without one (composes with idempotency.md)."
|
|
518
514
|
},
|
|
519
515
|
"rateLimit": {
|
|
520
516
|
"type": "object",
|
|
@@ -567,7 +563,7 @@
|
|
|
567
563
|
"wasm-component",
|
|
568
564
|
"remote"
|
|
569
565
|
],
|
|
570
|
-
"description": "How the engine loads the pack. See node-packs.md
|
|
566
|
+
"description": "How the engine loads the pack. See node-packs.md \u00a7runtime formats. `wasm` is the core-module WASM ABI (RFC 0008). `wasm-component` is the WASM Component Model variant (WIT-defined interfaces); hosts that advertise `capabilities.nodePackRuntimes.wasmComponent.supported: true` load it via wasmtime / wasmer Component Model runtimes. Both share the openwop ABI envelope; the wasm-component variant uses WIT interfaces instead of hand-rolled imports/exports."
|
|
571
567
|
},
|
|
572
568
|
"entry": {
|
|
573
569
|
"type": "string",
|
|
@@ -593,7 +589,7 @@
|
|
|
593
589
|
"requires": {
|
|
594
590
|
"type": "array",
|
|
595
591
|
"uniqueItems": true,
|
|
596
|
-
"description": "RFC 0076. Abstract platform primitives the pack's runtime code exercises, for install-time sandbox gating. Runtime-agnostic (not language builtin names). Absent or []
|
|
592
|
+
"description": "RFC 0076. Abstract platform primitives the pack's runtime code exercises, for install-time sandbox gating. Runtime-agnostic (not language builtin names). Absent or [] \u21d2 no elevated platform needs. A sandbox host MUST evaluate this at install time and refuse (`pack_runtime_requirement_unmet`) any primitive it will not grant; see node-packs.md \u00a7\"Runtime platform requirements\".",
|
|
597
593
|
"items": {
|
|
598
594
|
"oneOf": [
|
|
599
595
|
{
|
|
@@ -626,7 +622,7 @@
|
|
|
626
622
|
},
|
|
627
623
|
{
|
|
628
624
|
"const": "clock",
|
|
629
|
-
"description": "Reads wall-clock time as a behavioral input
|
|
625
|
+
"description": "Reads wall-clock time as a behavioral input \u2014 gated for REPLAY determinism, not access control. A pack that branches on the clock is non-deterministic on replay (replay.md)."
|
|
630
626
|
}
|
|
631
627
|
]
|
|
632
628
|
}
|
|
@@ -636,7 +632,7 @@
|
|
|
636
632
|
},
|
|
637
633
|
"Signing": {
|
|
638
634
|
"type": "object",
|
|
639
|
-
"description": "Optional signing metadata. See node-packs.md
|
|
635
|
+
"description": "Optional signing metadata. See node-packs.md \u00a7signing.",
|
|
640
636
|
"properties": {
|
|
641
637
|
"publicKeyRef": {
|
|
642
638
|
"type": "string",
|
|
@@ -660,8 +656,8 @@
|
|
|
660
656
|
},
|
|
661
657
|
"patternProperties": {
|
|
662
658
|
"^(openwop-|x-|vendor\\.)": {
|
|
663
|
-
"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`
|
|
659
|
+
"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` \u00a7\"Vendor-prefixed namespaces\", which requires a client receiving an unknown vendor-prefixed field to treat it as opaque \u2014 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` \u00a7\"Vendor extensions on pack manifests\" and the `pack-manifest-extension-opaque` invariant."
|
|
664
660
|
}
|
|
665
661
|
},
|
|
666
|
-
"x-openwop-anyOf-note": "constraint fragments (kind-conditional requirements)
|
|
662
|
+
"x-openwop-anyOf-note": "constraint fragments (kind-conditional requirements) \u2014 closure is the root's"
|
|
667
663
|
}
|