@openwop/spec-artifacts 2.42.9 → 2.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CORPUS-STAMP.json +55 -54
  2. package/api/seams-v2.yaml +57 -1
  3. package/api/v2/asyncapi.yaml +1 -1
  4. package/api/v2/openapi.yaml +5 -4
  5. package/package.json +1 -1
  6. package/schemas/audit-verify-result.schema.json +40 -8
  7. package/schemas/v2/audit-verify-result.schema.json +106 -10
  8. package/schemas/v2/capabilities.schema.json +96 -0
  9. package/schemas/v2/error-envelope.schema.json +3 -1
  10. package/schemas/v2/registry-version-manifest.schema.json +2 -2
  11. package/schemas/v2/run-event-payloads.schema.json +2 -1
  12. package/schemas/v2/suspend-request.schema.json +2 -2
  13. package/spec/v1/core-standard-manifest.json +2 -2
  14. package/spec/v1/gaps.json +323 -0
  15. package/spec/v2/core/capabilities.md +6 -2
  16. package/spec/v2/core/conformance.md +1 -1
  17. package/spec/v2/core/connection-packs.md +1 -1
  18. package/spec/v2/core/conversation.md +1 -1
  19. package/spec/v2/core/errors.md +5 -4
  20. package/spec/v2/core/events.md +1 -1
  21. package/spec/v2/core/form-content-packs.md +1 -1
  22. package/spec/v2/core/idempotency.md +1 -1
  23. package/spec/v2/core/identity.md +1 -1
  24. package/spec/v2/core/interop.md +1 -1
  25. package/spec/v2/core/interrupt.md +21 -7
  26. package/spec/v2/core/node-pack-runtimes.md +1 -1
  27. package/spec/v2/core/oauth.md +1 -1
  28. package/spec/v2/core/overview.md +1 -1
  29. package/spec/v2/core/packs.md +12 -5
  30. package/spec/v2/core/persistence.md +1 -1
  31. package/spec/v2/core/portability.md +1 -1
  32. package/spec/v2/core/replay.md +1 -1
  33. package/spec/v2/core/runs.md +1 -1
  34. package/spec/v2/core/security-defaults.md +13 -2
  35. package/spec/v2/core/tool-catalog.md +1 -1
  36. package/spec/v2/core/versioning.md +1 -1
  37. package/spec/v2/core/webhooks.md +1 -1
  38. package/spec/v2/core/workflow-chain-packs.md +1 -1
  39. package/spec/v2/corrections.json +18 -1
  40. package/spec/v2/declaration.json +39 -14
  41. package/spec/v2/errors.json +11 -1
  42. package/spec/v2/ext/brand/README.md +1 -1
  43. package/spec/v2/ext/chat/README.md +3 -3
  44. package/spec/v2/ext/coordination/README.md +1 -1
  45. package/spec/v2/ext/dataIntegration/README.md +2 -2
  46. package/spec/v2/ext/entities/README.md +2 -2
  47. package/spec/v2/ext/kanban/README.md +3 -3
  48. package/spec/v2/ext/knowledge/README.md +3 -3
  49. package/spec/v2/ext/messaging/README.md +1 -1
  50. package/spec/v2/ext/restTransport/README.md +2 -2
  51. package/spec/v2/ext/webResearch/README.md +3 -3
  52. package/spec/v2/facets/auditLogIntegrity.schema.json +30 -0
  53. package/spec/v2/release.json +2 -2
  54. package/spec/v2/surface-baseline.json +50 -2
@@ -7696,6 +7696,102 @@
7696
7696
  "description": "core/capabilities.md#auth — witness: seam-gated; maturity experimental/none; RFC 0154",
7697
7697
  "x-openwop-facets-from": "spec/v2/facets/auth.schema.json"
7698
7698
  },
