@ggui-ai/protocol-conformance 0.27.0 → 0.29.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 +3 -2
- package/dist/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +43 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/n1-compat-conformance/cases/release-0-28-ops-list-blueprints-gemini-3.1-flash-lite-preview.json +41 -0
- package/dist/n1-compat-conformance/cases/release-0-28-ops-list-blueprints-gemini-flash-latest.json +41 -0
- package/dist/n1-compat-conformance/index.d.ts.map +1 -1
- package/dist/n1-compat-conformance/index.js +4 -0
- package/dist/output-schema-conformance/index.d.ts +71 -0
- package/dist/output-schema-conformance/index.d.ts.map +1 -0
- package/dist/output-schema-conformance/index.js +76 -0
- package/dist/run-conformance.d.ts +11 -1
- package/dist/run-conformance.d.ts.map +1 -1
- package/dist/run-conformance.js +30 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -227,11 +227,12 @@ npx @ggui-ai/protocol-conformance --url ws://localhost:3000/ws --auth bearer:$TO
|
|
|
227
227
|
|
|
228
228
|
The CLI exits `0` only when at least one fixture executed and none failed; `1` on any fixture failure; `2` on invocation errors **or** when every fixture skipped (a zero-executed run never reads as success in CI). A warning never changes the exit code, and a warned fixture counts as executed.
|
|
229
229
|
|
|
230
|
-
The
|
|
230
|
+
The pure-function catalogs (`refusal-envelope`, `registry-completeness`, `transport-refusal`, `output-schema`) grade an in-process function and a data table, not the wire, so a URL alone cannot reach them. The CLI hands them their inputs by flag — `--registry <file.json>` (the deployment's refusal registry, a JSON object keyed by code), `--tools-list <file.json>` (the deployment's served `tools/list` document as a client receives it; grades that every advertised output object is open at every depth — SPEC §7.9 "Advertised output objects", ggui#1333), `--projector <module>` (an ES module whose `project(refusal)` — named or default export — returns the SPEC §7.1 tool result, or `null` for a code with no render envelope) and `--transport-projector <module>` (same shape, returning the endpoint's `{ httpStatus, error }` or `null`). A flag left out leaves its catalog on the scorecard as SKIPPED with the flag named. Catalog rows count as executed fixtures, so a run given a catalog flag can exit 0 while every wire fixture is SKIPPED — read the scorecard for the wire signal. Minimal spec-correct samples of each input live in the repository at [`src/cli-samples/`](https://github.com/ggui-ai/ggui/tree/main/packages/protocol-conformance/src/cli-samples) (not in the npm tarball); the test suite pins that they pass their catalogs.
|
|
231
231
|
|
|
232
232
|
```
|
|
233
233
|
npx @ggui-ai/protocol-conformance --url ws://localhost:3000/ws --auth bearer:$TOKEN \
|
|
234
|
-
--registry ./refusal-registry.json --
|
|
234
|
+
--registry ./refusal-registry.json --tools-list ./tools-list.json \
|
|
235
|
+
--projector ./project.mjs --transport-projector ./endpoint.mjs
|
|
235
236
|
```
|
|
236
237
|
|
|
237
238
|
To grade setup-dependent fixtures (and any `session-state` fixture), pass a `host` implementing the `ConformanceHost` adapter — `dispatchSetup` / `dispatchTeardown` for the directive vocabulary, plus the optional `readSessionField(sessionId, field)` introspection seam. Fixtures whose requirements the host doesn't meet skip with a precise reason; they never silently pass.
|
package/dist/cli.d.ts
CHANGED
|
@@ -14,16 +14,19 @@ interface ParsedArgs {
|
|
|
14
14
|
readonly transportProjector?: string;
|
|
15
15
|
/** Path to an ES module exporting a `tools/call` driver (SPEC §7.9 Plane 2, ggui#880). */
|
|
16
16
|
readonly toolCallDriver?: string;
|
|
17
|
+
/** Path to a JSON file holding the deployment's served `tools/list` document (SPEC §7.9 "Advertised output objects", ggui#1333). */
|
|
18
|
+
readonly toolsList?: string;
|
|
17
19
|
readonly verbose: boolean;
|
|
18
20
|
readonly help: boolean;
|
|
19
21
|
}
|
|
20
22
|
declare function parseArgs(argv: readonly string[]): ParsedArgs;
|
|
21
23
|
declare function parseAuth(spec: string): AuthConfig;
|
|
22
24
|
/** The three optional inputs a CLI run can hand the pure-function catalogs. */
|
|
23
|
-
export type CatalogInputs = Pick<RunConformanceConfig, 'refusalRegistry' | 'refusalProjector' | 'transportRefusalProjector' | 'toolCallDriver'>;
|
|
25
|
+
export type CatalogInputs = Pick<RunConformanceConfig, 'refusalRegistry' | 'refusalProjector' | 'transportRefusalProjector' | 'toolCallDriver' | 'toolsList'>;
|
|
24
26
|
/** The flag values that name where each catalog input comes from. */
|
|
25
27
|
export interface CatalogInputPaths {
|
|
26
28
|
readonly registry?: string | undefined;
|
|
29
|
+
readonly toolsList?: string | undefined;
|
|
27
30
|
readonly projector?: string | undefined;
|
|
28
31
|
readonly transportProjector?: string | undefined;
|
|
29
32
|
readonly toolCallDriver?: string | undefined;
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA6DA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAK9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA6DA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAK9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAO7C,UAAU,UAAU;IAClB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,0FAA0F;IAC1F,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,oIAAoI;IACpI,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,iBAAS,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAkEtD;AAOD,iBAAS,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAY3C;AAMD,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,oBAAoB,EACpB,iBAAiB,GAAG,kBAAkB,GAAG,2BAA2B,GAAG,gBAAgB,GAAG,WAAW,CACtG,CAAC;AAEF,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9C;AAsMD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC,CA+CxF;AAMD,eAAO,MAAM,KAAK,QAkEL,CAAC;AAEd,iBAAe,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAsE5D;AAED;;;;;;;;;GASG;AACH,iBAAS,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAI/D;AA+BD,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -53,6 +53,7 @@ function parseArgs(argv) {
|
|
|
53
53
|
const only = [];
|
|
54
54
|
let timeoutMs;
|
|
55
55
|
let registry;
|
|
56
|
+
let toolsList;
|
|
56
57
|
let projector;
|
|
57
58
|
let toolCallDriver;
|
|
58
59
|
let transportProjector;
|
|
@@ -86,6 +87,9 @@ function parseArgs(argv) {
|
|
|
86
87
|
case '--registry':
|
|
87
88
|
registry = next();
|
|
88
89
|
break;
|
|
90
|
+
case '--tools-list':
|
|
91
|
+
toolsList = next();
|
|
92
|
+
break;
|
|
89
93
|
case '--projector':
|
|
90
94
|
projector = next();
|
|
91
95
|
break;
|
|
@@ -107,7 +111,7 @@ function parseArgs(argv) {
|
|
|
107
111
|
throw new Error(`unknown flag '${flag}' — run with --help for usage`);
|
|
108
112
|
}
|
|
109
113
|
}
|
|
110
|
-
return { url, auth, only, timeoutMs, registry, projector, transportProjector, toolCallDriver, verbose, help };
|
|
114
|
+
return { url, auth, only, timeoutMs, registry, toolsList, projector, transportProjector, toolCallDriver, verbose, help };
|
|
111
115
|
}
|
|
112
116
|
/** The message of a thrown value, without pretending every throw is an Error. */
|
|
113
117
|
function errorMessage(err) {
|
|
@@ -132,6 +136,30 @@ function isRecord(value) {
|
|
|
132
136
|
function isStringArray(value) {
|
|
133
137
|
return Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
134
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* The runtime twin of {@link AdvertisedToolsListView} — a served `tools/list`
|
|
141
|
+
* document as the output-schema catalog reads it: `tools[]`, each with a
|
|
142
|
+
* string `name` and, optionally, an `outputSchema` of any shape (the walk
|
|
143
|
+
* grades it; a non-object there is simply a document with no closed object).
|
|
144
|
+
*/
|
|
145
|
+
function isToolsListView(value) {
|
|
146
|
+
return (isRecord(value) &&
|
|
147
|
+
Array.isArray(value.tools) &&
|
|
148
|
+
value.tools.every((tool) => isRecord(tool) && typeof tool.name === 'string'));
|
|
149
|
+
}
|
|
150
|
+
function parseToolsListView(text, path) {
|
|
151
|
+
let parsed;
|
|
152
|
+
try {
|
|
153
|
+
parsed = JSON.parse(text);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
throw new Error(`--tools-list ${path} is not JSON: ${errorMessage(err)}`);
|
|
157
|
+
}
|
|
158
|
+
if (!isToolsListView(parsed)) {
|
|
159
|
+
throw new Error(`--tools-list ${path} must be a tools/list document: { tools: [{ name, outputSchema? }, …] }`);
|
|
160
|
+
}
|
|
161
|
+
return parsed;
|
|
162
|
+
}
|
|
135
163
|
/**
|
|
136
164
|
* The runtime twin of {@link RefusalRegistryRow} — a JSON registry is
|
|
137
165
|
* held to exactly the shape a programmatic caller has to satisfy at
|
|
@@ -289,6 +317,16 @@ export async function loadCatalogInputs(paths) {
|
|
|
289
317
|
}
|
|
290
318
|
inputs.refusalRegistry = parseRegistryView(text, paths.registry);
|
|
291
319
|
}
|
|
320
|
+
if (paths.toolsList !== undefined) {
|
|
321
|
+
let text;
|
|
322
|
+
try {
|
|
323
|
+
text = await readFile(resolve(paths.toolsList), 'utf8');
|
|
324
|
+
}
|
|
325
|
+
catch (err) {
|
|
326
|
+
throw new Error(`--tools-list ${paths.toolsList} could not be read: ${errorMessage(err)}`);
|
|
327
|
+
}
|
|
328
|
+
inputs.toolsList = parseToolsListView(text, paths.toolsList);
|
|
329
|
+
}
|
|
292
330
|
if (paths.projector !== undefined) {
|
|
293
331
|
inputs.refusalProjector = await loadProjector('--projector', paths.projector, isProjectedRefusalResult);
|
|
294
332
|
}
|
|
@@ -326,6 +364,10 @@ Options:
|
|
|
326
364
|
--timeout-ms <N> Per-fixture observation window. Default 2000.
|
|
327
365
|
--registry <file.json> The deployment's refusal-code registry, a JSON
|
|
328
366
|
object keyed by code (grades registry-completeness).
|
|
367
|
+
--tools-list <file.json> The deployment's served tools/list document, as a
|
|
368
|
+
client receives it (grades output-schema: every
|
|
369
|
+
advertised output object is open — SPEC §7.9,
|
|
370
|
+
ggui#1333).
|
|
329
371
|
--projector <module> ES module whose \`project(refusal)\` — a named or
|
|
330
372
|
default export — returns the SPEC §7.1 tool result
|
|
331
373
|
for a refusal, or null when the code has no
|
package/dist/index.d.ts
CHANGED
|
@@ -46,5 +46,6 @@ export type { DispatchIdempotencyCaseName, DispatchIdempotencyCaseResult, Dispat
|
|
|
46
46
|
export { APP_THEME_CASES, OVERLAY_HASH_CASES, THEME_MODE_CASES, runThemeBindingConformance, } from './theme-binding-conformance/index.js';
|
|
47
47
|
export type { AppThemeCase, OverlayHashCase, ThemeBindingResult, ThemeModeCase, } from './theme-binding-conformance/index.js';
|
|
48
48
|
export { N1_COMPAT_CASES, N1_COMPAT_DIRECTIONS, N1_COMPAT_WIRES, runN1CompatConformance } from './n1-compat-conformance/index.js';
|
|
49
|
+
export { OUTPUT_SCHEMA_OPEN_DESCRIPTION, closedObjectsIn, runOutputSchemaConformance, type AdvertisedToolView, type AdvertisedToolsListView, type OutputSchemaConformanceResult, type OutputSchemaViolation, } from './output-schema-conformance/index.js';
|
|
49
50
|
export type { N1CompatCase, N1CompatDirection, N1CompatRelease, N1CompatResult, N1CompatWire } from './n1-compat-conformance/index.js';
|
|
50
51
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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
|
@@ -87,3 +87,7 @@ export { DISPATCH_IDEMPOTENCY_ACTION, DISPATCH_IDEMPOTENCY_ACTION_SPEC, runDispa
|
|
|
87
87
|
export { APP_THEME_CASES, OVERLAY_HASH_CASES, THEME_MODE_CASES, runThemeBindingConformance, } from './theme-binding-conformance/index.js';
|
|
88
88
|
// ── n1-compat (ggui#1014 §3.6 — previous-release payloads against today's parsers; ggui#1093 — a later release's payload against today's READ door) ──
|
|
89
89
|
export { N1_COMPAT_CASES, N1_COMPAT_DIRECTIONS, N1_COMPAT_WIRES, runN1CompatConformance } from './n1-compat-conformance/index.js';
|
|
90
|
+
// Output-schema catalog (SPEC §7.9 "Advertised output objects", ggui#1333):
|
|
91
|
+
// an advertised output object MUST NOT be closed — graded on the served
|
|
92
|
+
// `tools/list` document.
|
|
93
|
+
export { OUTPUT_SCHEMA_OPEN_DESCRIPTION, closedObjectsIn, runOutputSchemaConformance, } from './output-schema-conformance/index.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "release-0-28-ops-list-blueprints-gemini-3.1-flash-lite-preview",
|
|
3
|
+
"description": "A ggui_ops_list_blueprints result as @ggui-ai/* 0.28.0 (a734373b5) would emit it for a generation-minted row whose run route is `gemini/gemini-3.1-flash-lite-preview`: SYNTHESISED, not captured — `release-14-ops-list-blueprints.json` (the tag-14 capture) with exactly two edits, `source.model` set to that id and `blueprintId` renamed to say so; the id is one 0.28.0's `MODELS.google` admitted and which left the allowlist in 0.29 (ggui#1291; at the vendor it is a preview the vendor lists under Previous models as shut down). Between tag 14 and 0.28.0 the row schema gained one optional member this row does not carry (`clonedFrom`), nothing else. Today's opsListBlueprintsOutputSchema MUST accept the result and the parsed row MUST carry `source.model` as sent: a 0.29 reader refusing it would drop the stored row at its store's read door and refuse a 0.28 server's `ggui_ops_*` blueprint outputs naming `model` (VERSION-POLICY §3.6). The tolerance expires in 0.30, one release after the drop; this case leaves with it.",
|
|
4
|
+
"release": {
|
|
5
|
+
"label": "@ggui-ai/* 0.28.0",
|
|
6
|
+
"sha": "a734373b5"
|
|
7
|
+
},
|
|
8
|
+
"wire": "ops-list-blueprints",
|
|
9
|
+
"payload": {
|
|
10
|
+
"blueprints": [
|
|
11
|
+
{
|
|
12
|
+
"blueprintId": "bp_1291-gemini-3.1-flash-lite-preview",
|
|
13
|
+
"contractHash": "a8b8be414e9e53f7",
|
|
14
|
+
"appId": "IMud3W0m",
|
|
15
|
+
"codeS3Url": "s3://blueprint-code/code/be997120c9425551b4db6c041c32d632255ba166e5d3746fe3c4cbbbf3a2edd9.js",
|
|
16
|
+
"codeHash": "be997120c9425551b4db6c041c32d632255ba166e5d3746fe3c4cbbbf3a2edd9",
|
|
17
|
+
"source": {
|
|
18
|
+
"kind": "llm",
|
|
19
|
+
"generator": "ui-gen-default",
|
|
20
|
+
"model": "gemini/gemini-3.1-flash-lite-preview"
|
|
21
|
+
},
|
|
22
|
+
"variance": {},
|
|
23
|
+
"createdAt": "2026-09-27T16:40:27.386Z",
|
|
24
|
+
"createdBy": "agent",
|
|
25
|
+
"contract": {
|
|
26
|
+
"propsSpec": {
|
|
27
|
+
"properties": {
|
|
28
|
+
"harbour": {
|
|
29
|
+
"schema": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"required": true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"expect": "accepted"
|
|
41
|
+
}
|
package/dist/n1-compat-conformance/cases/release-0-28-ops-list-blueprints-gemini-flash-latest.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "release-0-28-ops-list-blueprints-gemini-flash-latest",
|
|
3
|
+
"description": "A ggui_ops_list_blueprints result as @ggui-ai/* 0.28.0 (a734373b5) would emit it for a generation-minted row whose run route is `gemini/gemini-flash-latest`: SYNTHESISED, not captured — `release-14-ops-list-blueprints.json` (the tag-14 capture) with exactly two edits, `source.model` set to that id and `blueprintId` renamed to say so; the id is one 0.28.0's `MODELS.google` admitted and which left the allowlist in 0.29 (ggui#1291; at the vendor it is a `-latest` alias that the vendor says is hot-swapped with every release, with no stated target). Between tag 14 and 0.28.0 the row schema gained one optional member this row does not carry (`clonedFrom`), nothing else. Today's opsListBlueprintsOutputSchema MUST accept the result and the parsed row MUST carry `source.model` as sent: a 0.29 reader refusing it would drop the stored row at its store's read door and refuse a 0.28 server's `ggui_ops_*` blueprint outputs naming `model` (VERSION-POLICY §3.6). The tolerance expires in 0.30, one release after the drop; this case leaves with it.",
|
|
4
|
+
"release": {
|
|
5
|
+
"label": "@ggui-ai/* 0.28.0",
|
|
6
|
+
"sha": "a734373b5"
|
|
7
|
+
},
|
|
8
|
+
"wire": "ops-list-blueprints",
|
|
9
|
+
"payload": {
|
|
10
|
+
"blueprints": [
|
|
11
|
+
{
|
|
12
|
+
"blueprintId": "bp_1291-gemini-flash-latest",
|
|
13
|
+
"contractHash": "a8b8be414e9e53f7",
|
|
14
|
+
"appId": "IMud3W0m",
|
|
15
|
+
"codeS3Url": "s3://blueprint-code/code/be997120c9425551b4db6c041c32d632255ba166e5d3746fe3c4cbbbf3a2edd9.js",
|
|
16
|
+
"codeHash": "be997120c9425551b4db6c041c32d632255ba166e5d3746fe3c4cbbbf3a2edd9",
|
|
17
|
+
"source": {
|
|
18
|
+
"kind": "llm",
|
|
19
|
+
"generator": "ui-gen-default",
|
|
20
|
+
"model": "gemini/gemini-flash-latest"
|
|
21
|
+
},
|
|
22
|
+
"variance": {},
|
|
23
|
+
"createdAt": "2026-09-27T16:40:27.386Z",
|
|
24
|
+
"createdBy": "agent",
|
|
25
|
+
"contract": {
|
|
26
|
+
"propsSpec": {
|
|
27
|
+
"properties": {
|
|
28
|
+
"harbour": {
|
|
29
|
+
"schema": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"required": true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"expect": "accepted"
|
|
41
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/n1-compat-conformance/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/n1-compat-conformance/index.ts"],"names":[],"mappings":"AA6CA,sDAAsD;AACtD,eAAO,MAAM,eAAe,0MAA2M,CAAC;AAExO,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,EAkBhC,CAAC;AAuNpB,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,SAAS,cAAc,EAAE,CAKlE"}
|
|
@@ -25,6 +25,8 @@ import release2OpsGenerateBlueprint from './cases/release-2-ops-generate-bluepri
|
|
|
25
25
|
import release91HandshakeSuggestion from './cases/release-9-1-handshake-suggestion.json' with { type: 'json' };
|
|
26
26
|
import release13RenderResult from './cases/release-13-render-result.json' with { type: 'json' };
|
|
27
27
|
import release14OpsListBlueprints from './cases/release-14-ops-list-blueprints.json' with { type: 'json' };
|
|
28
|
+
import release028OpsListBlueprintsGeminiFlashLatest from './cases/release-0-28-ops-list-blueprints-gemini-flash-latest.json' with { type: 'json' };
|
|
29
|
+
import release028OpsListBlueprintsGemini31FlashLitePreview from './cases/release-0-28-ops-list-blueprints-gemini-3.1-flash-lite-preview.json' with { type: 'json' };
|
|
28
30
|
import forwardAppThemeUnknownMember from './cases/forward-app-theme-unknown-member.json' with { type: 'json' };
|
|
29
31
|
import forwardAppThemeCarryUnknownMember from './cases/forward-app-theme-carry-unknown-member.json' with { type: 'json' };
|
|
30
32
|
import forwardAppThemeCarryUninterpretable from './cases/forward-app-theme-carry-uninterpretable.json' with { type: 'json' };
|
|
@@ -93,6 +95,8 @@ export const N1_COMPAT_CASES = [
|
|
|
93
95
|
release91HandshakeSuggestion,
|
|
94
96
|
release13RenderResult,
|
|
95
97
|
release14OpsListBlueprints,
|
|
98
|
+
release028OpsListBlueprintsGeminiFlashLatest,
|
|
99
|
+
release028OpsListBlueprintsGemini31FlashLitePreview,
|
|
96
100
|
forwardAppThemeUnknownMember,
|
|
97
101
|
forwardAppThemeCarryUnknownMember,
|
|
98
102
|
forwardAppThemeCarryUninterpretable,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output-schema catalog — an advertised output object MUST NOT be closed
|
|
3
|
+
* (SPEC §7.9 "Advertised output objects", ggui#1333).
|
|
4
|
+
*
|
|
5
|
+
* ## The obligation
|
|
6
|
+
*
|
|
7
|
+
* A host that caches a tool's advertised `outputSchema` at `tools/list` and
|
|
8
|
+
* validates every result's `structuredContent` against it (the MCP TS SDK
|
|
9
|
+
* client does) refuses a result carrying a member the cached schema does not
|
|
10
|
+
* name. So an object anywhere under an advertised `outputSchema` that says
|
|
11
|
+
* `additionalProperties: false` turns every later optional output member —
|
|
12
|
+
* MINOR by VERSION-POLICY §1.2 — into a break for every host that listed
|
|
13
|
+
* tools against the previous release. The advertised document is a
|
|
14
|
+
* projection, not the server's parse: a conforming server still strips what
|
|
15
|
+
* its own shape does not name before a result reaches the wire, so an open
|
|
16
|
+
* advertisement never widens what is sent.
|
|
17
|
+
*
|
|
18
|
+
* ## Why this is a pure-function catalog, graded on data
|
|
19
|
+
*
|
|
20
|
+
* Like `registry-completeness`, this catalog grades DATA: the deployment's
|
|
21
|
+
* served `tools/list` document. There is no transport to drive — the
|
|
22
|
+
* document is what any client already holds after one `listTools` — so the
|
|
23
|
+
* adopter passes it (`toolsList` on `runConformance()`, `--tools-list
|
|
24
|
+
* <file.json>` on the CLI) and every tool that advertises an `outputSchema`
|
|
25
|
+
* becomes one row, failing with the path of every closed object. A tool
|
|
26
|
+
* that advertises no `outputSchema` has no object to be closed and
|
|
27
|
+
* contributes no row here; when NO tool advertises one, the runner reports
|
|
28
|
+
* the single row `output-schema/none-advertised-vacuous` as a pass
|
|
29
|
+
* (ggui#1897), so a scorecard never shows the catalog as absent.
|
|
30
|
+
*
|
|
31
|
+
* ## Polyglot, decoupled
|
|
32
|
+
*
|
|
33
|
+
* The walk is the whole grader, and it reads JSON Schema, not zod: an
|
|
34
|
+
* adopter on any stack can feed the kit the document their server serves.
|
|
35
|
+
* The cases under `./cases/` are the kit's own unit lane for the walk.
|
|
36
|
+
*/
|
|
37
|
+
/** One advertised tool, in the kit's own loose vocabulary — only what the walk reads. */
|
|
38
|
+
export interface AdvertisedToolView {
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly outputSchema?: unknown;
|
|
41
|
+
}
|
|
42
|
+
/** The served `tools/list` document, as far as this catalog reads it. */
|
|
43
|
+
export interface AdvertisedToolsListView {
|
|
44
|
+
readonly tools: readonly AdvertisedToolView[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Every `additionalProperties: false` under a JSON Schema document, by path
|
|
48
|
+
* (`$` is the document root; `$.properties.x.items` and so on below it).
|
|
49
|
+
* Empty means open at every depth.
|
|
50
|
+
*/
|
|
51
|
+
export declare function closedObjectsIn(node: unknown, path?: string): string[];
|
|
52
|
+
/** One tool whose advertised output object is closed somewhere. */
|
|
53
|
+
export interface OutputSchemaViolation {
|
|
54
|
+
/** The tool's name — the row is `output-schema/<name>` in a run. */
|
|
55
|
+
readonly name: string;
|
|
56
|
+
readonly description: string;
|
|
57
|
+
/** Every closed object's path in the advertised `outputSchema`. */
|
|
58
|
+
readonly violations: readonly string[];
|
|
59
|
+
}
|
|
60
|
+
export interface OutputSchemaConformanceResult {
|
|
61
|
+
/** Tool names whose advertised output object is open at every depth. */
|
|
62
|
+
readonly passed: readonly string[];
|
|
63
|
+
readonly failed: readonly OutputSchemaViolation[];
|
|
64
|
+
}
|
|
65
|
+
export declare const OUTPUT_SCHEMA_OPEN_DESCRIPTION = "Every object under the advertised outputSchema is open \u2014 no `additionalProperties: false` at any depth \u2014 so a host caching this schema accepts a later release\u2019s added optional member (SPEC \u00A77.9 \"Advertised output objects\", ggui#1333).";
|
|
66
|
+
/**
|
|
67
|
+
* Grade a served `tools/list` document: one row per tool that advertises an
|
|
68
|
+
* `outputSchema`, failing with every closed object's path.
|
|
69
|
+
*/
|
|
70
|
+
export declare function runOutputSchemaConformance(list: AdvertisedToolsListView): OutputSchemaConformanceResult;
|
|
71
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/output-schema-conformance/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,yFAAyF;AACzF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,SAAM,GAAG,MAAM,EAAE,CAWnE;AAED,mEAAmE;AACnE,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,6BAA6B;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACnD;AAED,eAAO,MAAM,8BAA8B,qQACmM,CAAC;AAE/O;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,uBAAuB,GAC5B,6BAA6B,CAa/B"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output-schema catalog — an advertised output object MUST NOT be closed
|
|
3
|
+
* (SPEC §7.9 "Advertised output objects", ggui#1333).
|
|
4
|
+
*
|
|
5
|
+
* ## The obligation
|
|
6
|
+
*
|
|
7
|
+
* A host that caches a tool's advertised `outputSchema` at `tools/list` and
|
|
8
|
+
* validates every result's `structuredContent` against it (the MCP TS SDK
|
|
9
|
+
* client does) refuses a result carrying a member the cached schema does not
|
|
10
|
+
* name. So an object anywhere under an advertised `outputSchema` that says
|
|
11
|
+
* `additionalProperties: false` turns every later optional output member —
|
|
12
|
+
* MINOR by VERSION-POLICY §1.2 — into a break for every host that listed
|
|
13
|
+
* tools against the previous release. The advertised document is a
|
|
14
|
+
* projection, not the server's parse: a conforming server still strips what
|
|
15
|
+
* its own shape does not name before a result reaches the wire, so an open
|
|
16
|
+
* advertisement never widens what is sent.
|
|
17
|
+
*
|
|
18
|
+
* ## Why this is a pure-function catalog, graded on data
|
|
19
|
+
*
|
|
20
|
+
* Like `registry-completeness`, this catalog grades DATA: the deployment's
|
|
21
|
+
* served `tools/list` document. There is no transport to drive — the
|
|
22
|
+
* document is what any client already holds after one `listTools` — so the
|
|
23
|
+
* adopter passes it (`toolsList` on `runConformance()`, `--tools-list
|
|
24
|
+
* <file.json>` on the CLI) and every tool that advertises an `outputSchema`
|
|
25
|
+
* becomes one row, failing with the path of every closed object. A tool
|
|
26
|
+
* that advertises no `outputSchema` has no object to be closed and
|
|
27
|
+
* contributes no row here; when NO tool advertises one, the runner reports
|
|
28
|
+
* the single row `output-schema/none-advertised-vacuous` as a pass
|
|
29
|
+
* (ggui#1897), so a scorecard never shows the catalog as absent.
|
|
30
|
+
*
|
|
31
|
+
* ## Polyglot, decoupled
|
|
32
|
+
*
|
|
33
|
+
* The walk is the whole grader, and it reads JSON Schema, not zod: an
|
|
34
|
+
* adopter on any stack can feed the kit the document their server serves.
|
|
35
|
+
* The cases under `./cases/` are the kit's own unit lane for the walk.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* Every `additionalProperties: false` under a JSON Schema document, by path
|
|
39
|
+
* (`$` is the document root; `$.properties.x.items` and so on below it).
|
|
40
|
+
* Empty means open at every depth.
|
|
41
|
+
*/
|
|
42
|
+
export function closedObjectsIn(node, path = '$') {
|
|
43
|
+
if (Array.isArray(node)) {
|
|
44
|
+
return node.flatMap((item, i) => closedObjectsIn(item, `${path}[${String(i)}]`));
|
|
45
|
+
}
|
|
46
|
+
if (node === null || typeof node !== 'object')
|
|
47
|
+
return [];
|
|
48
|
+
const closed = [];
|
|
49
|
+
for (const [key, value] of Object.entries(node)) {
|
|
50
|
+
if (key === 'additionalProperties' && value === false)
|
|
51
|
+
closed.push(path);
|
|
52
|
+
closed.push(...closedObjectsIn(value, `${path}.${key}`));
|
|
53
|
+
}
|
|
54
|
+
return closed;
|
|
55
|
+
}
|
|
56
|
+
export const OUTPUT_SCHEMA_OPEN_DESCRIPTION = 'Every object under the advertised outputSchema is open — no `additionalProperties: false` at any depth — so a host caching this schema accepts a later release’s added optional member (SPEC §7.9 "Advertised output objects", ggui#1333).';
|
|
57
|
+
/**
|
|
58
|
+
* Grade a served `tools/list` document: one row per tool that advertises an
|
|
59
|
+
* `outputSchema`, failing with every closed object's path.
|
|
60
|
+
*/
|
|
61
|
+
export function runOutputSchemaConformance(list) {
|
|
62
|
+
const passed = [];
|
|
63
|
+
const failed = [];
|
|
64
|
+
for (const tool of list.tools) {
|
|
65
|
+
if (tool.outputSchema === undefined)
|
|
66
|
+
continue;
|
|
67
|
+
const violations = closedObjectsIn(tool.outputSchema);
|
|
68
|
+
if (violations.length === 0) {
|
|
69
|
+
passed.push(tool.name);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
failed.push({ name: tool.name, description: OUTPUT_SCHEMA_OPEN_DESCRIPTION, violations });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { passed, failed };
|
|
76
|
+
}
|
|
@@ -5,6 +5,7 @@ import type { AuthConfig, SessionStateBehavior, StreamUpdateBehavior, TestCase,
|
|
|
5
5
|
import { type PreGenerationRefusalInput, type ProjectedRefusalResult } from './refusal-envelope-conformance/index.js';
|
|
6
6
|
import { type RefusalRegistryView } from './registry-completeness/index.js';
|
|
7
7
|
import { type ProjectedTransportRefusal, type TransportRefusalInput } from './transport-refusal-conformance/index.js';
|
|
8
|
+
import { type AdvertisedToolsListView } from './output-schema-conformance/index.js';
|
|
8
9
|
import { type ToolCallDriver } from './domain-error-conformance/index.js';
|
|
9
10
|
export interface RunConformanceConfig {
|
|
10
11
|
/**
|
|
@@ -49,6 +50,15 @@ export interface RunConformanceConfig {
|
|
|
49
50
|
* this run; omitted ⇒ reported SKIPPED, same reasoning as above.
|
|
50
51
|
*/
|
|
51
52
|
readonly refusalRegistry?: RefusalRegistryView;
|
|
53
|
+
/**
|
|
54
|
+
* The deployment's served `tools/list` document, for the `output-schema`
|
|
55
|
+
* catalog (SPEC §7.9 "Advertised output objects", ggui#1333): every tool
|
|
56
|
+
* that advertises an `outputSchema` is one row, failing with the path of
|
|
57
|
+
* every closed object; a document in which no tool advertises one passes
|
|
58
|
+
* as the single row `output-schema/none-advertised-vacuous` (ggui#1897).
|
|
59
|
+
* Omitted ⇒ the catalog is SKIPPED, named.
|
|
60
|
+
*/
|
|
61
|
+
readonly toolsList?: AdvertisedToolsListView;
|
|
52
62
|
/**
|
|
53
63
|
* The deployment's PER-APP ENDPOINT refusal projector (SPEC §7.1's
|
|
54
64
|
* endpoint-level refusal, ggui#825): given a registry refusal, return
|
|
@@ -73,7 +83,7 @@ export interface RunConformanceConfig {
|
|
|
73
83
|
* WebSocket fixture name, and so the reporter can group them without a
|
|
74
84
|
* second registry of names.
|
|
75
85
|
*/
|
|
76
|
-
export declare const PURE_FUNCTION_CATALOG_SLUGS: readonly ["refusal-envelope", "registry-completeness", "transport-refusal", "domain-error", "theme-binding", "n1-compat"];
|
|
86
|
+
export declare const PURE_FUNCTION_CATALOG_SLUGS: readonly ["refusal-envelope", "registry-completeness", "transport-refusal", "domain-error", "theme-binding", "n1-compat", "output-schema"];
|
|
77
87
|
/** One member of {@link PURE_FUNCTION_CATALOG_SLUGS}. */
|
|
78
88
|
export type PureFunctionCatalogSlug = (typeof PURE_FUNCTION_CATALOG_SLUGS)[number];
|
|
79
89
|
export interface ConformanceResult {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-conformance.d.ts","sourceRoot":"","sources":["../src/run-conformance.ts"],"names":[],"mappings":"AA8DA,OAAO,KAAK,EACV,0BAA0B,EAG3B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,KAAK,EACV,eAAe,EACf,SAAS,IAAI,aAAa,EAE3B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,KAAK,EAEV,UAAU,EAEV,oBAAoB,EACpB,oBAAoB,EACpB,QAAQ,EACR,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGL,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC5B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAGL,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC3B,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,qCAAqC,CAAC;AAM7C,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,qDAAqD;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC;IAChC,sDAAsD;IACtD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAC1B,OAAO,EAAE,yBAAyB,KAC/B,sBAAsB,GAAG,IAAI,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IAC/C;;;;;;OAMG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CACnC,OAAO,EAAE,qBAAqB,KAC3B,yBAAyB,GAAG,IAAI,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;CAC1C;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"run-conformance.d.ts","sourceRoot":"","sources":["../src/run-conformance.ts"],"names":[],"mappings":"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"}
|
package/dist/run-conformance.js
CHANGED
|
@@ -69,6 +69,7 @@ import { registryCompletenessPins, runRegistryCompletenessConformance, } from '.
|
|
|
69
69
|
import { runTransportRefusalConformance, transportRefusalCases, } from './transport-refusal-conformance/index.js';
|
|
70
70
|
import { runThemeBindingConformance } from './theme-binding-conformance/index.js';
|
|
71
71
|
import { runN1CompatConformance } from './n1-compat-conformance/index.js';
|
|
72
|
+
import { runOutputSchemaConformance, } from './output-schema-conformance/index.js';
|
|
72
73
|
import { domainErrorCases, runDomainErrorConformance, } from './domain-error-conformance/index.js';
|
|
73
74
|
/**
|
|
74
75
|
* Row-name prefixes for the catalogs the runner folds into a run beside
|
|
@@ -85,6 +86,7 @@ export const PURE_FUNCTION_CATALOG_SLUGS = [
|
|
|
85
86
|
'domain-error',
|
|
86
87
|
'theme-binding',
|
|
87
88
|
'n1-compat',
|
|
89
|
+
'output-schema',
|
|
88
90
|
];
|
|
89
91
|
// =============================================================================
|
|
90
92
|
// Runner
|
|
@@ -264,6 +266,34 @@ async function runPureFunctionCatalogs(config, reporter, buckets) {
|
|
|
264
266
|
});
|
|
265
267
|
}
|
|
266
268
|
}
|
|
269
|
+
// ── output-schema (ggui#1333) ──
|
|
270
|
+
// Graded on the served `tools/list` document the adopter supplies; every
|
|
271
|
+
// tool advertising an `outputSchema` is one row. Absent input ⇒ one named
|
|
272
|
+
// SKIP row; a supplied document in which no tool advertises one ⇒ one
|
|
273
|
+
// named PASS row under its own id (ggui#1897: the obligation was checked
|
|
274
|
+
// against every tool and holds for all zero of them — an observation, not
|
|
275
|
+
// an absence). Either way the catalog is never silently not run.
|
|
276
|
+
const toolsList = config.toolsList;
|
|
277
|
+
if (toolsList === undefined) {
|
|
278
|
+
skip('output-schema/advertised-output-objects-open', 'no `toolsList` supplied — pass the deployment’s served tools/list document to runConformance(), or `--tools-list <file.json>` on the CLI, to grade that every advertised output object is open (SPEC §7.9, ggui#1333)');
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const outputSchemas = runOutputSchemaConformance(toolsList);
|
|
282
|
+
if (outputSchemas.passed.length === 0 && outputSchemas.failed.length === 0) {
|
|
283
|
+
pass('output-schema/none-advertised-vacuous');
|
|
284
|
+
}
|
|
285
|
+
for (const name of outputSchemas.passed)
|
|
286
|
+
pass(`output-schema/${name}`);
|
|
287
|
+
for (const violation of outputSchemas.failed) {
|
|
288
|
+
fail({
|
|
289
|
+
name: `output-schema/${violation.name}`,
|
|
290
|
+
criterion: 'advertised output objects are open (SPEC §7.9 "Advertised output objects", ggui#1333)',
|
|
291
|
+
expected: violation.description,
|
|
292
|
+
received: violation.violations,
|
|
293
|
+
message: `${String(violation.violations.length)} closed object(s) under the advertised outputSchema: ${violation.violations.join(', ')}`,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
267
297
|
// ── theme-binding (ggui#987) ──
|
|
268
298
|
// The theming wave's arbiter: graded against the protocol's own functions
|
|
269
299
|
// (`appThemeSchema`, `effectiveThemeMode`, `canonicalOverlayHash`), so
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/protocol-conformance",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Conformance test kit for the
|
|
3
|
+
"version": "0.29.0",
|
|
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 / warn / skip, where an unmet SHOULD is a warning that never fails a run. MCP builders adopt this kit to prove their implementation is protocol-conformant.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"ggui",
|
|
@@ -109,13 +109,13 @@
|
|
|
109
109
|
},
|
|
110
110
|
"dependencies": {
|
|
111
111
|
"ws": "^8.20.1",
|
|
112
|
-
"@ggui-ai/protocol": "0.
|
|
112
|
+
"@ggui-ai/protocol": "0.29.0"
|
|
113
113
|
},
|
|
114
114
|
"devDependencies": {
|
|
115
115
|
"@types/node": "^22.0.0",
|
|
116
116
|
"@types/ws": "^8.5.10",
|
|
117
117
|
"typescript": "^5.0.0",
|
|
118
|
-
"vitest": "^
|
|
118
|
+
"vitest": "^4.1.11"
|
|
119
119
|
},
|
|
120
120
|
"repository": {
|
|
121
121
|
"type": "git",
|