@ggui-ai/protocol-conformance 0.16.0 → 0.17.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 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/n1-compat-conformance/cases/forward-app-theme-unknown-member.json +27 -0
- package/dist/n1-compat-conformance/cases/release-2-app-theme-v2.json +24 -0
- package/dist/n1-compat-conformance/cases/release-2-generation-profile.json +16 -0
- package/dist/n1-compat-conformance/cases/release-2-ops-generate-blueprint.json +33 -0
- package/dist/n1-compat-conformance/cases/release-2-render-meta.json +40 -0
- package/dist/n1-compat-conformance/index.d.ts +36 -0
- package/dist/n1-compat-conformance/index.d.ts.map +1 -0
- package/dist/n1-compat-conformance/index.js +140 -0
- package/dist/run-conformance.d.ts +1 -1
- package/dist/run-conformance.d.ts.map +1 -1
- package/dist/run-conformance.js +22 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ One declared grading gap on the action loop: `action-ack` proves the append half
|
|
|
51
51
|
|
|
52
52
|
The behavioral fixture catalog above asserts what an implementation _does_ over the wire. Some protocol obligations aren't transport-observable at all — they are deterministic _validation functions_: given an input, accept or reject it. SPEC §7.7.2's gadget obligations are exactly this. Modeling them as WebSocket fixtures would mean faking wire frames the protocol never emits; instead the kit ships **pure-function catalogs** — accept/reject cases graded against a caller-supplied function, with no host, render, or transport.
|
|
53
53
|
|
|
54
|
-
Each catalog ships its cases as raw JSON so a non-TypeScript implementer can grade their own implementation, and each runner takes the implementation as a callback — the kit never hard-binds a concrete one.
|
|
54
|
+
Each catalog ships its cases as raw JSON so a non-TypeScript implementer can grade their own implementation, and each runner takes the implementation as a callback — the kit never hard-binds a concrete one. Eleven catalogs ship today:
|
|
55
55
|
|
|
56
56
|
- **`@ggui-ai/protocol-conformance/schema-conformance`** — which `DataContract.clientCapabilities` payloads a conformant parser MUST accept / reject (the gadget wire shape).
|
|
57
57
|
- **`@ggui-ai/protocol-conformance/registration-conformance`** — which `(contract, appGadgets, appPublicEnv)` triples the push-time gadget gate stack MUST accept / reject, and with which precise SPEC §7.9 reject code (`gadget_not_registered` / `gadget_package_mismatch` / `gadget_public_env_missing` / `duplicate_gadget_hook`).
|
|
@@ -62,6 +62,8 @@ Each catalog ships its cases as raw JSON so a non-TypeScript implementer can gra
|
|
|
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`.
|
|
65
|
+
- **`@ggui-ai/protocol-conformance/theme-binding-conformance`** — the theme-binding total order (ggui#987): which host-announced / stamped / sidecar mode a read door MUST paint, and which overlays it MUST keep.
|
|
66
|
+
- **`@ggui-ai/protocol-conformance/n1-compat-conformance`** — N−1 wire compatibility (VERSION-POLICY §3.6, ggui#1014): BACKWARD cases are the previous release's payloads today's parsers MUST accept; the FORWARD case (ggui#1093) is a later release's payload today's READ door MUST keep, stripping and naming the unknown top-level member. Graded on every `runConformance()`.
|
|
65
67
|
|
|
66
68
|
```ts
|
|
67
69
|
import { runSchemaConformance } from "@ggui-ai/protocol-conformance/schema-conformance";
|
package/dist/index.d.ts
CHANGED
|
@@ -41,4 +41,6 @@ export { domainErrorCases, isRawToolCallResult, runDomainErrorConformance, } fro
|
|
|
41
41
|
export type { DomainErrorConformanceCase, DomainErrorConformanceResult, DomainErrorCriterion, DomainErrorMismatch, DomainErrorSkip, RawToolCallResult, RunDomainErrorConformanceOptions, ToolCallArgs, ToolCallContent, ToolCallDriver, ToolCallScenario, } from './domain-error-conformance/index.js';
|
|
42
42
|
export { APP_THEME_CASES, OVERLAY_HASH_CASES, THEME_MODE_CASES, runThemeBindingConformance, } from './theme-binding-conformance/index.js';
|
|
43
43
|
export type { AppThemeCase, OverlayHashCase, ThemeBindingResult, ThemeModeCase, } from './theme-binding-conformance/index.js';
|
|
44
|
+
export { N1_COMPAT_CASES, N1_COMPAT_DIRECTIONS, N1_COMPAT_WIRES, runN1CompatConformance } from './n1-compat-conformance/index.js';
|
|
45
|
+
export type { N1CompatCase, N1CompatDirection, N1CompatRelease, N1CompatResult, N1CompatWire } from './n1-compat-conformance/index.js';
|
|
44
46
|
//# 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":"AAAA;;;;;;;;;;;GAWG;AAKH,YAAY,EAEV,eAAe,EACf,wBAAwB,EACxB,sBAAsB,EACtB,UAAU,EAEV,QAAQ,EACR,qBAAqB,EAErB,SAAS,EACT,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,yBAAyB,EACzB,gCAAgC,EAChC,gBAAgB,EAEhB,YAAY,EAEZ,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,eAAe,EAEf,aAAa,EACb,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAMpB,YAAY,EACV,eAAe,EAEf,SAAS,IAAI,aAAa,EAC1B,sBAAsB,EACtB,wBAAwB,EACxB,0BAA0B,EAC1B,iCAAiC,EACjC,iBAAiB,EAEjB,YAAY,IAAI,gBAAgB,GACjC,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,gCAAgC,EAChC,8BAA8B,EAC9B,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AASxD,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,qBAAqB,EACrB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,qCAAqC,CAAC;AAK7C,OAAO,EACL,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,2BAA2B,EAC3B,+BAA+B,EAC/B,6BAA6B,GAC9B,MAAM,qCAAqC,CAAC;AAK7C,OAAO,EACL,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,yBAAyB,EACzB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,mCAAmC,CAAC;AAM3C,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,gCAAgC,CAAC;AAOxC,OAAO,EACL,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,yCAAyC,CAAC;AACjD,YAAY,EACV,yBAAyB,EACzB,sBAAsB,EACtB,8BAA8B,EAC9B,gCAAgC,EAChC,uBAAuB,GACxB,MAAM,yCAAyC,CAAC;AAMjD,OAAO,EACL,wBAAwB,EACxB,kCAAkC,GACnC,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACV,kBAAkB,EAClB,mBAAmB,EACnB,4BAA4B,EAC5B,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,kCAAkC,CAAC;AAO1C,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,0CAA0C,CAAC;AAClD,YAAY,EACV,yBAAyB,EACzB,+BAA+B,EAC/B,iCAAiC,EACjC,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,0CAA0C,CAAC;AAQlD,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,4BAA4B,EAC5B,kBAAkB,EAClB,2BAA2B,EAC3B,8BAA8B,EAC9B,6BAA6B,EAC7B,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,EACvB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,0BAA0B,EAC1B,gBAAgB,EAChB,uBAAuB,EACvB,iCAAiC,GAClC,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EAInB,qBAAqB,EACrB,gCAAgC,GACjC,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAG5D,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,0BAA0B,EAC1B,4BAA4B,EAC5B,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,gCAAgC,EAChC,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,qCAAqC,CAAC;AAG7C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,0BAA0B,GAC3B,MAAM,sCAAsC,CAAC;AAC9C,YAAY,EACV,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,aAAa,GACd,MAAM,sCAAsC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -77,3 +77,5 @@ export { createDefaultReporter, formatScorecard, formatSummary, formatFailures,
|
|
|
77
77
|
export { domainErrorCases, isRawToolCallResult, runDomainErrorConformance, } from './domain-error-conformance/index.js';
|
|
78
78
|
// ── theme binding (ggui#987 — the theming wave's arbiter; guuey 1.3 judges against it) ──
|
|
79
79
|
export { APP_THEME_CASES, OVERLAY_HASH_CASES, THEME_MODE_CASES, runThemeBindingConformance, } from './theme-binding-conformance/index.js';
|
|
80
|
+
// ── 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) ──
|
|
81
|
+
export { N1_COMPAT_CASES, N1_COMPAT_DIRECTIONS, N1_COMPAT_WIRES, runN1CompatConformance } from './n1-compat-conformance/index.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "forward-app-theme-unknown-member",
|
|
3
|
+
"description": "FORWARD tolerance (ggui#1093 belt, VERSION-POLICY \u00a73.6): an AppTheme exactly as ggui Release 3 writes it PLUS a top-level member this release does not name (`futureMember`, synthetic \u2014 `fonts` and `imagery` became NAMED members with the #1093 carrier, so the forward case must always carry a key no release names). A READ door on this release MUST keep the theme \u2014 overlays byte-identical \u2014 strip the member and name it; dropping the whole theme over the unknown member is the violation (guuey#1266's class). Synthetic by construction: the payload is the NEXT release's, so it carries no landed sha.",
|
|
4
|
+
"direction": "forward",
|
|
5
|
+
"release": {
|
|
6
|
+
"label": "a later ggui release (synthetic): Release 3's theme plus a synthetic `futureMember`",
|
|
7
|
+
"sha": "synthetic"
|
|
8
|
+
},
|
|
9
|
+
"wire": "app-theme-read",
|
|
10
|
+
"payload": {
|
|
11
|
+
"overlayHash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
12
|
+
"overlays": {
|
|
13
|
+
"light": {
|
|
14
|
+
"--ggui-color-primary-600": "#7c3aed"
|
|
15
|
+
},
|
|
16
|
+
"dark": {
|
|
17
|
+
"--ggui-color-primary-600": "#a78bfa"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"mode": "dark",
|
|
21
|
+
"name": "violet",
|
|
22
|
+
"futureMember": {
|
|
23
|
+
"any": "shape"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"expect": "accepted"
|
|
27
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "release-2-app-theme-v2",
|
|
3
|
+
"description": "The app-theme overlay exactly as ggui Release 2 (24aacf8e2) writes it through putAppTheme and guuey 1.5 through forwardThemeWrite \u2014 both projections, the attestation, a default mode, a label. Today's appThemeSchema MUST accept it (VERSION-POLICY \u00a73.6).",
|
|
4
|
+
"release": {
|
|
5
|
+
"label": "ggui Release 2",
|
|
6
|
+
"sha": "24aacf8e2",
|
|
7
|
+
"pairedWith": "guuey 1.5 ceb3f59e9"
|
|
8
|
+
},
|
|
9
|
+
"wire": "app-theme",
|
|
10
|
+
"payload": {
|
|
11
|
+
"overlayHash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
12
|
+
"overlays": {
|
|
13
|
+
"light": {
|
|
14
|
+
"--ggui-color-primary-600": "#7c3aed"
|
|
15
|
+
},
|
|
16
|
+
"dark": {
|
|
17
|
+
"--ggui-color-primary-600": "#a78bfa"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"mode": "dark",
|
|
21
|
+
"name": "violet"
|
|
22
|
+
},
|
|
23
|
+
"expect": "accepted"
|
|
24
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "release-2-generation-profile",
|
|
3
|
+
"description": "The app's `generation.profile` exactly as ggui Release 2 (24aacf8e2) wrote it through the app-config door \u2014 the three text members styling / density / layout (direction, effort and aesthetic came later). Today's appGenerationProfileSchema MUST accept it (VERSION-POLICY \u00a73.6).",
|
|
4
|
+
"release": {
|
|
5
|
+
"label": "ggui Release 2",
|
|
6
|
+
"sha": "24aacf8e2",
|
|
7
|
+
"pairedWith": "guuey 1.5 ceb3f59e9"
|
|
8
|
+
},
|
|
9
|
+
"wire": "generation-profile",
|
|
10
|
+
"payload": {
|
|
11
|
+
"styling": "Editorial, warm neutrals; serif display, generous whitespace.",
|
|
12
|
+
"density": "comfortable",
|
|
13
|
+
"layout": "dashboard: KPIs on top, table below"
|
|
14
|
+
},
|
|
15
|
+
"expect": "accepted"
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "release-2-ops-generate-blueprint",
|
|
3
|
+
"description": "The `ggui_ops_generate_blueprint` input exactly as ggui Release 2 (24aacf8e2) accepted it \u2014 the contract plus a `seedPrompt` and no `intent` (added later as a non-identity prompt carrier). Today's opsGenerateBlueprintInputSchema MUST accept it (VERSION-POLICY \u00a73.6).",
|
|
4
|
+
"release": {
|
|
5
|
+
"label": "ggui Release 2",
|
|
6
|
+
"sha": "24aacf8e2",
|
|
7
|
+
"pairedWith": "control-plane operators + older mint images"
|
|
8
|
+
},
|
|
9
|
+
"wire": "ops-generate-blueprint",
|
|
10
|
+
"payload": {
|
|
11
|
+
"contract": {
|
|
12
|
+
"propsSpec": {
|
|
13
|
+
"properties": {
|
|
14
|
+
"note": {
|
|
15
|
+
"schema": {
|
|
16
|
+
"description": "free-text note"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"streamSpec": {
|
|
22
|
+
"ticks": {
|
|
23
|
+
"schema": {
|
|
24
|
+
"description": "local timer ticks"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"seedPrompt": "weekly kanban board",
|
|
30
|
+
"aesthetic": "calm"
|
|
31
|
+
},
|
|
32
|
+
"expect": "accepted"
|
|
33
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "release-2-render-meta",
|
|
3
|
+
"description": "The `_meta[\"ai.ggui/render\"]` slice exactly as ggui Release 2 (24aacf8e2) emits it on a fully-populated render \u2014 auth, render state, contract pointer, the v2 theme overlay. Today's parseMcpAppAiGguiRenderMeta MUST accept it and keep the theme (VERSION-POLICY \u00a73.6).",
|
|
4
|
+
"release": {
|
|
5
|
+
"label": "ggui Release 2",
|
|
6
|
+
"sha": "24aacf8e2",
|
|
7
|
+
"pairedWith": "guuey 1.5 ceb3f59e9"
|
|
8
|
+
},
|
|
9
|
+
"wire": "render-meta",
|
|
10
|
+
"payload": {
|
|
11
|
+
"ai.ggui/render": {
|
|
12
|
+
"sessionId": "r-1",
|
|
13
|
+
"appId": "app-1",
|
|
14
|
+
"runtimeUrl": "/_ggui/iframe-runtime.js",
|
|
15
|
+
"wsUrl": "ws://x",
|
|
16
|
+
"wsToken": "t",
|
|
17
|
+
"expiresAt": "9999-12-31T23:59:59.999Z",
|
|
18
|
+
"themeId": "indigo",
|
|
19
|
+
"themeMode": "dark",
|
|
20
|
+
"propsJson": "{}",
|
|
21
|
+
"contractHash": "sha256:abc",
|
|
22
|
+
"validatorsUrl": "/contract/sha256:abc.js",
|
|
23
|
+
"kind": "loading",
|
|
24
|
+
"theme": {
|
|
25
|
+
"overlayHash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
26
|
+
"overlays": {
|
|
27
|
+
"light": {
|
|
28
|
+
"--ggui-color-primary-600": "#7c3aed"
|
|
29
|
+
},
|
|
30
|
+
"dark": {
|
|
31
|
+
"--ggui-color-primary-600": "#a78bfa"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"mode": "dark",
|
|
35
|
+
"name": "violet"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"expect": "accepted"
|
|
40
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** The protocol-owned wires the catalog can grade. */
|
|
2
|
+
export declare const N1_COMPAT_WIRES: readonly ["app-theme", "app-theme-read", "render-meta", "generation-profile", "ops-generate-blueprint"];
|
|
3
|
+
/** `backward`: the previous release's payload against today's parser. `forward`: a later release's payload against today's READ door. */
|
|
4
|
+
export declare const N1_COMPAT_DIRECTIONS: readonly ["backward", "forward"];
|
|
5
|
+
export type N1CompatDirection = (typeof N1_COMPAT_DIRECTIONS)[number];
|
|
6
|
+
export type N1CompatWire = (typeof N1_COMPAT_WIRES)[number];
|
|
7
|
+
export interface N1CompatRelease {
|
|
8
|
+
/** Human label of the release that emitted the payload (e.g. "ggui Release 2"). */
|
|
9
|
+
readonly label: string;
|
|
10
|
+
/** The release's sha — the receipt that the payload is that release's, not a guess. A FORWARD case has no landed release and carries the literal `synthetic`. */
|
|
11
|
+
readonly sha: string;
|
|
12
|
+
/** The pairing of record on the other side, when the wire crosses fleets. */
|
|
13
|
+
readonly pairedWith?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface N1CompatCase {
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly description: string;
|
|
18
|
+
readonly release: N1CompatRelease;
|
|
19
|
+
/** Absent in a case file ⇒ `backward`. */
|
|
20
|
+
readonly direction: N1CompatDirection;
|
|
21
|
+
readonly wire: N1CompatWire;
|
|
22
|
+
/** The other release's payload, verbatim (previous for `backward`, later for `forward`). */
|
|
23
|
+
readonly payload: unknown;
|
|
24
|
+
/** Always `accepted` — a rejected N−1 payload is the violation this catalog exists to catch. */
|
|
25
|
+
readonly expect: 'accepted';
|
|
26
|
+
}
|
|
27
|
+
export interface N1CompatResult {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly direction: N1CompatDirection;
|
|
30
|
+
readonly pass: boolean;
|
|
31
|
+
readonly detail: string;
|
|
32
|
+
}
|
|
33
|
+
export declare const N1_COMPAT_CASES: readonly N1CompatCase[];
|
|
34
|
+
/** Grade every N−1 case against the protocol as shipped. */
|
|
35
|
+
export declare function runN1CompatConformance(): readonly N1CompatResult[];
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/n1-compat-conformance/index.ts"],"names":[],"mappings":"AA4BA,sDAAsD;AACtD,eAAO,MAAM,eAAe,yGAA0G,CAAC;AAEvI,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,EAMhC,CAAC;AA6CpB,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,SAAS,cAAc,EAAE,CAclE"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* N−1 wire compatibility — the §3.6 drift gate (ggui#1014).
|
|
3
|
+
*
|
|
4
|
+
* Every BACKWARD case is the PREVIOUS release's payload for a protocol-owned
|
|
5
|
+
* wire, tagged with that release's sha, and passes iff today's parser accepts
|
|
6
|
+
* it. Every FORWARD case (ggui#1093 belt) is a LATER release's payload —
|
|
7
|
+
* today's shape plus a top-level member today does not name, synthetic by
|
|
8
|
+
* construction — and passes iff today's READ door keeps it, overlays intact,
|
|
9
|
+
* stripping and naming the member. A case that starts failing is a receiver
|
|
10
|
+
* that broke N−1 across a rolling release — the fix is the receiver, never
|
|
11
|
+
* the fixture; a fixture changes only when the pairing of record moves
|
|
12
|
+
* (`docs/protocol/VERSION-POLICY.md` §3.6).
|
|
13
|
+
*
|
|
14
|
+
* Pure-function catalog: no transport, no adopter input — graded on every
|
|
15
|
+
* `runConformance()` and by the kit's own unit lane.
|
|
16
|
+
*/
|
|
17
|
+
import { appGenerationProfileSchema, appThemeSchema, opsGenerateBlueprintInputSchema, parseAppThemeAtReadDoor } from '@ggui-ai/protocol';
|
|
18
|
+
import { MCP_APP_AI_GGUI_RENDER_META_KEY, parseMcpAppAiGguiRenderMeta, } from '@ggui-ai/protocol/integrations/mcp-apps';
|
|
19
|
+
import release2AppThemeV2 from './cases/release-2-app-theme-v2.json' with { type: 'json' };
|
|
20
|
+
import release2RenderMeta from './cases/release-2-render-meta.json' with { type: 'json' };
|
|
21
|
+
import release2GenerationProfile from './cases/release-2-generation-profile.json' with { type: 'json' };
|
|
22
|
+
import release2OpsGenerateBlueprint from './cases/release-2-ops-generate-blueprint.json' with { type: 'json' };
|
|
23
|
+
import forwardAppThemeUnknownMember from './cases/forward-app-theme-unknown-member.json' with { type: 'json' };
|
|
24
|
+
/** The protocol-owned wires the catalog can grade. */
|
|
25
|
+
export const N1_COMPAT_WIRES = ['app-theme', 'app-theme-read', 'render-meta', 'generation-profile', 'ops-generate-blueprint'];
|
|
26
|
+
/** `backward`: the previous release's payload against today's parser. `forward`: a later release's payload against today's READ door. */
|
|
27
|
+
export const N1_COMPAT_DIRECTIONS = ['backward', 'forward'];
|
|
28
|
+
function isN1CompatWire(v) {
|
|
29
|
+
return typeof v === 'string' && N1_COMPAT_WIRES.includes(v);
|
|
30
|
+
}
|
|
31
|
+
function isN1CompatDirection(v) {
|
|
32
|
+
return typeof v === 'string' && N1_COMPAT_DIRECTIONS.includes(v);
|
|
33
|
+
}
|
|
34
|
+
function isRecord(v) {
|
|
35
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
36
|
+
}
|
|
37
|
+
function str(raw, key, where) {
|
|
38
|
+
const v = raw[key];
|
|
39
|
+
if (typeof v !== 'string' || v.length === 0)
|
|
40
|
+
throw new Error(`${where}: \`${key}\` must be a non-empty string`);
|
|
41
|
+
return v;
|
|
42
|
+
}
|
|
43
|
+
function n1CompatCase(raw) {
|
|
44
|
+
if (!isRecord(raw))
|
|
45
|
+
throw new Error('n1-compat case: not an object');
|
|
46
|
+
const name = str(raw, 'name', 'n1-compat case');
|
|
47
|
+
const where = `n1-compat case ${name}`;
|
|
48
|
+
const release = raw['release'];
|
|
49
|
+
if (!isRecord(release))
|
|
50
|
+
throw new Error(`${where}: \`release\` must be an object`);
|
|
51
|
+
const wire = str(raw, 'wire', where);
|
|
52
|
+
if (!isN1CompatWire(wire))
|
|
53
|
+
throw new Error(`${where}: unknown wire \`${wire}\``);
|
|
54
|
+
if (raw['expect'] !== 'accepted')
|
|
55
|
+
throw new Error(`${where}: \`expect\` must be "accepted"`);
|
|
56
|
+
if (!('payload' in raw))
|
|
57
|
+
throw new Error(`${where}: \`payload\` missing`);
|
|
58
|
+
const pairedWith = release['pairedWith'];
|
|
59
|
+
const direction = raw['direction'] ?? 'backward';
|
|
60
|
+
if (!isN1CompatDirection(direction))
|
|
61
|
+
throw new Error(`${where}: unknown direction \`${String(direction)}\``);
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
description: str(raw, 'description', where),
|
|
65
|
+
direction,
|
|
66
|
+
release: {
|
|
67
|
+
label: str(release, 'label', `${where}.release`),
|
|
68
|
+
sha: str(release, 'sha', `${where}.release`),
|
|
69
|
+
...(typeof pairedWith === 'string' ? { pairedWith } : {}),
|
|
70
|
+
},
|
|
71
|
+
wire,
|
|
72
|
+
payload: raw['payload'],
|
|
73
|
+
expect: 'accepted',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export const N1_COMPAT_CASES = [
|
|
77
|
+
release2AppThemeV2,
|
|
78
|
+
release2RenderMeta,
|
|
79
|
+
release2GenerationProfile,
|
|
80
|
+
release2OpsGenerateBlueprint,
|
|
81
|
+
forwardAppThemeUnknownMember,
|
|
82
|
+
].map(n1CompatCase);
|
|
83
|
+
function gradeAppTheme(payload) {
|
|
84
|
+
const r = appThemeSchema.safeParse(payload);
|
|
85
|
+
return r.success
|
|
86
|
+
? { pass: true, detail: 'appThemeSchema: accepted' }
|
|
87
|
+
: { pass: false, detail: `appThemeSchema refused the previous release's theme: ${r.error.issues.map((i) => i.message).join('; ')}` };
|
|
88
|
+
}
|
|
89
|
+
function gradeAppThemeRead(payload) {
|
|
90
|
+
const r = parseAppThemeAtReadDoor(payload);
|
|
91
|
+
if (!r.ok)
|
|
92
|
+
return { pass: false, detail: `the read door REFUSED a later release's theme: ${r.issues.join('; ')}` };
|
|
93
|
+
if (r.stripped.length === 0)
|
|
94
|
+
return { pass: false, detail: 'the read door stripped nothing — the case must carry a member today does not name' };
|
|
95
|
+
const sent = isRecord(payload) ? payload['overlays'] : undefined;
|
|
96
|
+
if (JSON.stringify(r.theme.overlays) !== JSON.stringify(sent))
|
|
97
|
+
return { pass: false, detail: 'the read door changed the overlays while stripping' };
|
|
98
|
+
return { pass: true, detail: `parseAppThemeAtReadDoor: kept, stripped [${r.stripped.join(', ')}]` };
|
|
99
|
+
}
|
|
100
|
+
function gradeGenerationProfile(payload) {
|
|
101
|
+
const r = appGenerationProfileSchema.safeParse(payload);
|
|
102
|
+
return r.success
|
|
103
|
+
? { pass: true, detail: 'appGenerationProfileSchema: accepted' }
|
|
104
|
+
: { pass: false, detail: `appGenerationProfileSchema refused the previous release's profile: ${r.error.issues.map((i) => i.message).join('; ')}` };
|
|
105
|
+
}
|
|
106
|
+
function gradeOpsGenerateBlueprint(payload) {
|
|
107
|
+
const r = opsGenerateBlueprintInputSchema.safeParse(payload);
|
|
108
|
+
return r.success
|
|
109
|
+
? { pass: true, detail: 'opsGenerateBlueprintInputSchema: accepted' }
|
|
110
|
+
: { pass: false, detail: `opsGenerateBlueprintInputSchema refused the previous release's input: ${r.error.issues.map((i) => i.message).join('; ')}` };
|
|
111
|
+
}
|
|
112
|
+
function gradeRenderMeta(payload) {
|
|
113
|
+
const themeIssues = [];
|
|
114
|
+
const r = parseMcpAppAiGguiRenderMeta(payload, { onInvalidTheme: (issues) => themeIssues.push(...issues) });
|
|
115
|
+
if (!r.ok)
|
|
116
|
+
return { pass: false, detail: `parseMcpAppAiGguiRenderMeta refused the previous release's slice: ${r.reason}` };
|
|
117
|
+
if (r.meta === undefined)
|
|
118
|
+
return { pass: false, detail: 'parseMcpAppAiGguiRenderMeta found no `ai.ggui/render` slice in the payload' };
|
|
119
|
+
const sent = isRecord(payload) ? payload[MCP_APP_AI_GGUI_RENDER_META_KEY] : undefined;
|
|
120
|
+
const sentTheme = isRecord(sent) && sent['theme'] !== undefined;
|
|
121
|
+
if (sentTheme && (themeIssues.length > 0 || r.meta.theme === undefined)) {
|
|
122
|
+
return { pass: false, detail: `the previous release's theme was dropped at the read door: ${themeIssues.join('; ') || 'theme absent on the parsed meta'}` };
|
|
123
|
+
}
|
|
124
|
+
return { pass: true, detail: 'parseMcpAppAiGguiRenderMeta: accepted' + (sentTheme ? ', theme preserved' : '') };
|
|
125
|
+
}
|
|
126
|
+
/** Grade every N−1 case against the protocol as shipped. */
|
|
127
|
+
export function runN1CompatConformance() {
|
|
128
|
+
return N1_COMPAT_CASES.map((c) => {
|
|
129
|
+
const graded = c.wire === 'app-theme'
|
|
130
|
+
? gradeAppTheme(c.payload)
|
|
131
|
+
: c.wire === 'app-theme-read'
|
|
132
|
+
? gradeAppThemeRead(c.payload)
|
|
133
|
+
: c.wire === 'render-meta'
|
|
134
|
+
? gradeRenderMeta(c.payload)
|
|
135
|
+
: c.wire === 'generation-profile'
|
|
136
|
+
? gradeGenerationProfile(c.payload)
|
|
137
|
+
: gradeOpsGenerateBlueprint(c.payload);
|
|
138
|
+
return { name: c.name, direction: c.direction, pass: graded.pass, detail: `${c.release.label} (${c.release.sha}) → ${graded.detail}` };
|
|
139
|
+
});
|
|
140
|
+
}
|
|
@@ -73,7 +73,7 @@ export interface RunConformanceConfig {
|
|
|
73
73
|
* WebSocket fixture name, and so the reporter can group them without a
|
|
74
74
|
* second registry of names.
|
|
75
75
|
*/
|
|
76
|
-
export declare const PURE_FUNCTION_CATALOG_SLUGS: readonly ["refusal-envelope", "registry-completeness", "transport-refusal", "domain-error", "theme-binding"];
|
|
76
|
+
export declare const PURE_FUNCTION_CATALOG_SLUGS: readonly ["refusal-envelope", "registry-completeness", "transport-refusal", "domain-error", "theme-binding", "n1-compat"];
|
|
77
77
|
/** One member of {@link PURE_FUNCTION_CATALOG_SLUGS}. */
|
|
78
78
|
export type PureFunctionCatalogSlug = (typeof PURE_FUNCTION_CATALOG_SLUGS)[number];
|
|
79
79
|
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,EAEpB,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;
|
|
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
|
@@ -68,6 +68,7 @@ import { refusalEnvelopeCases, runRefusalEnvelopeConformance, } from './refusal-
|
|
|
68
68
|
import { registryCompletenessPins, runRegistryCompletenessConformance, } from './registry-completeness/index.js';
|
|
69
69
|
import { runTransportRefusalConformance, transportRefusalCases, } from './transport-refusal-conformance/index.js';
|
|
70
70
|
import { runThemeBindingConformance } from './theme-binding-conformance/index.js';
|
|
71
|
+
import { runN1CompatConformance } from './n1-compat-conformance/index.js';
|
|
71
72
|
import { domainErrorCases, runDomainErrorConformance, } from './domain-error-conformance/index.js';
|
|
72
73
|
/**
|
|
73
74
|
* Row-name prefixes for the catalogs the runner folds into a run beside
|
|
@@ -83,6 +84,7 @@ export const PURE_FUNCTION_CATALOG_SLUGS = [
|
|
|
83
84
|
'transport-refusal',
|
|
84
85
|
'domain-error',
|
|
85
86
|
'theme-binding',
|
|
87
|
+
'n1-compat',
|
|
86
88
|
];
|
|
87
89
|
// =============================================================================
|
|
88
90
|
// Runner
|
|
@@ -276,6 +278,26 @@ async function runPureFunctionCatalogs(config, reporter, buckets) {
|
|
|
276
278
|
});
|
|
277
279
|
}
|
|
278
280
|
}
|
|
281
|
+
// ── n1-compat (ggui#1014 §3.6) ──
|
|
282
|
+
// Previous-release payloads against today's protocol parsers: no adopter
|
|
283
|
+
// input, never skipped; a failing row is a receiver that broke N−1.
|
|
284
|
+
for (const graded of runN1CompatConformance()) {
|
|
285
|
+
const name = `n1-compat/${graded.name}`;
|
|
286
|
+
if (graded.pass) {
|
|
287
|
+
pass(name);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
fail({
|
|
291
|
+
name,
|
|
292
|
+
criterion: 'N−1 wire compatibility (VERSION-POLICY §3.6, ggui#1014)',
|
|
293
|
+
expected: graded.direction === 'forward'
|
|
294
|
+
? 'a later release\u2019s payload KEPT by today\u2019s read door — the unknown top-level member stripped and named'
|
|
295
|
+
: 'the previous release\u2019s payload accepted by today\u2019s parser',
|
|
296
|
+
received: graded.detail,
|
|
297
|
+
message: graded.detail,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
279
301
|
}
|
|
280
302
|
async function runOneFixture(fixture, config, _reporter) {
|
|
281
303
|
const fixtureStarted = Date.now();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/protocol-conformance",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.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
|
+
"./n1-compat-conformance": {
|
|
55
|
+
"types": "./dist/n1-compat-conformance/index.d.ts",
|
|
56
|
+
"import": "./dist/n1-compat-conformance/index.js",
|
|
57
|
+
"default": "./dist/n1-compat-conformance/index.js"
|
|
58
|
+
},
|
|
54
59
|
"./theme-binding-conformance": {
|
|
55
60
|
"types": "./dist/theme-binding-conformance/index.d.ts",
|
|
56
61
|
"import": "./dist/theme-binding-conformance/index.js",
|
|
@@ -94,7 +99,7 @@
|
|
|
94
99
|
},
|
|
95
100
|
"dependencies": {
|
|
96
101
|
"ws": "^8.20.1",
|
|
97
|
-
"@ggui-ai/protocol": "0.
|
|
102
|
+
"@ggui-ai/protocol": "0.17.0"
|
|
98
103
|
},
|
|
99
104
|
"devDependencies": {
|
|
100
105
|
"@types/node": "^22.0.0",
|