7699
+ "auditLogIntegrity": {
7700
+ "type": "object",
7701
+ "additionalProperties": false,
7702
+ "required": [
7703
+ "status",
7704
+ "since",
7705
+ "witness",
7706
+ "checkpointSignatureAlgorithm",
7707
+ "checkpointPublicKey",
7708
+ "checkpointIntervalEntries",
7709
+ "checkpointIntervalSeconds"
7710
+ ],
7711
+ "properties": {
7712
+ "status": {
7713
+ "enum": [
7714
+ "stable",
7715
+ "experimental",
7716
+ "deprecated"
7717
+ ]
7718
+ },
7719
+ "since": {
7720
+ "type": "string",
7721
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$",
7722
+ "description": "The minor of THIS HOST's own contract at which it began serving the family — a point on its protocolVersions[] timeline, not the corpus minor that introduced the family. The corpus states no per-family since (spec/v2/declaration.json carries witness and maturity and no since), and `status`/`until` are the host's stability claim absorbed from v1 tier/experimentalUntil, so all three describe the host's offering and `witness` is the record's one corpus-derived field. A since naming a minor absent from protocolVersions[] puts adjacent same-grammar fields on two different timelines and is a defect. Ruled 2026-09-11."
7723
+ },
7724
+ "until": {
7725
+ "type": "string",
7726
+ "pattern": "^((0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)|\\d{4}-\\d{2}-\\d{2})$"
7727
+ },
7728
+ "witness": {
7729
+ "enum": [
7730
+ "witnessable-unaided",
7731
+ "witnessable-gated",
7732
+ "seam-gated",
7733
+ "claims-check",
7734
+ "negative-existence"
7735
+ ]
7736
+ },
7737
+ "checkpointSignatureAlgorithm": {
7738
+ "const": "ed25519",
7739
+ "description": "The checkpoint signature algorithm. Ed25519 over the 32 bytes `merkleRoot` hex-decodes to (RFC 0218 §A.4)."
7740
+ },
7741
+ "checkpointPublicKey": {
7742
+ "type": "string",
7743
+ "pattern": "^MCowBQYDK2VwAyEA[A-Za-z0-9+/]{43}=$",
7744
+ "description": "The audit-signing public key: base64 (RFC 4648 §4, padded) of its DER SubjectPublicKeyInfo, 44 bytes for Ed25519. Every checkpoint `GET /audit/verify` returns MUST verify under it."
7745
+ },
7746
+ "checkpointIntervalEntries": {
7747
+ "type": "integer",
7748
+ "minimum": 1,
7749
+ "description": "The most entries a checkpoint anchors: consecutive checkpoints' atSequence, and the first checkpoint's atSequence from 0, differ by at most this."
7750
+ },
7751
+ "checkpointIntervalSeconds": {
7752
+ "type": "integer",
7753
+ "minimum": 1,
7754
+ "description": "The longest an appended entry waits before a checkpoint anchors it."
7755
+ }
7756
+ },
7757
+ "allOf": [
7758
+ {
7759
+ "if": {
7760
+ "properties": {
7761
+ "status": {
7762
+ "const": "stable"
7763
+ }
7764
+ }
7765
+ },
7766
+ "then": {
7767
+ "not": {
7768
+ "required": [
7769
+ "until"
7770
+ ]
7771
+ }
7772
+ }
7773
+ },
7774
+ {
7775
+ "if": {
7776
+ "properties": {
7777
+ "status": {
7778
+ "enum": [
7779
+ "experimental",
7780
+ "deprecated"
7781
+ ]
7782
+ }
7783
+ }
7784
+ },
7785
+ "then": {
7786
+ "required": [
7787
+ "until"
7788
+ ]
7789
+ }
7790
+ }
7791
+ ],
7792
+ "description": "core/capabilities.md#auditLogIntegrity — witness: witnessable-gated; maturity experimental/none; RFC 0224",
7793
+ "x-openwop-facets-from": "spec/v2/facets/auditLogIntegrity.schema.json"
7794
+ },
7699
7795
  "i18n": {
7700
7796
  "type": "object",
7701
7797
  "additionalProperties": false,
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openwop.dev/spec/v2/error-envelope.schema.json",
4
4
  "title": "ErrorEnvelope (v2)",
5
- "description": "GENERATED from spec/v2/errors.json by scripts/generate-error-envelope.mjs (RFC 0171 §B.1). 107 registered codes; vendor codes match ^(?!openwop\\.)[a-z][a-z0-9]*(-[a-z0-9]+)*\\.[a-z][a-z0-9_]*$. Consumers MUST accept an unknown registered member and MUST NOT act on it (RFC 0171 §A.5).",
5
+ "description": "GENERATED from spec/v2/errors.json by scripts/generate-error-envelope.mjs (RFC 0171 §B.1). 108 registered codes; vendor codes match ^(?!openwop\\.)[a-z][a-z0-9]*(-[a-z0-9]+)*\\.[a-z][a-z0-9_]*$. Consumers MUST accept an unknown registered member and MUST NOT act on it (RFC 0171 §A.5).",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "required": [
@@ -95,6 +95,7 @@
95
95
  "payload_too_large",
96
96
  "workspace_too_large",
97
97
  "unsupported_media_type",
98
+ "approval_rejected",
98
99
  "capability_not_provided",
99
100
  "capability_required",
100
101
  "credential_required",
@@ -367,6 +368,7 @@
367
368
  "payload_too_large": 413,
368
369
  "workspace_too_large": 413,
369
370
  "unsupported_media_type": 415,
371
+ "approval_rejected": 422,
370
372
  "capability_not_provided": 422,
371
373
  "capability_required": 422,
372
374
  "credential_required": 422,
@@ -238,7 +238,7 @@
238
238
  },
239
239
  "yanked": {
240
240
  "type": "boolean",
241
- "description": "Hard refusal: this version was published in error. Registry MUST refuse to serve the tarball; consumers MUST refuse to dispatch nodes from yanked versions."
241
+ "description": "This version is yanked (spec/v2/core/packs.md §\"Version manifests\"). The registry keeps serving its manifest, tarball and signature, and its pack index never names it `latest` while an unyanked version exists. A consumer resolving a range excludes it; an exact pin MAY still resolve it."
242
242
  },
243
243
  "yankedReason": {
244
244
  "type": "string",
@@ -253,7 +253,7 @@
253
253
  "supersededBy": {
254
254
  "type": "string",
255
255
  "maxLength": 256,
256
- "description": "Optional pointer to the version (or `<name>@<version>`) that replaces this one. Per spec/v1/registry-operations.md, engine consumers in `open` / `verified` mode MUST surface this value in any deprecation warning when set."
256
+ "description": "Optional pointer to the version (or `<name>@<version>`) that replaces this one. Display only: a consumer that refuses or warns about a deprecated version can name it (spec/v2/core/packs.md §\"Version manifests\")."
257
257
  },
258
258
  "advisoryUrl": {
259
259
  "type": "string",
@@ -948,7 +948,8 @@
948
948
  "properties": {
949
949
  "code": {
950
950
  "type": "string",
951
- "minLength": 1
951
+ "minLength": 1,
952
+ "description": "A registered code from spec/v2/errors.json or a vendor code (errors.md §The registry, corrected by openwop#1698): the producer rule binds run.failed, node.failed and the snapshot error exactly as it binds an error response. Kept an open string on purpose — a consumer MUST accept an unknown code (overview.md §0) — so this schema does not enforce the rule; the suite's event-code-registered leg does."
952
953
  },
953
954
  "message": {
954
955
  "type": "string",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "key": {
29
29
  "type": "string",
30
- "description": "Deterministic key used to short-circuit on re-entry after process death. If two interrupt() calls in the same run emit the same key, the second returns the cached result of the first. Recommended: ${runId}:${nodeId}:${interruptCount}.",
30
+ "description": "The deterministic re-entry key of ONE invocation of an interrupt (interrupt.md §Re-entry and resume values; corrected 2026-09-28 by openwop#1697). A host MUST derive it from at least the run, the node and the node's visit index; the spelling is host-defined. Recommended: ${runId}:${nodeId}:${interruptCount}, where interruptCount is the visit index — the number of interrupts this node raised in this run whose resolution was consumed before the current execution of the node began (plus an ordinal when one execution raises several). A replay or recovery of the same execution re-derives the same key and returns the recorded resume value; a later execution of the node (a loop back over an edge) derives a new key and raises a new interrupt.requested.",
31
31
  "minLength": 1,
32
32
  "maxLength": 256
33
33
  },
@@ -299,7 +299,7 @@
299
299
  "approve",
300
300
  "escalate"
301
301
  ],
302
- "description": "RFC 0186 §A.3 — the disposition applied when `timeoutMs` elapses with no resolution. Every gate with a timer needs one; two production hosts recorded it as a bare key on `approval.requested` (280 rows on one) because the seat did not exist. `escalate` pairs with a host-defined escalation target. A `timeoutMs` of `0` means no timer, and `onTimeout` is then meaningless."
302
+ "description": "RFC 0186 §A.3, corrected by RFC 0223 (openwop#1696) — a hint recorded with the gate; it does not choose the outcome. Whatever it holds, when a non-zero `timeoutMs` elapses with no resolution the host MUST resolve the gate rejected (`action: timeout`, `decision: rejected`, `reason: timeout`) and the node and run fail with `approval_rejected` unless an edge routes the failure (interrupt.md §Rejection). A timeout never grants a gate: a host MUST treat `approve` as `reject` and SHOULD NOT emit it (RFC 0093 ruled fail-open non-conformant; the value stays in the enum only so recorded payloads validate). `escalate` MAY notify a host-defined target but MUST NOT extend or grant the gate. Absent means `reject`. A `timeoutMs` of `0` means no timer. Two production hosts recorded this as a bare key on `approval.requested` (280 rows on one) before the seat existed. No JSON-Schema `default` is declared, because a validator that fills defaults would write a value the host never recorded."
303
303
  },
304
304
  "description": {
305
305
  "type": "string"
@@ -4,7 +4,7 @@
4
4
  "provenance": {
5
5
  "suite": {
6
6
  "package": "@openwop/openwop-conformance",
7
- "version": "2.42.9"
7
+ "version": "2.43.1"
8
8
  },
9
9
  "note": "Derived from the corpus at generation time. Regenerate with --write; verify with --check."
10
10
  },
@@ -421,5 +421,5 @@
421
421
  "$id": "https://openwop.dev/spec/v1/workspace-file.schema.json"
422
422
  }
423
423
  ],
424
- "digest": "fb4145362ce7b57ba7e06e742acac2800106bb12e863f6eb6d2dc9dd2f50cb6c"
424
+ "digest": "7800a051d432c1244efd10dcee93b93ddde389aa6bfa843279d0ff6b9d734658"
425
425
  }
package/spec/v1/gaps.json CHANGED
@@ -9804,6 +9804,57 @@
9804
9804
  }
