@openwop/spec-artifacts 2.3.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CORPUS-STAMP.json +46 -46
  2. package/api/seams-v2.yaml +1 -1
  3. package/api/v2/asyncapi.yaml +1 -1
  4. package/api/v2/openapi.yaml +8 -4
  5. package/package.json +1 -1
  6. package/schemas/v2/form-content-pack-manifest.schema.json +31 -0
  7. package/schemas/v2/ids.schema.json +7 -7
  8. package/schemas/v2/run-event.schema.json +1 -1
  9. package/schemas/v2/trigger-subscription.schema.json +2 -3
  10. package/schemas/v2/webhook-delivery.schema.json +5 -5
  11. package/schemas/v2/workflow-chain-pack-manifest.schema.json +41 -40
  12. package/spec/v1/alias-detectors.json +7 -1
  13. package/spec/v1/core-standard-manifest.json +2 -2
  14. package/spec/v1/deprecations.json +86 -68
  15. package/spec/v1/gaps.json +41 -825
  16. package/spec/v1/spec-gaps.json +0 -784
  17. package/spec/v2/README.md +54 -15
  18. package/spec/v2/core/conformance.md +9 -7
  19. package/spec/v2/core/events.md +6 -1
  20. package/spec/v2/core/headers.md +1 -1
  21. package/spec/v2/core/interrupt.md +6 -0
  22. package/spec/v2/core/persistence.md +10 -7
  23. package/spec/v2/core/security-defaults.md +6 -7
  24. package/spec/v2/core/versioning.md +19 -7
  25. package/spec/v2/core/webhooks.md +4 -1
  26. package/spec/v2/ext/README.md +23 -13
  27. package/spec/v2/ext/a2uiSurface/README.md +18 -7
  28. package/spec/v2/ext/brand/README.md +18 -7
  29. package/spec/v2/ext/canvas/README.md +18 -7
  30. package/spec/v2/ext/chat/README.md +18 -7
  31. package/spec/v2/ext/coordination/README.md +18 -7
  32. package/spec/v2/ext/dataIntegration/README.md +18 -7
  33. package/spec/v2/ext/entities/README.md +18 -7
  34. package/spec/v2/ext/grpc-transport/README.md +10 -5
  35. package/spec/v2/ext/kanban/README.md +18 -7
  36. package/spec/v2/ext/knowledge/README.md +18 -7
  37. package/spec/v2/ext/launchStudio/README.md +18 -7
  38. package/spec/v2/ext/messaging/README.md +18 -7
  39. package/spec/v2/ext/portability/README.md +11 -2
  40. package/spec/v2/ext/provider-idempotency/README.md +10 -2
  41. package/spec/v2/ext/restTransport/README.md +18 -7
  42. package/spec/v2/ext/sandbox-runtime-notes/README.md +9 -2
  43. package/spec/v2/ext/webResearch/README.md +18 -7
  44. package/spec/v2/id-field-bindings.json +4 -4
  45. package/spec/v2/release.json +3 -3
package/spec/v2/README.md CHANGED
@@ -1,19 +1,58 @@
1
- # `spec/v2/` — the OpenWOP v2 tree (the current protocol major)
1
+ # OpenWOP v2 specification
2
2
 
3
- > **Status: released.** v2 is the current protocol major — `v2.0.0` was tagged 2026-09-05 and this tree is at corpus `v2.2.1` (`release.json`). Everything under `spec/v2/`, `schemas/v2/` and `api/v2/` is normative, is vendored into `@openwop/spec-artifacts`, and is what `@openwop/openwop-conformance` 2.x measures. A new integration targets v2.
4
- >
5
- > **v1 is not retired.** Through the overlap a host advertises both majors and `preferredVersion` MUST remain a `1.x` member (`core/versioning.md` §1.1); v1 clients keep working unchanged on `/v1/…`. v1 end-of-support is the later of two clocks in `core/overview.md`, earliest 2026-12-04, and until then `spec/v1/` stays the maintained parallel track. A `1.x` conformance tarball still excludes this tree (`conformance/scripts/pack-vendor.sh`).
6
- >
7
- > The banner that stood here until 2026-09-10 said *"in construction … until the `v2.0.0-rc.1` corpus tag"*. That tag landed 2026-09-03 and the line was never updated; a reader who trusted it concluded v2 did not exist. Status lines that are hand-kept drift; this one now names the tag and the file that carry the truth.
3
+ > **Status: released · corpus v2.3.3.** The authoritative version is
4
+ > [`release.json`](./release.json). Target v2 for new implementations.
8
5
 
9
- Layout (RFC 0167 §C; RFC 0174 §E.2 budget):
6
+ OpenWOP v2 is the current protocol major. Its contract consists of this
7
+ directory, [`schemas/v2/`](../../schemas/v2/), and
8
+ [`api/v2/`](../../api/v2/). Those artifacts are published together in
9
+ `@openwop/spec-artifacts` and measured by `@openwop/openwop-conformance` 2.x.
10
10
 
