@ggui-ai/protocol-conformance 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +89 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +193 -0
- package/dist/conformance-host.d.ts +155 -0
- package/dist/conformance-host.d.ts.map +1 -0
- package/dist/conformance-host.js +45 -0
- package/dist/fixtures/bootstrap-protocol/bootstrap-bundle-fetch-failed.json +26 -0
- package/dist/fixtures/bootstrap-protocol/bootstrap-meta-missing.json +32 -0
- package/dist/fixtures/bootstrap-protocol/bootstrap-success.json +17 -0
- package/dist/fixtures/bootstrap-protocol/index.d.ts +5 -0
- package/dist/fixtures/bootstrap-protocol/index.d.ts.map +1 -0
- package/dist/fixtures/bootstrap-protocol/index.js +24 -0
- package/dist/fixtures/canvas-mode-wire-shapes/canvas-bootstrap-mutual-exclusion.json +25 -0
- package/dist/fixtures/canvas-mode-wire-shapes/canvas-lifecycle-channel-emits-handshake-started.json +30 -0
- package/dist/fixtures/canvas-mode-wire-shapes/canvas-navigated-updates-active-stack-item.json +30 -0
- package/dist/fixtures/canvas-mode-wire-shapes/host-context-observed-persists.json +22 -0
- package/dist/fixtures/canvas-mode-wire-shapes/index.d.ts +5 -0
- package/dist/fixtures/canvas-mode-wire-shapes/index.d.ts.map +1 -0
- package/dist/fixtures/canvas-mode-wire-shapes/index.js +47 -0
- package/dist/fixtures/index.d.ts +78 -0
- package/dist/fixtures/index.d.ts.map +1 -0
- package/dist/fixtures/index.js +87 -0
- package/dist/fixtures/observability-events/index.d.ts +5 -0
- package/dist/fixtures/observability-events/index.d.ts.map +1 -0
- package/dist/fixtures/observability-events/index.js +22 -0
- package/dist/fixtures/observability-events/observability-contract-error-emitted.json +29 -0
- package/dist/fixtures/observability-events/observability-wired-tool-invoked.json +28 -0
- package/dist/fixtures/refresh-semantics/index.d.ts +5 -0
- package/dist/fixtures/refresh-semantics/index.d.ts.map +1 -0
- package/dist/fixtures/refresh-semantics/index.js +19 -0
- package/dist/fixtures/refresh-semantics/stream-refresh-success.json +40 -0
- package/dist/fixtures/reserved-channel-authority/index.d.ts +4 -0
- package/dist/fixtures/reserved-channel-authority/index.d.ts.map +1 -0
- package/dist/fixtures/reserved-channel-authority/index.js +21 -0
- package/dist/fixtures/reserved-channel-authority/props-update-roundtrip.json +34 -0
- package/dist/fixtures/reserved-channel-authority/stream-schema-violation.json +45 -0
- package/dist/fixtures/schema-version-handshake/index.d.ts +4 -0
- package/dist/fixtures/schema-version-handshake/index.d.ts.map +1 -0
- package/dist/fixtures/schema-version-handshake/index.js +20 -0
- package/dist/fixtures/schema-version-handshake/version-match.json +16 -0
- package/dist/fixtures/schema-version-handshake/version-mismatch.json +26 -0
- package/dist/fixtures/wired-action-dispatch/index.d.ts +5 -0
- package/dist/fixtures/wired-action-dispatch/index.d.ts.map +1 -0
- package/dist/fixtures/wired-action-dispatch/index.js +29 -0
- package/dist/fixtures/wired-action-dispatch/wired-action-success.json +36 -0
- package/dist/fixtures/wired-action-dispatch/wired-action-tool-not-found.json +31 -0
- package/dist/fixtures/wired-action-dispatch/wired-action-tool-threw.json +32 -0
- package/dist/fixtures/wired-action-dispatch/wired-action-tool-timeout.json +32 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/loader.d.ts +19 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +46 -0
- package/dist/match-behavior.d.ts +121 -0
- package/dist/match-behavior.d.ts.map +1 -0
- package/dist/match-behavior.js +385 -0
- package/dist/registration-conformance/cases/gate-export-not-registered.json +19 -0
- package/dist/registration-conformance/cases/gate-no-gadgets-accept.json +13 -0
- package/dist/registration-conformance/cases/gate-package-mismatch.json +19 -0
- package/dist/registration-conformance/cases/gate-priority-not-registered-outranks-mismatch.json +20 -0
- package/dist/registration-conformance/cases/gate-registered-resolves-accept.json +25 -0
- package/dist/registration-conformance/cases/gate-stdlib-hook-accept.json +27 -0
- package/dist/registration-conformance/cases/gate-typo-classifies-as-not-registered.json +27 -0
- package/dist/registration-conformance/index.d.ts +114 -0
- package/dist/registration-conformance/index.d.ts.map +1 -0
- package/dist/registration-conformance/index.js +63 -0
- package/dist/reporter.d.ts +32 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +151 -0
- package/dist/resolution-conformance/cases/resolve-bundle-host-computed.json +13 -0
- package/dist/resolution-conformance/cases/resolve-default-host.json +12 -0
- package/dist/resolution-conformance/cases/resolve-explicit-bundle-and-style-url.json +14 -0
- package/dist/resolution-conformance/cases/resolve-explicit-bundle-url.json +12 -0
- package/dist/resolution-conformance/cases/resolve-loopback-host-http-scheme.json +13 -0
- package/dist/resolution-conformance/cases/resolve-package-only-no-version.json +8 -0
- package/dist/resolution-conformance/cases/resolve-stdlib-no-urls.json +10 -0
- package/dist/resolution-conformance/index.d.ts +76 -0
- package/dist/resolution-conformance/index.d.ts.map +1 -0
- package/dist/resolution-conformance/index.js +81 -0
- package/dist/run-conformance.d.ts +58 -0
- package/dist/run-conformance.d.ts.map +1 -0
- package/dist/run-conformance.js +286 -0
- package/dist/schema-conformance/cases/wire-bad-export-name-reject.json +11 -0
- package/dist/schema-conformance/cases/wire-bad-package-name-reject.json +11 -0
- package/dist/schema-conformance/cases/wire-component-export-accept.json +10 -0
- package/dist/schema-conformance/cases/wire-empty-package-reject.json +11 -0
- package/dist/schema-conformance/cases/wire-minimal-accept.json +10 -0
- package/dist/schema-conformance/cases/wire-multi-package-accept.json +14 -0
- package/dist/schema-conformance/cases/wire-prose-accept.json +15 -0
- package/dist/schema-conformance/cases/wire-registry-metadata-reject.json +13 -0
- package/dist/schema-conformance/cases/wire-stale-libraries-reject.json +14 -0
- package/dist/schema-conformance/cases/wire-stdlib-accept.json +10 -0
- package/dist/schema-conformance/cases/wire-transport-field-reject.json +15 -0
- package/dist/schema-conformance/cases/wire-version-field-reject.json +13 -0
- package/dist/schema-conformance/index.d.ts +71 -0
- package/dist/schema-conformance/index.d.ts.map +1 -0
- package/dist/schema-conformance/index.js +103 -0
- package/dist/types.d.ts +434 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +62 -0
- package/dist/ws-transport.d.ts +42 -0
- package/dist/ws-transport.d.ts.map +1 -0
- package/dist/ws-transport.js +135 -0
- package/package.json +83 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stream-refresh-success",
|
|
3
|
+
"description": "Happy-path refresh: a wired action succeeds, the declared `streamSpec[channel].tool` refresh tool fires, and the channel's next stream-update reflects the new snapshot. Proves the refresh-after-action contract is observable on the wire (not only on the DOM).",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-refresh-success-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "tasks_create", "handler": "echo" },
|
|
8
|
+
{ "type": "register-tool", "toolName": "tasks_list", "handler": "list-snapshot" },
|
|
9
|
+
{ "type": "register-actionspec", "name": "createTask", "tool": "tasks_create" },
|
|
10
|
+
{ "type": "register-streamspec", "channel": "tasks", "tool": "tasks_list" }
|
|
11
|
+
],
|
|
12
|
+
"inputEnvelope": {
|
|
13
|
+
"type": "action",
|
|
14
|
+
"channel": 0,
|
|
15
|
+
"sessionId": "ck-refresh-success-1",
|
|
16
|
+
"action": {
|
|
17
|
+
"name": "createTask",
|
|
18
|
+
"data": { "title": "ck-refresh" }
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"expectedBehavior": {
|
|
22
|
+
"kind": "stream-update",
|
|
23
|
+
"channel": "tasks",
|
|
24
|
+
"value": {
|
|
25
|
+
"items": []
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"expectedObservability": [
|
|
29
|
+
{
|
|
30
|
+
"kind": "wired-tool-invoked",
|
|
31
|
+
"toolName": "tasks_create",
|
|
32
|
+
"actionName": "createTask"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"kind": "wired-tool-invoked",
|
|
36
|
+
"toolName": "tasks_list"
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-refresh-success-1" }]
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/reserved-channel-authority/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,qEAAqE;AACrE,eAAO,MAAM,gCAAgC,EAAE,SAAS,QAAQ,EAG/D,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `reserved-channel-authority` fixture sub-module.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the reserved-channel contract (SPEC §4.4 Reserved-channel
|
|
5
|
+
* Authority):
|
|
6
|
+
* - Declared-channel schema violations surface as
|
|
7
|
+
* `_ggui:contract-error` envelopes with `SCHEMA_VIOLATION` code.
|
|
8
|
+
* - Channel-0 `props_update` round-trips deliver new props and the
|
|
9
|
+
* iframe DOM reflects the update.
|
|
10
|
+
*
|
|
11
|
+
* Both fixtures are `ConformanceHost`-gated — `stream-schema-
|
|
12
|
+
* violation` drives via malformed-tool setup, `props-update-roundtrip`
|
|
13
|
+
* via direct envelope dispatch.
|
|
14
|
+
*/
|
|
15
|
+
import propsUpdateRoundtrip from './props-update-roundtrip.json' with { type: 'json' };
|
|
16
|
+
import streamSchemaViolation from './stream-schema-violation.json' with { type: 'json' };
|
|
17
|
+
/** All fixtures asserting reserved-channel authority (SPEC §4.4). */
|
|
18
|
+
export const reservedChannelAuthorityFixtures = [
|
|
19
|
+
propsUpdateRoundtrip,
|
|
20
|
+
streamSchemaViolation,
|
|
21
|
+
];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "props-update-roundtrip",
|
|
3
|
+
"description": "Host delivers a `props_update` envelope on channel 0 with a new props payload. The iframe's DOM reflects the new props within `timeoutMs` — evidence on a stamped data-attribute. Proves the host -> iframe props channel is live-wired, complementing the wired-action (iframe -> host) path.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-props-update-1" },
|
|
7
|
+
{
|
|
8
|
+
"type": "emit-envelope",
|
|
9
|
+
"channel": "_ggui:props",
|
|
10
|
+
"payload": {
|
|
11
|
+
"type": "props_update",
|
|
12
|
+
"sessionId": "ck-props-update-1",
|
|
13
|
+
"props": { "greeting": "initial" }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"inputEnvelope": {
|
|
18
|
+
"type": "props-update",
|
|
19
|
+
"channel": 0,
|
|
20
|
+
"sessionId": "ck-props-update-1",
|
|
21
|
+
"props": { "greeting": "updated-by-host" }
|
|
22
|
+
},
|
|
23
|
+
"expectedBehavior": {
|
|
24
|
+
"kind": "props-update",
|
|
25
|
+
"channel": "_ggui:props",
|
|
26
|
+
"props": { "greeting": "updated-by-host" },
|
|
27
|
+
"evidence": {
|
|
28
|
+
"selector": "[data-ggui-greeting]",
|
|
29
|
+
"attribute": "data-ggui-greeting",
|
|
30
|
+
"expected": "updated-by-host"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-props-update-1" }]
|
|
34
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stream-schema-violation",
|
|
3
|
+
"description": "Refresh-stream tool returns a shape that violates the declared channel schema. `assertStreamContract` rejects the payload BEFORE fanOut, emits `_ggui:contract-error` with code SCHEMA_VIOLATION + sourceAction `refresh-stream`. Channel's previous state is preserved — subscribers never see the corruption. Matches `runtime-contract.spec.ts::schema-violation-on-refresh`.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-schema-violation-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "tasks_list", "handler": "echo" },
|
|
8
|
+
{
|
|
9
|
+
"type": "register-tool",
|
|
10
|
+
"toolName": "tasks_malformed_list",
|
|
11
|
+
"handler": "malformed-stream"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"type": "register-actionspec",
|
|
15
|
+
"name": "triggerMalformedRefresh",
|
|
16
|
+
"tool": "tasks_list"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"type": "register-streamspec",
|
|
20
|
+
"channel": "tasks",
|
|
21
|
+
"tool": "tasks_malformed_list"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"inputEnvelope": {
|
|
25
|
+
"type": "action",
|
|
26
|
+
"channel": 0,
|
|
27
|
+
"sessionId": "ck-schema-violation-1",
|
|
28
|
+
"action": {
|
|
29
|
+
"name": "triggerMalformedRefresh",
|
|
30
|
+
"data": {}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"expectedBehavior": {
|
|
34
|
+
"kind": "contract-error",
|
|
35
|
+
"code": "SCHEMA_VIOLATION",
|
|
36
|
+
"toolName": "tasks_malformed_list",
|
|
37
|
+
"sourceAction": "refresh-stream",
|
|
38
|
+
"observability": {
|
|
39
|
+
"kind": "contract-error-emitted",
|
|
40
|
+
"code": "SCHEMA_VIOLATION",
|
|
41
|
+
"toolName": "tasks_malformed_list"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-schema-violation-1" }]
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/schema-version-handshake/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,yEAAyE;AACzE,eAAO,MAAM,8BAA8B,EAAE,SAAS,QAAQ,EAG7D,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `schema-version-handshake` fixture sub-module.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the optional version-negotiation handshake (SPEC §12.2.2):
|
|
5
|
+
* - `SubscribePayload.supportedVersions` + `AckPayload.serverVersion`.
|
|
6
|
+
* - `UPGRADE_REQUIRED` error frame on mismatch per server's
|
|
7
|
+
* `versionPolicy` setting.
|
|
8
|
+
*
|
|
9
|
+
* Two fixtures; `version-match` is redundant-by-design with
|
|
10
|
+
* `bootstrap-success` on today's harness but authored distinctly so
|
|
11
|
+
* a `ConformanceHost` can expose the handshake as a discrete
|
|
12
|
+
* assertion slot.
|
|
13
|
+
*/
|
|
14
|
+
import versionMatch from './version-match.json' with { type: 'json' };
|
|
15
|
+
import versionMismatch from './version-mismatch.json' with { type: 'json' };
|
|
16
|
+
/** All fixtures asserting the schema-version handshake (Protocol #3). */
|
|
17
|
+
export const schemaVersionHandshakeFixtures = [
|
|
18
|
+
versionMatch,
|
|
19
|
+
versionMismatch,
|
|
20
|
+
];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "version-match",
|
|
3
|
+
"description": "Happy-path version handshake: server advertises a schemaVersion the client supports (same as current canonical). Renderer completes the handshake without emitting `ggui:upgrade-required`. Baseline for `version-mismatch`'s negative assertion — proves the handshake path itself is observable.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [{ "type": "create-session", "sessionId": "ck-version-match-1" }],
|
|
6
|
+
"inputEnvelope": {
|
|
7
|
+
"type": "handshake",
|
|
8
|
+
"sessionId": "ck-version-match-1",
|
|
9
|
+
"clientAccepts": ["1.1"]
|
|
10
|
+
},
|
|
11
|
+
"expectedBehavior": {
|
|
12
|
+
"kind": "bootstrap-success",
|
|
13
|
+
"observabilitySequence": []
|
|
14
|
+
},
|
|
15
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-version-match-1" }]
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "version-mismatch",
|
|
3
|
+
"description": "Server advertises a protocol schemaVersion outside the client's accepted set. Renderer emits `{type:'ggui:upgrade-required', server, client}` to the parent host + a matching `ProtocolError{kind:'version'}`. Host SHOULD render an inline upgrade prompt — NOT treat this as a terminal failure.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-version-mismatch-1" },
|
|
7
|
+
{
|
|
8
|
+
"type": "server-version-override",
|
|
9
|
+
"sessionId": "ck-version-mismatch-1",
|
|
10
|
+
"advertiseVersion": "99.99-unsupported"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"inputEnvelope": {
|
|
14
|
+
"type": "render",
|
|
15
|
+
"sessionId": "ck-version-mismatch-1",
|
|
16
|
+
"resource": {
|
|
17
|
+
"uri": "ui://ggui/session"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"expectedBehavior": {
|
|
21
|
+
"kind": "version-mismatch",
|
|
22
|
+
"serverVersion": "99.99-unsupported",
|
|
23
|
+
"clientAccepts": ["1.1"]
|
|
24
|
+
},
|
|
25
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-version-mismatch-1" }]
|
|
26
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TestCase } from '../../types.js';
|
|
2
|
+
/** All fixtures asserting the wired-action-dispatch contract (Contract
|
|
3
|
+
* #3 — defined failure modes on `wiredActionRouter`). */
|
|
4
|
+
export declare const wiredActionDispatchFixtures: readonly TestCase[];
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/wired-action-dispatch/index.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;0DAC0D;AAC1D,eAAO,MAAM,2BAA2B,EAAE,SAAS,QAAQ,EAK1D,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `wired-action-dispatch` fixture sub-module.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the full `wiredActionRouter` dispatch contract — every
|
|
5
|
+
* `ContractErrorCode` failure path + the happy path:
|
|
6
|
+
* - `wired-action-success` — wired action dispatches → tool
|
|
7
|
+
* executes → observability event fires.
|
|
8
|
+
* - `wired-action-tool-not-found` — `TOOL_NOT_FOUND` error code
|
|
9
|
+
* emits on `_ggui:contract-error`.
|
|
10
|
+
* - `wired-action-tool-threw` — `TOOL_THREW` with sanitized
|
|
11
|
+
* `causedBy` in payload.
|
|
12
|
+
* - `wired-action-tool-timeout` — `TOOL_TIMEOUT` after router's
|
|
13
|
+
* configured timeout.
|
|
14
|
+
*
|
|
15
|
+
* `wired-action-success` + `wired-action-tool-threw` drive against
|
|
16
|
+
* the current harness; the other two are `ConformanceHost`-gated.
|
|
17
|
+
*/
|
|
18
|
+
import wiredActionSuccess from './wired-action-success.json' with { type: 'json' };
|
|
19
|
+
import wiredActionToolNotFound from './wired-action-tool-not-found.json' with { type: 'json' };
|
|
20
|
+
import wiredActionToolThrew from './wired-action-tool-threw.json' with { type: 'json' };
|
|
21
|
+
import wiredActionToolTimeout from './wired-action-tool-timeout.json' with { type: 'json' };
|
|
22
|
+
/** All fixtures asserting the wired-action-dispatch contract (Contract
|
|
23
|
+
* #3 — defined failure modes on `wiredActionRouter`). */
|
|
24
|
+
export const wiredActionDispatchFixtures = [
|
|
25
|
+
wiredActionSuccess,
|
|
26
|
+
wiredActionToolNotFound,
|
|
27
|
+
wiredActionToolThrew,
|
|
28
|
+
wiredActionToolTimeout,
|
|
29
|
+
];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wired-action-success",
|
|
3
|
+
"description": "Happy-path wired-action dispatch. A declared action tool fires, the refresh-stream tool follows, and the renderer emits a `wired-tool-invoked` observability event for each invocation. Baseline proof that the protocol's declare+wire+no-agent-code claim works end-to-end.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-wired-success-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "tasks_complete", "handler": "echo" },
|
|
8
|
+
{ "type": "register-tool", "toolName": "tasks_list", "handler": "echo" },
|
|
9
|
+
{ "type": "register-actionspec", "name": "toggleTask", "tool": "tasks_complete" }
|
|
10
|
+
],
|
|
11
|
+
"inputEnvelope": {
|
|
12
|
+
"type": "action",
|
|
13
|
+
"channel": 0,
|
|
14
|
+
"sessionId": "ck-wired-success-1",
|
|
15
|
+
"action": {
|
|
16
|
+
"name": "toggleTask",
|
|
17
|
+
"data": { "id": "seed-1" }
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"expectedBehavior": {
|
|
21
|
+
"kind": "observability-event",
|
|
22
|
+
"event": {
|
|
23
|
+
"kind": "wired-tool-invoked",
|
|
24
|
+
"toolName": "tasks_complete",
|
|
25
|
+
"actionName": "toggleTask"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"expectedObservability": [
|
|
29
|
+
{
|
|
30
|
+
"kind": "wired-tool-invoked",
|
|
31
|
+
"toolName": "tasks_complete",
|
|
32
|
+
"actionName": "toggleTask"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-wired-success-1" }]
|
|
36
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wired-action-tool-not-found",
|
|
3
|
+
"description": "Wired-action dispatch names an action whose declared tool is not registered on the session. The router MUST emit a `_ggui:contract-error` envelope with code TOOL_NOT_FOUND and a matching `contract-error-emitted` observability event. Session stays alive.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-tool-not-found-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "known-tool", "handler": "echo" }
|
|
8
|
+
],
|
|
9
|
+
"inputEnvelope": {
|
|
10
|
+
"type": "action",
|
|
11
|
+
"channel": 0,
|
|
12
|
+
"sessionId": "ck-tool-not-found-1",
|
|
13
|
+
"action": {
|
|
14
|
+
"name": "doesNotExist",
|
|
15
|
+
"data": {}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"expectedBehavior": {
|
|
19
|
+
"kind": "contract-error",
|
|
20
|
+
"code": "TOOL_NOT_FOUND",
|
|
21
|
+
"toolName": "doesNotExist",
|
|
22
|
+
"actionName": "doesNotExist",
|
|
23
|
+
"sourceAction": "wired-action",
|
|
24
|
+
"observability": {
|
|
25
|
+
"kind": "contract-error-emitted",
|
|
26
|
+
"code": "TOOL_NOT_FOUND",
|
|
27
|
+
"toolName": "doesNotExist"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-tool-not-found-1" }]
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wired-action-tool-threw",
|
|
3
|
+
"description": "Wired-action tool throws synchronously (or rejects). Router catches, emits `_ggui:contract-error` with code TOOL_THREW + sanitized causedBy. Session survives — the probe UI stays interactive. Matches `runtime-contract.spec.ts::tool-throws`.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-tool-threw-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "tasks_broken", "handler": "throw" },
|
|
8
|
+
{ "type": "register-actionspec", "name": "triggerBroken", "tool": "tasks_broken" }
|
|
9
|
+
],
|
|
10
|
+
"inputEnvelope": {
|
|
11
|
+
"type": "action",
|
|
12
|
+
"channel": 0,
|
|
13
|
+
"sessionId": "ck-tool-threw-1",
|
|
14
|
+
"action": {
|
|
15
|
+
"name": "triggerBroken",
|
|
16
|
+
"data": {}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"expectedBehavior": {
|
|
20
|
+
"kind": "contract-error",
|
|
21
|
+
"code": "TOOL_THREW",
|
|
22
|
+
"toolName": "tasks_broken",
|
|
23
|
+
"actionName": "triggerBroken",
|
|
24
|
+
"sourceAction": "wired-action",
|
|
25
|
+
"observability": {
|
|
26
|
+
"kind": "contract-error-emitted",
|
|
27
|
+
"code": "TOOL_THREW",
|
|
28
|
+
"toolName": "tasks_broken"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-tool-threw-1" }]
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wired-action-tool-timeout",
|
|
3
|
+
"description": "Wired-action tool exceeds the router's configured timeout. Router emits `_ggui:contract-error` with code TOOL_TIMEOUT + sourceAction `wired-action` + a matching `contract-error-emitted` observability event. Session survives; no stream update fires.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-tool-timeout-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "hanging_tool", "handler": "timeout" },
|
|
8
|
+
{ "type": "register-actionspec", "name": "triggerTimeout", "tool": "hanging_tool" }
|
|
9
|
+
],
|
|
10
|
+
"inputEnvelope": {
|
|
11
|
+
"type": "action",
|
|
12
|
+
"channel": 0,
|
|
13
|
+
"sessionId": "ck-tool-timeout-1",
|
|
14
|
+
"action": {
|
|
15
|
+
"name": "triggerTimeout",
|
|
16
|
+
"data": {}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"expectedBehavior": {
|
|
20
|
+
"kind": "contract-error",
|
|
21
|
+
"code": "TOOL_TIMEOUT",
|
|
22
|
+
"toolName": "hanging_tool",
|
|
23
|
+
"actionName": "triggerTimeout",
|
|
24
|
+
"sourceAction": "wired-action",
|
|
25
|
+
"observability": {
|
|
26
|
+
"kind": "contract-error-emitted",
|
|
27
|
+
"code": "TOOL_TIMEOUT",
|
|
28
|
+
"toolName": "hanging_tool"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-tool-timeout-1" }]
|
|
32
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ggui-ai/protocol-conformance` — conformance test kit for the
|
|
3
|
+
* ggui protocol.
|
|
4
|
+
*
|
|
5
|
+
* Packages the fixture catalog as a consumable npm artifact, plus a
|
|
6
|
+
* runner that drives each fixture against a live implementation over
|
|
7
|
+
* WebSocket and reports a scorecard-style pass / fail / skip summary.
|
|
8
|
+
*
|
|
9
|
+
* The kit IS the protocol's conformance surface — any drift between
|
|
10
|
+
* its assertions and `@ggui-ai/protocol`'s types is the canonical
|
|
11
|
+
* bug.
|
|
12
|
+
*/
|
|
13
|
+
export type { TransportConfig, WebSocketTransportConfig, UnknownTransportConfig, AuthConfig, TestCase, SetupStep, CreateSessionStep, RegisterToolStep, EmitEnvelopeStep, SeedChannelStep, UnknownSetupStep, TeardownStep, CloseSessionStep, UnregisterToolStep, UnknownTeardownStep, ExpectedBehavior, ContractErrorBehavior, StreamUpdateBehavior, ObservabilityBehavior, BootstrapFailureBehavior, BootstrapSuccessBehavior, VersionMismatchBehavior, PropsUpdateBehavior, NoOpBehavior, UnknownBehavior, ExpectedObservabilityEvent, ProtocolError, BootstrapFailureReason, ContractErrorCode, } from './types.js';
|
|
14
|
+
export type { ConformanceHost, SetupStep as HostSetupStep, CreateSessionSetup, RegisterToolSetup, RegisterActionSpecSetup, EmitEnvelopeSetup, RendererUrlOverrideSetup, UiInitializeResponseOverrideSetup, ServerVersionOverrideSetup, UnknownSetupStep as HostUnknownSetupStep, TeardownStep as HostTeardownStep, CloseSessionTeardown, UnregisterToolTeardown, UnknownTeardownStep as HostUnknownTeardownStep, } from './conformance-host.js';
|
|
15
|
+
export { allFixtures, fixturesByContract, bootstrapProtocolFixtures, canvasModeWireShapesFixtures, observabilityEventsFixtures, refreshSemanticsFixtures, reservedChannelAuthorityFixtures, schemaVersionHandshakeFixtures, wiredActionDispatchFixtures, } from './fixtures/index.js';
|
|
16
|
+
export type { ContractSlug } from './fixtures/index.js';
|
|
17
|
+
export { gadgetWireSchemaCases, runSchemaConformance, } from './schema-conformance/index.js';
|
|
18
|
+
export type { SchemaConformanceCase, SchemaConformanceMismatch, SchemaConformanceResult, } from './schema-conformance/index.js';
|
|
19
|
+
export { gadgetRegistrationCases, runRegistrationConformance, } from './registration-conformance/index.js';
|
|
20
|
+
export type { GadgetGateRejectCode, GateOutcome, RegistrationConformanceCase, RegistrationConformanceMismatch, RegistrationConformanceResult, } from './registration-conformance/index.js';
|
|
21
|
+
export { gadgetResolutionCases, runResolutionConformance, } from './resolution-conformance/index.js';
|
|
22
|
+
export type { GadgetUrlEntry, ResolvedGadgetUrls, ResolutionConformanceCase, ResolutionConformanceMismatch, ResolutionConformanceResult, } from './resolution-conformance/index.js';
|
|
23
|
+
export { loadFixture, listFixtures, loadAllFixtures } from './loader.js';
|
|
24
|
+
export { runConformance } from './run-conformance.js';
|
|
25
|
+
export type { RunConformanceConfig, ConformanceResult, ConformanceFailure, SkippedFixture, ConformanceReporter, } from './run-conformance.js';
|
|
26
|
+
export { createDefaultReporter, formatScorecard, formatSummary, formatFailures, formatSkips, } from './reporter.js';
|
|
27
|
+
export type { DefaultReporterOptions } from './reporter.js';
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,EAER,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAEhB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EAEnB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,0BAA0B,EAE1B,aAAa,EACb,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAMpB,YAAY,EACV,eAAe,EAEf,SAAS,IAAI,aAAa,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,wBAAwB,EACxB,iCAAiC,EACjC,0BAA0B,EAC1B,gBAAgB,IAAI,oBAAoB,EAExC,YAAY,IAAI,gBAAgB,EAChC,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,IAAI,uBAAuB,GAC/C,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,EAC3B,wBAAwB,EACxB,gCAAgC,EAChC,8BAA8B,EAC9B,2BAA2B,GAC5B,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;AAKvC,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;AAG3C,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,GACpB,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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ggui-ai/protocol-conformance` — conformance test kit for the
|
|
3
|
+
* ggui protocol.
|
|
4
|
+
*
|
|
5
|
+
* Packages the fixture catalog as a consumable npm artifact, plus a
|
|
6
|
+
* runner that drives each fixture against a live implementation over
|
|
7
|
+
* WebSocket and reports a scorecard-style pass / fail / skip summary.
|
|
8
|
+
*
|
|
9
|
+
* The kit IS the protocol's conformance surface — any drift between
|
|
10
|
+
* its assertions and `@ggui-ai/protocol`'s types is the canonical
|
|
11
|
+
* bug.
|
|
12
|
+
*/
|
|
13
|
+
// Fixture catalog — every authored conformance case, classified by
|
|
14
|
+
// contract. Third-party runners + the kit's own `runConformance()`
|
|
15
|
+
// consume this surface.
|
|
16
|
+
export { allFixtures, fixturesByContract, bootstrapProtocolFixtures, canvasModeWireShapesFixtures, observabilityEventsFixtures, refreshSemanticsFixtures, reservedChannelAuthorityFixtures, schemaVersionHandshakeFixtures, wiredActionDispatchFixtures, } from './fixtures/index.js';
|
|
17
|
+
// Pure-function conformance catalogs — SPEC §7.7.2's gadget
|
|
18
|
+
// obligations are deterministic validation functions, not transport-
|
|
19
|
+
// observable behaviors. Each catalog grades a caller-supplied function
|
|
20
|
+
// against authored accept/reject cases; no host, session, or wire.
|
|
21
|
+
//
|
|
22
|
+
// Schema-conformance — which `DataContract.clientCapabilities`
|
|
23
|
+
// payloads a conformant parser MUST accept / reject.
|
|
24
|
+
export { gadgetWireSchemaCases, runSchemaConformance, } from './schema-conformance/index.js';
|
|
25
|
+
// Registration-conformance — which `(contract, appGadgets)` pairs the
|
|
26
|
+
// push-time gadget registry gate MUST accept / reject, with which
|
|
27
|
+
// precise reject code.
|
|
28
|
+
export { gadgetRegistrationCases, runRegistrationConformance, } from './registration-conformance/index.js';
|
|
29
|
+
// Resolution-conformance — which bundle + style URLs the server MUST
|
|
30
|
+
// compute for a gadget descriptor's transport fields (`bundleHost`
|
|
31
|
+
// precedence, default host, loopback scheme).
|
|
32
|
+
export { gadgetResolutionCases, runResolutionConformance, } from './resolution-conformance/index.js';
|
|
33
|
+
// Runtime loader — look up a fixture by name from the inlined catalog.
|
|
34
|
+
export { loadFixture, listFixtures, loadAllFixtures } from './loader.js';
|
|
35
|
+
// Runner — drive the catalog against a live implementation.
|
|
36
|
+
export { runConformance } from './run-conformance.js';
|
|
37
|
+
// Default reporter — stdout-based bar-scorecard implementation +
|
|
38
|
+
// formatters programmatic consumers can reuse when building their
|
|
39
|
+
// own reporter (CI annotations, vitest integration, etc.).
|
|
40
|
+
export { createDefaultReporter, formatScorecard, formatSummary, formatFailures, formatSkips, } from './reporter.js';
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TestCase } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Look up one fixture by name. Throws `Error` if the name is not in
|
|
4
|
+
* the catalog, so callers don't silently drop typos.
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadFixture(name: string): TestCase;
|
|
7
|
+
/**
|
|
8
|
+
* List every fixture name in the catalog, sorted lexicographically.
|
|
9
|
+
* Deterministic output across filesystems / imports.
|
|
10
|
+
*/
|
|
11
|
+
export declare function listFixtures(): readonly string[];
|
|
12
|
+
/**
|
|
13
|
+
* Every fixture in the catalog, flat, in deterministic order.
|
|
14
|
+
* Convenience wrapper — equivalent to `import { allFixtures } from
|
|
15
|
+
* '@ggui-ai/protocol-conformance/fixtures'` but available through the
|
|
16
|
+
* package root.
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadAllFixtures(): readonly TestCase[];
|
|
19
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAM3C;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAWlD;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,SAAS,MAAM,EAAE,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,SAAS,QAAQ,EAAE,CAErD"}
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime loader for the fixture catalog.
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper over `./fixtures/index.ts`'s static-imported arrays:
|
|
5
|
+
* look up a fixture by name, list all names, get every fixture flat.
|
|
6
|
+
* The JSON data is inlined into `dist/fixtures/` at build time by tsc's
|
|
7
|
+
* `resolveJsonModule` pass — no filesystem reads, no async, no path
|
|
8
|
+
* resolution concerns.
|
|
9
|
+
*
|
|
10
|
+
* Third-party consumers parsing the raw `.json` files (Python, Go,
|
|
11
|
+
* Rust) skip this module entirely; it exists for in-process TS
|
|
12
|
+
* consumers that want the authored JSON without reimplementing name
|
|
13
|
+
* lookup.
|
|
14
|
+
*/
|
|
15
|
+
import { allFixtures } from './fixtures/index.js';
|
|
16
|
+
const FIXTURES_BY_NAME = new Map(allFixtures.map((fixture) => [fixture.name, fixture]));
|
|
17
|
+
/**
|
|
18
|
+
* Look up one fixture by name. Throws `Error` if the name is not in
|
|
19
|
+
* the catalog, so callers don't silently drop typos.
|
|
20
|
+
*/
|
|
21
|
+
export function loadFixture(name) {
|
|
22
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
23
|
+
throw new Error('protocol-conformance: loadFixture requires a non-empty name');
|
|
24
|
+
}
|
|
25
|
+
const found = FIXTURES_BY_NAME.get(name);
|
|
26
|
+
if (found === undefined) {
|
|
27
|
+
throw new Error(`protocol-conformance: fixture '${name}' not found — list available names via listFixtures()`);
|
|
28
|
+
}
|
|
29
|
+
return found;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* List every fixture name in the catalog, sorted lexicographically.
|
|
33
|
+
* Deterministic output across filesystems / imports.
|
|
34
|
+
*/
|
|
35
|
+
export function listFixtures() {
|
|
36
|
+
return allFixtures.map((fixture) => fixture.name);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Every fixture in the catalog, flat, in deterministic order.
|
|
40
|
+
* Convenience wrapper — equivalent to `import { allFixtures } from
|
|
41
|
+
* '@ggui-ai/protocol-conformance/fixtures'` but available through the
|
|
42
|
+
* package root.
|
|
43
|
+
*/
|
|
44
|
+
export function loadAllFixtures() {
|
|
45
|
+
return allFixtures;
|
|
46
|
+
}
|