9805
9805
  ]
9806
9806
  },
9807
+ {
9808
+ "id": "openwop.gap.0171.6",
9809
+ "rfc": "0171",
9810
+ "local": "G6",
9811
+ "section": "§B.1",
9812
+ "surface": "openwop-app emits error codes on `run.failed` / `node.failed` that are neither registered nor vendor codes (22 codes measured at openwop-app `0cfb264c9`, e.g. `invalid_config`, `host_capability_missing`); `errors.md` §The registry binds them since openwop#1698.",
9813
+ "witness": "unclassified",
9814
+ "requirementId": null,
9815
+ "disposition": "externally-gated",
9816
+ "target": "openwop-app-code-remap",
9817
+ "sources": [
9818
+ {
9819
+ "file": "RFCS/registers/0171-v2-wire-envelope.gaps.md",
9820
+ "token": "G6"
9821
+ }
9822
+ ]
9823
+ },
9824
+ {
9825
+ "id": "openwop.gap.0171.7",
9826
+ "rfc": "0171",
9827
+ "local": "G7",
9828
+ "section": "§B.1",
9829
+ "surface": "MyndHyve emits about 56 UPPER_CASE run-failure codes (normalised in `failurePayload`, measured at MyndHyve `fc3b007cf`) that are neither registered nor vendor codes.",
9830
+ "witness": "unclassified",
9831
+ "requirementId": null,
9832
+ "disposition": "externally-gated",
9833
+ "target": "myndhyve-code-remap",
9834
+ "sources": [
9835
+ {
9836
+ "file": "RFCS/registers/0171-v2-wire-envelope.gaps.md",
9837
+ "token": "G7"
9838
+ }
9839
+ ]
9840
+ },
9841
+ {
9842
+ "id": "openwop.gap.0171.8",
9843
+ "rfc": "0171",
9844
+ "local": "G8",
9845
+ "section": "§B.1",
9846
+ "surface": "The v2 reference host emitted 3 unregistered run-failure codes (measured at openwop-examples `456dfaa`).",
9847
+ "witness": "unclassified",
9848
+ "requirementId": null,
9849
+ "disposition": "closed",
9850
+ "target": null,
9851
+ "sources": [
9852
+ {
9853
+ "file": "RFCS/registers/0171-v2-wire-envelope.gaps.md",
9854
+ "token": "G8"
9855
+ }
9856
+ ]
9857
+ },
9807
9858
  {
9808
9859
  "id": "openwop.gap.0172.1",
9809
9860
  "rfc": "0172",
@@ -13068,6 +13119,23 @@
13068
13119
  }
