@ggui-ai/protocol-conformance 0.22.0 → 0.23.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.
package/README.md CHANGED
@@ -58,7 +58,7 @@ Each catalog ships its cases as raw JSON so a non-TypeScript implementer can gra
58
58
  - **`@ggui-ai/protocol-conformance/resolution-conformance`** — which bundle + style URLs the server MUST compute for a gadget descriptor's transport fields (`bundleHost` precedence, default host, loopback `http` scheme).
59
59
  - **`@ggui-ai/protocol-conformance/binding-conformance`** — which MCP tool-binding set a manifest resolves to (a declared `mcpTools` list wins entirely; blueprints without it derive bare tool-name entries from contract tool names) and which artifacts the registry `tool=` / `server=` search filters MUST match (SPEC §7.7.4.1).
60
60
  - **`@ggui-ai/protocol-conformance/props-schema-conformance`** — the schema-precise render arbiter (SPEC §2.3.2): the enforced-props-schema builder (drift), its RFC 8785 sha256 hash, the grammar-safe profile verdict, and returned-schema AUTHORITY (sample validity under the case's own `propsSchema`, including the 2026-08-19 out-of-vocabulary enum incident pinned as a permanent sample).
61
- - **`@ggui-ai/protocol-conformance/host-helper-conformance`** — which render coordinates a HOST-HELPER library MUST extract from a `tools/call` result, and which malformed results it MUST decline rather than guess at.
61
+ - **`@ggui-ai/protocol-conformance/host-helper-conformance`** — grades a HOST-HELPER library (what mounts a ggui view and answers the MCP Apps bridge) through a JSON-RPC port the implementer supplies: a well-formed `ui/initialize` (H1), truthful capability advertisement (H2: an advertised `serverTools` answers `tools/call`, an advertised `serverResources` answers `resources/read`), honest and bounded refusals (H3/H4), and an unmodified `tools/call` relay (R1/R2), plus optional chrome (C1) and theme-coverage (T1) grades. The scorecard names a tier: `relaying`, `read-only` (a legal grade), or `nonconforming`. Runner: `runHostHelperConformance(port)`.
62
62
  - **`@ggui-ai/protocol-conformance/refusal-envelope-conformance`** — the tool result a server MUST project for a PRE-GENERATION refusal (SPEC §7.1's refused arm): an in-result `isError` (never a throw), `content[0].text` leading with the code, `structuredContent` carrying `{outcome: 'refused', refusal}` and nothing else, no `_meta` — and no envelope at all for a registered code whose surfaces exclude the render gate.
63
63
  - **`@ggui-ai/protocol-conformance/registry-completeness`** — the structural obligations a deployment's closed refusal-code registry MUST satisfy: `surfaces` non-empty, `code === key`, every `after-fix` entry naming who acts (`fixBy`), and `retry` inside the closed four-value set. Grades DATA rather than a function — the caller passes their registry.
64
64
  - **`@ggui-ai/protocol-conformance/transport-refusal-conformance`** — the JSON-RPC error a per-app MCP endpoint MUST answer with when it refuses a request for a typed reason (SPEC §7.1's endpoint-level refusal, ggui#825): HTTP 403 with `{ code: -32003, message: 'App not found', data: { refusal } }`, where `refusal` is the registry projection without the render-only fields (`code`, `message`, `fix`, `retry`) — and no envelope at all for a registered code whose surfaces exclude `mcp-endpoint` (an untyped authorization failure answers 403 with `-32007` and no `data`, by contract — ggui#836). Runner: `runTransportRefusalConformance(project)`; folded into `runConformance()` via `transportRefusalProjector`.
@@ -118,6 +118,29 @@ The catalog grades all four failure classes (`NOT_FOUND` on `-32002`; `BLUEPRINT
118
118
 
119
119
  It deliberately does **not** grade: the order in which a substrate-less server answers (`NOT_SUPPORTED` describes the deployment, so answering it immediately is correct); `detail` wording on any code; the `NOT_FOUND` message literal (its _constancy_ is what is normative); internal-error message text; the number a URI naming no locator receives (that belongs to the transport binding — only the negative is graded, that it must not be one of the four); and the shell's markup (success is graded on the projected render meta, never on DOM shape).
120
120
 
121
+ ## Read-plane-only conformance — the posture's result (SPEC §7.10.6, ggui#1304)
122
+
123
+ Under the read-plane-only posture a server publishes a committed render's **identity only**: the render locator on `structuredContent.resourceUri` and the same value on the MCP Apps pointer `_meta.ui.resourceUri`. It sends neither the `ai.ggui/render` slice nor a live-channel token (`wsToken`), anywhere on the result, so a view mounts only through an authenticated `resources/read` of that locator. The resource-read catalog grades the read; this catalog grades the result that points at it, and then reads the locator the result published.
124
+
125
+ ```ts
126
+ import { runReadPlaneOnlyConformance } from "@ggui-ai/protocol-conformance/read-plane-only-conformance";
127
+
128
+ const result = await runReadPlaneOnlyConformance(async () => {
129
+ // Bring YOUR server up with the posture ON.
130
+ const server = await bootMyServer({ withholdResultMeta: true });
131
+ return {
132
+ // ONE committed render, by your own means (priming, handshake,
133
+ // generator: none of it is graded). Return the raw tools/call result.
134
+ render: () => server.renderOnce(),
135
+ // Same contract as the resource-read driver's read.
136
+ read: (uri) => server.readResource(uri),
137
+ dispose: () => server.close(),
138
+ };
139
+ });
140
+ ```
141
+
142
+ Each failure names its criterion: `render-committed` (gates the rest), `locator-on-structured-content`, `locator-on-meta`, `one-locator` (the legacy flat `_meta["ui/resourceUri"]` counts when present), `slice-withheld`, `credential-withheld`, `read-mounts`. It deliberately does **not** grade how the render was produced, `_meta` members beyond the named ones, or the host. The host-helper catalog's `H2-advertisement-truthful` grades a helper that advertises `serverResources` and does not answer `resources/read`.
143
+
121
144
  ## Domain-error conformance — the `tools/call` binding (SPEC §7.9 Plane 2, ggui#880)
122
145
 
123
146
  The kit's first `tools/call` driver. A Plane-2 failure — a missing session or handshake, props that do not satisfy the contract, an undeclared channel — is a tool-execution error, so it is a tool RESULT with `isError: true` (never a JSON-RPC error frame) whose `content[0].text` LEADS with the registered slug: `<code>: <detail>`. No `structuredContent`, no `_meta`. A raw MCP agent branches on `text.startsWith(code + ': ')` for a code in `@ggui-ai/protocol`'s `DOMAIN_ERROR_CODES` and on nothing else.
@@ -130,21 +153,23 @@ The catalog exists for one receipt: before the slug led the text, every first-pa
130
153
 
131
154
  What is actually graded against shipping code today, and what is still awaiting a driver. This is an inventory, not a roadmap — a mechanism is listed as proven only if a test in the repo drives it against the real implementation on every push.
132
155
 
133
- Every test below is a plain `*.test.ts` inside a package's `src/`, so it runs in that package's ordinary vitest suite. The ggui repo's per-push CI runs `turbo run test` across all non-e2e packages, so **all twelve rows below are gated on every push** — the kit needs no dedicated workflow, and adopters wiring it into their own CI need nothing more than their existing unit-test task.
134
-
135
- | Obligation | Graded against | Driver |
136
- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
137
- | Gadget wire schema (§7.7.2) | the shipping `@ggui-ai/protocol` `clientCapabilitiesSpecSchema` | this kit's own `src/schema-conformance/schema-conformance.test.ts` |
138
- | Registration gate (§7.7.3, §7.9) | the shipping gate trio in `@ggui-ai/mcp-server-handlers` | `mcp-server-handlers/src/renders/assert-gadgets.conformance.test.ts` |
139
- | Bundle-URL resolution (§7.7.2) | the shipping `resolveGadgetUrls` in `@ggui-ai/mcp-server-handlers` | `mcp-server-handlers/src/renders/resolve-gadget-urls.conformance.test.ts` |
140
- | Path-A WS fixtures — first-party | the real `@ggui-ai/mcp-server` GguiSession channel, booted in-process on an ephemeral port | `mcp-server/src/ggui-session-channel.conformance.test.ts` — **24 pass / 12 skip / 0 fail** |
141
- | Path-A WS fixtures — vendor-neutral | `@ggui-ai/protocol-reference-server` | `protocol-reference-server/src/conformance.test.ts` — **19 pass / 5 skip / 0 fail** |
142
- | `resources/read` typed failures + mount invariant | the shipping `registerGguiRenderResourceTemplate` in `@ggui-ai/mcp-server` | `mcp-server/src/mcp-apps-outbound.resource-read.conformance.test.ts` — **12 pass / 0 skip / 0 fail** |
143
- | Tool-binding resolution — declared wins, contract derivation (§7.7.4.1) | the shipping `resolveMcpToolBindings` in `@ggui-ai/artifact-manifest` | `artifact-manifest/src/mcp-tool-bindings.conformance.test.ts` |
144
- | Tool-binding search filters — `tool=` / `server=` semantics (§7.7.4.1) | the shipping `matchesMcpToolFilters` in `@ggui-ai/registry-core` | `registry-core/src/mcp-tool-filters.conformance.test.ts` |
145
- | Pre-generation refusal envelope (§7.1, refused arm) | `projectRenderRefusal` in `@ggui-ai/protocol` — the one source both the shipping `ggui_render` handler (`@ggui-ai/mcp-server-handlers`) and `@ggui-ai/protocol-reference-server` answer through | `mcp-server-handlers/src/renders/render-refusal-projection.conformance.test.ts` |
146
- | Refusal-registry completeness (ggui#786 ruling 5b) | the shipping `PRE_GENERATION_REFUSAL_CODES` in `@ggui-ai/protocol` | this kit's own `src/registry-completeness/registry-completeness.test.ts` |
147
- | Endpoint-level refusal (§7.1, `mcp-endpoint` surface, ggui#825) | the catalog's kit-local reference projector only — no shipping deployment projector is graded yet: the OSS route is generic (`errorMapper`), the first-party server and the reference server supply no projector (SKIPPED, named), and a hosted deployment's projector lands after this slice | this kit's own `src/transport-refusal-conformance/transport-refusal-conformance.test.ts` (coherence + discrimination) |
156
+ Every test below is a plain `*.test.ts` inside a package's `src/`, so it runs in that package's ordinary vitest suite. The ggui repo's per-push CI runs `turbo run test` across all non-e2e packages, so **all thirteen rows below are gated on every push** — the kit needs no dedicated workflow, and adopters wiring it into their own CI need nothing more than their existing unit-test task.
157
+
158
+ | Obligation | Graded against | Driver |
159
+ | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
160
+ | Gadget wire schema (§7.7.2) | the shipping `@ggui-ai/protocol` `clientCapabilitiesSpecSchema` | this kit's own `src/schema-conformance/schema-conformance.test.ts` |
161
+ | Registration gate (§7.7.3, §7.9) | the shipping gate trio in `@ggui-ai/mcp-server-handlers` | `mcp-server-handlers/src/renders/assert-gadgets.conformance.test.ts` |
162
+ | Bundle-URL resolution (§7.7.2) | the shipping `resolveGadgetUrls` in `@ggui-ai/mcp-server-handlers` | `mcp-server-handlers/src/renders/resolve-gadget-urls.conformance.test.ts` |
163
+ | Path-A WS fixtures — first-party | the real `@ggui-ai/mcp-server` GguiSession channel, booted in-process on an ephemeral port | `mcp-server/src/ggui-session-channel.conformance.test.ts` — **24 pass / 12 skip / 0 fail** |
164
+ | Path-A WS fixtures — vendor-neutral | `@ggui-ai/protocol-reference-server` | `protocol-reference-server/src/conformance.test.ts` — **19 pass / 5 skip / 0 fail** |
165
+ | `resources/read` typed failures + mount invariant | the shipping `registerGguiRenderResourceTemplate` in `@ggui-ai/mcp-server` | `mcp-server/src/mcp-apps-outbound.resource-read.conformance.test.ts` — **16 pass / 0 skip / 0 fail** (the pass set is pinned as the whole catalog) |
166
+ | `tools/call` domain errors (§7.9 Plane 2, ggui#880) | the shipping `createGguiServer` in `@ggui-ai/mcp-server`, over Streamable HTTP | `mcp-server/src/domain-error.conformance.test.ts` — **6 pass / 0 skip / 0 fail** |
167
+ | Read-plane-only posture result (§7.10.6, ggui#1304) | the shipping `createGguiServer({ withholdResultMeta: true })` in `@ggui-ai/mcp-server`, over Streamable HTTP | `mcp-server/src/read-plane-only.conformance.test.ts` — **1 pass / 0 skip / 0 fail**, plus a posture-OFF control that fails exactly `slice-withheld` and `credential-withheld` |
168
+ | Tool-binding resolution — declared wins, contract derivation (§7.7.4.1) | the shipping `resolveMcpToolBindings` in `@ggui-ai/artifact-manifest` | `artifact-manifest/src/mcp-tool-bindings.conformance.test.ts` |
169
+ | Tool-binding search filters — `tool=` / `server=` semantics (§7.7.4.1) | the shipping `matchesMcpToolFilters` in `@ggui-ai/registry-core` | `registry-core/src/mcp-tool-filters.conformance.test.ts` |
170
+ | Pre-generation refusal envelope (§7.1, refused arm) | `projectRenderRefusal` in `@ggui-ai/protocol` — the one source both the shipping `ggui_render` handler (`@ggui-ai/mcp-server-handlers`) and `@ggui-ai/protocol-reference-server` answer through | `mcp-server-handlers/src/renders/render-refusal-projection.conformance.test.ts` |
171
+ | Refusal-registry completeness (ggui#786 ruling 5b) | the shipping `PRE_GENERATION_REFUSAL_CODES` in `@ggui-ai/protocol` | this kit's own `src/registry-completeness/registry-completeness.test.ts` |
172
+ | Endpoint-level refusal (§7.1, `mcp-endpoint` surface, ggui#825) | the catalog's kit-local reference projector only — no shipping deployment projector is graded yet: the OSS route is generic (`errorMapper`), the first-party server and the reference server supply no projector (SKIPPED, named), and a hosted deployment's projector lands after this slice | this kit's own `src/transport-refusal-conformance/transport-refusal-conformance.test.ts` (coherence + discrimination) |
148
173
 
149
174
  Both WS drivers pin their pass set _and_ their skip set as exact sets, and the resource-read driver pins its skip set as exactly empty. A fixture silently degrading to a skip fails the build, and so does a skipped fixture that quietly starts passing — a skip set that can grow unnoticed is a false gate, and re-pinning it is meant to be a deliberate act.
150
175
 
@@ -42,13 +42,13 @@ import type { ActionSpecEntryDecl } from './types.js';
42
42
  * envelope drives the system under test.
43
43
  *
44
44
  * Closed union — the runner validates fixture-authored directives
45
- * before dispatch, so only these five kinds ever reach a host. A host
45
+ * before dispatch, so only these six kinds ever reach a host. A host
46
46
  * that does not implement one of them MUST throw (e.g.
47
47
  * `Error('host does not implement renderer-url-override')`) so the
48
48
  * runner records the fixture as SKIPPED with that reason — never
49
49
  * silently succeed.
50
50
  */
51
- export type SetupStep = CreateGguiSessionSetup | RendererUrlOverrideSetup | ServerVersionOverrideSetup | UiInitializeResponseOverrideSetup | EmitEnvelopeSetup;
51
+ export type SetupStep = CreateGguiSessionSetup | RendererUrlOverrideSetup | ServerVersionOverrideSetup | UiInitializeResponseOverrideSetup | ToolResultOverrideSetup | EmitEnvelopeSetup;
52
52
  export interface CreateGguiSessionSetup {
53
53
  readonly kind: 'create-session';
54
54
  readonly sessionId: string;
@@ -79,6 +79,12 @@ export interface UiInitializeResponseOverrideSetup {
79
79
  readonly sessionId: string;
80
80
  readonly override: unknown;
81
81
  }
82
+ /** Runtime form of `ToolResultOverrideStep` (see `./types`). */
83
+ export interface ToolResultOverrideSetup {
84
+ readonly kind: 'tool-result-override';
85
+ readonly sessionId: string;
86
+ readonly override: unknown;
87
+ }
82
88
  /** Runtime form of `EmitEnvelopeStep` (see `./types`). */
83
89
  export interface EmitEnvelopeSetup {
84
90
  readonly kind: 'emit-envelope';
@@ -1 +1 @@
1
- {"version":3,"file":"conformance-host.d.ts","sourceRoot":"","sources":["../src/conformance-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAMtD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GACjB,sBAAsB,GACtB,wBAAwB,GACxB,0BAA0B,GAC1B,iCAAiC,GACjC,iBAAiB,CAAC;AAEtB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;CACrE;AAED,iEAAiE;AACjE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,mEAAmE;AACnE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,0EAA0E;AAC1E,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAMD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC;AAMjC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;;;;OAKG;IACH,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,gBAAgB,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE"}
1
+ {"version":3,"file":"conformance-host.d.ts","sourceRoot":"","sources":["../src/conformance-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAMtD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GACjB,sBAAsB,GACtB,wBAAwB,GACxB,0BAA0B,GAC1B,iCAAiC,GACjC,uBAAuB,GACvB,iBAAiB,CAAC;AAEtB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;CACrE;AAED,iEAAiE;AACjE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,mEAAmE;AACnE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,0EAA0E;AAC1E,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,gEAAgE;AAChE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAMD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC;AAMjC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;;;;OAKG;IACH,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,gBAAgB,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvE"}
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "bootstrap-bundle-fetch-failed",
3
- "description": "Thin shell reads a valid `_meta.ggui.bootstrap.runtimeUrl` but the `<script src>` errors (network failure / 404 / CSP reject). Shell emits `postMessage({type:'ggui:bootstrap-failed', reason:'BUNDLE_FETCH_FAILED', message})` to the parent. No WS opens.",
3
+ "description": "The view reads a valid `ai.ggui/render` slice, but loading the runtime bundle from its `runtimeUrl` errors (network failure / 404 / CSP reject). The view emits `postMessage({type:'ggui:bootstrap-failed', reason:'BUNDLE_FETCH_FAILED', message})` to the parent. No WS opens.",
4
4
  "skipReason": null,
5
5
  "setup": [
6
- { "type": "create-session", "sessionId": "ck-bundle-fetch-failed-1" },
6
+ {
7
+ "type": "create-session",
8
+ "sessionId": "ck-bundle-fetch-failed-1"
9
+ },
7
10
  {
8
11
  "type": "renderer-url-override",
9
12
  "sessionId": "ck-bundle-fetch-failed-1",
@@ -1,18 +1,23 @@
1
1
  {
2
2
  "name": "bootstrap-meta-missing",
3
- "description": "Host's `ui/initialize` response returns a tool-output without `_meta.ggui.bootstrap` (or missing the `runtimeUrl` field). Thin shell emits `postMessage({type:'ggui:bootstrap-failed', reason:'BOOTSTRAP_META_MISSING', message})` to the parent. No WS connection opens — live-channel envelopes are out of scope pre-handshake.",
3
+ "description": "The host mounts the declaration-level shell (`ui://ggui/render`) and forwards a `ui/notifications/tool-result` whose `CallToolResult` carries neither the `ai.ggui/render` slice nor a render locator on its top-level `_meta`, so no source yields a slice: nothing inline on `globalThis.__GGUI_META__`, no read-plane door to take, and no slice on the forwarded result. After its bounded wait the view emits `postMessage({type:'ggui:bootstrap-failed', reason:'MISSING_META_GGUI_BOOTSTRAP', message})` to the parent, the spelling every reference emitter uses (SPEC §5.5.2). `BOOTSTRAP_META_MISSING` names the same failure and hosts classify both alike. No WS connection opens; live-channel envelopes are out of scope before the slice is read. (Rewritten under ggui#1304: the fixture used to override `ui/initialize` and look for `_meta.ggui.bootstrap`, a delivery path that no longer exists.)",
4
4
  "skipReason": null,
5
5
  "setup": [
6
- { "type": "create-session", "sessionId": "ck-bootstrap-meta-missing-1" },
7
6
  {
8
- "type": "ui-initialize-response-override",
7
+ "type": "create-session",
8
+ "sessionId": "ck-bootstrap-meta-missing-1"
9
+ },
10
+ {
11
+ "type": "tool-result-override",
9
12
  "sessionId": "ck-bootstrap-meta-missing-1",
10
13
  "override": {
11
- "toolOutput": {
12
- "_meta": {
13
- "ggui": {}
14
+ "content": [
15
+ {
16
+ "type": "text",
17
+ "text": "{}"
14
18
  }
15
- }
19
+ ],
20
+ "_meta": {}
16
21
  }
17
22
  }
18
23
  ],
@@ -25,7 +30,6 @@
25
30
  },
26
31
  "expectedBehavior": {
27
32
  "kind": "bootstrap-failure",
28
- "reason": "BOOTSTRAP_META_MISSING",
29
- "messageContains": "_meta.ggui.bootstrap"
33
+ "reason": "MISSING_META_GGUI_BOOTSTRAP"
30
34
  }
31
35
  }
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "bootstrap-success",
3
- "description": "Happy-path boot: host reads `_meta.ui.resourceUri`, fetches `ui://ggui/render`, the thin shell loads the renderer bundle, `ui/initialize` returns valid `_meta.ggui.bootstrap.{wsUrl, token, sessionId, appId, runtimeUrl}`, WS handshake succeeds, the render mounts with `data-ggui-code-ready=\"true\"`. No bootstrap-failed postMessage, no upgrade-required.",
3
+ "description": "Happy-path boot: the host reads `_meta.ui.resourceUri` and mounts the render resource. The view gets its `ai.ggui/render` slice (`runtimeUrl`, `sessionId`, `appId`, and a live trio `wsUrl` + `wsToken`) either inline on `globalThis.__GGUI_META__` (the per-render shell) or from the top-level `_meta` of the tool result the host forwards via `ui/notifications/tool-result` (the declaration-level shell). It loads the runtime bundle from `runtimeUrl`, the WS handshake succeeds, and the render mounts with `data-ggui-code-ready=\"true\"`. No bootstrap-failed postMessage, no upgrade-required.",
4
4
  "skipReason": null,
5
- "setup": [{ "type": "create-session", "sessionId": "ck-bootstrap-success-1" }],
5
+ "setup": [
6
+ {
7
+ "type": "create-session",
8
+ "sessionId": "ck-bootstrap-success-1"
9
+ }
10
+ ],
6
11
  "inputEnvelope": {
7
12
  "type": "render",
8
13
  "sessionId": "ck-bootstrap-success-1",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/bootstrap-protocol/index.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;mDACmD;AACnD,eAAO,MAAM,yBAAyB,EAAE,SAAS,QAAQ,EAIxD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/bootstrap-protocol/index.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;mDACmD;AACnD,eAAO,MAAM,yBAAyB,EAAE,SAAS,QAAQ,EAIxD,CAAC"}
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * `bootstrap-protocol` fixture sub-module.
3
3
  *
4
- * Exercises the MCP Apps bootstrap contract (SPEC §8):
5
- * - `ui/initialize` tool-result must stamp the per-window
6
- * `_meta["ai.ggui/render"]` slice with a well-formed payload.
4
+ * Exercises the MCP Apps bootstrap contract (SPEC §5.5):
5
+ * - The view gets a well-formed `ai.ggui/render` slice, inline on the
6
+ * per-render shell or on the top-level `_meta` of the forwarded
7
+ * `ui/notifications/tool-result`; a missing one surfaces as
8
+ * `MISSING_META_GGUI_BOOTSTRAP` (driven by `tool-result-override`).
7
9
  * - Renderer-bundle fetch must succeed (or surface a typed
8
10
  * `BOOTSTRAP_FAILURE` protocol error).
9
11
  * - Happy-path boot reaches `data-ggui-code-ready="true"` with no
@@ -29,8 +29,16 @@
29
29
  * carrying a `hostCapabilities` object (empty is legal).
30
30
  * - `H2-advertisement-truthful` — every advertised capability with a
31
31
  * probe mapping answers its method family (advertised ⊆ answered).
32
- * An advertises-but-refuses helper makes the runtime's confirmed-
33
- * failure latch structurally unreachable — the worst dead-tap shape.
32
+ * The map: `serverTools` → `tools/call`, and `serverResources` →
33
+ * `resources/read` (ggui#1304). An advertises-but-refuses helper
34
+ * makes the runtime's confirmed-failure latch structurally
35
+ * unreachable — the worst dead-tap shape. For the read, an answer is
36
+ * a `ReadResourceResult` (a `contents` array) or the server's own
37
+ * error forwarded in-band; a refusal, a drop, or a re-shaped result
38
+ * fails, because the declaration-level shell mounts only from what
39
+ * that read returns (the read-plane door, SPEC §7.1). Only an
40
+ * ADVERTISED `serverResources` is probed: a helper that does not
41
+ * advertise it is never sent `resources/read` and stays legal.
34
42
  * - `H3-refusal-honest` — an unsupported request is refused IN-BAND
35
43
  * with JSON-RPC `-32601` naming the method. Silent drops fail: a
36
44
  * refusal is recoverable, a hang leaves the runtime guessing.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host-helper-conformance/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host-helper-conformance/index.ts"],"names":[],"mappings":"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"}
@@ -29,8 +29,16 @@
29
29
  * carrying a `hostCapabilities` object (empty is legal).
30
30
  * - `H2-advertisement-truthful` — every advertised capability with a
31
31
  * probe mapping answers its method family (advertised ⊆ answered).
32
- * An advertises-but-refuses helper makes the runtime's confirmed-
33
- * failure latch structurally unreachable — the worst dead-tap shape.
32
+ * The map: `serverTools` → `tools/call`, and `serverResources` →
33
+ * `resources/read` (ggui#1304). An advertises-but-refuses helper
34
+ * makes the runtime's confirmed-failure latch structurally
35
+ * unreachable — the worst dead-tap shape. For the read, an answer is
36
+ * a `ReadResourceResult` (a `contents` array) or the server's own
37
+ * error forwarded in-band; a refusal, a drop, or a re-shaped result
38
+ * fails, because the declaration-level shell mounts only from what
39
+ * that read returns (the read-plane door, SPEC §7.1). Only an
40
+ * ADVERTISED `serverResources` is probed: a helper that does not
41
+ * advertise it is never sent `resources/read` and stays legal.
34
42
  * - `H3-refusal-honest` — an unsupported request is refused IN-BAND
35
43
  * with JSON-RPC `-32601` naming the method. Silent drops fail: a
36
44
  * refusal is recoverable, a hang leaves the runtime guessing.
@@ -56,10 +64,24 @@
56
64
  * `read-only`** — a LEGAL grade, with the R cases skipped, never
57
65
  * failed. `nonconforming` means a dishonesty case failed.
58
66
  */
67
+ import { renderLocatorUri } from '../resource-read-conformance/index.js';
59
68
  const METHOD_NOT_SUPPORTED = -32601;
60
69
  const DEFAULT_REFUSAL_TIMEOUT_MS = 2_000;
61
70
  /** A method no ggui helper answers — the honest-refusal probe. */
62
71
  const UNSUPPORTED_PROBE_METHOD = 'ggui-conformance/unsupported-probe';
72
+ /**
73
+ * The `resources/read` probe's URI: a well-formed render locator naming
74
+ * a render that does not exist, built with the kit's own locator grammar
75
+ * (one owner, `resource-read-conformance`; the kit never compiles against
76
+ * live protocol types). It is a locator on purpose, so a helper that
77
+ * forwards only `ui://ggui/render/` reads still forwards it; a relaying
78
+ * helper then hands back the server's own classification of the miss,
79
+ * which is an answer (ggui#1304).
80
+ */
81
+ const RESOURCE_READ_PROBE_URI = renderLocatorUri({
82
+ kind: 'render',
83
+ session: 'conformance-probe',
84
+ });
63
85
  /**
64
86
  * Containment styles a helper may legitimately apply to its mount
65
87
  * surfaces: sizing, layout participation, overflow clipping, and
@@ -129,6 +151,31 @@ async function sendWithTimeout(port, req, timeoutMs) {
129
151
  function isRefusal(resp) {
130
152
  return resp?.error !== undefined && resp.error.code === METHOD_NOT_SUPPORTED;
131
153
  }
154
+ /**
155
+ * Why an advertised `serverResources` is untruthful, or `undefined`
156
+ * when the read was answered: a `ReadResourceResult` (a `contents`
157
+ * array) or any in-band error other than the `-32601` refusal (the
158
+ * server's classification of the probe's miss, forwarded).
159
+ */
160
+ function readProbeUntruthful(probe) {
161
+ const resp = probe.response;
162
+ if (resp === null) {
163
+ return `serverResources advertised but resources/read was ${probe.timedOut ? 'not answered within the probe timeout' : 'silently dropped'} — a declaration-level shell against a read-plane-only server waits out its bound and fails with READ_DOOR_FAILED`;
164
+ }
165
+ if (isRefusal(resp)) {
166
+ return 'serverResources advertised but resources/read was refused (-32601) — a declaration-level shell against a read-plane-only server has no other way to reach its envelope';
167
+ }
168
+ if (resp.error !== undefined)
169
+ return undefined;
170
+ const result = resp.result;
171
+ const hasContents = typeof result === 'object' &&
172
+ result !== null &&
173
+ 'contents' in result &&
174
+ Array.isArray(result.contents);
175
+ return hasContents
176
+ ? undefined
177
+ : 'serverResources advertised and resources/read answered, but not with a ReadResourceResult (no contents array) — the read must be forwarded verbatim; a re-shaped answer leaves the shell nothing to mount';
178
+ }
132
179
  /**
133
180
  * Run the catalog against one helper port. Pure protocol driving —
134
181
  * safe anywhere node runs; a helper vendor calls this from their CI.
@@ -161,6 +208,7 @@ export async function runHostHelperConformance(port, options = {}) {
161
208
  : 'ui/initialize result carries no hostCapabilities object',
162
209
  });
163
210
  const advertisesServerTools = capabilities !== undefined && capabilities['serverTools'] !== undefined;
211
+ const advertisesServerResources = capabilities !== undefined && capabilities['serverResources'] !== undefined;
164
212
  // ── relay probe (feeds H2 and R1) ─────────────────────────────────
165
213
  // The probe's `payload: {}` is non-primitive DELIBERATELY: helpers
166
214
  // that stage primitive action payloads into a host affordance before
@@ -182,7 +230,32 @@ export async function runHostHelperConformance(port, options = {}) {
182
230
  }), refusalTimeoutMs);
183
231
  const relayAnswered = relayProbe.response !== null && relayProbe.response.error === undefined;
184
232
  const relayRefused = isRefusal(relayProbe.response);
233
+ // ── read probe (feeds H2, ggui#1304) ─────────────────────────────
234
+ // Sent only when `serverResources` is advertised: the capability is
235
+ // the spec's "host can proxy resource reads to the MCP server", and a
236
+ // helper that does not claim it owes no answer.
237
+ const readProbe = advertisesServerResources
238
+ ? await sendWithTimeout(port, request('resources/read', { uri: RESOURCE_READ_PROBE_URI }), refusalTimeoutMs)
239
+ : undefined;
185
240
  // ── H2: advertisement truthfulness ────────────────────────────────
241
+ // One verdict per advertised capability in the probe map; the grade
242
+ // fails on any untruthful one and names only those.
243
+ const probed = [];
244
+ if (advertisesServerTools) {
245
+ probed.push(relayAnswered
246
+ ? { claim: 'serverTools advertised and tools/call answered' }
247
+ : {
248
+ claim: 'serverTools',
249
+ untruthful: 'serverTools advertised but tools/call was refused or dropped — the runtime latch is structurally unreachable on this shape (ggui#596)',
250
+ });
251
+ }
252
+ if (readProbe !== undefined) {
253
+ const untruthful = readProbeUntruthful(readProbe);
254
+ probed.push(untruthful === undefined
255
+ ? { claim: 'serverResources advertised and resources/read answered' }
256
+ : { claim: 'serverResources', untruthful });
257
+ }
258
+ const untruthfulClaims = probed.flatMap((p) => p.untruthful === undefined ? [] : [p.untruthful]);
186
259
  if (capabilities === undefined) {
187
260
  cases.push({
188
261
  id: 'H2-advertisement-truthful',
@@ -190,7 +263,7 @@ export async function runHostHelperConformance(port, options = {}) {
190
263
  detail: 'no capabilities captured (H1 failed)',
191
264
  });
192
265
  }
193
- else if (!advertisesServerTools) {
266
+ else if (probed.length === 0) {
194
267
  cases.push({
195
268
  id: 'H2-advertisement-truthful',
196
269
  outcome: 'pass',
@@ -198,16 +271,16 @@ export async function runHostHelperConformance(port, options = {}) {
198
271
  });
199
272
  }
200
273
  else {
201
- cases.push(relayAnswered
274
+ cases.push(untruthfulClaims.length === 0
202
275
  ? {
203
276
  id: 'H2-advertisement-truthful',
204
277
  outcome: 'pass',
205
- detail: 'serverTools advertised and tools/call answered',
278
+ detail: probed.map((p) => p.claim).join('; '),
206
279
  }
207
280
  : {
208
281
  id: 'H2-advertisement-truthful',
209
282
  outcome: 'fail',
210
- detail: 'serverTools advertised but tools/call was refused or dropped — the runtime latch is structurally unreachable on this shape (ggui#596)',
283
+ detail: untruthfulClaims.join('; '),
211
284
  });
212
285
  }
213
286
  // ── H3 + H4: refusal honesty + boundedness ────────────────────────
package/dist/index.d.ts CHANGED
@@ -32,6 +32,8 @@ export { runTransportRefusalConformance, transportRefusalCases, } from './transp
32
32
  export type { ProjectedTransportRefusal, TransportRefusalConformanceCase, TransportRefusalConformanceResult, TransportRefusalInput, TransportRefusalMismatch, } from './transport-refusal-conformance/index.js';
33
33
  export { declaresDeliveryChannel, renderLocatorUri, resourceReadCases, runResourceReadConformance, GGUI_RENDER_RESOURCE_URI, } from './resource-read-conformance/index.js';
34
34
  export type { DurableSubstrateWiring, JsonRpcErrorFrame, PreparedResourceReadScenario, ResourceReadCaller, ResourceReadConformanceCase, ResourceReadConformanceFailure, ResourceReadConformanceResult, ResourceReadConformanceSkip, ResourceReadErrorCodeDecl, ResourceReadExpectation, ResourceReadKey, ResourceReadLocator, ResourceReadOutcome, ResourceReadProbe, ResourceReadRenderMeta, ResourceReadScenario, ResourceReadScenarioDriver, ResourceReadSeed, ResourceReadServerShape, RunResourceReadConformanceOptions, } from './resource-read-conformance/index.js';
35
+ export { readPlaneOnlyCases, runReadPlaneOnlyConformance, } from './read-plane-only-conformance/index.js';
36
+ export type { PreparedReadPlaneOnlyScenario, ReadPlaneOnlyConformanceCase, ReadPlaneOnlyConformanceResult, ReadPlaneOnlyCriterion, ReadPlaneOnlyExpectation, ReadPlaneOnlyMismatch, ReadPlaneOnlyScenario, ReadPlaneOnlyScenarioDriver, ReadPlaneOnlySkip, RunReadPlaneOnlyConformanceOptions, } from './read-plane-only-conformance/index.js';
35
37
  export { loadFixture, listFixtures, loadAllFixtures } from './loader.js';
36
38
  export { runConformance } from './run-conformance.js';
37
39
  export type { RunConformanceConfig, ConformanceResult, ConformanceFailure, SkippedFixture, ConformanceReporter, InputEnvelopeDispatch, HostContextObservedInputEnvelope, } from './run-conformance.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -65,6 +65,12 @@ export { runTransportRefusalConformance, transportRefusalCases, } from './transp
65
65
  // Unlike the three catalogs above this one drives a live server, so
66
66
  // the caller supplies a scenario driver rather than a pure function.
67
67
  export { declaresDeliveryChannel, renderLocatorUri, resourceReadCases, runResourceReadConformance, GGUI_RENDER_RESOURCE_URI, } from './resource-read-conformance/index.js';
68
+ // Read-plane-only conformance (ggui#1304, SPEC §7.10.6) — the tool
69
+ // RESULT under the read-plane-only posture: the locator on both slots,
70
+ // one value, no slice, no live credential; and the published locator's
71
+ // read mounts. Drives a live server through a scenario driver, like the
72
+ // resource-read catalog above.
73
+ export { readPlaneOnlyCases, runReadPlaneOnlyConformance, } from './read-plane-only-conformance/index.js';
68
74
  // Runtime loader — look up a fixture by name from the inlined catalog.
69
75
  export { loadFixture, listFixtures, loadAllFixtures } from './loader.js';
70
76
  // Runner — drive the catalog against a live implementation.
@@ -68,8 +68,8 @@
68
68
  * v1 Path-B-only kinds (return `unmatchable-on-ws`):
69
69
  *
70
70
  * - `bootstrap-failure` — the fault surface lives in the host's
71
- * bootstrap-fetch + `ui/initialize` round-trip; the fixture's
72
- * `renderer-url-override` / `ui-initialize-response-override`
71
+ * bootstrap-fetch + forwarded tool result; the fixture's
72
+ * `renderer-url-override` / `tool-result-override`
73
73
  * setup directives are MCP-Apps-host concerns, not WS server
74
74
  * concerns. The reference server's host adapter correctly throws
75
75
  * "out of scope" on these directives — that's not a bug, it's
@@ -129,7 +129,7 @@ export function matchBehavior(behavior, frames) {
129
129
  if (behavior.kind === 'bootstrap-failure') {
130
130
  return {
131
131
  kind: 'unmatchable-on-ws',
132
- reason: 'bootstrap-failure is a Path-B (browser-host) claim — the fault surface is the host\'s bootstrap-fetch + `ui/initialize` postMessage round-trip, not a WS frame the server emits. The `renderer-url-override` / `ui-initialize-response-override` setup directives are MCP-Apps-host concerns; the reference server\'s host adapter throws "out of scope" on them by design. The Path-B driver is not yet packaged — these fixtures skip until a browser-host adapter ships with the kit.',
132
+ reason: 'bootstrap-failure is a Path-B (browser-host) claim — the fault surface is the host\'s bootstrap-fetch + forwarded `ui/notifications/tool-result` round-trip, not a WS frame the server emits. The `renderer-url-override` / `tool-result-override` setup directives are MCP-Apps-host concerns; the reference server\'s host adapter throws "out of scope" on them by design. The Path-B driver is not yet packaged — these fixtures skip until a browser-host adapter ships with the kit.',
133
133
  };
134
134
  }
135
135
  if (behavior.kind === 'props-update') {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forward-render-meta-unknown-member",
3
- "description": "FORWARD tolerance (ggui#1178, VERSION-POLICY §3.6): the `_meta[\"ai.ggui/render\"]` slice a LATER release may write — a top-level member this release does not name (`futureMember`), and an `actionSpec` whose entry carries a member this release does not name (`futureEntryMember`). Both are synthetic by construction: the payload is the NEXT release's, so it carries no landed sha. The read door MUST accept the slice and KEEP the action contract (stripping the unknown entry member and naming it). Dropping the whole `actionSpec` is the violation: a runtime left with no contract has no one-shot guard and validates gestures permissively, which is the fail-open ggui#1178 closes.",
3
+ "description": "FORWARD tolerance (ggui#1178, VERSION-POLICY §3.6): the `_meta[\"ai.ggui/render\"]` slice a LATER release may write — a top-level member this release does not name (`futureMember`), and an `actionSpec` whose entry carries a member this release does not name (`futureEntryMember`). Both are synthetic by construction: the payload is the NEXT release's, so it carries no landed sha. The read door MUST accept the slice and KEEP the action contract (stripping the unknown entry member and naming it). Dropping the whole `actionSpec` is the violation: a runtime left with no contract has no one-shot guard and validates gestures permissively, which is the fail-open ggui#1178 closes. The slice also carries `spentOneShots` (ggui#1223): the card's spent `oneShot` names MUST survive the read door too — dropping them makes a consumed action read as live again after a reload.",
4
4
  "direction": "forward",
5
5
  "release": {
6
6
  "label": "a later ggui release (synthetic): a render slice plus a synthetic top-level member and a synthetic action-entry member",
@@ -26,7 +26,8 @@
26
26
  },
27
27
  "futureMember": {
28
28
  "any": "value"
29
- }
29
+ },
30
+ "spentOneShots": ["submit"]
30
31
  }
31
32
  },
32
33
  "expect": "accepted"
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/n1-compat-conformance/index.ts"],"names":[],"mappings":"AA8BA,sDAAsD;AACtD,eAAO,MAAM,eAAe,4HAA6H,CAAC;AAE1J,yIAAyI;AACzI,eAAO,MAAM,oBAAoB,kCAAmC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACtE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iKAAiK;IACjK,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,gGAAgG;IAChG,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAgDD,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAQhC,CAAC;AA+EpB,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,SAAS,cAAc,EAAE,CAgBlE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/n1-compat-conformance/index.ts"],"names":[],"mappings":"AA8BA,sDAAsD;AACtD,eAAO,MAAM,eAAe,4HAA6H,CAAC;AAE1J,yIAAyI;AACzI,eAAO,MAAM,oBAAoB,kCAAmC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACtE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iKAAiK;IACjK,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,gGAAgG;IAChG,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAgDD,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAQhC,CAAC;AA2FpB,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,SAAS,cAAc,EAAE,CAgBlE"}
@@ -141,9 +141,11 @@ function gradeOpsGenerateBlueprint(payload) {
141
141
  function gradeRenderMeta(payload) {
142
142
  const themeIssues = [];
143
143
  const actionIssues = [];
144
+ const spentIssues = [];
144
145
  const r = parseMcpAppAiGguiRenderMeta(payload, {
145
146
  onInvalidTheme: (issues) => themeIssues.push(...issues),
146
147
  onInvalidActionSpec: (issues) => actionIssues.push(...issues),
148
+ onInvalidSpentOneShots: (issues) => spentIssues.push(...issues),
147
149
  });
148
150
  if (!r.ok)
149
151
  return { pass: false, detail: `parseMcpAppAiGguiRenderMeta refused the previous release's slice: ${r.reason}` };
@@ -160,9 +162,18 @@ function gradeRenderMeta(payload) {
160
162
  if (sentActionSpec && (actionIssues.length > 0 || r.meta.actionSpec === undefined)) {
161
163
  return { pass: false, detail: `the slice's action contract was dropped at the read door: ${actionIssues.join('; ') || 'actionSpec absent on the parsed meta'}` };
162
164
  }
165
+ // ggui#1223 — the card's spent oneShot names must survive the read door: dropping them makes a
166
+ // consumed action read as live again after a reload.
167
+ const sentSpent = isRecord(sent) && sent['spentOneShots'] !== undefined;
168
+ if (sentSpent && (spentIssues.length > 0 || r.meta.spentOneShots === undefined)) {
169
+ return { pass: false, detail: `the card's spent oneShot set was dropped at the read door: ${spentIssues.join('; ') || 'spentOneShots absent on the parsed meta'}` };
170
+ }
163
171
  return {
164
172
  pass: true,
165
- detail: 'parseMcpAppAiGguiRenderMeta: accepted' + (sentTheme ? ', theme preserved' : '') + (sentActionSpec ? ', actionSpec preserved' : ''),
173
+ detail: 'parseMcpAppAiGguiRenderMeta: accepted' +
174
+ (sentTheme ? ', theme preserved' : '') +
175
+ (sentActionSpec ? ', actionSpec preserved' : '') +
176
+ (sentSpent ? ', spentOneShots preserved' : ''),
166
177
  };
167
178
  }
168
179
  /** Grade every N−1 case against the protocol as shipped. */
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "withheld-render-mounts-through-the-read",
3
+ "description": "SPEC §7.10.6: under the read-plane-only posture a committed render's result publishes the view's identity only — the render locator on structuredContent.resourceUri and the same value on _meta.ui.resourceUri (and on the legacy flat _meta['ui/resourceUri'] when present) — and carries neither the ai.ggui/render slice nor a live-channel token anywhere. A resources/read of that published locator then returns contents that declare a delivery channel.",
4
+ "expect": {
5
+ "locatorPrefix": "ui://ggui/render/",
6
+ "withheldMetaKeys": ["ai.ggui/render"],
7
+ "withheldCredentialKeys": ["wsToken"],
8
+ "read": "live-mount"
9
+ }
10
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Read-plane-only conformance catalog (ggui#1304) — grades a server's
3
+ * tool RESULT under the read-plane-only posture (SPEC §7.10.6), the half
4
+ * of the read-plane door the resource-read catalog does not see.
5
+ *
6
+ * ## The obligation this catalog grades
7
+ *
8
+ * A server running the posture publishes a committed render's IDENTITY
9
+ * and nothing else: the render locator on `structuredContent.resourceUri`
10
+ * and the same value on the MCP Apps pointer `_meta.ui.resourceUri`
11
+ * (and on the legacy flat `_meta["ui/resourceUri"]` when it emits one).
12
+ * The result carries neither the `ai.ggui/render` slice nor a live
13
+ * channel token, anywhere. A host then mounts only through an
14
+ * authenticated `resources/read` of that locator, and that read returns
15
+ * a live mount (SPEC §7.10.2, graded in full by the resource-read
16
+ * catalog; here, once, on the locator the result published).
17
+ *
18
+ * The two halves fail differently, which is why both are graded. A
19
+ * result carrying the slice or a token has sent mount material across a
20
+ * chat transcript the posture exists to keep it out of. A result missing
21
+ * the pointer, or carrying two different locators, leaves a
22
+ * spec-canonical host nothing to mount, or the wrong thing (the prod
23
+ * "Waiting for tool result…" of 2026-08-16→17, ggui#537).
24
+ *
25
+ * ## What an adopter implements
26
+ *
27
+ * {@link runReadPlaneOnlyConformance} takes a
28
+ * {@link ReadPlaneOnlyScenarioDriver}: bring a server up with the
29
+ * posture ON and hand back two operations. `render()` performs ONE
30
+ * committed render by the adopter's own means (priming, handshake,
31
+ * generator: none of it is graded) and returns the raw `tools/call`
32
+ * result the MCP client received. `read(uri)` performs one
33
+ * `resources/read` and reports the outcome in the resource-read
34
+ * catalog's shape. The kit imports no server.
35
+ *
36
+ * Grade rules, as in the resource-read catalog:
37
+ *
38
+ * - A driver that cannot bring the posture up throws from the driver
39
+ * function. Every case records a SKIP with that reason, never a pass.
40
+ * - A `render()` that throws, or returns anything but a committed
41
+ * result, FAILS `render-committed`: the render is under test, and
42
+ * nothing after it can be graded.
43
+ *
44
+ * ## What this catalog deliberately does NOT grade
45
+ *
46
+ * - **How the render was produced.** Priming, cache or fresh
47
+ * generation, the handshake: the posture governs the result, not
48
+ * the path to it.
49
+ * - **`_meta` keys beyond the named ones.** An MCP result may carry
50
+ * other `_meta` members; the catalog grades the absence of the slice
51
+ * and of the token, and the presence and equality of the pointer.
52
+ * - **The host.** Whether a host takes the door is graded by the
53
+ * host-helper catalog's H2 (an advertised `serverResources` answers
54
+ * `resources/read`) and by the reference e2e, not here.
55
+ * - **`ggui_update`.** The posture binds every handler's result; this
56
+ * catalog grades the render, the one every mount starts from.
57
+ */
58
+ import type { RawToolCallResult } from '../domain-error-conformance/index.js';
59
+ import { type ResourceReadOutcome } from '../resource-read-conformance/index.js';
60
+ /** What a case pins, as literals in its JSON. */
61
+ export interface ReadPlaneOnlyExpectation {
62
+ /** The prefix every render locator carries. */
63
+ readonly locatorPrefix: string;
64
+ /** `_meta` members the result MUST NOT carry: the slice. */
65
+ readonly withheldMetaKeys: readonly string[];
66
+ /** Keys that MUST NOT appear at any depth of the result: live credentials. */
67
+ readonly withheldCredentialKeys: readonly string[];
68
+ /** What the read of the published locator MUST produce. */
69
+ readonly read: 'live-mount';
70
+ }
71
+ /**
72
+ * One read-plane-only case. Authored as JSON under `./cases/`, consumed
73
+ * via {@link readPlaneOnlyCases}. The shape IS the public API — additive
74
+ * changes only.
75
+ */
76
+ export interface ReadPlaneOnlyConformanceCase {
77
+ /** Unique case name. MUST match the JSON filename without `.json`. */
78
+ readonly name: string;
79
+ readonly description: string;
80
+ readonly expect: ReadPlaneOnlyExpectation;
81
+ }
82
+ /**
83
+ * The criteria a case is graded on, in the order they are checked.
84
+ * `render-committed` gates the rest: a render that did not commit has no
85
+ * result to grade.
86
+ */
87
+ export type ReadPlaneOnlyCriterion = 'render-committed' | 'locator-on-structured-content' | 'locator-on-meta' | 'one-locator' | 'slice-withheld' | 'credential-withheld' | 'read-mounts';
88
+ /** What the driver is asked to bring up. */
89
+ export interface ReadPlaneOnlyScenario {
90
+ /** The case being prepared — for the driver's own diagnostics. */
91
+ readonly caseName: string;
92
+ }
93
+ /** A server running the posture, ready to render and be read. */
94
+ export interface PreparedReadPlaneOnlyScenario {
95
+ /**
96
+ * Perform ONE committed render with the posture on, and return the raw
97
+ * `tools/call` result exactly as the MCP client received it.
98
+ */
99
+ render(): Promise<RawToolCallResult>;
100
+ /**
101
+ * Read one locator. MUST resolve — a protocol-level failure is
102
+ * `{kind: 'error'}` carrying the raw frame, as in the resource-read
103
+ * catalog.
104
+ */
105
+ read(uri: string): Promise<ResourceReadOutcome>;
106
+ /** Tear the scenario down. Invoked after every case, pass or fail. */
107
+ dispose?(): Promise<void>;
108
+ }
109
+ /**
110
+ * Bring a server up with the read-plane-only posture on. Throwing
111
+ * signals "I cannot express this scenario": the runner records a SKIP
112
+ * with the message.
113
+ */
114
+ export type ReadPlaneOnlyScenarioDriver = (scenario: ReadPlaneOnlyScenario) => Promise<PreparedReadPlaneOnlyScenario>;
115
+ /** Every read-plane-only case the kit ships. */
116
+ export declare const readPlaneOnlyCases: readonly ReadPlaneOnlyConformanceCase[];
117
+ export interface ReadPlaneOnlyMismatch {
118
+ readonly name: string;
119
+ readonly criterion: ReadPlaneOnlyCriterion;
120
+ readonly detail: string;
121
+ }
122
+ export interface ReadPlaneOnlySkip {
123
+ readonly name: string;
124
+ readonly reason: string;
125
+ }
126
+ export interface ReadPlaneOnlyConformanceResult {
127
+ readonly passed: readonly string[];
128
+ readonly failed: readonly ReadPlaneOnlyMismatch[];
129
+ readonly skipped: readonly ReadPlaneOnlySkip[];
130
+ }
131
+ export interface RunReadPlaneOnlyConformanceOptions {
132
+ /** Override the shipped catalog (tests, subsets). */
133
+ readonly cases?: readonly ReadPlaneOnlyConformanceCase[];
134
+ }
135
+ /**
136
+ * Grade a server's read-plane-only posture. Vendor-neutral: the driver
137
+ * binds the adopter's own server; the kit owns every assertion.
138
+ */
139
+ export declare function runReadPlaneOnlyConformance(driver: ReadPlaneOnlyScenarioDriver, options?: RunReadPlaneOnlyConformanceOptions): Promise<ReadPlaneOnlyConformanceResult>;
140
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/read-plane-only-conformance/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,uCAAuC,CAAC;AAO/C,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACvC,+CAA+C;IAC/C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,4DAA4D;IAC5D,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,8EAA8E;IAC9E,QAAQ,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IACnD,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAC9B,kBAAkB,GAClB,+BAA+B,GAC/B,iBAAiB,GACjB,aAAa,GACb,gBAAgB,GAChB,qBAAqB,GACrB,aAAa,CAAC;AAMlB,4CAA4C;AAC5C,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,iEAAiE;AACjE,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,MAAM,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrC;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAChD,sEAAsE;IACtE,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG,CACxC,QAAQ,EAAE,qBAAqB,KAC5B,OAAO,CAAC,6BAA6B,CAAC,CAAC;AAM5C,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,EAAE,SAAS,4BAA4B,EAErE,CAAC;AAMF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,kCAAkC;IACjD,qDAAqD;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;CAC1D;AA+ID;;;GAGG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,2BAA2B,EACnC,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,8BAA8B,CAAC,CAuBzC"}
@@ -0,0 +1,131 @@
1
+ import { declaresDeliveryChannel, } from '../resource-read-conformance/index.js';
2
+ import withheldRenderMounts from './cases/withheld-render-mounts-through-the-read.json' with { type: 'json' };
3
+ // =============================================================================
4
+ // Catalog
5
+ // =============================================================================
6
+ /** Every read-plane-only case the kit ships. */
7
+ export const readPlaneOnlyCases = [
8
+ withheldRenderMounts,
9
+ ];
10
+ function isObject(value) {
11
+ return typeof value === 'object' && value !== null;
12
+ }
13
+ function stringMember(value, key) {
14
+ if (!isObject(value))
15
+ return undefined;
16
+ const member = Reflect.get(value, key);
17
+ return typeof member === 'string' ? member : undefined;
18
+ }
19
+ /** Every path at which one of `keys` appears, at any depth. */
20
+ function pathsOfKeys(value, keys, at) {
21
+ if (Array.isArray(value)) {
22
+ return value.flatMap((item, i) => pathsOfKeys(item, keys, `${at}[${i}]`));
23
+ }
24
+ if (!isObject(value))
25
+ return [];
26
+ return Object.entries(value).flatMap(([key, member]) => [
27
+ ...(keys.has(key) ? [`${at}.${key}`] : []),
28
+ ...pathsOfKeys(member, keys, `${at}.${key}`),
29
+ ]);
30
+ }
31
+ function describeRead(outcome) {
32
+ return outcome.kind === 'error'
33
+ ? `an error (${outcome.error.code}${stringMember(outcome.error.data, 'code') !== undefined ? `, data.code ${stringMember(outcome.error.data, 'code')}` : ''})`
34
+ : 'contents that declare no delivery channel';
35
+ }
36
+ async function gradeCase(c, prepared) {
37
+ const fail = (criterion, detail) => ({
38
+ name: c.name,
39
+ criterion,
40
+ detail,
41
+ });
42
+ let result;
43
+ try {
44
+ result = await prepared.render();
45
+ }
46
+ catch (err) {
47
+ return [fail('render-committed', `render() threw: ${err instanceof Error ? err.message : String(err)}`)];
48
+ }
49
+ if (result.isError === true || !isObject(result.structuredContent)) {
50
+ return [
51
+ fail('render-committed', result.isError === true
52
+ ? 'the render result is isError — the posture is graded on a committed render'
53
+ : 'the render result carries no structuredContent'),
54
+ ];
55
+ }
56
+ const mismatches = [];
57
+ const { locatorPrefix } = c.expect;
58
+ const onContent = stringMember(result.structuredContent, 'resourceUri');
59
+ if (onContent === undefined || !onContent.startsWith(locatorPrefix)) {
60
+ mismatches.push(fail('locator-on-structured-content', onContent === undefined
61
+ ? 'structuredContent.resourceUri is absent — a client that strips _meta has no identity to hold'
62
+ : `structuredContent.resourceUri '${onContent}' is not a render locator (${locatorPrefix}…)`));
63
+ }
64
+ const meta = result._meta;
65
+ const onMeta = stringMember(isObject(meta) ? Reflect.get(meta, 'ui') : undefined, 'resourceUri');
66
+ if (onMeta === undefined) {
67
+ mismatches.push(fail('locator-on-meta', '_meta.ui.resourceUri is absent — a spec-canonical host has no pointer to mount, and falls back to the declaration-level shell'));
68
+ }
69
+ const legacy = stringMember(meta, 'ui/resourceUri');
70
+ const published = [onContent, onMeta, legacy].filter((v) => v !== undefined);
71
+ if (new Set(published).size > 1) {
72
+ mismatches.push(fail('one-locator', `the result publishes more than one locator: ${[...new Set(published)].join(' ≠ ')}`));
73
+ }
74
+ const presentSlices = c.expect.withheldMetaKeys.filter((key) => isObject(meta) && Reflect.get(meta, key) !== undefined);
75
+ if (presentSlices.length > 0) {
76
+ mismatches.push(fail('slice-withheld', `_meta carries ${presentSlices.join(', ')} — the posture withholds the mount material`));
77
+ }
78
+ const credentialKeys = new Set(c.expect.withheldCredentialKeys);
79
+ const credentialPaths = [
80
+ ...pathsOfKeys(meta, credentialKeys, '_meta'),
81
+ ...pathsOfKeys(result.structuredContent, credentialKeys, 'structuredContent'),
82
+ ];
83
+ if (credentialPaths.length > 0) {
84
+ mismatches.push(fail('credential-withheld', `a live credential crosses the transcript at ${credentialPaths.join(', ')} — the posture mints credentials only on the read`));
85
+ }
86
+ const target = onContent ?? onMeta;
87
+ if (target !== undefined && target.startsWith(locatorPrefix)) {
88
+ let outcome;
89
+ try {
90
+ outcome = await prepared.read(target);
91
+ }
92
+ catch (err) {
93
+ mismatches.push(fail('read-mounts', `read('${target}') threw: ${err instanceof Error ? err.message : String(err)} — a protocol failure resolves as {kind: 'error'}; a throw is graded as a failed read`));
94
+ return mismatches;
95
+ }
96
+ if (outcome.kind !== 'mount' || !declaresDeliveryChannel(outcome.renderMeta)) {
97
+ mismatches.push(fail('read-mounts', `reading the published locator '${target}' returned ${describeRead(outcome)} — under the posture the read is the only way to mount`));
98
+ }
99
+ }
100
+ return mismatches;
101
+ }
102
+ /**
103
+ * Grade a server's read-plane-only posture. Vendor-neutral: the driver
104
+ * binds the adopter's own server; the kit owns every assertion.
105
+ */
106
+ export async function runReadPlaneOnlyConformance(driver, options = {}) {
107
+ const passed = [];
108
+ const failed = [];
109
+ const skipped = [];
110
+ for (const c of options.cases ?? readPlaneOnlyCases) {
111
+ let prepared;
112
+ try {
113
+ prepared = await driver({ caseName: c.name });
114
+ }
115
+ catch (err) {
116
+ skipped.push({ name: c.name, reason: err instanceof Error ? err.message : String(err) });
117
+ continue;
118
+ }
119
+ try {
120
+ const mismatches = await gradeCase(c, prepared);
121
+ if (mismatches.length === 0)
122
+ passed.push(c.name);
123
+ else
124
+ failed.push(...mismatches);
125
+ }
126
+ finally {
127
+ await prepared.dispose?.();
128
+ }
129
+ }
130
+ return { passed, failed, skipped };
131
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"run-conformance.d.ts","sourceRoot":"","sources":["../src/run-conformance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-conformance.d.ts","sourceRoot":"","sources":["../src/run-conformance.ts"],"names":[],"mappings":"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"}
@@ -828,6 +828,13 @@ export function parseSetupStep(fixtureName, step) {
828
828
  }
829
829
  return { kind: 'ui-initialize-response-override', sessionId, override: step['override'] };
830
830
  }
831
+ if (type === 'tool-result-override') {
832
+ const sessionId = requireStringField(fixtureName, type, step, 'sessionId');
833
+ if (!('override' in step)) {
834
+ throw malformedDirective(fixtureName, type, step, "missing the 'override' tool-result params");
835
+ }
836
+ return { kind: 'tool-result-override', sessionId, override: step['override'] };
837
+ }
831
838
  if (type === 'emit-envelope') {
832
839
  const channel = requireStringField(fixtureName, type, step, 'channel');
833
840
  if (!('payload' in step)) {
@@ -835,7 +842,7 @@ export function parseSetupStep(fixtureName, step) {
835
842
  }
836
843
  return { kind: 'emit-envelope', channel, payload: step['payload'] };
837
844
  }
838
- throw new Error(`protocol-conformance: fixture '${fixtureName}' authors unknown setup directive type='${type}'. The setup vocabulary is closed; known directives: create-session, renderer-url-override, server-version-override, ui-initialize-response-override, emit-envelope.`);
845
+ throw new Error(`protocol-conformance: fixture '${fixtureName}' authors unknown setup directive type='${type}'. The setup vocabulary is closed; known directives: create-session, renderer-url-override, server-version-override, ui-initialize-response-override, tool-result-override, emit-envelope.`);
839
846
  }
840
847
  /**
841
848
  * Teardown counterpart of {@link parseSetupStep}. The teardown
package/dist/types.d.ts CHANGED
@@ -122,7 +122,7 @@ export type AuthConfig = {
122
122
  * a (valid) directive signal it by throwing from `dispatchSetup`,
123
123
  * which the runner records as a SKIP.
124
124
  */
125
- export type SetupStep = CreateGguiSessionStep | RendererUrlOverrideStep | ServerVersionOverrideStep | UiInitializeResponseOverrideStep | EmitEnvelopeStep;
125
+ export type SetupStep = CreateGguiSessionStep | RendererUrlOverrideStep | ServerVersionOverrideStep | UiInitializeResponseOverrideStep | ToolResultOverrideStep | EmitEnvelopeStep;
126
126
  /**
127
127
  * Declared-action entry for {@link CreateGguiSessionStep.actionSpec}.
128
128
  * An empty entry declares a void-payload action — fixtures over it
@@ -210,9 +210,14 @@ export interface ServerVersionOverrideStep {
210
210
  }
211
211
  /**
212
212
  * Substitute the MCP Apps `ui/initialize` response the host returns to
213
- * the iframe — drives bootstrap-failure paths like
214
- * `BOOTSTRAP_META_MISSING`. A browser-host (Path-B) concern: WS-only
215
- * hosts throw on it and the fixture skips.
213
+ * the iframe. A browser-host (Path-B) concern: WS-only hosts throw on it
214
+ * and the fixture skips.
215
+ *
216
+ * No shipped fixture authors it (ggui#1304). The spec-canonical
217
+ * `McpUiInitializeResult` carries no `ai.ggui/render` slice, so
218
+ * overriding it cannot drive a missing-slice failure; that path is
219
+ * driven by {@link ToolResultOverrideStep}. The directive stays in the
220
+ * vocabulary because the kit's authored shapes evolve additively.
216
221
  */
217
222
  export interface UiInitializeResponseOverrideStep {
218
223
  readonly type: 'ui-initialize-response-override';
@@ -221,6 +226,22 @@ export interface UiInitializeResponseOverrideStep {
221
226
  /** Response body the host returns from `ui/initialize` verbatim. */
222
227
  readonly override: unknown;
223
228
  }
229
+ /**
230
+ * Substitute the `ui/notifications/tool-result` the host forwards to the
231
+ * view: `override` is the `params` (a `CallToolResult`) the host sends
232
+ * verbatim, whose top-level `_meta` is where the `ai.ggui/render` slice
233
+ * rides. Drives the forwarded-result bootstrap failures, such as a
234
+ * result carrying neither the slice nor a locator
235
+ * (`MISSING_META_GGUI_BOOTSTRAP`). A browser-host (Path-B) concern:
236
+ * WS-only hosts throw on it and the fixture skips (ggui#1304).
237
+ */
238
+ export interface ToolResultOverrideStep {
239
+ readonly type: 'tool-result-override';
240
+ /** GguiSession the override scopes to (a prior `create-session`). */
241
+ readonly sessionId: string;
242
+ /** The `params` the host forwards verbatim. */
243
+ readonly override: unknown;
244
+ }
224
245
  export interface EmitEnvelopeStep {
225
246
  readonly type: 'emit-envelope';
226
247
  /** Reserved-channel or declared-channel name. */
@@ -337,7 +358,7 @@ export interface StreamUpdateBehavior {
337
358
  * Expect a bootstrap-failure postMessage envelope + the renderer's
338
359
  * {@link ProtocolError} of kind `'bootstrap'` with the matching
339
360
  * reason. Post-wire paths (`BUNDLE_FETCH_FAILED`,
340
- * `BOOTSTRAP_META_MISSING`) are pre-WS — they surface via
361
+ * `MISSING_META_GGUI_BOOTSTRAP`) are pre-WS — they surface via
341
362
  * `postMessage({type:'ggui:bootstrap-failed', …})` only, NOT on
342
363
  * the live channel.
343
364
  */
@@ -569,6 +590,10 @@ export interface TestCase {
569
590
  * copy per the drift-decoupling posture in the module docstring:
570
591
  * fixtures compile against the kit's frozen vocabulary, never the
571
592
  * live protocol or renderer types.
593
+ *
594
+ * `MISSING_META_GGUI_BOOTSTRAP` and `BOOTSTRAP_META_MISSING` name one
595
+ * condition; fixtures expect the first, the spelling reference
596
+ * emitters send (SPEC §5.5.2).
572
597
  */
573
598
  export type BootstrapFailureReason = 'MISSING_TOOL_OUTPUT' | 'MISSING_META_GGUI_BOOTSTRAP' | 'BOOTSTRAP_META_MISSING' | 'MALFORMED_BOOTSTRAP' | 'EXPIRED_BOOTSTRAP' | 'UI_INITIALIZE_FAILED' | 'WS_HANDSHAKE_FAILED' | 'UPGRADE_REQUIRED' | 'BUNDLE_FETCH_FAILED' | 'CSP_VIOLATION' | 'SESSION_NOT_FOUND' | 'AUTH_REJECTED' | (string & {});
574
599
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ggui-ai/protocol-conformance",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Conformance test kit for the ggui protocol. Drives a behavioral fixture catalog against a live implementation over WebSocket, a resources/read catalog against a live MCP server, and nine pure-function catalogs (schema, registration, resolution, binding, props-schema, host-helper, refusal-envelope, registry-completeness, transport-refusal) for the gadget, tool-binding, schema-precise-render, host-helper and pre-generation-refusal obligations, reporting a scorecard-style pass / fail / skip. MCP builders adopt this kit to prove their implementation is protocol-conformant.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -51,6 +51,11 @@
51
51
  "import": "./dist/resource-read-conformance/index.js",
52
52
  "default": "./dist/resource-read-conformance/index.js"
53
53
  },
54
+ "./read-plane-only-conformance": {
55
+ "types": "./dist/read-plane-only-conformance/index.d.ts",
56
+ "import": "./dist/read-plane-only-conformance/index.js",
57
+ "default": "./dist/read-plane-only-conformance/index.js"
58
+ },
54
59
  "./n1-compat-conformance": {
55
60
  "types": "./dist/n1-compat-conformance/index.d.ts",
56
61
  "import": "./dist/n1-compat-conformance/index.js",
@@ -99,7 +104,7 @@
99
104
  },
100
105
  "dependencies": {
101
106
  "ws": "^8.20.1",
102
- "@ggui-ai/protocol": "0.22.0"
107
+ "@ggui-ai/protocol": "0.23.0"
103
108
  },
104
109
  "devDependencies": {
105
110
  "@types/node": "^22.0.0",