@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.
Files changed (107) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +89 -0
  3. package/dist/cli.d.ts +15 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +193 -0
  6. package/dist/conformance-host.d.ts +155 -0
  7. package/dist/conformance-host.d.ts.map +1 -0
  8. package/dist/conformance-host.js +45 -0
  9. package/dist/fixtures/bootstrap-protocol/bootstrap-bundle-fetch-failed.json +26 -0
  10. package/dist/fixtures/bootstrap-protocol/bootstrap-meta-missing.json +32 -0
  11. package/dist/fixtures/bootstrap-protocol/bootstrap-success.json +17 -0
  12. package/dist/fixtures/bootstrap-protocol/index.d.ts +5 -0
  13. package/dist/fixtures/bootstrap-protocol/index.d.ts.map +1 -0
  14. package/dist/fixtures/bootstrap-protocol/index.js +24 -0
  15. package/dist/fixtures/canvas-mode-wire-shapes/canvas-bootstrap-mutual-exclusion.json +25 -0
  16. package/dist/fixtures/canvas-mode-wire-shapes/canvas-lifecycle-channel-emits-handshake-started.json +30 -0
  17. package/dist/fixtures/canvas-mode-wire-shapes/canvas-navigated-updates-active-stack-item.json +30 -0
  18. package/dist/fixtures/canvas-mode-wire-shapes/host-context-observed-persists.json +22 -0
  19. package/dist/fixtures/canvas-mode-wire-shapes/index.d.ts +5 -0
  20. package/dist/fixtures/canvas-mode-wire-shapes/index.d.ts.map +1 -0
  21. package/dist/fixtures/canvas-mode-wire-shapes/index.js +47 -0
  22. package/dist/fixtures/index.d.ts +78 -0
  23. package/dist/fixtures/index.d.ts.map +1 -0
  24. package/dist/fixtures/index.js +87 -0
  25. package/dist/fixtures/observability-events/index.d.ts +5 -0
  26. package/dist/fixtures/observability-events/index.d.ts.map +1 -0
  27. package/dist/fixtures/observability-events/index.js +22 -0
  28. package/dist/fixtures/observability-events/observability-contract-error-emitted.json +29 -0
  29. package/dist/fixtures/observability-events/observability-wired-tool-invoked.json +28 -0
  30. package/dist/fixtures/refresh-semantics/index.d.ts +5 -0
  31. package/dist/fixtures/refresh-semantics/index.d.ts.map +1 -0
  32. package/dist/fixtures/refresh-semantics/index.js +19 -0
  33. package/dist/fixtures/refresh-semantics/stream-refresh-success.json +40 -0
  34. package/dist/fixtures/reserved-channel-authority/index.d.ts +4 -0
  35. package/dist/fixtures/reserved-channel-authority/index.d.ts.map +1 -0
  36. package/dist/fixtures/reserved-channel-authority/index.js +21 -0
  37. package/dist/fixtures/reserved-channel-authority/props-update-roundtrip.json +34 -0
  38. package/dist/fixtures/reserved-channel-authority/stream-schema-violation.json +45 -0
  39. package/dist/fixtures/schema-version-handshake/index.d.ts +4 -0
  40. package/dist/fixtures/schema-version-handshake/index.d.ts.map +1 -0
  41. package/dist/fixtures/schema-version-handshake/index.js +20 -0
  42. package/dist/fixtures/schema-version-handshake/version-match.json +16 -0
  43. package/dist/fixtures/schema-version-handshake/version-mismatch.json +26 -0
  44. package/dist/fixtures/wired-action-dispatch/index.d.ts +5 -0
  45. package/dist/fixtures/wired-action-dispatch/index.d.ts.map +1 -0
  46. package/dist/fixtures/wired-action-dispatch/index.js +29 -0
  47. package/dist/fixtures/wired-action-dispatch/wired-action-success.json +36 -0
  48. package/dist/fixtures/wired-action-dispatch/wired-action-tool-not-found.json +31 -0
  49. package/dist/fixtures/wired-action-dispatch/wired-action-tool-threw.json +32 -0
  50. package/dist/fixtures/wired-action-dispatch/wired-action-tool-timeout.json +32 -0
  51. package/dist/index.d.ts +28 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +40 -0
  54. package/dist/loader.d.ts +19 -0
  55. package/dist/loader.d.ts.map +1 -0
  56. package/dist/loader.js +46 -0
  57. package/dist/match-behavior.d.ts +121 -0
  58. package/dist/match-behavior.d.ts.map +1 -0
  59. package/dist/match-behavior.js +385 -0
  60. package/dist/registration-conformance/cases/gate-export-not-registered.json +19 -0
  61. package/dist/registration-conformance/cases/gate-no-gadgets-accept.json +13 -0
  62. package/dist/registration-conformance/cases/gate-package-mismatch.json +19 -0
  63. package/dist/registration-conformance/cases/gate-priority-not-registered-outranks-mismatch.json +20 -0
  64. package/dist/registration-conformance/cases/gate-registered-resolves-accept.json +25 -0
  65. package/dist/registration-conformance/cases/gate-stdlib-hook-accept.json +27 -0
  66. package/dist/registration-conformance/cases/gate-typo-classifies-as-not-registered.json +27 -0
  67. package/dist/registration-conformance/index.d.ts +114 -0
  68. package/dist/registration-conformance/index.d.ts.map +1 -0
  69. package/dist/registration-conformance/index.js +63 -0
  70. package/dist/reporter.d.ts +32 -0
  71. package/dist/reporter.d.ts.map +1 -0
  72. package/dist/reporter.js +151 -0
  73. package/dist/resolution-conformance/cases/resolve-bundle-host-computed.json +13 -0
  74. package/dist/resolution-conformance/cases/resolve-default-host.json +12 -0
  75. package/dist/resolution-conformance/cases/resolve-explicit-bundle-and-style-url.json +14 -0
  76. package/dist/resolution-conformance/cases/resolve-explicit-bundle-url.json +12 -0
  77. package/dist/resolution-conformance/cases/resolve-loopback-host-http-scheme.json +13 -0
  78. package/dist/resolution-conformance/cases/resolve-package-only-no-version.json +8 -0
  79. package/dist/resolution-conformance/cases/resolve-stdlib-no-urls.json +10 -0
  80. package/dist/resolution-conformance/index.d.ts +76 -0
  81. package/dist/resolution-conformance/index.d.ts.map +1 -0
  82. package/dist/resolution-conformance/index.js +81 -0
  83. package/dist/run-conformance.d.ts +58 -0
  84. package/dist/run-conformance.d.ts.map +1 -0
  85. package/dist/run-conformance.js +286 -0
  86. package/dist/schema-conformance/cases/wire-bad-export-name-reject.json +11 -0
  87. package/dist/schema-conformance/cases/wire-bad-package-name-reject.json +11 -0
  88. package/dist/schema-conformance/cases/wire-component-export-accept.json +10 -0
  89. package/dist/schema-conformance/cases/wire-empty-package-reject.json +11 -0
  90. package/dist/schema-conformance/cases/wire-minimal-accept.json +10 -0
  91. package/dist/schema-conformance/cases/wire-multi-package-accept.json +14 -0
  92. package/dist/schema-conformance/cases/wire-prose-accept.json +15 -0
  93. package/dist/schema-conformance/cases/wire-registry-metadata-reject.json +13 -0
  94. package/dist/schema-conformance/cases/wire-stale-libraries-reject.json +14 -0
  95. package/dist/schema-conformance/cases/wire-stdlib-accept.json +10 -0
  96. package/dist/schema-conformance/cases/wire-transport-field-reject.json +15 -0
  97. package/dist/schema-conformance/cases/wire-version-field-reject.json +13 -0
  98. package/dist/schema-conformance/index.d.ts +71 -0
  99. package/dist/schema-conformance/index.d.ts.map +1 -0
  100. package/dist/schema-conformance/index.js +103 -0
  101. package/dist/types.d.ts +434 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/types.js +62 -0
  104. package/dist/ws-transport.d.ts +42 -0
  105. package/dist/ws-transport.d.ts.map +1 -0
  106. package/dist/ws-transport.js +135 -0
  107. 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,4 @@
1
+ import type { TestCase } from '../../types.js';
2
+ /** All fixtures asserting reserved-channel authority (SPEC §4.4). */
3
+ export declare const reservedChannelAuthorityFixtures: readonly TestCase[];
4
+ //# sourceMappingURL=index.d.ts.map
@@ -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,4 @@
1
+ import type { TestCase } from '../../types.js';
2
+ /** All fixtures asserting the schema-version handshake (Protocol #3). */
3
+ export declare const schemaVersionHandshakeFixtures: readonly TestCase[];
4
+ //# sourceMappingURL=index.d.ts.map
@@ -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
+ }
@@ -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';
@@ -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
+ }