13069
13120
  ]
13070
13121
  },
13122
+ {
13123
+ "id": "openwop.gap.0220.4",
13124
+ "rfc": "0220",
13125
+ "local": "G4",
13126
+ "section": "§B",
13127
+ "surface": "`brand`, `canvas`, `coordination` and `launchStudio` have no tier-2 host. MyndHyve's executors for them run in the browser engine or on `canvas-runtime`, which does no OpenWOP version negotiation. `coordination`'s vote/consensus nodes need server-side agent dispatch.",
13128
+ "witness": "unclassified",
13129
+ "requirementId": null,
13130
+ "disposition": "externally-gated",
13131
+ "target": "tier-2-host-serves-family",
13132
+ "sources": [
13133
+ {
13134
+ "file": "RFCS/registers/0220-ext-families-graduate-on-evidence.gaps.md",
13135
+ "token": "G4"
13136
+ }
13137
+ ]
13138
+ },
13071
13139
  {
13072
13140
  "id": "openwop.gap.0221.1",
13073
13141
  "rfc": "0221",
@@ -13085,6 +13153,261 @@
13085
13153
  }
13086
13154
  ]
13087
13155
  },
13156
+ {
13157
+ "id": "openwop.gap.0222.1",
13158
+ "rfc": "0222",
13159
+ "local": "G1",
13160
+ "section": "§A",
13161
+ "surface": "The earlier major's registry write endpoints (`deprecate`, `yank`, `keychain`, `keychain/rotate`), their scopes, the `rotationProof` chain and the 72-hour unpublish window have no v2 home.",
13162
+ "witness": "unclassified",
13163
+ "requirementId": null,
13164
+ "disposition": "closed",
13165
+ "target": null,
13166
+ "sources": [
13167
+ {
13168
+ "file": "RFCS/registers/0222-v2-registry-operations.gaps.md",
13169
+ "token": "G1"
13170
+ }
13171
+ ]
13172
+ },
13173
+ {
13174
+ "id": "openwop.gap.0222.2",
13175
+ "rfc": "0222",
13176
+ "local": "G2",
13177
+ "section": "§C",
13178
+ "surface": "No corpus schema describes `.well-known/openwop-registry.json`, so the `signingKeys[]` members §C names are validated only by the conformance leg.",
13179
+ "witness": "unclassified",
13180
+ "requirementId": null,
13181
+ "disposition": "closed",
13182
+ "target": null,
13183
+ "sources": [
13184
+ {
13185
+ "file": "RFCS/registers/0222-v2-registry-operations.gaps.md",
13186
+ "token": "G2"
13187
+ }
13188
+ ]
13189
+ },
13190
+ {
13191
+ "id": "openwop.gap.0223.1",
13192
+ "rfc": "0223",
13193
+ "local": "G1",
13194
+ "section": "§Conformance",
13195
+ "surface": "The routed case (a rejected gate followed over an `all_complete` or `any_failed` edge) had no witness.",
13196
+ "witness": "unclassified",
13197
+ "requirementId": null,
13198
+ "disposition": "closed",
13199
+ "target": null,
13200
+ "sources": [
13201
+ {
13202
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13203
+ "token": "G1"
13204
+ }
13205
+ ]
13206
+ },
13207
+ {
13208
+ "id": "openwop.gap.0223.2",
13209
+ "rfc": "0223",
13210
+ "local": "G2",
13211
+ "section": "§Conformance",
13212
+ "surface": "The timeout disposition had no witness.",
13213
+ "witness": "unclassified",
13214
+ "requirementId": null,
13215
+ "disposition": "closed",
13216
+ "target": null,
13217
+ "sources": [
13218
+ {
13219
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13220
+ "token": "G2"
13221
+ }
13222
+ ]
13223
+ },
13224
+ {
13225
+ "id": "openwop.gap.0223.3",
13226
+ "rfc": "0223",
13227
+ "local": "G3",
13228
+ "section": "§Implementation notes",
13229
+ "surface": "The v2 reference host did not record `action` on `interrupt.resolved`, did not emit `approval.rejected`, failed the run directly rather than through the scheduler, and had no timeout disposition.",
13230
+ "witness": "unclassified",
13231
+ "requirementId": null,
13232
+ "disposition": "closed",
13233
+ "target": null,
13234
+ "sources": [
13235
+ {
13236
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13237
+ "token": "G3"
13238
+ }
13239
+ ]
13240
+ },
13241
+ {
13242
+ "id": "openwop.gap.0223.4",
13243
+ "rfc": "0223",
13244
+ "local": "G4",
13245
+ "section": "§Implementation notes",
13246
+ "surface": "openwop-app records no `action` on single reject or timeout, emits no `interrupt.resolved` on quorum reject, never emits `approval.rejected`, and emits no `node.failed` / `failedNodeId` on either reject path.",
13247
+ "witness": "unclassified",
13248
+ "requirementId": null,
13249
+ "disposition": "externally-gated",
13250
+ "target": "openwop-app-followup",
13251
+ "sources": [
13252
+ {
13253
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13254
+ "token": "G4"
13255
+ }
13256
+ ]
13257
+ },
13258
+ {
13259
+ "id": "openwop.gap.0223.5",
13260
+ "rfc": "0223",
13261
+ "local": "G5",
13262
+ "section": "§Implementation notes",
13263
+ "surface": "MyndHyve fails the gate with the unregistered `APPROVAL_REJECTED`.",
13264
+ "witness": "unclassified",
13265
+ "requirementId": null,
13266
+ "disposition": "externally-gated",
13267
+ "target": "myndhyve-next-cut",
13268
+ "sources": [
13269
+ {
13270
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13271
+ "token": "G5"
13272
+ }
13273
+ ]
13274
+ },
13275
+ {
13276
+ "id": "openwop.gap.0223.6",
13277
+ "rfc": "0223",
13278
+ "local": "G6",
13279
+ "section": "§Unresolved questions",
13280
+ "surface": "The `majority` threshold was stated from one v1 fixture.",
13281
+ "witness": "unclassified",
13282
+ "requirementId": null,
13283
+ "disposition": "closed",
13284
+ "target": null,
13285
+ "sources": [
13286
+ {
13287
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13288
+ "token": "G6"
13289
+ }
13290
+ ]
13291
+ },
13292
+ {
13293
+ "id": "openwop.gap.0223.7",
13294
+ "rfc": "0223",
13295
+ "local": "G7",
13296
+ "section": "§Unresolved questions",
13297
+ "surface": "`onTimeout: approve` re-legalised the fail-open timeout RFC 0093 ruled non-conformant.",
13298
+ "witness": "unclassified",
13299
+ "requirementId": null,
13300
+ "disposition": "closed",
13301
+ "target": null,
13302
+ "sources": [
13303
+ {
13304
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13305
+ "token": "G7"
13306
+ }
13307
+ ]
13308
+ },
13309
+ {
13310
+ "id": "openwop.gap.0223.8",
13311
+ "rfc": "0223",
13312
+ "local": "G8",
13313
+ "section": "§A",
13314
+ "surface": "A gate re-entered over a reject loop collided with the one-interrupt-per-key rule (`interrupt.md` §Re-entry); v2 had no per-iteration key derivation.",
13315
+ "witness": "unclassified",
13316
+ "requirementId": null,
13317
+ "disposition": "closed",
13318
+ "target": null,
13319
+ "sources": [
13320
+ {
13321
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13322
+ "token": "G8"
13323
+ }
13324
+ ]
13325
+ },
13326
+ {
13327
+ "id": "openwop.gap.0223.9",
13328
+ "rfc": "0223",
13329
+ "local": "G9",
13330
+ "section": "§Motivation",
13331
+ "surface": "Whether a run-failure code on `run.failed` / `node.failed` must be registered: `errors.md` scopes its MUST to error responses, overview §0 to every producer.",
13332
+ "witness": "unclassified",
13333
+ "requirementId": null,
13334
+ "disposition": "transferred",
13335
+ "target": "openwop#1698",
13336
+ "sources": [
13337
+ {
13338
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13339
+ "token": "G9"
13340
+ }
13341
+ ]
13342
+ },
13343
+ {
13344
+ "id": "openwop.gap.0223.9",
13345
+ "rfc": "0223",
13346
+ "local": "G9",
13347
+ "section": "§Conformance",
13348
+ "surface": "`openwop.requirement.0223.reject-loopback-reasks` (openwop #1697) has no positive witness on any host. The v2 reference host does not run cycles. MyndHyve runs request-changes loops over condition edges on a successful gate output, and does not route a failed node over `any_failed` (its Cloud Run executor has no `triggerRule` handling), so the row stays `inapplicable` there. openwop-app rejects cycles. The row exists and is negatively controlled: registering the fixture on a host that does not loop records `executed-fail`.",
13349
+ "witness": "unclassified",
13350
+ "requirementId": null,
13351
+ "disposition": "externally-gated",
13352
+ "target": "host-routes-failed-gate-over-cycle",
13353
+ "sources": [
13354
+ {
13355
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13356
+ "token": "G9"
13357
+ }
13358
+ ]
13359
+ },
13360
+ {
13361
+ "id": "openwop.gap.0223.10",
13362
+ "rfc": "0223",
13363
+ "local": "G10",
13364
+ "section": "§Conformance",
13365
+ "surface": "`openwop.requirement.0223.timeout-rejects` and `0223.timeout-never-grants` have no MyndHyve witness: its `core.approvalGate` has no timeout configuration. On the v2 reference host both rows are negatively controlled (sweep sabotaged, or the `onTimeout` exclusion present) and pass locally with the fixtures registered. They need suite 2.43.1 and a new certified cut.",
13366
+ "witness": "unclassified",
13367
+ "requirementId": null,
13368
+ "disposition": "externally-gated",
13369
+ "target": "certified-cut-on-2.43.1",
13370
+ "sources": [
13371
+ {
13372
+ "file": "RFCS/registers/0223-approval-reject-disposition.gaps.md",
13373
+ "token": "G10"
13374
+ }
13375
+ ]
13376
+ },
13377
+ {
13378
+ "id": "openwop.gap.0224.1",
13379
+ "rfc": "0224",
13380
+ "local": "G1",
13381
+ "section": "§Conformance",
13382
+ "surface": "The witness is loopback only; `Accepted` needs a certified public v2 bundle from a host advertising the family.",
13383
+ "witness": "unclassified",
13384
+ "requirementId": null,
13385
+ "disposition": "externally-gated",
13386
+ "target": "v2-reference-public-cut",
13387
+ "sources": [
13388
+ {
13389
+ "file": "RFCS/registers/0224-v2-audit-log-integrity.gaps.md",
13390
+ "token": "G1"
13391
+ }
13392
+ ]
13393
+ },
13394
+ {
13395
+ "id": "openwop.gap.0224.2",
13396
+ "rfc": "0224",
13397
+ "local": "G2",
13398
+ "section": "§Unresolved questions",
13399
+ "surface": "A dual-signing host lists a checkpoint under a key other than `checkpointPublicKey`, which the signature row fails; v2 advertises one key.",
13400
+ "witness": "unclassified",
13401
+ "requirementId": null,
13402
+ "disposition": "externally-gated",
13403
+ "target": "first-rotating-host",
13404
+ "sources": [
13405
+ {
13406
+ "file": "RFCS/registers/0224-v2-audit-log-integrity.gaps.md",
13407
+ "token": "G2"
13408
+ }
13409
+ ]
13410
+ },
13088
13411
  {
13089
13412
  "id": "openwop.gap.spec.a2a-integration.g1",
13090
13413
  "rfc": "0152",
@@ -111,7 +111,7 @@ These keys are not part of the v2 root:
111
111
 
112
112
  Operation paths live in `spec/v2/path-manifest.json` ([`versioning.md`](versioning.md)). The declaration is generated from nothing and checked against everything (`scripts/check-declaration.mjs`).
113
113
 
114
- ## 5. Core families (72)
114
+ ## 5. Core families (73)
115
115
 
116
116
  Each heading below is a `spec/v2/declaration.json` row with `anchor: core`. `scripts/check-declaration.mjs` MUST fail when a heading here, a root key in the generated schema, or a pack peer-dependency identifier names a family the declaration does not. The peer-dependency identifier is identical to the key ([`packs.md`](packs.md)).
117
117
 
@@ -394,6 +394,10 @@ Witness `witnessable-gated`.
394
394
 
395
395
  Witness `seam-gated`. Facets: `lanes`, `subjectLinkKey`.
396
396
 
397
+ ### § auditLogIntegrity
398
+
399
+ Witness `witnessable-gated`. Facets: `checkpointSignatureAlgorithm`, `checkpointPublicKey`, `checkpointIntervalEntries`, `checkpointIntervalSeconds` ([security-defaults.md](security-defaults.md) §Audit-log integrity).
400
+
397
401
  ### § i18n
398
402
 
399
403
  Witness `witnessable-gated`.
@@ -463,4 +467,4 @@ A profile is a predicate over the declaration file, published in `spec/v2/profil
463
467
 
464
468
  Rows `C2.1`–`C2.10` are `spec/v1/migrations.json` entries. `openwop.codemod.discovery-document-v2` transforms `C2.2`–`C2.8`: it drops a family with `supported: false` and promotes a dotted-only declared family to its plain key. Certification bundles naming `openwop-core` are never upgraded; they remain valid v1 evidence at their version.
465
469
 
466
- *Sources: RFC 0144, RFC 0169, RFC 0175, RFC 0176, RFC 0179, RFC 0197. Each family's owning RFC is its `owningRfc` in [`declaration.json`](../declaration.json).*
470
+ *Sources: RFCs 0144, 0169, 0175, 0176, 0179, 0197. Each family's owning RFC is its `owningRfc` in [`declaration.json`](../declaration.json).*
@@ -145,4 +145,4 @@ This proves the arithmetic and that recovery ran once inside the bound. It does
145
145
 
146
146
  An RFC whose acceptance criteria are corpus gates rather than host scenarios records the evidence label **corpus gate — no host tier** in its `Updated` line. For such an RFC the accepted-predicate check reads `(corpus)` rows from `evidence/corpus-ledger.json` and MUST NOT require a host bundle.
147
147
 
148
- *Sources: RFC 0158, RFC 0168, RFC 0212, RFC 0216.*
148
+ *Sources: RFCs 0158, 0168, 0212, 0216.*
@@ -35,4 +35,4 @@ A host advertising `connections.packsSupported` MUST resolve a connector's `auth
35
35
 
36
36
  Both codes are in `spec/v2/errors.json`: `connection_provider_conflict` (two claimants for one bare id) and `connection_provider_unresolved` (no definition for the referenced id).
37
37
 
38
- *Sources: RFC 0095, RFC 0177.*
38
+ *Sources: RFCs 0095, 0177.*
@@ -23,4 +23,4 @@ A host advertising `channelPresence` MUST report present members as a subset of
23
23
 
24
24
  A host that stamps model provenance on an agent turn MUST advertise `conversationTurnModelProvenance`. The stamp is non-secret and non-PII (provider and model identifiers only), and a host MUST NOT place prompt or completion content in it.
25
25
 
26
- *Sources: RFC 0101, RFC 0109, RFC 0110.*
26
+ *Sources: RFCs 0101, 0109, 0110.*
@@ -8,9 +8,9 @@ Every error a v2 host returns is a row in one registry. A client routes on `erro
8
8
 
9
9
  ## The registry
10
10
 
11
- `spec/v2/errors.json` holds one row per code: `{ code, httpStatus, retriable, details, since, deprecated? }` plus the provenance fields `statusSource` and `source`, and an optional one-line `meaning`. `spec/v2/errors.schema.json` defines the row. It registers **107** codes. `schemas/v2/error-envelope.schema.json` is GENERATED from it and MUST NOT be edited by hand.
11
+ `spec/v2/errors.json` holds one row per code, defined by `spec/v2/errors.schema.json`. It registers **108** codes. `schemas/v2/error-envelope.schema.json` is GENERATED from it and MUST NOT be edited by hand.
12
12
 
13
- - A host MUST return a registered code, or a vendor code, in every error response.
13
+ - A host MUST emit a registered code, or a vendor code, wherever it emits an error code: the `error` of every error response, and `error.code` on `run.failed`, `node.failed` and the snapshot's `error` (overview.md §0). A recorded event re-emitted by replay or `:fork` is carried as recorded ([replay.md](replay.md)).
14
14
  - A vendor code MUST match `^(?!openwop\.)[a-z][a-z0-9]*(-[a-z0-9]+)*\.[a-z][a-z0-9_]*$`, with its first segment an org registered in `spec/v2/declaration.json`. `openwop.` is reserved.
15
15
  - The registry grows by [overview.md](overview.md) §0.
16
16
 
@@ -47,7 +47,7 @@ The idempotency mismatch code is `idempotency_key_mismatch` only ([idempotency.m
47
47
 
48
48
  ## Codes by HTTP status
49
49
 
50
- Generated from `spec/v2/errors.json` (107 codes; `retriable` and `statusSource` are in the registry).
50
+ Generated from `spec/v2/errors.json` (108 codes; `retriable` and `statusSource` are in the registry).
51
51
 
52
52
  Code | Status
53
53
  --- | ---
@@ -130,6 +130,7 @@ Code | Status
130
130
  `payload_too_large` | 413
131
131
  `workspace_too_large` | 413
132
132
  `unsupported_media_type` | 415
133
+ `approval_rejected` | 422
133
134
  `capability_not_provided` | 422
134
135
  `capability_required` | 422
135
136
  `connection_auth_metadata_mismatch` | 422
@@ -159,4 +160,4 @@ Code | Status
159
160
  `pack_registry_unreachable` | 503
160
161
  `runner_unavailable` | 503
161
162
 
162
- *Sources: RFC 0171, RFC 0213.*
163
+ *Sources: RFCs 0171, 0213.*
@@ -188,4 +188,4 @@ An absent `kinds` is not an empty catalog and is not an unrestricted one: a host
188
188
  - **`feedback.targets`** names the resources an annotation may be attached to. A host MUST refuse an annotation whose target is outside the advertised set, and MUST NOT write it to the replayable run event log.
189
189
  - **`providerUsage.costEstimates`** advertises that the host stamps a derived cost on the `provider.usage` event. That figure is an estimate from the host's own rate table; a consumer MUST NOT treat it as a billed amount.
190
190
 
191
- *Sources: RFC 0171, RFC 0172, RFC 0176, RFC 0185, RFC 0194, RFC 0213.*
191
+ *Sources: RFCs 0171, 0172, 0176, 0185, 0194, 0213.*
@@ -40,4 +40,4 @@ A form instantiated from a pack advertised through `forms.contentPacks` MUST be
40
40
 
41
41
  The five spec-reserved `format` values are the core set. A host that recognizes a format SHOULD apply it; one that does not MUST ignore it and accept plain text. A host MUST ignore `format` on any type other than `text` or `longtext`.
42
42
 
43
- *Sources: RFC 0137, RFC 0177.*
43
+ *Sources: RFCs 0137, 0177.*
@@ -68,4 +68,4 @@ Layer 1 deduplicates the caller's request; Layer 2 deduplicates the run's effect
68
68
  - `multiRegion` is the behavioural claim. When a host advertises it, both layers MUST hold across regions: an `Idempotency-Key` replayed into a second region MUST resolve to the first region's response rather than starting new work, and effect identity MUST collapse a duplicate effect wherever it is observed.
69
69
  - A host that does not advertise `multiRegion` makes no cross-region promise, and a client MUST NOT infer one from `crossRegion` alone.
70
70
 
71
- *Sources: RFC 0170, RFC 0171, RFC 0173, RFC 0213.*
71
+ *Sources: RFCs 0170, 0171, 0173, 0213.*
@@ -222,4 +222,4 @@ Every code below is a row with `retriable: false` and no `details` contract; the
222
222
 
223
223
  The identity invariants are registered in `SECURITY/invariants.yaml` with their scenarios. An invariant without a witness is demoted from `protocol` tier.
224
224
 
225
- *Sources: RFC 0132, RFC 0165, RFC 0170, RFC 0176, RFC 0184, RFC 0200, RFC 0210.*
225
+ *Sources: RFCs 0132, 0165, 0170, 0176, 0184, 0200, 0210.*