@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,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ConformanceHost` — the seam between the kit's authored fixtures
|
|
3
|
+
* and the implementation under test.
|
|
4
|
+
*
|
|
5
|
+
* Most fixtures declare `setup` / `teardown` directives (see
|
|
6
|
+
* {@link SetupStep} / {@link TeardownStep} in `./types`) that the host
|
|
7
|
+
* dispatches against its live server. v1.0 of the kit does NOT
|
|
8
|
+
* require implementations to ship a host — fixtures that need setup
|
|
9
|
+
* directives skip cleanly when `runConformance()` is called without
|
|
10
|
+
* a `host`.
|
|
11
|
+
*
|
|
12
|
+
* When a host IS provided, the runner calls `dispatchSetup()` for
|
|
13
|
+
* every step before driving the fixture's `inputEnvelope`, then
|
|
14
|
+
* `dispatchTeardown()` for every step after the assertion. Unknown
|
|
15
|
+
* `kind` values MUST throw so unimplemented directives surface as a
|
|
16
|
+
* test SKIP with a clear "host does not implement X" reason — never
|
|
17
|
+
* a silent pass.
|
|
18
|
+
*
|
|
19
|
+
* ## Extensibly-closed
|
|
20
|
+
*
|
|
21
|
+
* The concrete step vocabulary below mirrors `./types`' vocabulary
|
|
22
|
+
* but is re-exported here as a host-facing narrower form:
|
|
23
|
+
* - Every arm carries the full semantic payload (not the JSON-
|
|
24
|
+
* loader's `unknown`-fields view).
|
|
25
|
+
* - The tail `(Record<string, unknown> & { readonly kind: string & {} })`
|
|
26
|
+
* catches fixture-JSON directives the host hasn't wired — the host
|
|
27
|
+
* returns by throwing, the runner maps it to a skip.
|
|
28
|
+
*
|
|
29
|
+
* Third-party hosts MAY extend either union with additional arms by
|
|
30
|
+
* augmenting the declaration in their own module. v1.0 of the kit
|
|
31
|
+
* does not require exhaustive coverage — it requires *honest*
|
|
32
|
+
* coverage: either implement the directive OR throw, never silently
|
|
33
|
+
* succeed on an unknown kind.
|
|
34
|
+
*
|
|
35
|
+
* ## Relation to `./types`
|
|
36
|
+
*
|
|
37
|
+
* `./types` defines the JSON-authoring surface: every directive has
|
|
38
|
+
* optional-by-default fields so JSON authors don't have to think
|
|
39
|
+
* about shape. This module defines the *runtime* surface: once the
|
|
40
|
+
* loader has validated a directive, the host receives a narrowed
|
|
41
|
+
* form. The two are intentionally parallel but not identical — JSON
|
|
42
|
+
* loaders accept what the author wrote; hosts receive what the
|
|
43
|
+
* runner confirmed is shape-valid.
|
|
44
|
+
*/
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bootstrap-bundle-fetch-failed",
|
|
3
|
+
"description": "Thin shell reads a valid `_meta.ggui.bootstrap.runtimeUrl` but the `<script src>` errors (network failure / 404 / CSP reject). Shell emits `postMessage({type:'ggui:bootstrap-failed', reason:'BUNDLE_FETCH_FAILED', message})` to the parent. No WS opens.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-bundle-fetch-failed-1" },
|
|
7
|
+
{
|
|
8
|
+
"type": "renderer-url-override",
|
|
9
|
+
"sessionId": "ck-bundle-fetch-failed-1",
|
|
10
|
+
"url": "http://127.0.0.1:1/does-not-exist.js"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"inputEnvelope": {
|
|
14
|
+
"type": "render",
|
|
15
|
+
"sessionId": "ck-bundle-fetch-failed-1",
|
|
16
|
+
"resource": {
|
|
17
|
+
"uri": "ui://ggui/session"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"expectedBehavior": {
|
|
21
|
+
"kind": "bootstrap-failure",
|
|
22
|
+
"reason": "BUNDLE_FETCH_FAILED",
|
|
23
|
+
"messageContains": "Runtime bundle failed to load"
|
|
24
|
+
},
|
|
25
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-bundle-fetch-failed-1" }]
|
|
26
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bootstrap-meta-missing",
|
|
3
|
+
"description": "Host's `ui/initialize` response returns a tool-output without `_meta.ggui.bootstrap` (or missing the `runtimeUrl` field). Thin shell emits `postMessage({type:'ggui:bootstrap-failed', reason:'BOOTSTRAP_META_MISSING', message})` to the parent. No WS connection opens — live-channel envelopes are out of scope pre-handshake.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-bootstrap-meta-missing-1" },
|
|
7
|
+
{
|
|
8
|
+
"type": "ui-initialize-response-override",
|
|
9
|
+
"sessionId": "ck-bootstrap-meta-missing-1",
|
|
10
|
+
"override": {
|
|
11
|
+
"toolOutput": {
|
|
12
|
+
"_meta": {
|
|
13
|
+
"ggui": {}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"inputEnvelope": {
|
|
20
|
+
"type": "render",
|
|
21
|
+
"sessionId": "ck-bootstrap-meta-missing-1",
|
|
22
|
+
"resource": {
|
|
23
|
+
"uri": "ui://ggui/session"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"expectedBehavior": {
|
|
27
|
+
"kind": "bootstrap-failure",
|
|
28
|
+
"reason": "BOOTSTRAP_META_MISSING",
|
|
29
|
+
"messageContains": "_meta.ggui.bootstrap"
|
|
30
|
+
},
|
|
31
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-bootstrap-meta-missing-1" }]
|
|
32
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bootstrap-success",
|
|
3
|
+
"description": "Happy-path boot: host reads `_meta.ui.resourceUri`, fetches `ui://ggui/session`, the thin shell loads the renderer bundle, `ui/initialize` returns valid `_meta.ggui.bootstrap.{wsUrl, token, sessionId, appId, runtimeUrl}`, WS handshake succeeds, first stack item renders with `data-ggui-code-ready=\"true\"`. No bootstrap-failed postMessage, no contract-error, no upgrade-required.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [{ "type": "create-session", "sessionId": "ck-bootstrap-success-1" }],
|
|
6
|
+
"inputEnvelope": {
|
|
7
|
+
"type": "render",
|
|
8
|
+
"sessionId": "ck-bootstrap-success-1",
|
|
9
|
+
"resource": {
|
|
10
|
+
"uri": "ui://ggui/session"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"expectedBehavior": {
|
|
14
|
+
"kind": "bootstrap-success"
|
|
15
|
+
},
|
|
16
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-bootstrap-success-1" }]
|
|
17
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TestCase } from '../../types.js';
|
|
2
|
+
/** All fixtures asserting the bootstrap contract (Protocol #5 — named
|
|
3
|
+
* failure modes + SPEC §8 `GguiBootstrapMeta`). */
|
|
4
|
+
export declare const bootstrapProtocolFixtures: readonly TestCase[];
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/bootstrap-protocol/index.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;oDACoD;AACpD,eAAO,MAAM,yBAAyB,EAAE,SAAS,QAAQ,EAIxD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bootstrap-protocol` fixture sub-module.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the MCP Apps bootstrap contract (SPEC §8):
|
|
5
|
+
* - `ui/initialize` tool-result must stamp `_meta.ggui.bootstrap`
|
|
6
|
+
* with a well-formed envelope.
|
|
7
|
+
* - Renderer-bundle fetch must succeed (or surface a typed
|
|
8
|
+
* `BOOTSTRAP_FAILURE` protocol error).
|
|
9
|
+
* - Happy-path boot reaches `data-ggui-code-ready="true"` with no
|
|
10
|
+
* error frames.
|
|
11
|
+
*
|
|
12
|
+
* Three fixtures today; `bootstrap-success` drives against the
|
|
13
|
+
* current harness, the other two are `ConformanceHost`-gated.
|
|
14
|
+
*/
|
|
15
|
+
import bootstrapBundleFetchFailed from './bootstrap-bundle-fetch-failed.json' with { type: 'json' };
|
|
16
|
+
import bootstrapMetaMissing from './bootstrap-meta-missing.json' with { type: 'json' };
|
|
17
|
+
import bootstrapSuccess from './bootstrap-success.json' with { type: 'json' };
|
|
18
|
+
/** All fixtures asserting the bootstrap contract (Protocol #5 — named
|
|
19
|
+
* failure modes + SPEC §8 `GguiBootstrapMeta`). */
|
|
20
|
+
export const bootstrapProtocolFixtures = [
|
|
21
|
+
bootstrapBundleFetchFailed,
|
|
22
|
+
bootstrapMetaMissing,
|
|
23
|
+
bootstrapSuccess,
|
|
24
|
+
];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "canvas-bootstrap-mutual-exclusion",
|
|
3
|
+
"description": "Bootstrap with both `canvasMode: true` AND `stackItemId` is malformed — canvas iframes are session-scoped (no pinned stack item). Defensive parsers SHOULD reject; the protocol does not require them to. Reference parser (`@ggui-ai/iframe-runtime` `validateBootstrapMeta`) currently accepts the combination but the field-pair has no defined consumer semantics. This fixture pins the contract intent so future parsers can opt into strict rejection without surprise.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-canvas-bootstrap-exclusion-1" },
|
|
7
|
+
{
|
|
8
|
+
"type": "set-app-mode",
|
|
9
|
+
"appId": "ck-canvas-bootstrap-exclusion-app",
|
|
10
|
+
"defaultMcpAppsMode": "canvas"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"inputEnvelope": {
|
|
14
|
+
"type": "render",
|
|
15
|
+
"sessionId": "ck-canvas-bootstrap-exclusion-1",
|
|
16
|
+
"resource": {
|
|
17
|
+
"uri": "ui://ggui/session/ck-canvas-bootstrap-exclusion-1"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"expectedBehavior": {
|
|
21
|
+
"kind": "bootstrap-success",
|
|
22
|
+
"observabilitySequence": []
|
|
23
|
+
},
|
|
24
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-canvas-bootstrap-exclusion-1" }]
|
|
25
|
+
}
|
package/dist/fixtures/canvas-mode-wire-shapes/canvas-lifecycle-channel-emits-handshake-started.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "canvas-lifecycle-channel-emits-handshake-started",
|
|
3
|
+
"description": "When a canvas-mode session (`mcpAppsMode === 'canvas'`) enters `ggui_handshake`, the server publishes a `_ggui:lifecycle` envelope with `CanvasLifecyclePayload {kind: 'handshake_started', handshakeId, intent}` BEFORE the handshake completes. Animator pill state machine advances on receipt. Discriminator-narrowing: payload's `kind` field is the union tag; unknown `kind` values drop with a no-op on the iframe side. Fire-and-forget on the server: failure to publish degrades the animator (no pill state change) but MUST NOT abort the handshake's primary result.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-canvas-lifecycle-handshake-1" },
|
|
7
|
+
{
|
|
8
|
+
"type": "set-app-mode",
|
|
9
|
+
"appId": "ck-canvas-lifecycle-handshake-app",
|
|
10
|
+
"defaultMcpAppsMode": "canvas"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"inputEnvelope": {
|
|
14
|
+
"type": "action",
|
|
15
|
+
"channel": 0,
|
|
16
|
+
"sessionId": "ck-canvas-lifecycle-handshake-1",
|
|
17
|
+
"action": {
|
|
18
|
+
"name": "ggui_handshake",
|
|
19
|
+
"data": { "intent": "test" }
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"expectedBehavior": {
|
|
23
|
+
"kind": "stream-update",
|
|
24
|
+
"channel": "_ggui:lifecycle",
|
|
25
|
+
"value": {
|
|
26
|
+
"kind": "handshake_started"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-canvas-lifecycle-handshake-1" }]
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "canvas-navigated-updates-active-stack-item",
|
|
3
|
+
"description": "Client emits a `canvas_navigated` WS message (Client→Server) carrying `{sessionId, previousActiveItemId, activeItemId}`. Server updates `Session.activeStackItemId` to `activeItemId` (or null when the user popped to empty). Subsequent `ggui_consume` calls observe the new active pipe. Payload omits `appId` — the subscriber binding is the authoritative scope; an inbound message scoped to a wrong session is rejected with `SESSION_MISMATCH` rather than implicit reroute.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-canvas-navigated-1" },
|
|
7
|
+
{
|
|
8
|
+
"type": "seed-channel",
|
|
9
|
+
"sessionId": "ck-canvas-navigated-1",
|
|
10
|
+
"channel": "_internal:stack",
|
|
11
|
+
"value": [
|
|
12
|
+
{ "id": "item-a", "type": "component" },
|
|
13
|
+
{ "id": "item-b", "type": "component" }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"inputEnvelope": {
|
|
18
|
+
"type": "canvas_navigated",
|
|
19
|
+
"payload": {
|
|
20
|
+
"sessionId": "ck-canvas-navigated-1",
|
|
21
|
+
"previousActiveItemId": "item-b",
|
|
22
|
+
"activeItemId": "item-a"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"expectedBehavior": {
|
|
26
|
+
"kind": "no-op",
|
|
27
|
+
"reason": "canvas_navigated has no synchronous response envelope — the side effect is a Session field mutation observed via subsequent ggui_consume / handshake output."
|
|
28
|
+
},
|
|
29
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-canvas-navigated-1" }]
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "host-context-observed-persists",
|
|
3
|
+
"description": "Client iframe echoes the `McpUiHostContext` it received from `ui/initialize` via `host_context_observed` WS message (Client→Server). Server projects to `HostContextProjection` and persists on `Session.hostContext`. Persisted projection is observable via subsequent `ggui_handshake` and `ggui_consume` output. Field shape: `availableDisplayModes`, `displayMode`, `theme` — sourced verbatim from the spec-compliant host's `_meta.ui.host` projection. Stale-snapshot guard: a later `host_context_observed` overwrites earlier values.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [{ "type": "create-session", "sessionId": "ck-host-context-observed-1" }],
|
|
6
|
+
"inputEnvelope": {
|
|
7
|
+
"type": "host_context_observed",
|
|
8
|
+
"payload": {
|
|
9
|
+
"sessionId": "ck-host-context-observed-1",
|
|
10
|
+
"hostContext": {
|
|
11
|
+
"availableDisplayModes": ["inline", "pip", "fullscreen"],
|
|
12
|
+
"displayMode": "inline",
|
|
13
|
+
"theme": "light"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"expectedBehavior": {
|
|
18
|
+
"kind": "no-op",
|
|
19
|
+
"reason": "host_context_observed has no synchronous response — the side effect is `Session.hostContext` mutation observable via subsequent ggui_consume / handshake output."
|
|
20
|
+
},
|
|
21
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-host-context-observed-1" }]
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/canvas-mode-wire-shapes/index.ts"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;yBACyB;AACzB,eAAO,MAAM,4BAA4B,EAAE,SAAS,QAAQ,EAK3D,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `canvas-mode-wire-shapes` fixture sub-module.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the canvas-mode wire additions (protocol draft-2026-05-17):
|
|
5
|
+
*
|
|
6
|
+
* - `GguiBootstrapMeta.canvasMode` — discriminator + mutual-exclusion
|
|
7
|
+
* with `stackItemId`. Canvas iframes are session-scoped; no pinned
|
|
8
|
+
* item.
|
|
9
|
+
* - `_ggui:lifecycle` reserved channel + `CanvasLifecyclePayload`
|
|
10
|
+
* discriminated union (`handshake_started` / `handshake_completed` /
|
|
11
|
+
* `push_started` / `consume_polling`). Server fires fire-and-forget;
|
|
12
|
+
* iframe animator advances state machine on each kind.
|
|
13
|
+
* - `canvas_navigated` C→S WS message — user back-navigated; server
|
|
14
|
+
* updates `Session.activeStackItemId`. Payload omits `appId` —
|
|
15
|
+
* subscriber binding is authoritative scope.
|
|
16
|
+
* - `host_context_observed` C→S WS message — iframe echoes
|
|
17
|
+
* `McpUiHostContext` so server persists `HostContextProjection` on
|
|
18
|
+
* the session.
|
|
19
|
+
*
|
|
20
|
+
* All four fixtures ship with `skipReason: null`: the kit does not
|
|
21
|
+
* JSON-gate skip behavior. The runner dispatches every fixture and
|
|
22
|
+
* per-fixture skips emerge at RUNTIME from the host adapter throwing
|
|
23
|
+
* on an unimplemented setup directive (`set-app-mode`,
|
|
24
|
+
* `assert-session-field`, `assert-channel-envelope`) or from
|
|
25
|
+
* `match-behavior.ts` returning `unmatchable-on-ws`. Runner
|
|
26
|
+
* activation against the reference `ConformanceHost` is a follow-up
|
|
27
|
+
* kit minor once those directives land.
|
|
28
|
+
*
|
|
29
|
+
* Rationale: per the kit's drift discipline (see `../../types.ts`
|
|
30
|
+
* "Authored protocol vocabulary"), fixtures freeze the contract intent
|
|
31
|
+
* at the time the wire shape lands — not when the runner catches up.
|
|
32
|
+
* Third-party host implementers can read these JSONs directly to
|
|
33
|
+
* understand canvas-mode obligations without waiting for the reference
|
|
34
|
+
* host's directive coverage.
|
|
35
|
+
*/
|
|
36
|
+
import canvasBootstrapMutualExclusion from './canvas-bootstrap-mutual-exclusion.json' with { type: 'json' };
|
|
37
|
+
import canvasLifecycleChannelEmitsHandshakeStarted from './canvas-lifecycle-channel-emits-handshake-started.json' with { type: 'json' };
|
|
38
|
+
import canvasNavigatedUpdatesActiveStackItem from './canvas-navigated-updates-active-stack-item.json' with { type: 'json' };
|
|
39
|
+
import hostContextObservedPersists from './host-context-observed-persists.json' with { type: 'json' };
|
|
40
|
+
/** All fixtures asserting canvas-mode wire shapes (protocol
|
|
41
|
+
* draft-2026-05-17). */
|
|
42
|
+
export const canvasModeWireShapesFixtures = [
|
|
43
|
+
canvasBootstrapMutualExclusion,
|
|
44
|
+
canvasLifecycleChannelEmitsHandshakeStarted,
|
|
45
|
+
canvasNavigatedUpdatesActiveStackItem,
|
|
46
|
+
hostContextObservedPersists,
|
|
47
|
+
];
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixture catalog — every conformance fixture, classified by the
|
|
3
|
+
* contract or protocol criterion it exercises.
|
|
4
|
+
*
|
|
5
|
+
* The sub-module layout (one directory per contract) is load-bearing:
|
|
6
|
+
* it is how the reporter groups results on the bar-scorecard output,
|
|
7
|
+
* and how third-party implementers understand which criterion each
|
|
8
|
+
* fixture asserts. Renaming a sub-module directory breaks the
|
|
9
|
+
* reporter's output shape — treat the classification as the public
|
|
10
|
+
* API.
|
|
11
|
+
*
|
|
12
|
+
* ## Why static imports
|
|
13
|
+
*
|
|
14
|
+
* The fixture JSON files are statically imported (`import … from
|
|
15
|
+
* './foo.json' with { type: 'json' }`) so tsc inlines the fixture
|
|
16
|
+
* data into `dist/fixtures/`. Third-party TS consumers get typed
|
|
17
|
+
* arrays without a runtime file-read. Non-TS consumers (Python, Go,
|
|
18
|
+
* Rust) read the raw `.json` files directly — they ship in `dist/`
|
|
19
|
+
* via the package's `files` field.
|
|
20
|
+
*
|
|
21
|
+
* ## Current coverage
|
|
22
|
+
*
|
|
23
|
+
* Seven sub-modules with content (18 fixtures). Three additional
|
|
24
|
+
* sub-modules (`data-contract`, `tool-name-uniqueness`,
|
|
25
|
+
* `contract-error-payload`) are reserved for additive fixture
|
|
26
|
+
* expansion and not yet materialized — adding fixtures there is a
|
|
27
|
+
* kit minor version.
|
|
28
|
+
*
|
|
29
|
+
* `canvas-mode-wire-shapes` (4 fixtures) ships the canvas-mode wire
|
|
30
|
+
* contract intent: `canvasMode` bootstrap discriminator,
|
|
31
|
+
* `_ggui:lifecycle` channel + payload, `canvas_navigated` +
|
|
32
|
+
* `host_context_observed` C→S WS messages. Runner activation is a
|
|
33
|
+
* follow-up kit minor once the reference `ConformanceHost` exposes
|
|
34
|
+
* `set-app-mode` + `assert-session-field` + `assert-channel-envelope`
|
|
35
|
+
* directives.
|
|
36
|
+
*
|
|
37
|
+
* ## What is NOT here — the gadget pure-function obligations
|
|
38
|
+
*
|
|
39
|
+
* SPEC §7.7.2's gadget obligations are pure-function obligations, not
|
|
40
|
+
* transport-observable behaviors: which `clientCapabilities` payloads
|
|
41
|
+
* a parser accepts (`../schema-conformance`) and which `(contract,
|
|
42
|
+
* appGadgets)` pairs the push-time registry gate accepts / rejects
|
|
43
|
+
* (`../registration-conformance`). They are graded against a
|
|
44
|
+
* caller-supplied function — there is no session, transport, or wire
|
|
45
|
+
* frame to drive — so they do NOT belong in this behavioral fixture
|
|
46
|
+
* catalog.
|
|
47
|
+
*/
|
|
48
|
+
export { bootstrapProtocolFixtures } from './bootstrap-protocol/index.js';
|
|
49
|
+
export { canvasModeWireShapesFixtures } from './canvas-mode-wire-shapes/index.js';
|
|
50
|
+
export { observabilityEventsFixtures } from './observability-events/index.js';
|
|
51
|
+
export { refreshSemanticsFixtures } from './refresh-semantics/index.js';
|
|
52
|
+
export { reservedChannelAuthorityFixtures } from './reserved-channel-authority/index.js';
|
|
53
|
+
export { schemaVersionHandshakeFixtures } from './schema-version-handshake/index.js';
|
|
54
|
+
export { wiredActionDispatchFixtures } from './wired-action-dispatch/index.js';
|
|
55
|
+
import type { TestCase } from '../types.js';
|
|
56
|
+
/**
|
|
57
|
+
* Contract slugs — match the sub-module directory names. The
|
|
58
|
+
* reporter uses these verbatim as group headers on the scorecard.
|
|
59
|
+
* Extensibly-closed via `(string & {})` so additive sub-modules
|
|
60
|
+
* register without an API break.
|
|
61
|
+
*/
|
|
62
|
+
export type ContractSlug = 'bootstrap-protocol' | 'canvas-mode-wire-shapes' | 'observability-events' | 'refresh-semantics' | 'reserved-channel-authority' | 'schema-version-handshake' | 'wired-action-dispatch' | (string & {});
|
|
63
|
+
/**
|
|
64
|
+
* Every fixture the kit ships, grouped by the contract it exercises.
|
|
65
|
+
* Order within each group matches the sub-module's `export` order.
|
|
66
|
+
*
|
|
67
|
+
* Map shape is load-bearing — the runner iterates
|
|
68
|
+
* `Object.entries(fixturesByContract)` to produce the bar scorecard,
|
|
69
|
+
* and consumers iterate it for custom reporters.
|
|
70
|
+
*/
|
|
71
|
+
export declare const fixturesByContract: Readonly<Record<ContractSlug, readonly TestCase[]>>;
|
|
72
|
+
/**
|
|
73
|
+
* Every fixture flat, in deterministic lexicographic order by
|
|
74
|
+
* `name`. Runners that don't care about classification iterate this
|
|
75
|
+
* list directly.
|
|
76
|
+
*/
|
|
77
|
+
export declare const allFixtures: readonly TestCase[];
|
|
78
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAClF,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAE/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAS5C;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACpB,oBAAoB,GACpB,yBAAyB,GACzB,sBAAsB,GACtB,mBAAmB,GACnB,4BAA4B,GAC5B,0BAA0B,GAC1B,uBAAuB,GACvB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,QAAQ,EAAE,CAAC,CAQlF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,QAAQ,EAGwB,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixture catalog — every conformance fixture, classified by the
|
|
3
|
+
* contract or protocol criterion it exercises.
|
|
4
|
+
*
|
|
5
|
+
* The sub-module layout (one directory per contract) is load-bearing:
|
|
6
|
+
* it is how the reporter groups results on the bar-scorecard output,
|
|
7
|
+
* and how third-party implementers understand which criterion each
|
|
8
|
+
* fixture asserts. Renaming a sub-module directory breaks the
|
|
9
|
+
* reporter's output shape — treat the classification as the public
|
|
10
|
+
* API.
|
|
11
|
+
*
|
|
12
|
+
* ## Why static imports
|
|
13
|
+
*
|
|
14
|
+
* The fixture JSON files are statically imported (`import … from
|
|
15
|
+
* './foo.json' with { type: 'json' }`) so tsc inlines the fixture
|
|
16
|
+
* data into `dist/fixtures/`. Third-party TS consumers get typed
|
|
17
|
+
* arrays without a runtime file-read. Non-TS consumers (Python, Go,
|
|
18
|
+
* Rust) read the raw `.json` files directly — they ship in `dist/`
|
|
19
|
+
* via the package's `files` field.
|
|
20
|
+
*
|
|
21
|
+
* ## Current coverage
|
|
22
|
+
*
|
|
23
|
+
* Seven sub-modules with content (18 fixtures). Three additional
|
|
24
|
+
* sub-modules (`data-contract`, `tool-name-uniqueness`,
|
|
25
|
+
* `contract-error-payload`) are reserved for additive fixture
|
|
26
|
+
* expansion and not yet materialized — adding fixtures there is a
|
|
27
|
+
* kit minor version.
|
|
28
|
+
*
|
|
29
|
+
* `canvas-mode-wire-shapes` (4 fixtures) ships the canvas-mode wire
|
|
30
|
+
* contract intent: `canvasMode` bootstrap discriminator,
|
|
31
|
+
* `_ggui:lifecycle` channel + payload, `canvas_navigated` +
|
|
32
|
+
* `host_context_observed` C→S WS messages. Runner activation is a
|
|
33
|
+
* follow-up kit minor once the reference `ConformanceHost` exposes
|
|
34
|
+
* `set-app-mode` + `assert-session-field` + `assert-channel-envelope`
|
|
35
|
+
* directives.
|
|
36
|
+
*
|
|
37
|
+
* ## What is NOT here — the gadget pure-function obligations
|
|
38
|
+
*
|
|
39
|
+
* SPEC §7.7.2's gadget obligations are pure-function obligations, not
|
|
40
|
+
* transport-observable behaviors: which `clientCapabilities` payloads
|
|
41
|
+
* a parser accepts (`../schema-conformance`) and which `(contract,
|
|
42
|
+
* appGadgets)` pairs the push-time registry gate accepts / rejects
|
|
43
|
+
* (`../registration-conformance`). They are graded against a
|
|
44
|
+
* caller-supplied function — there is no session, transport, or wire
|
|
45
|
+
* frame to drive — so they do NOT belong in this behavioral fixture
|
|
46
|
+
* catalog.
|
|
47
|
+
*/
|
|
48
|
+
export { bootstrapProtocolFixtures } from './bootstrap-protocol/index.js';
|
|
49
|
+
export { canvasModeWireShapesFixtures } from './canvas-mode-wire-shapes/index.js';
|
|
50
|
+
export { observabilityEventsFixtures } from './observability-events/index.js';
|
|
51
|
+
export { refreshSemanticsFixtures } from './refresh-semantics/index.js';
|
|
52
|
+
export { reservedChannelAuthorityFixtures } from './reserved-channel-authority/index.js';
|
|
53
|
+
export { schemaVersionHandshakeFixtures } from './schema-version-handshake/index.js';
|
|
54
|
+
export { wiredActionDispatchFixtures } from './wired-action-dispatch/index.js';
|
|
55
|
+
import { bootstrapProtocolFixtures } from './bootstrap-protocol/index.js';
|
|
56
|
+
import { canvasModeWireShapesFixtures } from './canvas-mode-wire-shapes/index.js';
|
|
57
|
+
import { observabilityEventsFixtures } from './observability-events/index.js';
|
|
58
|
+
import { refreshSemanticsFixtures } from './refresh-semantics/index.js';
|
|
59
|
+
import { reservedChannelAuthorityFixtures } from './reserved-channel-authority/index.js';
|
|
60
|
+
import { schemaVersionHandshakeFixtures } from './schema-version-handshake/index.js';
|
|
61
|
+
import { wiredActionDispatchFixtures } from './wired-action-dispatch/index.js';
|
|
62
|
+
/**
|
|
63
|
+
* Every fixture the kit ships, grouped by the contract it exercises.
|
|
64
|
+
* Order within each group matches the sub-module's `export` order.
|
|
65
|
+
*
|
|
66
|
+
* Map shape is load-bearing — the runner iterates
|
|
67
|
+
* `Object.entries(fixturesByContract)` to produce the bar scorecard,
|
|
68
|
+
* and consumers iterate it for custom reporters.
|
|
69
|
+
*/
|
|
70
|
+
export const fixturesByContract = {
|
|
71
|
+
'bootstrap-protocol': bootstrapProtocolFixtures,
|
|
72
|
+
'canvas-mode-wire-shapes': canvasModeWireShapesFixtures,
|
|
73
|
+
'observability-events': observabilityEventsFixtures,
|
|
74
|
+
'refresh-semantics': refreshSemanticsFixtures,
|
|
75
|
+
'reserved-channel-authority': reservedChannelAuthorityFixtures,
|
|
76
|
+
'schema-version-handshake': schemaVersionHandshakeFixtures,
|
|
77
|
+
'wired-action-dispatch': wiredActionDispatchFixtures,
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Every fixture flat, in deterministic lexicographic order by
|
|
81
|
+
* `name`. Runners that don't care about classification iterate this
|
|
82
|
+
* list directly.
|
|
83
|
+
*/
|
|
84
|
+
export const allFixtures = Object.values(fixturesByContract)
|
|
85
|
+
.flat()
|
|
86
|
+
.slice()
|
|
87
|
+
.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/observability-events/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;kDACkD;AAClD,eAAO,MAAM,2BAA2B,EAAE,SAAS,QAAQ,EAG1D,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `observability-events` fixture sub-module.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the renderer's observability-event emission contract:
|
|
5
|
+
* every wired-action dispatch emits a `wired-tool-invoked` event;
|
|
6
|
+
* every `_ggui:contract-error` envelope emits a matching
|
|
7
|
+
* `contract-error-emitted` event.
|
|
8
|
+
*
|
|
9
|
+
* Both fixtures are `ConformanceHost`-gated — the direct
|
|
10
|
+
* postMessage-frame assertion requires a `page.exposeBinding` harness
|
|
11
|
+
* hook that the runner supplies. The effects are asserted implicitly
|
|
12
|
+
* via DOM state on the `wired-action-success` + contract-error
|
|
13
|
+
* fixtures in `wired-action-dispatch/`.
|
|
14
|
+
*/
|
|
15
|
+
import observabilityContractErrorEmitted from './observability-contract-error-emitted.json' with { type: 'json' };
|
|
16
|
+
import observabilityWiredToolInvoked from './observability-wired-tool-invoked.json' with { type: 'json' };
|
|
17
|
+
/** All fixtures asserting the observability-event contract
|
|
18
|
+
* (SPEC §"Runtime Consequence Chain" Tier 3). */
|
|
19
|
+
export const observabilityEventsFixtures = [
|
|
20
|
+
observabilityContractErrorEmitted,
|
|
21
|
+
observabilityWiredToolInvoked,
|
|
22
|
+
];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "observability-contract-error-emitted",
|
|
3
|
+
"description": "Standalone `contract-error-emitted` observability row. Every `_ggui:contract-error` envelope the server emits on the live channel MUST be mirrored as a `contract-error-emitted` observability event for host-side inspection without requiring the host to parse live-channel frames. Asserts the mirror-emission contract directly on the observability envelope.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-obs-ce-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "broken_tool", "handler": "throw" },
|
|
8
|
+
{ "type": "register-actionspec", "name": "triggerBroken", "tool": "broken_tool" }
|
|
9
|
+
],
|
|
10
|
+
"inputEnvelope": {
|
|
11
|
+
"type": "action",
|
|
12
|
+
"channel": 0,
|
|
13
|
+
"sessionId": "ck-obs-ce-1",
|
|
14
|
+
"action": {
|
|
15
|
+
"name": "triggerBroken",
|
|
16
|
+
"data": {}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"expectedBehavior": {
|
|
20
|
+
"kind": "observability-event",
|
|
21
|
+
"event": {
|
|
22
|
+
"kind": "contract-error-emitted",
|
|
23
|
+
"code": "TOOL_THREW",
|
|
24
|
+
"toolName": "broken_tool",
|
|
25
|
+
"actionName": "triggerBroken"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-obs-ce-1" }]
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "observability-wired-tool-invoked",
|
|
3
|
+
"description": "Standalone `wired-tool-invoked` observability row. Distinct from `wired-action-success`'s DOM-level assertion — asserts directly on the postMessage observability envelope shape so Phase 3.1 can assert wire-byte equality without DOM observation.",
|
|
4
|
+
"skipReason": null,
|
|
5
|
+
"setup": [
|
|
6
|
+
{ "type": "create-session", "sessionId": "ck-obs-wired-1" },
|
|
7
|
+
{ "type": "register-tool", "toolName": "tasks_complete", "handler": "echo" },
|
|
8
|
+
{ "type": "register-actionspec", "name": "toggleTask", "tool": "tasks_complete" }
|
|
9
|
+
],
|
|
10
|
+
"inputEnvelope": {
|
|
11
|
+
"type": "action",
|
|
12
|
+
"channel": 0,
|
|
13
|
+
"sessionId": "ck-obs-wired-1",
|
|
14
|
+
"action": {
|
|
15
|
+
"name": "toggleTask",
|
|
16
|
+
"data": { "id": "seed-1" }
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"expectedBehavior": {
|
|
20
|
+
"kind": "observability-event",
|
|
21
|
+
"event": {
|
|
22
|
+
"kind": "wired-tool-invoked",
|
|
23
|
+
"toolName": "tasks_complete",
|
|
24
|
+
"actionName": "toggleTask"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"teardown": [{ "type": "close-session", "sessionId": "ck-obs-wired-1" }]
|
|
28
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TestCase } from '../../types.js';
|
|
2
|
+
/** All fixtures asserting refresh semantics (SPEC §2.3 StreamSpec +
|
|
3
|
+
* §4.4 Envelope Specification refresh triggers). */
|
|
4
|
+
export declare const refreshSemanticsFixtures: readonly TestCase[];
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fixtures/refresh-semantics/index.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;qDACqD;AACrD,eAAO,MAAM,wBAAwB,EAAE,SAAS,QAAQ,EAEvD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `refresh-semantics` fixture sub-module.
|
|
3
|
+
*
|
|
4
|
+
* Exercises stream-refresh contract:
|
|
5
|
+
* - Successful action → declared `streamSpec[channel].triggers` list
|
|
6
|
+
* triggers a refresh → new stream-update observed on the channel.
|
|
7
|
+
* - Failed action → refresh does NOT fire; stream state preserved.
|
|
8
|
+
*
|
|
9
|
+
* One fixture today (`stream-refresh-success`) driving through the
|
|
10
|
+
* `todo-list` blueprint's DOM state. The direct stream-update channel
|
|
11
|
+
* assertion is `ConformanceHost`-gated pending a channel-subscription
|
|
12
|
+
* transport seam.
|
|
13
|
+
*/
|
|
14
|
+
import streamRefreshSuccess from './stream-refresh-success.json' with { type: 'json' };
|
|
15
|
+
/** All fixtures asserting refresh semantics (SPEC §2.3 StreamSpec +
|
|
16
|
+
* §4.4 Envelope Specification refresh triggers). */
|
|
17
|
+
export const refreshSemanticsFixtures = [
|
|
18
|
+
streamRefreshSuccess,
|
|
19
|
+
];
|