11
- | Path | Owner | What |
12
- | --- | --- | --- |
13
- | `declaration.json` (+ `declaration.schema.json`) | RFC 0169 §B | The one declaration file: every root key of the v2 discovery document with its anchor (`core`, `ext` or `deleted`), witness class, maturity, facets, peer-dependency identifier (≡ key), floor scenarios and requirement ids, and the profile predicates. Hand-reviewed source; everything else is generated from it (`scripts/generate-from-declaration.mjs`) and checked against it (`scripts/check-declaration.mjs`). |
14
- | `profiles.json`, `peer-dependency-aliases.json` | RFC 0169 §C, RFC 0177 §B.2 | Generated. |
15
- | `errors.json` (→ generated `schemas/v2/error-envelope.schema.json`), `event-codemap.json` (all rows decided), `path-manifest.json` (operations + channels), `release.json` (the one release identity `info.version` reads), `facets/<key>.schema.json` (hand-decided facet shapes the capabilities generator reads) | RFC 0171, 0176, 0172, 0169 | Landed P3-B/P3-C. `migrations.json` / `deprecations.json` stay at `spec/v1/` until the RC promotes them with `applied` marks (RFC 0167). |
16
- | `core/*.md` | one per child | Normative prose, ≤ 25,000 words total (`scripts/check-core-budget.mjs`, `wc -w` on raw markdown, generated `core/headers.md` included). `capabilities.md` carries one `### § <key>` heading per core family (`check-declaration.mjs`). Lands in P3-D. |
17
- | `ext/<key>/` | RFC 0169 §B.3, RFC 0175 §A.1, RFC 0173 §D | Extension documents with a declared `witness:` / `technical:` / `adoption:` header: the 13 ext-anchored families, plus `grpc-transport/` (demoted; non-normative proto), `portability/` (goals/export/import), `sandbox-runtime-notes/` (RFC 0035 history), `provider-idempotency/` (the Layer-2 provider registry). |
11
+ v1 remains available during the overlap period. Dual-stack requirements and
12
+ the retirement rule are defined in
13
+ [`core/versioning.md`](./core/versioning.md#5-the-overlap-rfc-0167-b5-rfc-0176)
14
+ and [`core/overview.md`](./core/overview.md).
18
15
 
19
- Machine artifacts here are published in `@openwop/spec-artifacts` (RFC 0168 §D.2), never inside the suite tarball.
16
+ ## Start here
17
+
18
+ 1. [`core/overview.md`](./core/overview.md) — scope, conformance target, and
19
+ lifecycle.
20
+ 2. [`core/versioning.md`](./core/versioning.md) — discovery and major-version
21
+ negotiation.
22
+ 3. [`core/capabilities.md`](./core/capabilities.md) — the closed discovery
23
+ document.
24
+ 4. [`core/runs.md`](./core/runs.md), [`core/events.md`](./core/events.md), and
25
+ [`core/interrupt.md`](./core/interrupt.md) — the execution model.
26
+ 5. [`core/security-defaults.md`](./core/security-defaults.md) and
27
+ [`core/conformance.md`](./core/conformance.md) — mandatory safety defaults
28
+ and evidence rules.
29
+
30
+ ## Source-of-truth map
31
+
32
+ | Path | Purpose |
33
+ | --- | --- |
34
+ | [`declaration.json`](./declaration.json) | Hand-reviewed inventory of discovery keys, capability families, maturity, witnesses, facets, profiles, and peer-dependency identifiers. |
35
+ | [`declaration.schema.json`](./declaration.schema.json) | Schema for the declaration. |
36
+ | [`core/`](./core/) | Normative protocol prose. |
37
+ | [`ext/`](./ext/) | Optional extensions and explicitly non-core notes. See the extension maturity rules in [`ext/README.md`](./ext/README.md). |
38
+ | [`facets/`](./facets/) | Hand-reviewed capability facet schemas. |
39
+ | [`errors.json`](./errors.json) | Error-code registry. |
40
+ | [`event-codemap.json`](./event-codemap.json) | v1-to-v2 event-name mapping. |
41
+ | [`path-manifest.json`](./path-manifest.json) | Canonical operation and channel paths. |
42
+ | [`profiles.json`](./profiles.json) | Generated profile predicates. |
43
+ | [`peer-dependency-aliases.json`](./peer-dependency-aliases.json) | Generated v1 alias mapping. |
44
+ | [`release.json`](./release.json) | Authoritative corpus release identity. |
45
+
46
+ Generated files identify their generator in `$comment` or their header. Do not
47
+ edit generated outputs directly. Machine artifacts are published in
48
+ `@openwop/spec-artifacts`; the conformance package consumes them as an
49
+ exact-version peer dependency.
50
+
51
+ ## Core documents
52
+
53
+ | Area | Documents |
54
+ | --- | --- |
55
+ | Foundation | [`overview`](./core/overview.md), [`versioning`](./core/versioning.md), [`headers`](./core/headers.md), [`identity`](./core/identity.md), [`capabilities`](./core/capabilities.md) |
56
+ | Execution | [`runs`](./core/runs.md), [`events`](./core/events.md), [`interrupt`](./core/interrupt.md), [`persistence`](./core/persistence.md), [`idempotency`](./core/idempotency.md), [`replay`](./core/replay.md) |
57
+ | Integration | [`webhooks`](./core/webhooks.md), [`interop`](./core/interop.md), [`packs`](./core/packs.md), [`connection packs`](./core/connection-packs.md), [`form-content packs`](./core/form-content-packs.md), [`workflow-chain packs`](./core/workflow-chain-packs.md) |
58
+ | Reliability | [`errors`](./core/errors.md), [`security defaults`](./core/security-defaults.md), [`conformance`](./core/conformance.md) |
@@ -14,13 +14,15 @@ The ledger records per `it`, and a bundle's `results.requirements[]` is the per-
14
14
 
15
15
  ### Whose fact is the reason?
16
16
 
17
- A soft-skip carries a disposition and a reason string, and the two answer different questions. The disposition says whether the row counts; the reason says *why*, and it is the only part a reader can act on. A reason MUST name a fact about the **host under test**. Where the predicate is instead a fact about the **suite** — its layout, its corpus data, a fixture it cannot resolve — the row MUST record `blocked`, never `inapplicable`.
18
-
19
- `inapplicable` asserts that the requirement does not bind this host. A suite that could not read its own corpus has established no such thing; the requirement binds exactly as before and the suite simply did not measure it. Recording `inapplicable` there states something false about the host, and states it in the quietest way available: `blocked` is bundle-wide fatal (RFC 0168 §E.1), while `inapplicable` certifies. A suite that cannot read its own corpus MUST NOT issue a certification on the strength of it.
20
-
21
- Ordering follows from this. Where an `it` can soft-skip for several reasons, gates whose predicate is a host fact MUST be evaluated before gates whose predicate is a suite fact, so the row keeps describing the host for as long as it truthfully can. Ordering alone is not the guarantee, though — it only decides *which* true reason is reported. The guarantee is that a suite-side gate can never be silent, because it is never `inapplicable`.
22
-
23
- **Why this is written down.** The failure it prevents is invisible at the disposition layer. A row already `inapplicable` for a true host reason, re-gated onto a suite-side precondition, stays `inapplicable`: `skip → skip`, no count moves, no gate reddens, and the row silently stops describing the host it names. Nothing in a bundle diff shows it. The rule is what makes that class of drift loud.
17
+ A soft-skip carries a disposition and a reason. The reason MUST identify a fact
18
+ about the host under test. Use `inapplicable` only when the requirement does not
19
+ bind that host. A missing fixture, unreadable corpus file, or other suite-side
20
+ failure MUST be `blocked`, never `inapplicable`; a suite with a blocked row MUST
21
+ NOT issue a certification (RFC 0168 §E.1).
22
+
23
+ When more than one gate can skip a test, evaluate host predicates before suite
24
+ predicates. This preserves the most specific truthful reason while ensuring a
25
+ suite failure cannot be hidden as an inapplicable host requirement.
24
26
 
25
27
  ## Witness class
26
28
 
@@ -42,7 +42,12 @@ A consumer MUST NOT throw on an event whose `type` it does not know; it folds wh
42
42
 
43
43
  The CloudEvents mapping and the webhook delivery envelope are GENERATED from the same definition (one source, three renderings): the event's `type`, `eventId`, `sequence` and `payload` are byte-identical across the run stream, a CloudEvents rendering and a webhook delivery.
44
44
 
45
- `run.started` carries `owner { tenant, workspace?, subject }`, the same closed block as `RunSnapshot.owner` with `subject` REQUIRED (runs.md, identity.md). `run.cancelled` carries `reason`, `cancelledBy`, `durationMs` and `parentRunId`. `run.completed` MUST carry `outputs` as an object — an empty object is a valid value; an absent key is not. A client cannot tell "no outputs" from "outputs not rendered" when the key is missing, and until 2026-09-04 no schema in either major required it: v1 named the property, required nothing and left the object open, so a host emitted the singular `output` for its whole life and validated every time. Closing the object in v2 caught the extra key; only this sentence and its witness (`v2-run-completed-outputs`) catch an absent one.
45
+ `run.started` carries `owner { tenant, workspace?, subject }`, the same closed
46
+ block as `RunSnapshot.owner` with `subject` REQUIRED (runs.md, identity.md).
47
+ `run.cancelled` carries `reason`, `cancelledBy`, `durationMs`, and `parentRunId`.
48
+ `run.completed` MUST carry `outputs` as an object; an empty object is valid, but
49
+ an absent key is not. This distinguishes “no outputs” from “outputs not
50
+ rendered” and is witnessed by `v2-run-completed-outputs`.
46
51
 
47
52
  ## AI envelopes: E1–E5
48
53
 
@@ -1,6 +1,6 @@
1
1
  # Headers
2
2
 
3
- > **Status: Stable · v2.2.1 (2026-09-16) · RFC 0171 §C.1, RFC 0172 §A.3–§A.4.** GENERATED by `scripts/derive-v2-api.py` from `api/v2/openapi.yaml`; do not edit.
3
+ > **Status: Stable · v2.4.0 (2026-09-18) · RFC 0171 §C.1, RFC 0172 §A.3–§A.4.** GENERATED by `scripts/derive-v2-api.py` from `api/v2/openapi.yaml`; do not edit.
4
4
 
5
5
  ## Why this exists
6
6
 
@@ -80,4 +80,10 @@ Enforcement is an obligation of the fields, not a discovery flag (RFC 0173 §B).
80
80
  | `approverRoleRefs` | Only where `refKinds` includes `role`: as for groups, with holders |
81
81
  | `audience` | A notification hint, never eligibility; omitted ⇒ the host SHOULD notify the union of the eligibility refs |
82
82
 
83
+ Eligibility binds every WRITER of the suspension record, not every route. A
84
+ host whose durable store is writable by a principal other than the engine MUST
85
+ enforce the same eligibility at the store, or MUST NOT expose the record to
86
+ that principal for write: a rule enforced per route is only as complete as the
87
+ census of writers (RFC 0187 §C.1).
88
+
83
89
  Refs are opaque to the engine; the host resolves them against its own identity model. Membership MUST be resolved at decision time and MUST NOT be re-resolved during replay or `forkRun`: the recorded eligibility decision is fixed history (replay.md). A host that does not advertise a ref kind MUST ignore that field. A relaxation of any obligation here is an operator setting recorded in the certification bundle, never a discovery field (security-defaults.md).
@@ -71,6 +71,10 @@ read with `event_type_unmapped` on a name the codemap does not carry on its v1
71
71
  side. A run created after the upgrade is era `3` and is written in v2
72
72
  vocabulary, untranslated.
73
73
 
74
+ A writer that emits a property a closed def cannot seat (RFC 0185 §B) MUST
75
+ mark the row with what it could not seat, so the refusal names the writer
76
+ instead of surfacing as an unexplained read failure (RFC 0187 §D.1).
77
+
74
78
  This binds every writer for as long as an era-`2` run stays open, which on a
75
79
  host with human-approval interrupts can be days. Draining era-`2` runs before
76
80
  serving v2 is not the path — see §"Runs pinned to v1" — so the writer rule is
@@ -95,18 +99,17 @@ property at load rather than assume it; if a future row folds two v1 names onto
95
99
  one v2 name, the inverse stops being a function and the host MUST refuse to
96
100
  serve the v1 representation rather than guess which spelling to emit.
97
101
 
98
- Two alternatives are rejected, and naming them is the point of this section.
99
- Storing v1 spellings under an era-`3` stamp makes the stamp a lie, and the
100
- closed-enum scenario would pass it by luck on any run whose types happen to be
101
- identity rows. Serving v2 names on `/v1/…` breaks the v1 wire, which the
102
- overlap exists to preserve. Neither is a smaller change than the inverse map;
103
- they are the same change with the honesty removed.
102
+ A type with NO codemap row — v2-only vocabulary, anything RFC 0185/0186 seated
103
+ — has no v1 spelling to invert to. A host MUST emit it unchanged on the v1 read
104
+ path, MUST NOT drop the row, and MUST NOT refuse the read for it (RFC 0187
105
+ §B.1): a v1 consumer already tolerates an unknown `type`, and the alternatives
106
+ lose data or make one new row cost an otherwise readable run.
104
107
 
105
108
  ### The seat
106
109
 
107
110
  The adapter MUST sit at the storage boundary every reader passes through — the storage interface's event-list method, not a wrapper some call sites bypass. A host leg MUST name its seat in its ADR.
108
111
 
109
- The seat is a **claims-check** (conformance.md §Witness class): it is discharged by that disclosure and by audit, never by the wire. `v2-v1-events-translated` drives poll, SSE and a fork, and what those three legs witness is that *those three readers* translate. They do not witness the seat. Three wrappers pass them exactly as one correctly seated adapter does, and the rule binds **every** reader — including the ones the suite has no name for. A universal is not discharged by three examples: the scenario catches a reader that was *missed*, not an adapter that was *misplaced*.
112
+ The seat is a **claims-check** (conformance.md §Witness class): discharged by that disclosure and by audit, never by the wire. The rule binds **every** reader, including the ones the suite has no name for; `run-event.schema.json` records why three passing legs do not discharge it.
110
113
 
111
114
  ### Forking a v1 run
112
115
 
@@ -75,21 +75,20 @@ Every security obligation in `core/` is exactly one of (RFC 0173 §D.1):
75
75
  | extension | `spec/v2/ext/` | MUST declare a witness class and both maturity axes. |
76
76
  | removed | — | No text survives. |
77
77
 
78
- There is no unimplemented MUST. Compensation and Layer-2 effect identity are core obligations at filing; either MUST move to `ext/` at the cut if its witness does not land. RFC 0150's sub-decisions: operation ids in the declaration file are canonical and aliases are register rows; the provider semantic-option registry is `spec/v2/ext/provider-idempotency/registry.json` with a witness per provider; the qualification test is a fixture provider that rejects a changed key (§D.2).
79
-
80
- ### RFC 0035
81
-
82
- RFC 0035 (Parked) is resolved by the `packs` row: its §B probes become the `packs` obligation, and the RFC flips `Superseded` by RFC 0173 at the cut in the same PR (RFC 0174 §A.1). Its tripwire — a non-steward host fencing untrusted packs — becomes the `adoption: independent` axis, not a status gate.
78
+ Operation ids in the declaration file are canonical, and aliases are migration
79
+ register rows. The provider semantic-option registry is
80
+ `spec/v2/ext/provider-idempotency/registry.json`; provider qualification uses a
81
+ fixture that rejects a changed idempotency key (§D.2).
83
82
 
84
83
  ## Threat models
85
84
 
86
- RFC 0173 §E requires three threat-model artifacts before its dependents flip Accepted:
85
+ The following threat-model artifacts are required:
87
86
 
88
87
  | Artifact | Requirement |
89
88
  | --- | --- |
90
89
  | `SECURITY/threat-model-replay.md` §6 Residual risks | MUST record branch re-fires, seams outside the manifest, and the manifest as a self-declaration. |
91
90
  | `SECURITY/threat-model-replay.md` §7 Verification, §8 References | MUST name the manifest scenario and `fork-a-v1-run`; a threat model missing a sibling section fails the template gate. |
92
- | `SECURITY/threat-model-interop.md` | MUST exist before RFC 0175 flips Accepted (written by RFC 0175's cut). |
91
+ | `SECURITY/threat-model-interop.md` | MUST cover downgrade, identity, and cross-tenant risks in protocol composition. |
93
92
 
94
93
  ## Migration
95
94
 
@@ -20,7 +20,9 @@ v1 operations keep their `/v1/…` path keys unchanged through the overlap. v2 o
20
20
 
21
21
  A host that advertises a major in `protocolVersions[]` MUST reach, under that major, every operation **named in `spec/v2/path-manifest.json`** that it serves under the other. Advertising a major is a claim about the **path space**, not about `/.well-known/openwop` alone — that resource's representation is *selected* by the request header (§1.3), so it answers correctly for a host that has mounted nothing else, and every discovery-level probe of the advertisement passes with it. Concretely: if `/v1/<op>` answers and the unversioned `/<op>` returns `404` under the advertised major, the advertisement overstates what the host serves and the host MUST NOT advertise that major until the surface is reachable. The pairing is normative because a lone `404` cannot distinguish *"this host does not serve that operation"* from *"this host serves it and did not mount it under this major"*, and only the second is a defect.
22
22
 
23
- **The manifest is the scope, and that qualifier is load-bearing.** An earlier wording quantified over *every operation it serves*, which is not jointly satisfiable with `conformance.md` §"Test seams": the seams profile mounts the real path space `/conformance/seams/…`, and that same document requires `spec/v2/path-manifest.json` and `api/v2/openapi.yaml` to contain **no** seam operation. Under the unqualified reading a host serving seams under one major owed them under the other, while the manifest against which the claim is measured was forbidden to name them. Surfaces a host serves that the manifest does not name — seam paths, and any path the protocol does not define — are **not** bound by this paragraph; §5 records what the protocol does and does not say about the second class. The narrowing does not weaken the case the rule exists for: the defect that motivated it was `POST /webhooks` answering `404` under major 2 while `POST /v1/webhooks` answered `201`, and `webhooks` is a manifest operation.
23
+ The manifest defines the scope of this pairing rule. Seam paths and proprietary
24
+ paths are not manifest operations and do not require a per-major twin. The
25
+ canonical OpenAPI therefore contains no conformance-seam operation.
24
26
 
25
27
  `spec/v2/path-manifest.json` (generated) carries operations (`method`, `path`, `operationId`) and channels (`name`, `address`) on a bare origin, and **every path in it is unversioned** — there are no `/v1` rows. The `/v1` twin of a manifest row is derived by prefixing, which is what the pairing above compares. OpenAPI (`api/v2/openapi.yaml`), AsyncAPI (`api/v2/asyncapi.yaml`), and any kept proto MUST resolve to identical absolute paths for the shared event stream (`scripts/check-path-parity.mjs`); the canonical OpenAPI MUST contain no seam or test-mode operation (those live in the seams profile, see `conformance.md`).
26
28
 
@@ -41,7 +43,10 @@ A request on a `/v1/…` path key MUST NOT carry `OpenWOP-Version` with a value
41
43
 
42
44
  Every protocol response MUST carry `OpenWOP-Version: <major>.<minor>` naming the contract that produced it. Reporting a version other than the one used is a silent downgrade and non-conformant; the `dual-stack-negotiation` scenario falsifies it. Emitting the header on `/v1/` responses is additive in v1.x and REQUIRED in v2.
43
45
 
44
- A *protocol response* is one produced by an operation named in `spec/v2/path-manifest.json` (or its `/v1/` twin through the overlap); a shell, a hosting fallback or a proprietary route on the same origin has no version to name. Errata 2026-09-10: this read "any path" — §1.2's quantifier defect again.
46
+ A *protocol response* is one produced by an operation named in
47
+ `spec/v2/path-manifest.json` (or its `/v1/` twin through the overlap). A shell,
48
+ hosting fallback, conformance seam, or proprietary route has no protocol
49
+ version to name.
45
50
 
46
51
  **On a manifest-named path, a non-protocol response MUST NOT carry `OpenWOP-Version` and MUST NOT be `application/json`**; a reader, a cache or the suite MUST NOT count a response without the header, or with a `text/html` body, as reaching the operation (`reachedUnderMajor2`). A vendor path (§5) is not a shared name and is unconstrained.
47
52
 
@@ -57,7 +62,9 @@ Otherwise the page MUST move off the shared name.
57
62
 
58
63
  When both majors are advertised, a v2 client MUST select the highest major it implements that the host lists; a v1 client (no header, `/v1/` paths) is unaffected. `minClientVersion` (axis 15, grammar as axis 1) is a MUST: a host MAY refuse a client below it with `426` `client_version_unsupported`.
59
64
 
60
- `OpenWOP-Version` on a request selects by MAJOR; the `<major>.<minor>` spelling is accepted because `protocolVersions[]` members are `<major>.<minor>` and a client echoing one back is the obvious thing to do — the conformance driver does exactly that. A minor pin is what `minClientVersion` and the additive rules cover (RFC 0172 UQ1, recommended disposition; the integer-only reading was corrected in Phase 4 after it contradicted the suite that tests it).
65
+ `OpenWOP-Version` selects by major. The `<major>.<minor>` spelling is accepted so
66
+ a client may echo a `protocolVersions[]` member. Minor compatibility is governed
67
+ by `minClientVersion` and the additive-change rules.
61
68
 
62
69
  ## 2. The 18 version axes (RFC 0172 §B; RFC 0167 §E.1)
63
70
 
@@ -108,15 +115,20 @@ A consumer that vendors any file from `schemas/`, `api/`, or `spec/` MUST pin to
108
115
 
109
116
  Through the overlap a host MUST advertise both majors (§1.1), MUST emit `OpenWOP-Version` on every response (§1.4), and MUST serve `/.well-known/openwop` as one resource whose representation the request header selects (`capabilities.md`). The dual-stack scenario creates one run through `/v1/runs` with no header and reads it through `/runs` with `OpenWOP-Version: 2`; the response headers name the contract used.
110
117
 
111
- **A run minted under major 1 and read under major 2 MUST be named by its tenant-bound projection** `<tenantId>/<the v1 id>` (`identity.md` §5). A host MUST NOT return the bare v1 id in a major-2 response body. Normative since 2026-09-04, when a conformance check asserting byte-equality with the v1 id and a host implementing `identity.md` §5 could not both hold — §5 had no reading.
112
-
113
- The projection is mandatory for a reason that is not stylistic: a tenant-bound id carries the segment `identity.md` §5's `403 id_tenant_mismatch` check reads, and **a bare id has none, so the cross-tenant refusal cannot run on it at all.** A legacy unprefixed form in documents would be a class of long-lived identifiers on which major 2's tenant isolation is structurally inapplicable; the grammar in `ids.schema.json` has no legacy branch and MUST NOT acquire one.
118
+ **A run minted under major 1 and read under major 2 MUST use the tenant-bound
119
+ projection** `<tenantId>/<v1-id>` (`identity.md` §5). A host MUST NOT return a
120
+ bare v1 id in a major-2 response. The tenant segment is required for the
121
+ `id_tenant_mismatch` check; `ids.schema.json` has no legacy unprefixed branch.
114
122
 
115
123
  The overlap ends at v1 end-of-support (`overview.md`), when `protocolVersions[]` drops the `1.<n>` member and every alias carrying the `v1-end-of-support` trigger is removed.
116
124
 
117
125
  **Retirement is atomic, and that is a consequence of §1.1 rather than a separate rule.** Through the overlap `preferredVersion` MUST name a `1.x` member; a host that drops v1 from `protocolVersions[]` advertises a `2.x` `preferredVersion`. There is no legal intermediate state in which both majors are advertised and `2.x` is preferred, so flipping `preferredVersion` ahead of the drop is not a smaller first step — it is the same step. Dropping v1 therefore retires the whole `/v1` path space at once, not incrementally.
118
126
 
119
- **Retirement flips every header-less request's contract.** Through the overlap a header-less request on an unversioned name is served major 1 (§1.3); where the v1 surface lives under `/v1/` that name is not a v1 key and falls through to whatever else is served there — typically a page. At end-of-support the same request is served major 2 and the page starts answering the operation. A `/v1/`-counting inventory cannot see this. Test: `manifest top-level segments ∩ anything else served unversioned` (`{agents, prompts, runs}` on the host that found it). A non-empty intersection MUST be resolved before end-of-support: move the page, or serve it under §1.4's conditions.
127
+ **Retirement changes every header-less request's default contract.** Before
128
+ end-of-support, a header-less unversioned request uses major 1; afterward it uses
129
+ major 2. Before retirement, a host MUST check for collisions between manifest
130
+ top-level path segments and non-protocol unversioned routes. It MUST move each
131
+ colliding route or apply §1.4 content negotiation.
120
132
 
121
133
  **Host-proprietary paths live at `/host/<org>/…` (RFC 0181).** Every vendor namespace — capability records (`capabilities.md` §3.2), error codes, event types, pack properties — is keyed to an org registered in `spec/v2/declaration.json`; paths join that pattern. A host MAY serve operations the manifest does not name under `/host/<org>/…` for its registered org: no major in the path, served regardless of `OpenWOP-Version`, never a protocol operation, never measured, outside §1.4. An org MUST NOT be named after a manifest segment under `/host/` (`reservedOrgs`); a host SHOULD advertise the mount under `extensions.<org>.<name>`. A `/v1/host/<org>/…` twin MAY ride the overlap and retires atomically with `/v1`.
122
134
 
@@ -21,7 +21,10 @@ A subscription MUST receive only events from runs within its tenant scope; cross
21
21
 
22
22
  The delivery envelope is generated from the same payload definition as the event itself and the CloudEvents mapping — one source, three renderings (RFC 0171 §A.4). The body is `{ runId, workspaceId?, event }` where `event` is the verbatim run event (events.md), and it MUST validate against `schemas/v2/webhook-delivery.schema.json`. `workspaceId` is present exactly when `RunSnapshot.owner.workspace` is (`identity.md` §1) — a host MUST NOT substitute its tenant id for an absent workspace.
23
23
 
24
- The envelope's `runId` is tenant-bound (`identity.md` §5), like every other rendering of a v2 `runId`. An outbound emission is not a response to a versioned request, so nothing in the request cycle supplies the form — the grammar does. **A host that projects on responses and not on emissions hands the subscriber an identifier the client has never seen**, and the failure is silent: the subscriber's correlation matches nothing, with no error, no `4xx` and no log line. Until 2026-09-04 the nested `event.runId` was bound by `run-event.schema.json` while the envelope's own was carried by this paragraph alone, which is how a real host shipped the split.
24
+ The envelope's `runId` MUST use the tenant-bound v2 form defined by
25
+ `identity.md` §5, matching the nested event and every response representation.
26
+ This requirement applies to outbound delivery even though no versioned request
27
+ exists at delivery time.
25
28
 
26
29
  ### Headers
27
30
 
@@ -1,28 +1,38 @@
1
- # `spec/v2/ext/` — extension families
1
+ # OpenWOP v2 extensions
2
2
 
3
- > **Status: Stable · 2026-09-17 · RFC 0177 §E (this file), RFC 0174 §E.2.** This README is the one place the extension tail's *maturity* rule lives. It is not counted against the `spec/v2/core/` word budget.
3
+ > **Status: Stable · RFC 0177 §E, RFC 0174 §E.2.** This page defines the
4
+ > maturity labels used by extension documents. Extensions are outside the core
5
+ > profile unless a core document explicitly incorporates them.
4
6
 
5
- ## Why this exists
7
+ Each declared extension has a page at `spec/v2/ext/<name>/README.md` and a row
8
+ in [`../declaration.json`](../declaration.json). Presence in the declaration
9
+ reserves its identifier; it does not make the extension interoperable. Read the
10
+ individual page to determine whether it defines portable behavior or only a
11
+ discovery claim.
6
12
 
7
- Seventeen extension documents shipped `Status: Draft` on the day v2 was tagged, and nothing in the corpus said what moves one. RFC 0177 owns *declaring* an extension family; the step after "declared" was unwritten, so every family stayed Draft by default rather than by decision. A status that can only go one way is not a status.
13
+ ## Maturity labels
8
14
 
9
- ## The rule
10
-
11
- An extension document under `spec/v2/ext/<name>/` carries a `Status:` header with one of three values. Movement between them is a **predicate over evidence**, checked by `scripts/check-ext-status-coherence.mjs` in the corpus gate:
15
+ `scripts/check-ext-status-coherence.mjs` checks these labels against committed
16
+ conformance evidence.
12
17
 
13
18
  | Status | Meaning | Predicate |
14
19
  | --- | --- | --- |
15
- | `Draft` | Declared. A host MAY advertise it; the corpus makes no claim about it. | The family is declared in `spec/v2/declaration.json` with `anchor: ext`. |
20
+ | `Draft` | Declared, but not supported by qualifying interoperability evidence. | The family is declared in `spec/v2/declaration.json` with `anchor: ext`. |
16
21
  | `Stable` | Witnessed. At least one host at evidence tier 2 or better serves it, and a **certified** bundle in `evidence/v2-host-bundles/` records the family's declared witness class satisfied. | Every `Stable` doc's family has ≥ 1 `executed-pass` row under its witness id in a bundle whose relevant profile claim is `certified: true`, **and** the 7-day comment window has run since the promotion PR. |
17
22
  | `Retired` | Withdrawn. The family is removed from the declaration and the document names its replacement or the RFC that retired it. | The family is absent from the declaration; the doc carries a `Superseded by:` or `Retired by:` line. |
18
23
 
19
- Two consequences the gate enforces, both directions:
24
+ The gate enforces both directions:
20
25
 
21
- - A `Stable` document whose family **no longer** has a certified passing row is a defect — the gate goes red, and the honest move is to demote to `Draft` with the date, not to find a bundle.
22
- - A `Draft` document whose family **does** have a certified passing row is reported as **graduable** (a warning, not a failure): the evidence exists and the steward has not acted on it. That is the state this README was written to end.
26
+ - A `Stable` document without qualifying evidence fails validation.
27
+ - A `Draft` document with qualifying evidence is reported as eligible for
28
+ review and promotion.
23
29
 
24
- A family with no directory here (the four `ext/` directories with no declared family — `grpc-transport`, `portability`, `provider-idempotency`, `sandbox-runtime-notes` — are notes, not families) is outside this rule and MUST say so in its own header.
30
+ A directory without a corresponding declared family is an implementation or
31
+ migration note and MUST identify itself as outside this maturity rule. This
32
+ currently applies to `grpc-transport`, `portability`,
33
+ `provider-idempotency`, and `sandbox-runtime-notes`.
25
34
 
26
35
  ## What this does not decide
27
36
 
28
- Whether an `ext` family should ever become `core`. That is an RFC 0167-family question (a core family costs budget and needs a codemap row); this file only governs the tail.
37
+ Whether an extension should become core. That requires a separate RFC,
38
+ normative text, machine-readable contracts, and a behavioral witness.
@@ -1,4 +1,7 @@
1
- # `a2uiSurface` — extension
1
+ # `a2uiSurface` extension
2
+
3
+ > **Status: Draft · v2 extension.** Discovery-only reservation; no portable
4
+ > operations or payload contract is defined in v2.3.3.
2
5
 
3
6
  | Field | Value |
4
7
  | --- | --- |
@@ -6,15 +9,23 @@
6
9
  | **technical:** | `experimental` |
7
10
  | **adoption:** | `none` |
8
11
  | **peer-dependency id** | `a2uiSurface` |
9
- | **advertised as** | `extensions.<org>.a2uiSurface` (RFC 0169 §A.4) — never a root key |
12
+ | **advertised as** | `extensions.<org>.a2uiSurface` |
10
13
  | **owning RFC** | RFC 0114 |
14
+ | **declared facets** | `deltaTransport` |
11
15
 
12
- > **Status: Draft · v2.0.0-rc (2026-09-03).** Extension document (RFC 0169 §B.3; RFC 0167 Axiom 1: a family that cannot be witnessed unaided lives here and is not a core obligation).
16
+ ## Contract boundary
13
17
 
14
- ## What it is
18
+ A host MAY advertise this identifier under its registered organization namespace.
19
+ The extension record is organization-defined, so clients MUST NOT infer portable
20
+ operations, payloads, or authorization semantics from its presence. A pack may
21
+ name `a2uiSurface` as a dependency only when the host and pack share
22
+ an out-of-band definition of that dependency.
15
23
 
16
- RFC 0169 §C.5 (deltaTransport claims-check; ext/ unless a behavioral witness lands) The v1 prose that defines the surface is `spec/v1/capabilities.md` (root key `a2uiSurface`, RFC 0114); it stands as the definition until this document carries its own normative text (P3-E and the Phase 4 host legs). A host that serves this surface advertises it under `extensions.<org>.a2uiSurface` with the RFC 0169 record shape; a pack that requires it names `a2uiSurface` in `peerDependencies` (RFC 0177 §B.1).
24
+ The v1 description, [`spec/v1/capabilities.md`](https://github.com/openwop/openwop/blob/v2.3.3/spec/v1/capabilities.md) (`a2uiSurface`), is useful for migration but is not a
25
+ standalone v2 interoperability contract. A future revision can replace this
26
+ boundary with normative behavior, schemas, and a behavioral witness.
17
27
 
18
- ## Witness
28
+ ## Conformance
19
29
 
20
- `claims-check`: the suite can read the claim from discovery but has no behavioral probe; adoption is measured by the INTEROP-MATRIX bundle evidence.
30
+ The current `claims-check` witness validates only that the discovery claim is
31
+ well formed. It does not demonstrate compatible runtime behavior.
@@ -1,4 +1,7 @@
1
- # `brand` — extension
1
+ # `brand` extension
2
+
3
+ > **Status: Draft · v2 extension.** Discovery-only reservation; no portable
4
+ > operations or payload contract is defined in v2.3.3.
2
5
 
3
6
  | Field | Value |
4
7
  | --- | --- |
@@ -6,15 +9,23 @@
6
9
  | **technical:** | `experimental` |
7
10
  | **adoption:** | `single-witness` |
8
11
  | **peer-dependency id** | `brand` |
9
- | **advertised as** | `extensions.<org>.brand` (RFC 0169 §A.4) — never a root key |
12
+ | **advertised as** | `extensions.<org>.brand` |
10
13
  | **owning RFC** | RFC 0144 |
14
+ | **declared facets** | none defined |
11
15
 
12
- > **Status: Draft · v2.0.0-rc (2026-09-03).** Extension document (RFC 0169 §B.3; RFC 0167 Axiom 1: a family that cannot be witnessed unaided lives here and is not a core obligation).
16
+ ## Contract boundary
13
17
 
14
- ## What it is
18
+ A host MAY advertise this identifier under its registered organization namespace.
19
+ The extension record is organization-defined, so clients MUST NOT infer portable
20
+ operations, payloads, or authorization semantics from its presence. A pack may
21
+ name `brand` as a dependency only when the host and pack share
22
+ an out-of-band definition of that dependency.
15
23
 
16
- RFC 0169 §B.3 (RFC 0144 extension class; prose-only §host.* section in v1; served under extensions.openwop-app.* by the one host that has it) The v1 prose that defines the surface is `spec/v1/host-capabilities.md` §host.brand (RFC 0144 extension class); it stands as the definition until this document carries its own normative text (P3-E and the Phase 4 host legs). A host that serves this surface advertises it under `extensions.<org>.brand` with the RFC 0169 record shape; a pack that requires it names `brand` in `peerDependencies` (RFC 0177 §B.1).
24
+ The v1 description, [`spec/v1/host-capabilities.md`](https://github.com/openwop/openwop/blob/v2.3.3/spec/v1/host-capabilities.md#hostbrand) (§host.brand), is useful for migration but is not a
25
+ standalone v2 interoperability contract. A future revision can replace this
26
+ boundary with normative behavior, schemas, and a behavioral witness.
17
27
 
18
- ## Witness
28
+ ## Conformance
19
29
 
20
- `claims-check`: the suite can read the claim from discovery but has no behavioral probe; adoption is measured by the INTEROP-MATRIX bundle evidence.
30
+ The current `claims-check` witness validates only that the discovery claim is
31
+ well formed. It does not demonstrate compatible runtime behavior.
@@ -1,4 +1,7 @@
1
- # `canvas` — extension
1
+ # `canvas` extension
2
+
3
+ > **Status: Draft · v2 extension.** Discovery-only reservation; no portable
4
+ > operations or payload contract is defined in v2.3.3.
2
5
 
3
6
  | Field | Value |
4
7
  | --- | --- |
@@ -6,15 +9,23 @@
6
9
  | **technical:** | `experimental` |
7
10
  | **adoption:** | `single-witness` |
8
11
  | **peer-dependency id** | `canvas` |
9
- | **advertised as** | `extensions.<org>.canvas` (RFC 0169 §A.4) — never a root key |
12
+ | **advertised as** | `extensions.<org>.canvas` |
10
13
  | **owning RFC** | RFC 0144 |
14
+ | **declared facets** | none defined |
11
15
 
12
- > **Status: Draft · v2.0.0-rc (2026-09-03).** Extension document (RFC 0169 §B.3; RFC 0167 Axiom 1: a family that cannot be witnessed unaided lives here and is not a core obligation).
16
+ ## Contract boundary
13
17
 
14
- ## What it is
18
+ A host MAY advertise this identifier under its registered organization namespace.
19
+ The extension record is organization-defined, so clients MUST NOT infer portable
20
+ operations, payloads, or authorization semantics from its presence. A pack may
21
+ name `canvas` as a dependency only when the host and pack share
22
+ an out-of-band definition of that dependency.
15
23
 
16
- RFC 0169 §B.3 (RFC 0144 extension class; prose-only §host.* section in v1; served under extensions.openwop-app.* by the one host that has it) The v1 prose that defines the surface is `spec/v1/host-capabilities.md` §host.canvas (RFC 0144 extension class); it stands as the definition until this document carries its own normative text (P3-E and the Phase 4 host legs). A host that serves this surface advertises it under `extensions.<org>.canvas` with the RFC 0169 record shape; a pack that requires it names `canvas` in `peerDependencies` (RFC 0177 §B.1).
24
+ The v1 description, [`spec/v1/host-capabilities.md`](https://github.com/openwop/openwop/blob/v2.3.3/spec/v1/host-capabilities.md#hostcanvas) (§host.canvas), is useful for migration but is not a
25
+ standalone v2 interoperability contract. A future revision can replace this
26
+ boundary with normative behavior, schemas, and a behavioral witness.
17
27
 
18
- ## Witness
28
+ ## Conformance
19
29
 
20
- `claims-check`: the suite can read the claim from discovery but has no behavioral probe; adoption is measured by the INTEROP-MATRIX bundle evidence.
30
+ The current `claims-check` witness validates only that the discovery claim is
31
+ well formed. It does not demonstrate compatible runtime behavior.
@@ -1,4 +1,7 @@
1
- # `chat` — extension
1
+ # `chat` extension
2
+
3
+ > **Status: Draft · v2 extension.** Discovery-only reservation; no portable
4
+ > operations or payload contract is defined in v2.3.3.
2
5
 
3
6
  | Field | Value |
4
7
  | --- | --- |
@@ -6,15 +9,23 @@
6
9
  | **technical:** | `experimental` |
7
10
  | **adoption:** | `single-witness` |
8
11
  | **peer-dependency id** | `chat` |
9
- | **advertised as** | `extensions.<org>.chat` (RFC 0169 §A.4) — never a root key |
12
+ | **advertised as** | `extensions.<org>.chat` |
10
13
  | **owning RFC** | RFC 0144 |
14
+ | **declared facets** | none defined |
11
15
 
12
- > **Status: Draft · v2.0.0-rc (2026-09-03).** Extension document (RFC 0169 §B.3; RFC 0167 Axiom 1: a family that cannot be witnessed unaided lives here and is not a core obligation).
16
+ ## Contract boundary
13
17
 
14
- ## What it is
18
+ A host MAY advertise this identifier under its registered organization namespace.
19
+ The extension record is organization-defined, so clients MUST NOT infer portable
20
+ operations, payloads, or authorization semantics from its presence. A pack may
21
+ name `chat` as a dependency only when the host and pack share
22
+ an out-of-band definition of that dependency.
15
23
 
16
- RFC 0169 §B.3 (RFC 0144 extension class; prose-only §host.* section in v1; served under extensions.openwop-app.* by the one host that has it) The v1 prose that defines the surface is `spec/v1/host-capabilities.md` §host.chat (RFC 0144 extension class); it stands as the definition until this document carries its own normative text (P3-E and the Phase 4 host legs). A host that serves this surface advertises it under `extensions.<org>.chat` with the RFC 0169 record shape; a pack that requires it names `chat` in `peerDependencies` (RFC 0177 §B.1).
24
+ The v1 description, [`spec/v1/host-capabilities.md`](https://github.com/openwop/openwop/blob/v2.3.3/spec/v1/host-capabilities.md#hostchat) (§host.chat), is useful for migration but is not a
25
+ standalone v2 interoperability contract. A future revision can replace this
26
+ boundary with normative behavior, schemas, and a behavioral witness.
17
27
 
18
- ## Witness
28
+ ## Conformance
19
29
 
20
- `claims-check`: the suite can read the claim from discovery but has no behavioral probe; adoption is measured by the INTEROP-MATRIX bundle evidence.
30
+ The current `claims-check` witness validates only that the discovery claim is
31
+ well formed. It does not demonstrate compatible runtime behavior.
@@ -1,4 +1,7 @@
1
- # `coordination` — extension
1
+ # `coordination` extension
2
+
3
+ > **Status: Draft · v2 extension.** Discovery-only reservation; no portable
4
+ > operations or payload contract is defined in v2.3.3.
2
5
 
3
6
  | Field | Value |
4
7
  | --- | --- |
@@ -6,15 +9,23 @@
6
9
  | **technical:** | `experimental` |
7
10
  | **adoption:** | `single-witness` |
8
11
  | **peer-dependency id** | `coordination` |
9
- | **advertised as** | `extensions.<org>.coordination` (RFC 0169 §A.4) — never a root key |
12
+ | **advertised as** | `extensions.<org>.coordination` |
10
13
  | **owning RFC** | RFC 0144 |
14
+ | **declared facets** | none defined |
11
15
 
12
- > **Status: Draft · v2.0.0-rc (2026-09-03).** Extension document (RFC 0169 §B.3; RFC 0167 Axiom 1: a family that cannot be witnessed unaided lives here and is not a core obligation).
16
+ ## Contract boundary
13
17
 
14
- ## What it is
18
+ A host MAY advertise this identifier under its registered organization namespace.
19
+ The extension record is organization-defined, so clients MUST NOT infer portable
20
+ operations, payloads, or authorization semantics from its presence. A pack may
21
+ name `coordination` as a dependency only when the host and pack share
22
+ an out-of-band definition of that dependency.
15
23
 
16
- RFC 0169 §B.3 (RFC 0144 extension class; prose-only §host.* section in v1; served under extensions.openwop-app.* by the one host that has it) The v1 prose that defines the surface is `spec/v1/host-capabilities.md` §host.coordination (RFC 0144 extension class); it stands as the definition until this document carries its own normative text (P3-E and the Phase 4 host legs). A host that serves this surface advertises it under `extensions.<org>.coordination` with the RFC 0169 record shape; a pack that requires it names `coordination` in `peerDependencies` (RFC 0177 §B.1).
24
+ The v1 description, [`spec/v1/host-capabilities.md`](https://github.com/openwop/openwop/blob/v2.3.3/spec/v1/host-capabilities.md#hostcoordination) (§host.coordination), is useful for migration but is not a
25
+ standalone v2 interoperability contract. A future revision can replace this
26
+ boundary with normative behavior, schemas, and a behavioral witness.
17
27
 
18
- ## Witness
28
+ ## Conformance
19
29
 
20
- `claims-check`: the suite can read the claim from discovery but has no behavioral probe; adoption is measured by the INTEROP-MATRIX bundle evidence.
30
+ The current `claims-check` witness validates only that the discovery claim is
31
+ well formed. It does not demonstrate compatible runtime behavior.
@@ -1,4 +1,7 @@
1
- # `dataIntegration` — extension
1
+ # `dataIntegration` extension
2
+
3
+ > **Status: Draft · v2 extension.** Discovery-only reservation; no portable
4
+ > operations or payload contract is defined in v2.3.3.
2
5
 
3
6
  | Field | Value |
4
7
  | --- | --- |
@@ -6,15 +9,23 @@
6
9
  | **technical:** | `experimental` |
7
10
  | **adoption:** | `single-witness` |
8
11
  | **peer-dependency id** | `dataIntegration` |
9
- | **advertised as** | `extensions.<org>.dataIntegration` (RFC 0169 §A.4) — never a root key |
12
+ | **advertised as** | `extensions.<org>.dataIntegration` |
10
13
  | **owning RFC** | RFC 0144 |
14
+ | **declared facets** | none defined |
11
15
 
12
- > **Status: Draft · v2.0.0-rc (2026-09-03).** Extension document (RFC 0169 §B.3; RFC 0167 Axiom 1: a family that cannot be witnessed unaided lives here and is not a core obligation).
16
+ ## Contract boundary
13
17
 
14
- ## What it is
18
+ A host MAY advertise this identifier under its registered organization namespace.
19
+ The extension record is organization-defined, so clients MUST NOT infer portable
20
+ operations, payloads, or authorization semantics from its presence. A pack may
21
+ name `dataIntegration` as a dependency only when the host and pack share
22
+ an out-of-band definition of that dependency.
15
23
 
16
- RFC 0169 §B.3 (RFC 0144 extension class; prose-only §host.* section in v1; served under extensions.openwop-app.* by the one host that has it) The v1 prose that defines the surface is `spec/v1/host-capabilities.md` §host.dataIntegration (RFC 0144 extension class); it stands as the definition until this document carries its own normative text (P3-E and the Phase 4 host legs). A host that serves this surface advertises it under `extensions.<org>.dataIntegration` with the RFC 0169 record shape; a pack that requires it names `dataIntegration` in `peerDependencies` (RFC 0177 §B.1).
24
+ The v1 description, [`spec/v1/host-capabilities.md`](https://github.com/openwop/openwop/blob/v2.3.3/spec/v1/host-capabilities.md#hostdataintegration) (§host.dataIntegration), is useful for migration but is not a
25
+ standalone v2 interoperability contract. A future revision can replace this
26
+ boundary with normative behavior, schemas, and a behavioral witness.
17
27
 
18
- ## Witness
28
+ ## Conformance
19
29
 
20
- `claims-check`: the suite can read the claim from discovery but has no behavioral probe; adoption is measured by the INTEROP-MATRIX bundle evidence.
30
+ The current `claims-check` witness validates only that the discovery claim is
31
+ well formed. It does not demonstrate compatible runtime behavior.