@openwop/spec-artifacts 2.0.0-rc.2 → 2.0.0-rc.29
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 +18 -18
- package/api/seams-v2.yaml +1 -1
- package/api/v2/asyncapi.yaml +1 -1
- package/api/v2/openapi.yaml +8 -7
- package/package.json +18 -5
- package/schemas/capabilities.schema.json +40 -1
- package/schemas/certification-bundle-v2.schema.json +119 -27
- package/schemas/run-snapshot.schema.json +103 -33
- package/schemas/v2/capabilities.schema.json +39 -0
- package/schemas/v2/certification-bundle.schema.json +1 -1
- package/schemas/v2/ids.schema.json +118 -21
- package/schemas/v2/run-event-payloads.schema.json +1 -1
- package/schemas/v2/run-event.schema.json +2 -126
- package/schemas/v2/run-snapshot.schema.json +22 -1
- package/spec/v1/core-standard-manifest.json +2 -2
- package/spec/v1/extensions.json +3 -2
- package/spec/v2/declaration.json +7 -0
- package/spec/v2/release.json +2 -2
package/CORPUS-STAMP.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Provenance of @openwop/spec-artifacts (RFC 0168 §D.2). files: SHA-256 per file; the conformance suite compares the installed peer against dist/spec-artifacts.lock.json at start.",
|
|
3
3
|
"package": "@openwop/spec-artifacts",
|
|
4
|
-
"version": "2.0.0-rc.
|
|
4
|
+
"version": "2.0.0-rc.29",
|
|
5
5
|
"corpusTag": null,
|
|
6
6
|
"files": {
|
|
7
7
|
"api/.redocly.lint-ignore.yaml": "bf5a8350b88a72fa43f59605ed8d903ed24b6cfccda5e45509c9f6ed9ee4e712",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"api/grpc/openwop.proto": "c3e72bb17cba514ee98feb6434e6c9b6ea6795bfd086489ec69fd882dd1ad977",
|
|
10
10
|
"api/openapi.yaml": "39081c59fb696159806b0f2f9a42e7e9ff830d622fcf2ad4159b21357580a955",
|
|
11
11
|
"api/redocly.yaml": "b0604c89b2ca6d5076ec25725c539dad44a741a811fe524439ee6daef8baa09f",
|
|
12
|
-
"api/seams-v2.yaml": "
|
|
13
|
-
"api/v2/asyncapi.yaml": "
|
|
14
|
-
"api/v2/openapi.yaml": "
|
|
12
|
+
"api/seams-v2.yaml": "db41292cd3c1c1e87270c04aacf6be9fa7726e28c25961ddcc0e5a77d69ffb2e",
|
|
13
|
+
"api/v2/asyncapi.yaml": "0fadad06111bdeb2a2724c448f78b9e5d9722ffc2b0b733854a168aa50321c67",
|
|
14
|
+
"api/v2/openapi.yaml": "2a2921c71ed5b5e9de0cf277b134b156e9a08c93b31725e799bbd38a04de8f7e",
|
|
15
15
|
"api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
|
|
16
16
|
"schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
|
|
17
17
|
"schemas/a2a-task-state.schema.json": "c9365918f993f943b4b619d42551eb066a1ed33a08d895d51b395432a5b1f1bc",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"schemas/artifact-type-pack-manifest.schema.json": "13932ea58e819e01b3a0cc7a65590b70683dd5fe9208fc06c64c339943d3c4ce",
|
|
32
32
|
"schemas/audit-verify-result.schema.json": "e8fd013fb610ba5db27ab0113ec2eb18e7da5f9310dd3de2dd3dc87a259c21fe",
|
|
33
33
|
"schemas/budget-policy.schema.json": "3d4fe30ae129fe136ab9ece395f2a2a42a76360786b1b9a1d5f1cbc753eb5b39",
|
|
34
|
-
"schemas/capabilities.schema.json": "
|
|
35
|
-
"schemas/certification-bundle-v2.schema.json": "
|
|
34
|
+
"schemas/capabilities.schema.json": "b413e0235cad412081df09234237e0f322a85903b7411b91aaff54032e946671",
|
|
35
|
+
"schemas/certification-bundle-v2.schema.json": "2f85530dd04824a15810c94e96869362dee1e78396eca21fdd18e5501416bb7d",
|
|
36
36
|
"schemas/channel-presence-payload.schema.json": "f9d0ef4219814c2b765baf3e68cbe5eea2cb42379f516a93a0459dcd5f7db47e",
|
|
37
37
|
"schemas/channel-written-payload.schema.json": "54723a56bc5a35232f64544ca686ac1ac959a5fb05b32b2401facca6b3ef51a3",
|
|
38
38
|
"schemas/chat-card-pack-manifest.schema.json": "402f7e9081cc39857a52e772061f4e034a957dcbc17501fe6e8e0bcb3d337e42",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"schemas/run-event.schema.json": "c70c06932b9831295042836213e617c8e946f20ddd49cf4e889b74d89d2175a8",
|
|
87
87
|
"schemas/run-options.schema.json": "f8241ece6ddc6527de9160d811d42c231b4f77b935f2e107b3c05608545c59ab",
|
|
88
88
|
"schemas/run-orchestrator-decided-event.schema.json": "17a43a3c44680a24d411141357a867b3caed6107d56de88fe2e062eaf93fa2c1",
|
|
89
|
-
"schemas/run-snapshot.schema.json": "
|
|
89
|
+
"schemas/run-snapshot.schema.json": "3343550f6973a0975c61624df569d341e843ac8592a2aa2b3b7cf540d72563ad",
|
|
90
90
|
"schemas/security-advisory.schema.json": "9c550f0bf10a3193dcca4a127081fb66fe5dc1b6f729c4c17bfaea3ba3ce05fc",
|
|
91
91
|
"schemas/self-hosted-runner-dispatch-frame.schema.json": "3f1d7edd572c6747657299525d8e85329b93b6fadf670e3a19c74d53e725adec",
|
|
92
92
|
"schemas/self-hosted-runner-registration.schema.json": "6c781adf1bb915a9e47796494f4a527353cbbf72b480e5a05be4aac65a6d0c6e",
|
|
@@ -115,8 +115,8 @@
|
|
|
115
115
|
"schemas/v2/artifact-type-pack-manifest.schema.json": "c911757562e521cb4f31a47c097f562573b64087efe60c8acb81fd352367d300",
|
|
116
116
|
"schemas/v2/audit-verify-result.schema.json": "cb54c4d89ba5dfb73f49aa8959a980be65c2dc2a87a12f71ba36d3e836fe85da",
|
|
117
117
|
"schemas/v2/budget-policy.schema.json": "c7449daeb6e1d95e7a047b8c2814d3d54748697c27046972834874867d9b5f4c",
|
|
118
|
-
"schemas/v2/capabilities.schema.json": "
|
|
119
|
-
"schemas/v2/certification-bundle.schema.json": "
|
|
118
|
+
"schemas/v2/capabilities.schema.json": "792669b2cc7b1fd44ce9a4fd3e79696ad1277734e29299a4504b39eda15913ed",
|
|
119
|
+
"schemas/v2/certification-bundle.schema.json": "d441198893c01cd14d84abe9c5bf591b69f47554db749c01899512f36cea11fa",
|
|
120
120
|
"schemas/v2/channel-presence-payload.schema.json": "9475d46f358d21c19126e78204987a5633979917a2293653354ef5c5e044d54e",
|
|
121
121
|
"schemas/v2/channel-written-payload.schema.json": "ccecff3c71a3275ad8db035ac0e04db25e6f8d23cf091ddbcd5a60d1be1cbb6b",
|
|
122
122
|
"schemas/v2/chat-card-pack-manifest.schema.json": "566982ce509a96d1619d58a72e383eff0773fe43fc65e4bfc85a4fe158f4eaff",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"schemas/v2/goal.schema.json": "d202ef21ed3dbff87c25fd4b553fa978862a3200999878d25c5918f6794b3060",
|
|
150
150
|
"schemas/v2/heartbeat-evaluated.schema.json": "4086b1ba1d0547c08b038dfb263ac89416a3e406430db1250156fb2f9b74f8d6",
|
|
151
151
|
"schemas/v2/heartbeat-state-changed.schema.json": "eb68d0082aa996650e3a6b8ccf32457f959cebc7e6728cc7c331b9d171a4bef6",
|
|
152
|
-
"schemas/v2/ids.schema.json": "
|
|
152
|
+
"schemas/v2/ids.schema.json": "dc6c99dea35a3416167b2b883ac08694794da1c7552bbfa48fc489c612d1cf97",
|
|
153
153
|
"schemas/v2/localized-content-language-settings.schema.json": "92240f19a2b4b2f05ab41a797f703485a28813848035478e72f395edd04c1d35",
|
|
154
154
|
"schemas/v2/localized-content-page-response.schema.json": "476b5f2775b42e35e679814a4ce846a7be1d5311d3a748c10df4275a78b0fb27",
|
|
155
155
|
"schemas/v2/localized-content-page.schema.json": "717bb51fbc64d0b34eb0a4b35c8b463d08d505267bf251b4cbc67e0a016a567a",
|
|
@@ -169,11 +169,11 @@
|
|
|
169
169
|
"schemas/v2/residency.schema.json": "af2658a7104cbcacd0e20a91226271c4a77f91ef46ae97612768fe743e6091d8",
|
|
170
170
|
"schemas/v2/run-ancestry-response.schema.json": "907e36341ba83a2147a5d76963950b6dcd47506b663ecbccae9dfa553f3724d3",
|
|
171
171
|
"schemas/v2/run-diff-response.schema.json": "6ab6cd265dc7e0a2086c6659c46aa0e7b43e6302949f0adac5d7deb1c7c0ecd3",
|
|
172
|
-
"schemas/v2/run-event-payloads.schema.json": "
|
|
173
|
-
"schemas/v2/run-event.schema.json": "
|
|
172
|
+
"schemas/v2/run-event-payloads.schema.json": "bd5cb6687828a86fb4411d331893ec183dce2c52cb27c22035d4cd7a8bc3c1a2",
|
|
173
|
+
"schemas/v2/run-event.schema.json": "1a9946374af9323b71635d00fed22abe02c300fa2cf3ae3e9c30f3e553e408ec",
|
|
174
174
|
"schemas/v2/run-options.schema.json": "6d6052596ab0f17acfb00fdfc89907da7724f952e5ffbe1f81d94ba23d4c77cd",
|
|
175
175
|
"schemas/v2/run-orchestrator-decided-event.schema.json": "bb76e15ff72e669f12938684033b55dc567470e1a378e19ffc3fa0e4034ab5a7",
|
|
176
|
-
"schemas/v2/run-snapshot.schema.json": "
|
|
176
|
+
"schemas/v2/run-snapshot.schema.json": "01408d8dac93e2d08d8db30f9cd7a4d903dce882a60bc1d48c3e6b921267f2a3",
|
|
177
177
|
"schemas/v2/security-advisory.schema.json": "6a382f737730a738d634266315e9d335e5760020a0cdd9f30727c2f987a01770",
|
|
178
178
|
"schemas/v2/self-hosted-runner-dispatch-frame.schema.json": "d8129f11d4e731d17ea951e66faaea2086081d13958b62ceaaa359fd6637dd7d",
|
|
179
179
|
"schemas/v2/self-hosted-runner-registration.schema.json": "93d60003a668cacb0eeac37699ca2884c6b79332d9494cb9e0a1752ac8f8a16c",
|
|
@@ -198,19 +198,19 @@
|
|
|
198
198
|
"schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
|
|
199
199
|
"spec/v1/alias-detectors.json": "fee4594ef49953953ffcd0b3813300067d16b3e65ebff2aac722034ac9b3f545",
|
|
200
200
|
"spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
|
|
201
|
-
"spec/v1/core-standard-manifest.json": "
|
|
201
|
+
"spec/v1/core-standard-manifest.json": "722518840db1d1d9ad3ed190dcb151537860e31e92c45649307945c79eb523f1",
|
|
202
202
|
"spec/v1/deprecations.json": "520d79927a8ed43ccf62c207a7cf6cf7b19b16e00bbbbdf0410667e939c19d85",
|
|
203
203
|
"spec/v1/deprecations.schema.json": "4cdbbb8eb9c0092913a5704c943880f0c8581bcf0f640a7df5a84105d53c8aee",
|
|
204
204
|
"spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
|
|
205
205
|
"spec/v1/event-codemap.schema.json": "d52caf29071e3784d4c20259cdbd5a7b533986548a440bb632a80b82cadd7ea5",
|
|
206
|
-
"spec/v1/extensions.json": "
|
|
206
|
+
"spec/v1/extensions.json": "79a60754aa16cbdbdb604f8e5c00038af535a1690a4d07bd5ff7c38f0256a7bc",
|
|
207
207
|
"spec/v1/gaps.json": "96ca051cb20f1a669b355d67a89421c56fef28aa5e6710c9519f592f26af33a3",
|
|
208
208
|
"spec/v1/gaps.schema.json": "8fd83259f556553c9df0f53e7a82ca8c2a4771d471197f69b4e2ae0ceeacfd66",
|
|
209
209
|
"spec/v1/migrations.json": "8839497d6a4830b53fa7867014a8336f0d725ef2346352e54fb580b7947897af",
|
|
210
210
|
"spec/v1/migrations.schema.json": "886779aa6c22e646db097f5df210adb018a4dd14a7b815465a18c8a7056c8f72",
|
|
211
211
|
"spec/v1/operation-path-manifest.json": "5f5f4e3842669371730ebbd1aace3fb794192615f0018dc144f484ba5db82ac3",
|
|
212
212
|
"spec/v1/spec-gaps.json": "6cc9962c6b969f632e07a78b52a4f61447ff579e2990cbae989866f584a86042",
|
|
213
|
-
"spec/v2/declaration.json": "
|
|
213
|
+
"spec/v2/declaration.json": "52b8c24a2dd463d44086129bf792ad108746f5102778cbbf0ff469fa534eca48",
|
|
214
214
|
"spec/v2/declaration.schema.json": "b0881a76228dfbd1b85a2ec7b7259a60197f768344535cdb475db6ff719b0e54",
|
|
215
215
|
"spec/v2/errors.json": "ad1725dc7c11002450e8abc682858eb5c11952a0718ea8ef6bdb2fb5ae6e7e21",
|
|
216
216
|
"spec/v2/event-codemap.json": "37869a03cdfd8758b57e6f350641a6ebbd383231cebda51f5473ad85f94ab74c",
|
|
@@ -228,7 +228,7 @@
|
|
|
228
228
|
"spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
|
|
229
229
|
"spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
|
|
230
230
|
"spec/v2/profiles.json": "1f0ee40491131cf561ef19a0394c47ba476b4567514fe16befb6cada4a10a5a4",
|
|
231
|
-
"spec/v2/release.json": "
|
|
231
|
+
"spec/v2/release.json": "38cf198fc25ff7af322a1781bd128bc31e8c213194436ba538e6e065170ddc09"
|
|
232
232
|
},
|
|
233
|
-
"corpusCommit": "
|
|
233
|
+
"corpusCommit": "9e0c76b709aed18afa85f6b84250418047861f5a"
|
|
234
234
|
}
|
package/api/seams-v2.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: OpenWOP conformance seams profile (openwop-conformance-seams-v2)
|
|
4
|
-
version: 2.0.0-rc.
|
|
4
|
+
version: 2.0.0-rc.29
|
|
5
5
|
description: 'GENERATED by scripts/derive-v2-api.py. RFC 0168 §C: the seams are a versioned conformance profile with their
|
|
6
6
|
own document and path space (/conformance/seams/…), validated against the canonical v2 schemas with no tolerance path,
|
|
7
7
|
forbidden from the capability namespace (a host advertises the profile, never a testSeams flag). This document carries
|
package/api/v2/asyncapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
asyncapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: OpenWOP v2 event streams
|
|
4
|
-
version: 2.0.0-rc.
|
|
4
|
+
version: 2.0.0-rc.29
|
|
5
5
|
description: GENERATED by scripts/derive-v2-api.py (RFC 0171 §E.1, RFC 0172 §C.2). One run-events channel whose address
|
|
6
6
|
is the OpenAPI path key; the server pathname is empty (bare origin). streamMode is a pattern over the closed set and its
|
|
7
7
|
comma-separated combinations (`values` never combines). hostEvents has a real address (RFC 0171 §E.1) — the documented
|
package/api/v2/openapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: OpenWOP v2 API
|
|
4
|
-
version: 2.0.0-rc.
|
|
4
|
+
version: 2.0.0-rc.29
|
|
5
5
|
summary: REST surface for declaring, executing, suspending, resuming, and observing multi-step workflows.
|
|
6
6
|
description: GENERATED by scripts/derive-v2-api.py from api/openapi.yaml and the RFC 0167 children (v2 charter Phase 3,
|
|
7
7
|
P3-C). Bare origin, unversioned path keys, negotiation by `OpenWOP-Version` + `protocolVersions[]` (RFC 0172 §A). No seam
|
|
@@ -3046,17 +3046,18 @@ components:
|
|
|
3046
3046
|
name: workflowId
|
|
3047
3047
|
required: true
|
|
3048
3048
|
schema:
|
|
3049
|
-
|
|
3050
|
-
minLength: 1
|
|
3051
|
-
maxLength: 128
|
|
3049
|
+
$ref: ../../schemas/v2/ids.schema.json#/$defs/workflowId
|
|
3052
3050
|
RunId:
|
|
3053
3051
|
in: path
|
|
3054
3052
|
name: runId
|
|
3055
3053
|
required: true
|
|
3056
3054
|
schema:
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3055
|
+
$ref: ../../schemas/v2/ids.schema.json#/$defs/runId
|
|
3056
|
+
description: 'Tenant-bound `<tenantId>/<opaque>` (`identity.md` §5). The `/` is part of the
|
|
3057
|
+
|
|
3058
|
+
identifier and MUST be percent-encoded as `%2F` in the path segment.
|
|
3059
|
+
|
|
3060
|
+
'
|
|
3060
3061
|
IdempotencyKey:
|
|
3061
3062
|
in: header
|
|
3062
3063
|
name: Idempotency-Key
|
package/package.json
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwop/spec-artifacts",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
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
|
|
3
|
+
"version": "2.0.0-rc.29",
|
|
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 \u2014 published from the openwop/openwop corpus tag; the peer dependency @openwop/openwop-conformance digest-checks at start (RFC 0168 \u00a7D.2).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
-
"repository": {
|
|
7
|
-
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/openwop/openwop.git",
|
|
9
|
+
"directory": "spec-artifacts"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"api",
|
|
13
|
+
"schemas",
|
|
14
|
+
"spec",
|
|
15
|
+
"CORPUS-STAMP.json",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
8
19
|
"sideEffects": false,
|
|
9
|
-
"publishConfig": {
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
}
|
|
10
23
|
}
|
|
@@ -1089,7 +1089,7 @@
|
|
|
1089
1089
|
"confidenceEscalationFloor": {
|
|
1090
1090
|
"type": "number",
|
|
1091
1091
|
"minimum": 0.5,
|
|
1092
|
-
"maximum": 1
|
|
1092
|
+
"maximum": 1,
|
|
1093
1093
|
"description": "RFC 0039 §A. Operator-declared confidence floor at or above the spec floor of 0.5; when an OrchestratorDecision carries `confidence` below this floor, the host MUST escalate via a `clarify` or `escalate` interrupt instead of executing the decision. Absent: the spec floor 0.5 applies. Values < 0.5 are non-conformant; values > 1.0 are nonsense. Applies only when `version >= 2`."
|
|
1094
1094
|
},
|
|
1095
1095
|
"confidenceEscalationInterruptKind": {
|
|
@@ -4154,6 +4154,45 @@
|
|
|
4154
4154
|
"description": "RFC 0114. Host delivers RFC 6902 (`a2ui-surface-delta-frame.schema.json`) delta frames over the run event stream to subscribers that negotiate `?a2uiDelta=1`; the full surface is materialized for everyone else, the event-log read, and replay. The recorded `ui.a2ui-surface` envelope stays full. The consumer re-validates the post-patch surface against the closed `catalogVersion` catalog before render and falls back fail-closed on any apply/validation failure (the host then re-materializes full)."
|
|
4155
4155
|
}
|
|
4156
4156
|
}
|
|
4157
|
+
},
|
|
4158
|
+
"signingKeys": {
|
|
4159
|
+
"type": "array",
|
|
4160
|
+
"description": "RFC 0168 §E.2, v1.x additive half (the same shape RFC 0179 used for root `preferredVersion`). The public keys this host signs certification bundles with; a bundle signature names a `keyId` and a verifier resolves it HERE. OPTIONAL in v1.x. It belongs on the v1 root and not only the v2 root because a certification bundle is v3 REGARDLESS OF MAJOR: under the one-package decision (RFC 0168 §D.3) a v1 host measured by a 2.x suite at `--target-major 1` emits a v3 bundle whose signature needs attribution exactly as much as a v2 host does, and a v1-only host has only this document to hand a verifier. Without it, every v1 host bundle is permanently unattributable: the signature attests INTEGRITY only — that the bundle was not altered after signing — and says nothing about who signed it, because a signer can mint a keypair and a key id at will. A host that publishes no key MUST NOT be read as having made a verifiable claim.",
|
|
4161
|
+
"items": {
|
|
4162
|
+
"type": "object",
|
|
4163
|
+
"required": [
|
|
4164
|
+
"keyId",
|
|
4165
|
+
"alg",
|
|
4166
|
+
"publicKey"
|
|
4167
|
+
],
|
|
4168
|
+
"properties": {
|
|
4169
|
+
"keyId": {
|
|
4170
|
+
"type": "string",
|
|
4171
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}$",
|
|
4172
|
+
"description": "The identifier a bundle signature carries in `signature.keyId`. Unique within this array."
|
|
4173
|
+
},
|
|
4174
|
+
"alg": {
|
|
4175
|
+
"const": "ed25519",
|
|
4176
|
+
"description": "RFC 0168 §E.2 fixes the attestation algorithm; no other value is defined."
|
|
4177
|
+
},
|
|
4178
|
+
"publicKey": {
|
|
4179
|
+
"type": "string",
|
|
4180
|
+
"pattern": "^[A-Za-z0-9_-]{43}$",
|
|
4181
|
+
"description": "The Ed25519 public key: raw 32 bytes, base64url, unpadded — NOT PEM. One encoding on purpose; admitting two would mean every verifier handles both. Note that a plausible 43-character string can still fail to import as a curve point, so a publisher SHOULD verify the value imports as a real Ed25519 key rather than only checking its shape."
|
|
4182
|
+
},
|
|
4183
|
+
"use": {
|
|
4184
|
+
"enum": [
|
|
4185
|
+
"certification-bundle"
|
|
4186
|
+
],
|
|
4187
|
+
"description": "What the key signs. Closed, so a future use is an explicit addition rather than a reinterpretation of a key already published for something else."
|
|
4188
|
+
},
|
|
4189
|
+
"retiredAt": {
|
|
4190
|
+
"type": "string",
|
|
4191
|
+
"format": "date-time",
|
|
4192
|
+
"description": "When the key stopped signing. A retired key MUST stay listed: dropping it silently invalidates every bundle it already signed, which is the opposite of what an evidence trail is for."
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4157
4196
|
}
|
|
4158
4197
|
},
|
|
4159
4198
|
"additionalProperties": true
|
|
@@ -5,26 +5,58 @@
|
|
|
5
5
|
"description": "A certification bundle that records what EXECUTED, not merely what passed.\n\nThe v1 bundle carried `{passed, failed, skipped}` scenario-file lists. Those three cannot express the distinction the whole program turns on: a scenario file counted as `passed` whether its assertions ran or its runner returned early, and a `skipped` entry could mean 'the operator excluded this', 'the requirement does not apply', or 'we could not check' — three claims with different consequences flattened into one word.\n\nv2 replaces the lists with per-requirement dispositions from RFC 0148 §A, and adds the counts §A.4 requires so a reader can tell a thorough run from a thin one without re-running it. `blocked` is its own total precisely because it is the one that invalidates a claim.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": true,
|
|
8
|
-
"required": [
|
|
8
|
+
"required": [
|
|
9
|
+
"bundleVersion",
|
|
10
|
+
"suite",
|
|
11
|
+
"host",
|
|
12
|
+
"discovery",
|
|
13
|
+
"claimedProfiles",
|
|
14
|
+
"results",
|
|
15
|
+
"scenarioManifestSha256",
|
|
16
|
+
"targetConfigurationSha256"
|
|
17
|
+
],
|
|
9
18
|
"properties": {
|
|
10
|
-
"bundleVersion": {
|
|
19
|
+
"bundleVersion": {
|
|
20
|
+
"const": "2"
|
|
21
|
+
},
|
|
11
22
|
"suite": {
|
|
12
23
|
"type": "object",
|
|
13
24
|
"additionalProperties": false,
|
|
14
|
-
"required": [
|
|
25
|
+
"required": [
|
|
26
|
+
"package",
|
|
27
|
+
"version"
|
|
28
|
+
],
|
|
15
29
|
"properties": {
|
|
16
|
-
"package": {
|
|
17
|
-
|
|
30
|
+
"package": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"minLength": 1
|
|
33
|
+
},
|
|
34
|
+
"version": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z.-]+)?$",
|
|
37
|
+
"description": "The suite version that produced this bundle. A SemVer prerelease is admitted because RFC 0168 §D.3 makes the 2.x suite one package with `--target-major`: a v1 host measured by a prerelease 2.x suite legitimately emits a v2 bundle whose `suite.version` is `2.0.0-rc.N`. The original three-part-only pattern predates that decision and made such a bundle unvalidatable — found in Phase 4 when a host pinned to the RC line tried to certify."
|
|
38
|
+
}
|
|
18
39
|
}
|
|
19
40
|
},
|
|
20
41
|
"host": {
|
|
21
42
|
"type": "object",
|
|
22
43
|
"additionalProperties": true,
|
|
23
|
-
"required": [
|
|
44
|
+
"required": [
|
|
45
|
+
"name",
|
|
46
|
+
"version"
|
|
47
|
+
],
|
|
24
48
|
"properties": {
|
|
25
|
-
"name": {
|
|
26
|
-
|
|
27
|
-
|
|
49
|
+
"name": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"minLength": 1
|
|
52
|
+
},
|
|
53
|
+
"version": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"minLength": 1
|
|
56
|
+
},
|
|
57
|
+
"vendor": {
|
|
58
|
+
"type": "string"
|
|
59
|
+
},
|
|
28
60
|
"commit": {
|
|
29
61
|
"type": "string",
|
|
30
62
|
"minLength": 1,
|
|
@@ -40,41 +72,80 @@
|
|
|
40
72
|
"discovery": {
|
|
41
73
|
"type": "object",
|
|
42
74
|
"additionalProperties": true,
|
|
43
|
-
"required": [
|
|
75
|
+
"required": [
|
|
76
|
+
"sha256",
|
|
77
|
+
"document"
|
|
78
|
+
],
|
|
44
79
|
"properties": {
|
|
45
|
-
"url": {
|
|
46
|
-
|
|
47
|
-
|
|
80
|
+
"url": {
|
|
81
|
+
"type": "string"
|
|
82
|
+
},
|
|
83
|
+
"sha256": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
86
|
+
},
|
|
87
|
+
"document": {
|
|
88
|
+
"type": "object"
|
|
89
|
+
}
|
|
48
90
|
}
|
|
49
91
|
},
|
|
50
92
|
"claimedProfiles": {
|
|
51
93
|
"type": "array",
|
|
52
94
|
"minItems": 1,
|
|
53
95
|
"uniqueItems": true,
|
|
54
|
-
"items": {
|
|
96
|
+
"items": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"pattern": "^openwop-[a-z0-9-]+$"
|
|
99
|
+
},
|
|
55
100
|
"description": "RFC 0155 §E — canonical profile IDs only. Deprecated aliases go in `aliases`, never here, so a badge cannot be substantiated by a name that no longer means what it did."
|
|
56
101
|
},
|
|
57
102
|
"aliases": {
|
|
58
103
|
"type": "array",
|
|
59
104
|
"uniqueItems": true,
|
|
60
|
-
"items": {
|
|
105
|
+
"items": {
|
|
106
|
+
"type": "string"
|
|
107
|
+
}
|
|
61
108
|
},
|
|
62
109
|
"results": {
|
|
63
110
|
"type": "object",
|
|
64
111
|
"additionalProperties": false,
|
|
65
|
-
"required": [
|
|
112
|
+
"required": [
|
|
113
|
+
"totals",
|
|
114
|
+
"requirements"
|
|
115
|
+
],
|
|
66
116
|
"properties": {
|
|
67
117
|
"totals": {
|
|
68
118
|
"type": "object",
|
|
69
119
|
"additionalProperties": false,
|
|
70
|
-
"required": [
|
|
120
|
+
"required": [
|
|
121
|
+
"executedPass",
|
|
122
|
+
"executedFail",
|
|
123
|
+
"skipped",
|
|
124
|
+
"inapplicable",
|
|
125
|
+
"blocked"
|
|
126
|
+
],
|
|
71
127
|
"description": "RFC 0148 §A/§C. All five are REQUIRED — an omitted total is indistinguishable from zero, and `blocked: 0` asserted is a different claim from `blocked` unstated.",
|
|
72
128
|
"properties": {
|
|
73
|
-
"executedPass": {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"
|
|
129
|
+
"executedPass": {
|
|
130
|
+
"type": "integer",
|
|
131
|
+
"minimum": 0
|
|
132
|
+
},
|
|
133
|
+
"executedFail": {
|
|
134
|
+
"type": "integer",
|
|
135
|
+
"minimum": 0
|
|
136
|
+
},
|
|
137
|
+
"skipped": {
|
|
138
|
+
"type": "integer",
|
|
139
|
+
"minimum": 0
|
|
140
|
+
},
|
|
141
|
+
"inapplicable": {
|
|
142
|
+
"type": "integer",
|
|
143
|
+
"minimum": 0
|
|
144
|
+
},
|
|
145
|
+
"blocked": {
|
|
146
|
+
"type": "integer",
|
|
147
|
+
"minimum": 0
|
|
148
|
+
}
|
|
78
149
|
}
|
|
79
150
|
},
|
|
80
151
|
"requirements": {
|
|
@@ -84,17 +155,38 @@
|
|
|
84
155
|
"items": {
|
|
85
156
|
"type": "object",
|
|
86
157
|
"additionalProperties": false,
|
|
87
|
-
"required": [
|
|
158
|
+
"required": [
|
|
159
|
+
"requirementId",
|
|
160
|
+
"scenarioId",
|
|
161
|
+
"disposition"
|
|
162
|
+
],
|
|
88
163
|
"properties": {
|
|
89
|
-
"requirementId": {
|
|
90
|
-
|
|
91
|
-
|
|
164
|
+
"requirementId": {
|
|
165
|
+
"type": "string",
|
|
166
|
+
"minLength": 1
|
|
167
|
+
},
|
|
168
|
+
"scenarioId": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"minLength": 1
|
|
171
|
+
},
|
|
172
|
+
"disposition": {
|
|
173
|
+
"enum": [
|
|
174
|
+
"executed-pass",
|
|
175
|
+
"executed-fail",
|
|
176
|
+
"skipped",
|
|
177
|
+
"inapplicable",
|
|
178
|
+
"blocked"
|
|
179
|
+
]
|
|
180
|
+
},
|
|
92
181
|
"assertionCount": {
|
|
93
182
|
"type": "integer",
|
|
94
183
|
"minimum": 0,
|
|
95
184
|
"description": "How many assertions actually ran. `executed-pass` with `assertionCount: 0` is the vacuous pass this program exists to close, and a reader can now see it."
|
|
96
185
|
},
|
|
97
|
-
"witnessSha256": {
|
|
186
|
+
"witnessSha256": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
189
|
+
},
|
|
98
190
|
"detail": {
|
|
99
191
|
"type": "string",
|
|
100
192
|
"description": "Required by RFC 0148 §A for any disposition other than `executed-pass` — an unexplained `blocked` is an outcome nobody can act on."
|
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
"title": "RunSnapshot",
|
|
5
5
|
"description": "Projected run state returned by `GET /v1/runs/{runId}`. Source is the run's append-only event log (run-event.schema.json) folded through the `RunProjection`. Forward-compat tolerant: readers MUST ignore unknown fields rather than reject.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"runId",
|
|
9
|
+
"workflowId",
|
|
10
|
+
"status"
|
|
11
|
+
],
|
|
8
12
|
"properties": {
|
|
9
13
|
"runId": {
|
|
10
14
|
"type": "string",
|
|
@@ -31,50 +35,82 @@
|
|
|
31
35
|
"cancelling",
|
|
32
36
|
"cancelled"
|
|
33
37
|
],
|
|
34
|
-
"description": "Current run state. `waiting-external` MUST be used when the suspended interrupt's `kind` is `external-event` per `interrupt-profiles.md
|
|
38
|
+
"description": "Current run state. `waiting-external` MUST be used when the suspended interrupt's `kind` is `external-event` per `interrupt-profiles.md \u00a7openwop-interrupt-external-event` \u2014 distinguishes external-event waits from HITL waits at the wire level. `cancelling` (RFC 0094 \u00a7B) is the transitional state between a cancel request being accepted and the terminal `cancelled` \u2014 `rest-endpoints.md` and the OpenAPI cancel responses already document the transition; a snapshot read during the cancel cascade carries it. Forward-compat: future statuses MAY be added; readers SHOULD treat unknown values as terminal-unknown rather than throw."
|
|
35
39
|
},
|
|
36
40
|
"compensationStatus": {
|
|
37
41
|
"type": "string",
|
|
38
|
-
"enum": [
|
|
39
|
-
|
|
42
|
+
"enum": [
|
|
43
|
+
"none",
|
|
44
|
+
"pending",
|
|
45
|
+
"running",
|
|
46
|
+
"completed",
|
|
47
|
+
"partial",
|
|
48
|
+
"failed",
|
|
49
|
+
"manual"
|
|
50
|
+
],
|
|
51
|
+
"description": "RFC 0151 \u00a7D \u2014 the run's compensation (unwind) rollup, kept separate from `status` on purpose: `status` is the FORWARD execution state and a closed union exported by the SDK, so RFC 0151 forbids reinterpreting it (there is deliberately no `compensating` run status). OPTIONAL and capability-gated \u2014 a host that does not advertise `capabilities.compensation` MUST omit this field; a host that advertises it MUST include it on every snapshot, `none` when no compensation was ever requested for the run. Presence is therefore a wire witness of the advert, and a `none` cannot be read as \"unwind is monitored here\" from a host that would never unwind. Values are the deterministic fold of the six `compensation.*` events over the persisted plan, defined normatively in `spec/v1/compensation.md \u00a7\"Run rollup: compensationStatus\"`: `none` (no `compensation.requested`), `pending` (requested, no `started`), `running` (started, plan active \u2014 a \u00a7E approval pause does NOT change it; the run's own `status: waiting-approval` carries the wait), `completed` (every inverse action completed), `partial` (plan inactive; some completed and some did not \u2014 reported, never rounded), `failed` (plan inactive; none completed), `manual` (`manual_intervention_required` recorded and unresolved; takes precedence over `partial`/`failed` while unresolved). Content-free by construction. Resolves RFC 0151 UQ3: `RunSnapshot` (`GET /v1/runs/{runId}`) is the sole owner; debug bundles and the AsyncAPI `run.snapshot` reuse it by `$ref`."
|
|
40
52
|
},
|
|
41
53
|
"owner": {
|
|
42
54
|
"type": "object",
|
|
43
|
-
"description": "RFC 0048. The identity triple that owns this run. Redaction-safe
|
|
44
|
-
"required": [
|
|
55
|
+
"description": "RFC 0048. The identity triple that owns this run. Redaction-safe \u2014 `principal` is an opaque identifier, never PII or credential material. Optional: single-tenant hosts omit it. A principal scoped to one `workspace` MUST NOT read a run owned by another (`run_forbidden`).",
|
|
56
|
+
"required": [
|
|
57
|
+
"tenant"
|
|
58
|
+
],
|
|
45
59
|
"properties": {
|
|
46
|
-
"tenant": {
|
|
47
|
-
|
|
48
|
-
|
|
60
|
+
"tenant": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"minLength": 1,
|
|
63
|
+
"description": "Top-level isolation boundary."
|
|
64
|
+
},
|
|
65
|
+
"workspace": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"minLength": 1,
|
|
68
|
+
"description": "Optional sub-tenant within the tenant (RFC 0048 workspace)."
|
|
69
|
+
},
|
|
70
|
+
"principal": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"minLength": 1,
|
|
73
|
+
"description": "Acting identity (user or agent) \u2014 opaque id, never PII."
|
|
74
|
+
},
|
|
49
75
|
"subject": {
|
|
50
76
|
"$ref": "subject.schema.json",
|
|
51
77
|
"description": "RFC 0165 \u00a7B. OPTIONAL issuer-scoped Subject record for the acting identity. When present: `subject.tenant` MUST equal `tenant`, `subject.subjectId` MUST equal `principal` when both are present, `subject.kind` MUST equal `principalKind` when both are present. A host that emits it on new runs synthesizes `issuer: \"urn:openwop:legacy\"` for runs that predate emission (\u00a7B.3) and copies it verbatim onto forks (\u00a7B.4)."
|
|
52
78
|
},
|
|
53
79
|
"principalKind": {
|
|
54
80
|
"type": "string",
|
|
55
|
-
"enum": [
|
|
56
|
-
|
|
81
|
+
"enum": [
|
|
82
|
+
"user",
|
|
83
|
+
"agent",
|
|
84
|
+
"anonymous"
|
|
85
|
+
],
|
|
86
|
+
"description": "RFC 0132. The kind of the acting principal. OPTIONAL and EXPLICIT \u2014 absent \u21d2 unconstrained (today's RFC 0048 behavior; a host that does not distinguish kinds omits it). `anonymous` \u21d2 the RFC 0132 \u00a7A anonymous-actor rules and the \u00a7C default-deny per-surface grant bind: the `principal` id MUST be opaque, origin-bound, ephemeral, non-cross-linkable, non-PII, and never inherit a role or a default-on tool baseline. A host that advertises `capabilities.anonymousActor` and dispatches through a public surface MUST set `anonymous` on the resulting run. Resolves RFC 0048 \u00a7Unresolved-Q1 for the anonymous case."
|
|
57
87
|
}
|
|
58
88
|
},
|
|
59
89
|
"additionalProperties": false
|
|
60
90
|
},
|
|
61
91
|
"currentNodeId": {
|
|
62
92
|
"type": "string",
|
|
63
|
-
"description": "Set when the run is suspended at a specific node (`waiting-approval` / `waiting-input` / `waiting-external`)
|
|
93
|
+
"description": "Set when the run is suspended at a specific node (`waiting-approval` / `waiting-input` / `waiting-external`) \u2014 identifies which node holds the interrupt."
|
|
94
|
+
},
|
|
95
|
+
"startedAt": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"format": "date-time"
|
|
98
|
+
},
|
|
99
|
+
"completedAt": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"format": "date-time"
|
|
64
102
|
},
|
|
65
|
-
"startedAt": { "type": "string", "format": "date-time" },
|
|
66
|
-
"completedAt": { "type": "string", "format": "date-time" },
|
|
67
103
|
"agent": {
|
|
68
104
|
"$ref": "agent-ref.schema.json",
|
|
69
|
-
"description": "Optional run-level agent identity (Multi-Agent Shift Phase 1). When the run is driven by a single agent, this field carries that agent's `AgentRef`. In supervisor-orchestrated runs (Phase 5), this field rotates as workers hand off
|
|
105
|
+
"description": "Optional run-level agent identity (Multi-Agent Shift Phase 1). When the run is driven by a single agent, this field carries that agent's `AgentRef`. In supervisor-orchestrated runs (Phase 5), this field rotates as workers hand off \u2014 it always carries the active worker for the current node. See `runOrchestrator` for the run-lifetime supervisor identity. Absent for runs with no agent provenance (legacy single-actor host)."
|
|
70
106
|
},
|
|
71
107
|
"runOrchestrator": {
|
|
72
108
|
"$ref": "agent-ref.schema.json",
|
|
73
|
-
"description": "Optional orchestrator-supervisor identity (Multi-Agent Shift Phase 5). When set, this agent owns dispatch decisions across the run's lifetime; `runOrchestrator.decided` events emitted during the run carry this agent's `agentId`. Distinct from `agent`
|
|
109
|
+
"description": "Optional orchestrator-supervisor identity (Multi-Agent Shift Phase 5). When set, this agent owns dispatch decisions across the run's lifetime; `runOrchestrator.decided` events emitted during the run carry this agent's `agentId`. Distinct from `agent` \u2014 `agent` rotates with each worker; `runOrchestrator` is set at run start (or first `core.orchestrator.supervisor` node) and MUST NOT change for the run's lifetime. In single-agent runs (no supervisor), this field is absent; in supervisor runs both fields MAY co-exist."
|
|
74
110
|
},
|
|
75
111
|
"nodeStates": {
|
|
76
112
|
"type": "object",
|
|
77
|
-
"description": "Per-node state map. Keys are nodeIds; values are implementation-shaped state objects. Spec doesn't constrain the inner shape
|
|
113
|
+
"description": "Per-node state map. Keys are nodeIds; values are implementation-shaped state objects. Spec doesn't constrain the inner shape \u2014 see version-negotiation.md \u00a7node-states."
|
|
78
114
|
},
|
|
79
115
|
"variables": {
|
|
80
116
|
"type": "object",
|
|
@@ -87,26 +123,40 @@
|
|
|
87
123
|
"error": {
|
|
88
124
|
"type": "object",
|
|
89
125
|
"description": "Set on terminal `failed`. Structured so consumers can route on code without parsing message text.",
|
|
90
|
-
"required": [
|
|
126
|
+
"required": [
|
|
127
|
+
"code",
|
|
128
|
+
"message"
|
|
129
|
+
],
|
|
91
130
|
"properties": {
|
|
92
|
-
"code": {
|
|
93
|
-
|
|
94
|
-
|
|
131
|
+
"code": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"minLength": 1
|
|
134
|
+
},
|
|
135
|
+
"message": {
|
|
136
|
+
"type": "string",
|
|
137
|
+
"minLength": 1
|
|
138
|
+
},
|
|
139
|
+
"details": {
|
|
140
|
+
"type": "object"
|
|
141
|
+
}
|
|
95
142
|
},
|
|
96
143
|
"additionalProperties": false
|
|
97
144
|
},
|
|
98
145
|
"engineVersion": {
|
|
99
|
-
"type": "
|
|
100
|
-
"description": "Engine version the run was started under. Used by the projection for forward-compat folds."
|
|
146
|
+
"type": "number",
|
|
147
|
+
"description": "Engine version the run was started under. Used by the projection for forward-compat folds. TYPE CORRECTED 2026-09-04: this was `string`, contradicting version-negotiation.md \u00a7Stamping \u2014 \"Every persisted run document MUST carry an `engineVersion: number` field\" \u2014 so a host obeying the prose emitted a document failing its own schema, and a host obeying the schema violated the MUST. Unimplementable as written. `spec/v1/extensions.json` already described the axis as \"a number, not a feature\", and schemas/v2 types it `integer` (RFC 0172 \u00a7B axis 3), so prose, register and v2 agreed and only this file dissented. Safe to correct: measured on both production hosts 2026-09-04, NEITHER emits the field at all, so no existing document is invalidated."
|
|
101
148
|
},
|
|
102
149
|
"eventLogSchemaVersion": {
|
|
103
150
|
"type": "integer",
|
|
104
151
|
"minimum": 0,
|
|
105
|
-
"description": "Per-run event-log subcollection schema version. See version-negotiation.md."
|
|
152
|
+
"description": "Per-run event-log subcollection schema version. See version-negotiation.md. `minimum: 0` is DELIBERATE and MUST NOT be raised to 2 in v1: \u00a7Legacy detection identifies a legacy run as one whose value is \"undefined or < 2\", so a legacy document carrying 0 or 1 is contemplated by the contract and MUST still validate. schemas/v2 uses `minimum: 2` correctly, because the v2 era key admits only 2 and 3."
|
|
106
153
|
},
|
|
107
154
|
"tags": {
|
|
108
155
|
"type": "array",
|
|
109
|
-
"items": {
|
|
156
|
+
"items": {
|
|
157
|
+
"type": "string",
|
|
158
|
+
"maxLength": 256
|
|
159
|
+
},
|
|
110
160
|
"maxItems": 100,
|
|
111
161
|
"description": "Caller-supplied tags from `RunOptions.tags`."
|
|
112
162
|
},
|
|
@@ -120,24 +170,44 @@
|
|
|
120
170
|
},
|
|
121
171
|
"metrics": {
|
|
122
172
|
"type": "object",
|
|
123
|
-
"description": "Aggregate run-level metrics. Forward-compat: readers MUST tolerate missing/unknown fields. Fields are populated lazily as the engine emits them
|
|
173
|
+
"description": "Aggregate run-level metrics. Forward-compat: readers MUST tolerate missing/unknown fields. Fields are populated lazily as the engine emits them \u2014 absence does NOT mean zero. Implementation-specific fields (e.g., legacy `cost: number` estimates) MAY appear alongside the spec-canonical fields below.",
|
|
124
174
|
"properties": {
|
|
125
175
|
"openwopCost": {
|
|
126
176
|
"type": "object",
|
|
127
|
-
"description": "Spec-canonical cost rollup aggregated from per-node `recordCost()` calls. Keys mirror the `openwop.cost.*` OTel attribute allowlist (see `observability.md`
|
|
177
|
+
"description": "Spec-canonical cost rollup aggregated from per-node `recordCost()` calls. Keys mirror the `openwop.cost.*` OTel attribute allowlist (see `observability.md` \u00a7Cost attribution). Named `openwopCost` rather than `cost` because some implementations carry a legacy `metrics.cost: number` estimate that predates the typed rollup; using a distinct name avoids collision. Multi-provider runs report `provider`/`model` of the LAST contributing call; SDKs that need per-call detail SHOULD subscribe to OTel spans instead of reading this rollup.",
|
|
128
178
|
"properties": {
|
|
129
|
-
"usd": {
|
|
179
|
+
"usd": {
|
|
180
|
+
"type": "number",
|
|
181
|
+
"minimum": 0,
|
|
182
|
+
"description": "Total USD cost across all node-level recordCost emissions."
|
|
183
|
+
},
|
|
130
184
|
"tokens": {
|
|
131
185
|
"type": "object",
|
|
132
186
|
"properties": {
|
|
133
|
-
"input": {
|
|
134
|
-
|
|
187
|
+
"input": {
|
|
188
|
+
"type": "integer",
|
|
189
|
+
"minimum": 0
|
|
190
|
+
},
|
|
191
|
+
"output": {
|
|
192
|
+
"type": "integer",
|
|
193
|
+
"minimum": 0
|
|
194
|
+
}
|
|
135
195
|
},
|
|
136
196
|
"additionalProperties": false
|
|
137
197
|
},
|
|
138
|
-
"model": {
|
|
139
|
-
|
|
140
|
-
|
|
198
|
+
"model": {
|
|
199
|
+
"type": "string",
|
|
200
|
+
"description": "Model identifier of the most recent recordCost emission (e.g., `claude-opus-4-7`). For multi-model runs, surfaces the last value."
|
|
201
|
+
},
|
|
202
|
+
"provider": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"description": "Normalized provider name (e.g., `anthropic`, `openai`, `gemini`)."
|
|
205
|
+
},
|
|
206
|
+
"duration_ms": {
|
|
207
|
+
"type": "integer",
|
|
208
|
+
"minimum": 0,
|
|
209
|
+
"description": "Sum of per-call durations across all recordCost emissions in this run."
|
|
210
|
+
}
|
|
141
211
|
},
|
|
142
212
|
"additionalProperties": false
|
|
143
213
|
}
|
|
@@ -232,6 +232,45 @@
|
|
|
232
232
|
"additionalProperties": true,
|
|
233
233
|
"x-openwop-seeded-from": "v1"
|
|
234
234
|
},
|
|
235
|
+
"signingKeys": {
|
|
236
|
+
"type": "array",
|
|
237
|
+
"description": "RFC 0168 §E.2 — the public keys this host signs certification bundles with. A bundle signature names a keyId; a verifier resolves it HERE, in the discovery document of the host the bundle is about, and checks the Ed25519 signature with the matching publicKey. Without this array a signature attests integrity only: it proves the bundle was not altered after signing and says nothing about who signed it, because a signer can mint a keypair and a keyId at will. RFC 0168 disposed of \"an Ed25519 attestation without a key registry is a signature nobody can check\" by naming this surface; this is that surface.",
|
|
238
|
+
"items": {
|
|
239
|
+
"type": "object",
|
|
240
|
+
"additionalProperties": false,
|
|
241
|
+
"required": [
|
|
242
|
+
"keyId",
|
|
243
|
+
"alg",
|
|
244
|
+
"publicKey"
|
|
245
|
+
],
|
|
246
|
+
"properties": {
|
|
247
|
+
"keyId": {
|
|
248
|
+
"$ref": "ids.schema.json#/$defs/keyId",
|
|
249
|
+
"description": "The identifier a bundle signature carries in signature.keyId. Unique within this array."
|
|
250
|
+
},
|
|
251
|
+
"alg": {
|
|
252
|
+
"const": "ed25519",
|
|
253
|
+
"description": "RFC 0168 §E.2 fixes the attestation algorithm; no other value is defined."
|
|
254
|
+
},
|
|
255
|
+
"publicKey": {
|
|
256
|
+
"type": "string",
|
|
257
|
+
"pattern": "^[A-Za-z0-9_-]{43}$",
|
|
258
|
+
"description": "The Ed25519 public key, base64url, unpadded (32 bytes) — the half that verifies, never the half that signs."
|
|
259
|
+
},
|
|
260
|
+
"use": {
|
|
261
|
+
"enum": [
|
|
262
|
+
"certification-bundle"
|
|
263
|
+
],
|
|
264
|
+
"description": "What the key signs. Closed, so a future use is an explicit addition rather than a reinterpretation of a key already published for something else."
|
|
265
|
+
},
|
|
266
|
+
"retiredAt": {
|
|
267
|
+
"type": "string",
|
|
268
|
+
"format": "date-time",
|
|
269
|
+
"description": "When the key stopped signing. A retired key stays listed so bundles it already signed remain verifiable; dropping it would silently invalidate historical evidence, which is the opposite of what an evidence trail is for."
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
},
|
|
235
274
|
"discovery": {
|
|
236
275
|
"type": "object",
|
|
237
276
|
"description": "Discovery advertisement (capabilities-change-detection.md). Optional in v1; absence means the host serves only the public unauthenticated payload at /.well-known/openwop. Landed by RFC 0011.",
|
|
@@ -254,7 +254,7 @@
|
|
|
254
254
|
"properties": {
|
|
255
255
|
"id": {
|
|
256
256
|
"type": "string",
|
|
257
|
-
"pattern": "^openwop\\.(?!it\\.(?:artifact-schema-compile-bounded|artifact-type-legacy-ids|capability-example-root-layout|certification-floor-enforcement|chain-subchain-unsupported-refused|compensation-profile|core-manifest-and-extension-registry|discovery-canonical-family-no-shadow|edge-condition-truthy-falsy|effect-identity-composition|effect-identity-cross-scope|error-envelope-canonical-shape|event-codemap-complete|form-content-packs|multi-region-effect-vocabulary|normative-example-extraction|openapi-asyncapi-sdk-parity|pack-manifest-extensions|protocol-version-grammar|registry-declarative-kinds|rfc-0147-self-audit|rfc-lifecycle-coherence|semantic-digest-v2|spec-corpus-validity|spec-section-citations|tool-result-trust-monotone|v2-alias-covers-reword|v2-corpus-tag-pinned|v2-declaration-parity|v2-event-naming-rule|v2-events-channel-parity|v2-externally-gated-never-stable|v2-one-signing-scheme|v2-path-parity|v2-release-identity|v2-req-only-assertions|v2-seams-not-in-canonical|v2-security-defaults-table|v2-spec-artifacts-digest|v2-threat-model-template|v2-witness-required|versioned-composition-profiles|workflow-chain-internal-flag|workload-identity-profile)\\.)(requirement|it|scenario|floor|profile|family)\\.[a-z0-9]",
|
|
257
|
+
"pattern": "^openwop\\.(?!it\\.(?:artifact-schema-compile-bounded|artifact-type-legacy-ids|capability-example-root-layout|certification-floor-enforcement|chain-subchain-unsupported-refused|compensation-profile|core-manifest-and-extension-registry|discovery-canonical-family-no-shadow|edge-condition-truthy-falsy|effect-identity-composition|effect-identity-cross-scope|error-envelope-canonical-shape|event-codemap-complete|form-content-packs|multi-region-effect-vocabulary|normative-example-extraction|openapi-asyncapi-sdk-parity|pack-manifest-extensions|protocol-version-grammar|registry-declarative-kinds|rfc-0147-self-audit|rfc-lifecycle-coherence|semantic-digest-v2|spec-corpus-validity|spec-section-citations|tool-result-trust-monotone|v2-alias-covers-reword|v2-corpus-tag-pinned|v2-declaration-parity|v2-error-registry-prose-parity|v2-event-naming-rule|v2-events-channel-parity|v2-externally-gated-never-stable|v2-bundle-signature-attributable|v2-one-signing-scheme|v2-path-parity|v2-release-identity|v2-req-only-assertions|v2-seams-not-in-canonical|v2-security-defaults-table|v2-spec-artifacts-digest|v2-threat-model-template|v2-witness-required|versioned-composition-profiles|workflow-chain-internal-flag|workload-identity-profile)\\.)(requirement|it|scenario|floor|profile|family)\\.[a-z0-9]",
|
|
258
258
|
"description": "RFC 0168 §A.1 — `openwop.<area>.<slug>`. The suite mints six areas: `requirement` (an explicit `req()` id), `it` (a per-test id from the scenario file and title), `scenario` and `floor` (per-file rows), `profile` (a claimed-profile row) and `family` (a capability gate). The lookahead refuses every id minted from a corpus-coherence file: those run in the spec repo’s CI and MUST NOT appear in a host bundle (conformance.md §\"Two products, two ledgers\"; RFC 0168 §D.1). `scripts/check-req-only.mjs` fails when the list drifts from `conformance/src/coherence/`."
|
|
259
259
|
},
|
|
260
260
|
"scenario": {
|
|
@@ -6,26 +6,123 @@
|
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"$defs": {
|
|
9
|
-
"opaque": {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
9
|
+
"opaque": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"pattern": "^[A-Za-z0-9._~-]{16,128}$",
|
|
12
|
+
"description": "Host-minted opaque token: no `@`, no whitespace, no `/`; 16–128 characters."
|
|
13
|
+
},
|
|
14
|
+
"tenantId": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"pattern": "^(anon:)?[A-Za-z0-9._~-]{1,128}$",
|
|
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 §A.5 makes the anonymous surface first-class — 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 — renaming anonymous tenants at the cut — was rejected: it is a write to historical identity, which is the one thing the v2 migration does not do."
|
|
19
|
+
},
|
|
20
|
+
"workspaceId": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}$",
|
|
23
|
+
"x-openwop-minted": "host"
|
|
24
|
+
},
|
|
25
|
+
"subjectId": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"pattern": "^[^\\s/]{1,256}$",
|
|
28
|
+
"description": "Issuer-scoped, stable, opaque (RFC 0170 §A); the issuer's grammar, never PII.",
|
|
29
|
+
"x-openwop-minted": "host"
|
|
30
|
+
},
|
|
31
|
+
"runId": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}/[A-Za-z0-9._~-]{16,128}$",
|
|
34
|
+
"description": "Tenant-bound: `<tenantId>/<opaque>`.",
|
|
35
|
+
"x-openwop-minted": "host",
|
|
36
|
+
"x-openwop-tenant-bound": true
|
|
37
|
+
},
|
|
38
|
+
"interruptId": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}/[A-Za-z0-9._~-]{16,128}$",
|
|
41
|
+
"x-openwop-minted": "host",
|
|
42
|
+
"x-openwop-tenant-bound": true
|
|
43
|
+
},
|
|
44
|
+
"subscriptionId": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}/[A-Za-z0-9._~-]{16,128}$",
|
|
47
|
+
"x-openwop-minted": "host",
|
|
48
|
+
"x-openwop-tenant-bound": true
|
|
49
|
+
},
|
|
50
|
+
"deliveryId": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}/[A-Za-z0-9._~-]{16,128}$",
|
|
53
|
+
"x-openwop-minted": "host",
|
|
54
|
+
"x-openwop-tenant-bound": true
|
|
55
|
+
},
|
|
56
|
+
"effectId": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}/[A-Za-z0-9._~-]{16,128}$",
|
|
59
|
+
"x-openwop-minted": "host",
|
|
60
|
+
"x-openwop-tenant-bound": true
|
|
61
|
+
},
|
|
62
|
+
"eventId": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"pattern": "^[A-Za-z0-9._~-]{16,128}$",
|
|
65
|
+
"x-openwop-minted": "host"
|
|
66
|
+
},
|
|
67
|
+
"traceId": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"pattern": "^[0-9a-f]{32}$",
|
|
70
|
+
"description": "W3C trace-context trace-id.",
|
|
71
|
+
"x-openwop-minted": "host"
|
|
72
|
+
},
|
|
73
|
+
"spanId": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"pattern": "^[0-9a-f]{16}$",
|
|
76
|
+
"description": "W3C trace-context parent-id.",
|
|
77
|
+
"x-openwop-minted": "host"
|
|
78
|
+
},
|
|
79
|
+
"keyId": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"pattern": "^[A-Za-z0-9._~-]{1,128}$",
|
|
82
|
+
"description": "A signing-key identifier (registry `signingKeys[].keyId`, resume-token `kid`, bundle signature `keyId`).",
|
|
83
|
+
"x-openwop-minted": "registry"
|
|
84
|
+
},
|
|
85
|
+
"nodeId": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"pattern": "^[A-Za-z0-9._~:-]{1,128}$",
|
|
88
|
+
"description": "Author-chosen within a workflow definition.",
|
|
89
|
+
"x-openwop-minted": "author"
|
|
90
|
+
},
|
|
91
|
+
"workflowId": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"pattern": "^[A-Za-z0-9._~:-]{1,128}$",
|
|
94
|
+
"x-openwop-minted": "author"
|
|
95
|
+
},
|
|
96
|
+
"agentId": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"pattern": "^[A-Za-z0-9._~:-]{1,128}$",
|
|
99
|
+
"x-openwop-minted": "author"
|
|
100
|
+
},
|
|
101
|
+
"chainId": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"pattern": "^[A-Za-z0-9._~:-]{1,128}$",
|
|
104
|
+
"x-openwop-minted": "author"
|
|
105
|
+
},
|
|
106
|
+
"pluginId": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"pattern": "^[A-Za-z0-9._~:-]{1,128}$",
|
|
109
|
+
"x-openwop-minted": "author"
|
|
110
|
+
},
|
|
111
|
+
"templateId": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"pattern": "^[A-Za-z0-9._~:-]{1,128}$",
|
|
114
|
+
"x-openwop-minted": "author"
|
|
115
|
+
},
|
|
116
|
+
"libraryId": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"pattern": "^[A-Za-z0-9._~:-]{1,128}$",
|
|
119
|
+
"x-openwop-minted": "author"
|
|
120
|
+
},
|
|
121
|
+
"typeId": {
|
|
122
|
+
"type": "string",
|
|
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.",
|
|
125
|
+
"x-openwop-minted": "author"
|
|
126
|
+
}
|
|
30
127
|
}
|
|
31
128
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/run-event-payloads.schema.json",
|
|
4
4
|
"title": "RunEventPayloads",
|
|
5
|
-
"description": "Per-RunEventType payload schemas. The base RunEventDoc shape (run-event.schema.json) leaves `payload` permissive for forward-compat. This schema defines the canonical payload contract for each known RunEventType. Consumers MAY pin strict payload validation via `$defs.<typeId>` and `ajv.validate(schema.$defs[event.type], event.payload)`. Unknown event types MUST be tolerated (no $defs match → fold best-effort).\n\
|
|
5
|
+
"description": "Per-RunEventType payload schemas. The base RunEventDoc shape (run-event.schema.json) leaves `payload` permissive for forward-compat. This schema defines the canonical payload contract for each known RunEventType. Consumers MAY pin strict payload validation via `$defs.<typeId>` and `ajv.validate(schema.$defs[event.type], event.payload)`. Unknown event types MUST be tolerated (no $defs match → fold best-effort).\n\n118 variants from the generated `type` branch of `run-event.schema.json` are covered (the v2 vocabulary is `spec/v2/event-codemap.json`; the old `$defs.RunEventType` twin is deleted — it held 36 retired v1 spellings and nothing referenced it), grouped into ~20 shape families with shared $defs. Naming convention: camelCase keys mirror dotted RunEventType names (e.g., `run.started` → `runStarted`). v2: every definition closed; _typeIndex normative; the legacy interrupt payloads (approval*/clarification*) removed per deprecation row legacy-interrupt-payloads.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"$defs": {
|
|
8
8
|
"_typeIndex": {
|
|
@@ -195,131 +195,7 @@
|
|
|
195
195
|
"description": "Optional ID of the event that caused this one (e.g., node.completed caused by approval.received). Lets projections build causal chains without inferring from timing."
|
|
196
196
|
}
|
|
197
197
|
},
|
|
198
|
-
"$comment": "RFC
|
|
198
|
+
"$comment": "RFC 0171 §A / `events.md` §\"The envelope\": in v2 RunEventDoc is CLOSED (`additionalProperties: false`). This reverses the v1 rule, which left the envelope open so v1.x hosts could add optional fields additively. The v2 envelope carries host-specific data in the registered vendor branch, not at the root. Do not restore the v1 sentence: a host that follows it emits root-level extension fields and fails `v2-event-type-closed`, and the schema keyword is the contract while a comment is only a claim about it.",
|
|
199
199
|
"additionalProperties": false,
|
|
200
|
-
"$defs": {
|
|
201
|
-
"RunEventType": {
|
|
202
|
-
"type": "string",
|
|
203
|
-
"description": "Discriminator for event payload shape. Dotted naming convention. New variants extend the union — readers MUST NOT throw on unknown types (forward-compat: fold best-effort, ignore unknowns). RFC 0151 §D adds the six content-free `compensation.*` events. They are added to this CLOSED enum because without them a conforming host cannot emit them at all: the RFC named the events, the enum did not contain them, and any host following §D would have produced run events that fail schema validation. Payloads carry opaque node/effect IDs, attempt, ordering model, and closed reason codes — never provider bodies or credentials (§D/§G).",
|
|
204
|
-
"enum": [
|
|
205
|
-
"run.started",
|
|
206
|
-
"run.completed",
|
|
207
|
-
"run.failed",
|
|
208
|
-
"run.cancelled",
|
|
209
|
-
"run.resuming",
|
|
210
|
-
"run.paused",
|
|
211
|
-
"run.resumed",
|
|
212
|
-
"run.restored-from-snapshot",
|
|
213
|
-
"run.dead_lettered",
|
|
214
|
-
"node.started",
|
|
215
|
-
"node.completed",
|
|
216
|
-
"node.failed",
|
|
217
|
-
"node.suspended",
|
|
218
|
-
"node.suspend-failed",
|
|
219
|
-
"node.resumed",
|
|
220
|
-
"node.retried",
|
|
221
|
-
"node.skipped",
|
|
222
|
-
"node.cancelled",
|
|
223
|
-
"approval.requested",
|
|
224
|
-
"approval.received",
|
|
225
|
-
"approval.granted",
|
|
226
|
-
"approval.rejected",
|
|
227
|
-
"approval.overridden",
|
|
228
|
-
"clarification.requested",
|
|
229
|
-
"clarification.resolved",
|
|
230
|
-
"interrupt.requested",
|
|
231
|
-
"interrupt.resolved",
|
|
232
|
-
"channel.written",
|
|
233
|
-
"channel.presence",
|
|
234
|
-
"context.summarized",
|
|
235
|
-
"artifact.created",
|
|
236
|
-
"output.chunk",
|
|
237
|
-
"variable.changed",
|
|
238
|
-
"log.appended",
|
|
239
|
-
"version.pinned",
|
|
240
|
-
"workflow.restored",
|
|
241
|
-
"workflow.loopback-limit",
|
|
242
|
-
"workflow.stalled",
|
|
243
|
-
"cap.breached",
|
|
244
|
-
"lease.acquired",
|
|
245
|
-
"lease.renewed",
|
|
246
|
-
"lease.lost",
|
|
247
|
-
"lease.handed-off",
|
|
248
|
-
"replay.diverged",
|
|
249
|
-
"replay.divergedAtRefusal",
|
|
250
|
-
"agent.reasoned",
|
|
251
|
-
"agent.reasoning.delta",
|
|
252
|
-
"provider.usage",
|
|
253
|
-
"prompt.composed",
|
|
254
|
-
"agent.promptResolved",
|
|
255
|
-
"model.capability.substituted",
|
|
256
|
-
"model.capability.insufficient",
|
|
257
|
-
"envelope.retry.attempted",
|
|
258
|
-
"envelope.retry.exhausted",
|
|
259
|
-
"envelope.refusal",
|
|
260
|
-
"envelope.truncated",
|
|
261
|
-
"envelope.nlToFormat.engaged",
|
|
262
|
-
"envelope.recovery.applied",
|
|
263
|
-
"agent.toolCalled",
|
|
264
|
-
"agent.toolReturned",
|
|
265
|
-
"agent.handoff",
|
|
266
|
-
"agent.decided",
|
|
267
|
-
"agent.verified",
|
|
268
|
-
"agent.invocation.started",
|
|
269
|
-
"agent.invocation.completed",
|
|
270
|
-
"eval.started",
|
|
271
|
-
"eval.scored",
|
|
272
|
-
"eval.completed",
|
|
273
|
-
"deployment.promoted",
|
|
274
|
-
"deployment.rolled-back",
|
|
275
|
-
"deployment.canary.adjusted",
|
|
276
|
-
"deployment.state.changed",
|
|
277
|
-
"roster.run.initiated",
|
|
278
|
-
"tool.session.opened",
|
|
279
|
-
"tool.session.closed",
|
|
280
|
-
"egress.decided",
|
|
281
|
-
"trigger.subscription.state.changed",
|
|
282
|
-
"trigger.delivery.attempted",
|
|
283
|
-
"budget.reserved",
|
|
284
|
-
"budget.consumed",
|
|
285
|
-
"budget.threshold.crossed",
|
|
286
|
-
"budget.exhausted",
|
|
287
|
-
"runOrchestrator.decided",
|
|
288
|
-
"node.dispatched",
|
|
289
|
-
"core.dispatch.fanOut",
|
|
290
|
-
"core.dispatch.join",
|
|
291
|
-
"conversation.opened",
|
|
292
|
-
"conversation.exchanged",
|
|
293
|
-
"conversation.closed",
|
|
294
|
-
"memory.compacted",
|
|
295
|
-
"memory.written",
|
|
296
|
-
"agent.memory.consolidated",
|
|
297
|
-
"commitment.fired",
|
|
298
|
-
"workspace.updated",
|
|
299
|
-
"core.workflowChain.event",
|
|
300
|
-
"core.workflowChain.confidence-escalated",
|
|
301
|
-
"connector.authorized",
|
|
302
|
-
"connector.auth_expired",
|
|
303
|
-
"authorization.decided",
|
|
304
|
-
"proposal.created",
|
|
305
|
-
"proposal.activated",
|
|
306
|
-
"goal.evaluated",
|
|
307
|
-
"goal.closed",
|
|
308
|
-
"import.applied",
|
|
309
|
-
"voice.speech_start",
|
|
310
|
-
"voice.transcript",
|
|
311
|
-
"voice.endpoint_candidate",
|
|
312
|
-
"voice.turn_commit",
|
|
313
|
-
"voice.synthesis_chunk",
|
|
314
|
-
"voice.barge_in",
|
|
315
|
-
"voice.cancelled",
|
|
316
|
-
"compensation.requested",
|
|
317
|
-
"compensation.started",
|
|
318
|
-
"compensation.completed",
|
|
319
|
-
"compensation.failed",
|
|
320
|
-
"compensation.paused",
|
|
321
|
-
"compensation.manual_intervention_required"
|
|
322
|
-
]
|
|
323
|
-
}
|
|
324
|
-
}
|
|
200
|
+
"$defs": {}
|
|
325
201
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/run-snapshot.schema.json",
|
|
4
4
|
"title": "RunSnapshot",
|
|
5
|
-
"description": "Projected run state returned by `GET /
|
|
5
|
+
"description": "Projected run state returned by `GET /runs/{runId}`. Source is the run’s append-only event log (run-event.schema.json) folded through the `RunProjection`. CLOSED in v2 (`additionalProperties: false`): a reader MUST NOT expect to ignore unknown root fields, because there are none to ignore — host-specific state goes in `extensions`. The v1 schema was open and therefore never had to declare what hosts actually served; closing the object is what made that visible.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"required": [
|
|
8
8
|
"eventLogSchemaVersion",
|
|
@@ -201,6 +201,27 @@
|
|
|
201
201
|
}
|
|
202
202
|
},
|
|
203
203
|
"additionalProperties": false
|
|
204
|
+
},
|
|
205
|
+
"parentRunId": {
|
|
206
|
+
"$ref": "ids.schema.json#/$defs/runId",
|
|
207
|
+
"description": "RFC 0022 / `runs.md` §forkRun — the run this one was forked from, absent on a root run. Declared because the object is closed: a fork’s lineage is real protocol state, and an undeclared field on a closed object is deleted rather than ignored."
|
|
208
|
+
},
|
|
209
|
+
"inputs": {
|
|
210
|
+
"type": "object",
|
|
211
|
+
"description": "RFC 0022 §A — the inputs the run was created with. Declared for the same reason as parentRunId: the v1 wire carried it under an open schema, and closing the object without a seat would force every host to drop it.",
|
|
212
|
+
"additionalProperties": true
|
|
213
|
+
},
|
|
214
|
+
"extensions": {
|
|
215
|
+
"type": "object",
|
|
216
|
+
"additionalProperties": false,
|
|
217
|
+
"patternProperties": {
|
|
218
|
+
"^[a-z][a-z0-9]*(-[a-z0-9]+)*\\.[a-z][a-z0-9]*(-[a-z0-9]+)*$": {
|
|
219
|
+
"type": "object",
|
|
220
|
+
"additionalProperties": true,
|
|
221
|
+
"description": "A vendor/host extension record; its shape is the org’s, declared open on purpose."
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"description": "RFC 0169 §A.4 — the seat for host-specific snapshot state, keyed `<org>.<name>`. Closing an object without an extension seat does not make hosts stop having extra state; it makes them delete it or serve an invalid document. Every other closed v2 surface has this seat and the snapshot was the omission."
|
|
204
225
|
}
|
|
205
226
|
},
|
|
206
227
|
"additionalProperties": false
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"provenance": {
|
|
5
5
|
"suite": {
|
|
6
6
|
"package": "@openwop/openwop-conformance",
|
|
7
|
-
"version": "2.0.0-rc.
|
|
7
|
+
"version": "2.0.0-rc.29"
|
|
8
8
|
},
|
|
9
9
|
"note": "Derived from the corpus at generation time. Regenerate with --write; verify with --check."
|
|
10
10
|
},
|
|
@@ -419,5 +419,5 @@
|
|
|
419
419
|
"$id": "https://openwop.dev/spec/v1/workspace-file.schema.json"
|
|
420
420
|
}
|
|
421
421
|
],
|
|
422
|
-
"digest": "
|
|
422
|
+
"digest": "3c923a9b9ff975f5014c7bcf0fd166a7852782c147df7bfb8c3ddb0491bbc172"
|
|
423
423
|
}
|
package/spec/v1/extensions.json
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"rfc": "0155 \u00a7C",
|
|
38
38
|
"coverage": {
|
|
39
39
|
"rule": "Derived by scripts/generate-extension-registry-coverage.mjs from the top-level keys of schemas/capabilities.schema.json. coreFields = the openwop-discovery-core predicate fields (profiles.md); metadataFields = keys that describe the document or host rather than gate an optional feature (each carries its rationale in metadataRationale; a key that gates behaviour may not be listed there); covered = extension families reached by some record capabilityPath; uncovered = every other family. Uncovered means no registry record exists \u2014 not that the family is non-compliant. Regenerate with --write; the gate runs --check.",
|
|
40
|
-
"familiesTotal":
|
|
40
|
+
"familiesTotal": 93,
|
|
41
41
|
"coreFields": [
|
|
42
42
|
"limits",
|
|
43
43
|
"protocolVersion",
|
|
@@ -153,7 +153,8 @@
|
|
|
153
153
|
"workspace"
|
|
154
154
|
],
|
|
155
155
|
"uncovered": [
|
|
156
|
-
"preferredVersion"
|
|
156
|
+
"preferredVersion",
|
|
157
|
+
"signingKeys"
|
|
157
158
|
]
|
|
158
159
|
},
|
|
159
160
|
"extensions": [
|
package/spec/v2/declaration.json
CHANGED
|
@@ -121,6 +121,13 @@
|
|
|
121
121
|
"note": null,
|
|
122
122
|
"disposition": "kept"
|
|
123
123
|
},
|
|
124
|
+
{
|
|
125
|
+
"key": "signingKeys",
|
|
126
|
+
"kind": "metadata",
|
|
127
|
+
"schema": "metadata/signingKeys",
|
|
128
|
+
"note": "host bundle-signing public keys (RFC 0168 §E.2); v2-only — the surface the RFC named when it disposed of \"a signature nobody can check\"",
|
|
129
|
+
"disposition": "kept"
|
|
130
|
+
},
|
|
124
131
|
{
|
|
125
132
|
"key": "discovery",
|
|
126
133
|
"kind": "metadata",
|
package/spec/v2/release.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "RFC 0172
|
|
3
|
-
"version": "2.0.0-rc.
|
|
2
|
+
"$comment": "RFC 0172 \u00a7D.1 \u2014 the one release identity the v2 artifacts derive from. `version` is the next corpus tag `v<version>` (the publish workflow's coordinated-release tag pattern `v*`; RFC 0172's `openwop/v2.<minor>.<patch>` spelling is amended to this at its flip). api/v2/*.yaml info.version, the suite's 2.x version and @openwop/spec-artifacts read it. Bumped by the release PR that cuts the tag, never by hand elsewhere.",
|
|
3
|
+
"version": "2.0.0-rc.29",
|
|
4
4
|
"corpusTag": null,
|
|
5
5
|
"updated": "2026-09-03"
|
|
6
6
|
}
|