@immediately-run/sandbox-protocol 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/fixtures.d.ts +40 -0
- package/dist/fixtures.js +144 -0
- package/dist/sandbox.d.ts +13 -7
- package/dist/sandbox.js +4 -5
- package/dist/sdk.d.ts +6 -5
- package/dist/sdk.js +4 -4
- package/package.json +5 -1
- package/snapshots/sandbox.json +69 -18
- package/snapshots/sdk.json +33 -13
package/README.md
CHANGED
|
@@ -56,11 +56,26 @@ are already published. Add; never rename in place.
|
|
|
56
56
|
|
|
57
57
|
## Divergences
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
the
|
|
59
|
+
**There are none. R3-274e (0.2.0) resolved the last three**, and a test asserts the
|
|
60
|
+
count is zero — so a marker reappearing is a failure, not a normal state.
|
|
61
|
+
|
|
62
|
+
The mechanism stays, because the next one will be found the same way. A name whose two
|
|
63
|
+
sides disagree carries `divergent: true` plus a note explaining the disagreement; the
|
|
64
|
+
tests here fail a marker without a note, and fail a divergence marked on only one side.
|
|
65
|
+
Mark it, file the item, resolve it — do not fix it silently in one side's source, which
|
|
66
|
+
is how the three below got there.
|
|
67
|
+
|
|
68
|
+
What 0.2.0 decided, in one line each (the reasoning is in
|
|
69
|
+
`PLATFORM_LAYERING_SPEC` §6):
|
|
70
|
+
|
|
71
|
+
| name | was | resolution |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `sdk-handshake` | two producers declaring two payloads under one name | the **union**, every field optional — each producer populates what it owns |
|
|
74
|
+
| `editor-context` | the frame declared 2 of the host's 4 fields | the frame's declaration catches up; what it *caches* stays a subset |
|
|
75
|
+
| `fs-change` | neither side declared a type; one read `paths`, the other `paths`+`epoch` | both declare `{paths, epoch}`; `epoch` is kept (apps read it) |
|
|
76
|
+
|
|
77
|
+
All three are **declaration** changes. No side sends a different byte than it sent
|
|
78
|
+
before — which is what made them resolvable without a compatibility window.
|
|
64
79
|
|
|
65
80
|
## Publishing
|
|
66
81
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** The shape grammar a snapshot channel is written in (mirrors `WireShape`). */
|
|
2
|
+
interface Shape {
|
|
3
|
+
fields?: Field[];
|
|
4
|
+
union?: Shape[];
|
|
5
|
+
array?: Shape;
|
|
6
|
+
tuple?: Shape[];
|
|
7
|
+
type?: string;
|
|
8
|
+
reads?: string[];
|
|
9
|
+
}
|
|
10
|
+
interface Field {
|
|
11
|
+
name: string;
|
|
12
|
+
optional: boolean;
|
|
13
|
+
type?: string;
|
|
14
|
+
union?: Shape[];
|
|
15
|
+
array?: Shape;
|
|
16
|
+
tuple?: Shape[];
|
|
17
|
+
fields?: Field[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A sample message for every wire name R3-274e resolved.
|
|
21
|
+
*
|
|
22
|
+
* Values are deliberately DISTINGUISHABLE — no empty arrays, no all-null unions, no
|
|
23
|
+
* two fields sharing a value — so a parser that drops, reorders or conflates a field
|
|
24
|
+
* produces a visibly different result instead of an accidentally-equal one. Both legs
|
|
25
|
+
* of every nullable union are exercised across the set (`activeFile` a string,
|
|
26
|
+
* `viewedFile` null).
|
|
27
|
+
*/
|
|
28
|
+
export declare const WIRE_FIXTURES: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
29
|
+
/** The wire names `WIRE_FIXTURES` covers. */
|
|
30
|
+
export declare const FIXTURE_NAMES: readonly string[];
|
|
31
|
+
/**
|
|
32
|
+
* Validate `value` against a snapshot `Shape`, returning one message per problem
|
|
33
|
+
* (empty = conformant). Exported so BOTH consuming repos check the fixture with the
|
|
34
|
+
* same code — a per-repo validator would be one more thing that can agree by accident.
|
|
35
|
+
*
|
|
36
|
+
* Deliberately strict about EXTRA fields: a fixture carrying a key the side does not
|
|
37
|
+
* declare is exactly the drift this is here to catch.
|
|
38
|
+
*/
|
|
39
|
+
export declare function shapeProblems(shape: Shape, value: unknown, path?: string): string[];
|
|
40
|
+
export {};
|
package/dist/fixtures.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// One sample message per resolved wire name — the cross-side proof for R3-274e1.
|
|
3
|
+
//
|
|
4
|
+
// R3-274e resolved three names whose two sides had been declaring different shapes
|
|
5
|
+
// under one name (`fs-change`, `editor-context`, `sdk-handshake`; the decisions are in
|
|
6
|
+
// PLATFORM_LAYERING_SPEC §6). Each side's `protocol:check` compares that side's source
|
|
7
|
+
// against its own snapshot — which proves each side matches the CONTRACT, and proves
|
|
8
|
+
// nothing about the two sides matching EACH OTHER. Two snapshots projected from one
|
|
9
|
+
// descriptor set will agree by construction until someone edits the descriptors, and
|
|
10
|
+
// then they will disagree quietly, because nothing reads both.
|
|
11
|
+
//
|
|
12
|
+
// This module is the thing that reads both. It carries ONE sample per name, and this
|
|
13
|
+
// package's own test validates each sample against BOTH sides' declared shapes at once
|
|
14
|
+
// (`fixtures.test.ts`). The consuming repos then drive the SAME object through their
|
|
15
|
+
// real parsers. That is what makes deleting a field from a fixture below fail on both
|
|
16
|
+
// sides rather than one:
|
|
17
|
+
//
|
|
18
|
+
// epoch removed from `fs-change` → sandbox: payload.fields requires it
|
|
19
|
+
// → sdk: value.fields requires it, and
|
|
20
|
+
// payload.reads names it
|
|
21
|
+
//
|
|
22
|
+
// Put a fixture here, never in a consuming repo. A per-repo fixture re-creates exactly
|
|
23
|
+
// the "two shapes, one name" condition R3-274e closed — this time in the test data.
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.FIXTURE_NAMES = exports.WIRE_FIXTURES = void 0;
|
|
26
|
+
exports.shapeProblems = shapeProblems;
|
|
27
|
+
/**
|
|
28
|
+
* A sample message for every wire name R3-274e resolved.
|
|
29
|
+
*
|
|
30
|
+
* Values are deliberately DISTINGUISHABLE — no empty arrays, no all-null unions, no
|
|
31
|
+
* two fields sharing a value — so a parser that drops, reorders or conflates a field
|
|
32
|
+
* produces a visibly different result instead of an accidentally-equal one. Both legs
|
|
33
|
+
* of every nullable union are exercised across the set (`activeFile` a string,
|
|
34
|
+
* `viewedFile` null).
|
|
35
|
+
*/
|
|
36
|
+
exports.WIRE_FIXTURES = Object.freeze({
|
|
37
|
+
// `{paths, epoch}` — both sides declare both fields. The frame reads only `paths`
|
|
38
|
+
// (it recompiles on every batch); the SDK's consumers read `epoch` as an ordering
|
|
39
|
+
// token. Keeping `epoch` was the resolution: apps read it.
|
|
40
|
+
'fs-change': Object.freeze({
|
|
41
|
+
epoch: 7,
|
|
42
|
+
paths: Object.freeze(['/app/src/App.tsx', '/app/content/home.mdx']),
|
|
43
|
+
}),
|
|
44
|
+
// The frame's declaration caught up to the host's four fields. What each side
|
|
45
|
+
// CACHES stays a subset; what travels is all four.
|
|
46
|
+
'editor-context': Object.freeze({
|
|
47
|
+
activeFile: '/app/src/App.tsx',
|
|
48
|
+
dirtyPaths: Object.freeze(['/app/src/App.tsx']),
|
|
49
|
+
openFiles: Object.freeze(['/app/src/App.tsx', '/app/src/main.tsx']),
|
|
50
|
+
viewedFile: null,
|
|
51
|
+
}),
|
|
52
|
+
// Two legitimate producers, each populating what it owns — hence the union with
|
|
53
|
+
// every field optional. The fixture populates ALL of them on purpose: a sample
|
|
54
|
+
// that omitted a field could not detect a side that stopped declaring it.
|
|
55
|
+
'sdk-handshake': Object.freeze({
|
|
56
|
+
protocolVersion: '1',
|
|
57
|
+
sandboxProtocolVersion: '2',
|
|
58
|
+
sdkVersion: '0.44.0',
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
/** The wire names `WIRE_FIXTURES` covers. */
|
|
62
|
+
exports.FIXTURE_NAMES = Object.freeze(Object.keys(exports.WIRE_FIXTURES));
|
|
63
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
64
|
+
const primitiveMatches = (type, v) => {
|
|
65
|
+
switch (type) {
|
|
66
|
+
case 'string':
|
|
67
|
+
return typeof v === 'string';
|
|
68
|
+
case 'number':
|
|
69
|
+
return typeof v === 'number';
|
|
70
|
+
case 'boolean':
|
|
71
|
+
return typeof v === 'boolean';
|
|
72
|
+
case 'null':
|
|
73
|
+
return v === null;
|
|
74
|
+
case 'undefined':
|
|
75
|
+
return v === undefined;
|
|
76
|
+
default:
|
|
77
|
+
// A named type (`FsChange`, `EditorContext`) carries no structure here — the
|
|
78
|
+
// sibling `fields` does. Unknown type text is NOT a failure, or every named
|
|
79
|
+
// type would have to be duplicated in this file.
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Validate `value` against a snapshot `Shape`, returning one message per problem
|
|
85
|
+
* (empty = conformant). Exported so BOTH consuming repos check the fixture with the
|
|
86
|
+
* same code — a per-repo validator would be one more thing that can agree by accident.
|
|
87
|
+
*
|
|
88
|
+
* Deliberately strict about EXTRA fields: a fixture carrying a key the side does not
|
|
89
|
+
* declare is exactly the drift this is here to catch.
|
|
90
|
+
*/
|
|
91
|
+
function shapeProblems(shape, value, path = '$') {
|
|
92
|
+
const problems = [];
|
|
93
|
+
if (shape.union) {
|
|
94
|
+
const ok = shape.union.some((m) => shapeProblems(m, value, path).length === 0);
|
|
95
|
+
if (!ok)
|
|
96
|
+
problems.push(`${path}: matches no member of the declared union`);
|
|
97
|
+
return problems;
|
|
98
|
+
}
|
|
99
|
+
if (shape.array) {
|
|
100
|
+
if (!Array.isArray(value)) {
|
|
101
|
+
problems.push(`${path}: declared an array, got ${typeof value}`);
|
|
102
|
+
return problems;
|
|
103
|
+
}
|
|
104
|
+
value.forEach((el, i) => problems.push(...shapeProblems(shape.array, el, `${path}[${i}]`)));
|
|
105
|
+
return problems;
|
|
106
|
+
}
|
|
107
|
+
if (shape.tuple) {
|
|
108
|
+
if (!Array.isArray(value)) {
|
|
109
|
+
problems.push(`${path}: declared a tuple, got ${typeof value}`);
|
|
110
|
+
return problems;
|
|
111
|
+
}
|
|
112
|
+
if (value.length !== shape.tuple.length) {
|
|
113
|
+
problems.push(`${path}: tuple declares ${shape.tuple.length} slot(s), got ${value.length}`);
|
|
114
|
+
return problems;
|
|
115
|
+
}
|
|
116
|
+
shape.tuple.forEach((m, i) => problems.push(...shapeProblems(m, value[i], `${path}[${i}]`)));
|
|
117
|
+
return problems;
|
|
118
|
+
}
|
|
119
|
+
if (shape.fields) {
|
|
120
|
+
if (!isRecord(value)) {
|
|
121
|
+
problems.push(`${path}: declared an object, got ${Array.isArray(value) ? 'array' : typeof value}`);
|
|
122
|
+
return problems;
|
|
123
|
+
}
|
|
124
|
+
for (const f of shape.fields) {
|
|
125
|
+
const present = Object.prototype.hasOwnProperty.call(value, f.name);
|
|
126
|
+
if (!present) {
|
|
127
|
+
if (!f.optional)
|
|
128
|
+
problems.push(`${path}.${f.name}: required by the declaration, absent`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
problems.push(...shapeProblems(f, value[f.name], `${path}.${f.name}`));
|
|
132
|
+
}
|
|
133
|
+
const declared = new Set(shape.fields.map((f) => f.name));
|
|
134
|
+
for (const k of Object.keys(value)) {
|
|
135
|
+
if (!declared.has(k))
|
|
136
|
+
problems.push(`${path}.${k}: present but not declared`);
|
|
137
|
+
}
|
|
138
|
+
return problems;
|
|
139
|
+
}
|
|
140
|
+
if (shape.type && !primitiveMatches(shape.type, value)) {
|
|
141
|
+
problems.push(`${path}: declared \`${shape.type}\`, got ${value === null ? 'null' : typeof value}`);
|
|
142
|
+
}
|
|
143
|
+
return problems;
|
|
144
|
+
}
|
package/dist/sandbox.d.ts
CHANGED
|
@@ -41,11 +41,13 @@ export declare const DONE = "done";
|
|
|
41
41
|
export interface DonePayload {
|
|
42
42
|
compilatonError: boolean;
|
|
43
43
|
}
|
|
44
|
-
/** `editor-context` — push · host->app. polled with `request-editor-context`.
|
|
44
|
+
/** `editor-context` — push · host->app. polled with `request-editor-context`. */
|
|
45
45
|
export declare const EDITOR_CONTEXT = "editor-context";
|
|
46
46
|
export interface EditorContextPayload {
|
|
47
|
-
activeFile
|
|
47
|
+
activeFile: null | string;
|
|
48
48
|
dirtyPaths: Array<string>;
|
|
49
|
+
openFiles: Array<string>;
|
|
50
|
+
viewedFile: null | string;
|
|
49
51
|
}
|
|
50
52
|
/** `evaluate` — message · host->app. */
|
|
51
53
|
export declare const EVALUATE = "evaluate";
|
|
@@ -53,9 +55,12 @@ export declare const EVALUATE = "evaluate";
|
|
|
53
55
|
/** `form-factor` — push · host->app. polled with `request-form-factor`. */
|
|
54
56
|
export declare const FORM_FACTOR = "form-factor";
|
|
55
57
|
/** Read off this message today: `formFactor`. */
|
|
56
|
-
/** `fs-change` — message · host->app.
|
|
58
|
+
/** `fs-change` — message · host->app. */
|
|
57
59
|
export declare const FS_CHANGE = "fs-change";
|
|
58
|
-
|
|
60
|
+
export interface FsChangePayload {
|
|
61
|
+
epoch: number;
|
|
62
|
+
paths: Array<string>;
|
|
63
|
+
}
|
|
59
64
|
/** `initialized` — message · app->host. */
|
|
60
65
|
export declare const INITIALIZED = "initialized";
|
|
61
66
|
/** `ir-marker` — message · app->host. */
|
|
@@ -102,11 +107,12 @@ export declare const RESIZE = "resize";
|
|
|
102
107
|
export interface ResizePayload {
|
|
103
108
|
height: number;
|
|
104
109
|
}
|
|
105
|
-
/** `sdk-handshake` — message · app->host.
|
|
110
|
+
/** `sdk-handshake` — message · app->host. */
|
|
106
111
|
export declare const SDK_HANDSHAKE = "sdk-handshake";
|
|
107
112
|
export interface SdkHandshakePayload {
|
|
108
|
-
protocolVersion
|
|
109
|
-
sandboxProtocolVersion
|
|
113
|
+
protocolVersion?: string | undefined;
|
|
114
|
+
sandboxProtocolVersion?: string | undefined;
|
|
115
|
+
sdkVersion?: string | undefined;
|
|
110
116
|
}
|
|
111
117
|
/** `start` — message · app->host. */
|
|
112
118
|
export declare const START = "start";
|
package/dist/sandbox.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// GENERATED by scripts/generate.mjs — DO NOT EDIT.
|
|
3
3
|
// Source of truth: src/descriptors.protocol.mjs (@immediately-run/sandbox-protocol)
|
|
4
|
-
// descriptorsHash:
|
|
4
|
+
// descriptorsHash: 235f4011d391bd63
|
|
5
5
|
//
|
|
6
6
|
// The sandbox↔SDK wire vocabulary (PLATFORM_LAYERING_SPEC §2 / S1). Import the
|
|
7
7
|
// constants instead of writing the string: a rename then has ONE edit site and
|
|
@@ -23,7 +23,7 @@ exports.AUTH_STATE = 'auth-state';
|
|
|
23
23
|
exports.CONSOLE = 'console';
|
|
24
24
|
/** `done` — message · app->host. */
|
|
25
25
|
exports.DONE = 'done';
|
|
26
|
-
/** `editor-context` — push · host->app. polled with `request-editor-context`.
|
|
26
|
+
/** `editor-context` — push · host->app. polled with `request-editor-context`. */
|
|
27
27
|
exports.EDITOR_CONTEXT = 'editor-context';
|
|
28
28
|
/** `evaluate` — message · host->app. */
|
|
29
29
|
exports.EVALUATE = 'evaluate';
|
|
@@ -31,9 +31,8 @@ exports.EVALUATE = 'evaluate';
|
|
|
31
31
|
/** `form-factor` — push · host->app. polled with `request-form-factor`. */
|
|
32
32
|
exports.FORM_FACTOR = 'form-factor';
|
|
33
33
|
/** Read off this message today: `formFactor`. */
|
|
34
|
-
/** `fs-change` — message · host->app.
|
|
34
|
+
/** `fs-change` — message · host->app. */
|
|
35
35
|
exports.FS_CHANGE = 'fs-change';
|
|
36
|
-
/** Read off this message today: `paths`. */
|
|
37
36
|
/** `initialized` — message · app->host. */
|
|
38
37
|
exports.INITIALIZED = 'initialized';
|
|
39
38
|
/** `ir-marker` — message · app->host. */
|
|
@@ -72,7 +71,7 @@ exports.REQUEST_THEME = 'request-theme';
|
|
|
72
71
|
exports.REQUEST_VCS_STATE = 'request-vcs-state';
|
|
73
72
|
/** `resize` — message · app->host. */
|
|
74
73
|
exports.RESIZE = 'resize';
|
|
75
|
-
/** `sdk-handshake` — message · app->host.
|
|
74
|
+
/** `sdk-handshake` — message · app->host. */
|
|
76
75
|
exports.SDK_HANDSHAKE = 'sdk-handshake';
|
|
77
76
|
/** `start` — message · app->host. */
|
|
78
77
|
exports.START = 'start';
|
package/dist/sdk.d.ts
CHANGED
|
@@ -54,13 +54,13 @@ export interface DroppedItemPayload {
|
|
|
54
54
|
y: number;
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
/** `editor-context` — push · host->app. polled with `request-editor-context`.
|
|
57
|
+
/** `editor-context` — push · host->app. polled with `request-editor-context`. */
|
|
58
58
|
export declare const EDITOR_CONTEXT = "editor-context";
|
|
59
59
|
/** Read off this message today: `activeFile`, `dirtyPaths`, `openFiles`, `viewedFile`. */
|
|
60
60
|
/** `form-factor` — push · host->app. polled with `request-form-factor`. */
|
|
61
61
|
export declare const FORM_FACTOR = "form-factor";
|
|
62
62
|
/** Read off this message today: `formFactor`. */
|
|
63
|
-
/** `fs-change` — push · host->app.
|
|
63
|
+
/** `fs-change` — push · host->app. */
|
|
64
64
|
export declare const FS_CHANGE = "fs-change";
|
|
65
65
|
/** Read off this message today: `epoch`, `paths`. */
|
|
66
66
|
/** `invitations` — push · host->app. polled with `request-invitations`. */
|
|
@@ -283,11 +283,12 @@ export declare const REQUEST_SESSION_MOUNTS = "request-session-mounts";
|
|
|
283
283
|
export declare const REQUEST_THEME = "request-theme";
|
|
284
284
|
/** `request-vcs-state` — poll · app->host. */
|
|
285
285
|
export declare const REQUEST_VCS_STATE = "request-vcs-state";
|
|
286
|
-
/** `sdk-handshake` — message · app->host.
|
|
286
|
+
/** `sdk-handshake` — message · app->host. */
|
|
287
287
|
export declare const SDK_HANDSHAKE = "sdk-handshake";
|
|
288
288
|
export interface SdkHandshakePayload {
|
|
289
|
-
protocolVersion
|
|
290
|
-
|
|
289
|
+
protocolVersion?: string | undefined;
|
|
290
|
+
sandboxProtocolVersion?: string | undefined;
|
|
291
|
+
sdkVersion?: string | undefined;
|
|
291
292
|
}
|
|
292
293
|
/** `secrets-metadata` — push · host->app. polled with `request-secrets-metadata`. */
|
|
293
294
|
export declare const SECRETS_METADATA = "secrets-metadata";
|
package/dist/sdk.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// GENERATED by scripts/generate.mjs — DO NOT EDIT.
|
|
3
3
|
// Source of truth: src/descriptors.protocol.mjs (@immediately-run/sandbox-protocol)
|
|
4
|
-
// descriptorsHash:
|
|
4
|
+
// descriptorsHash: 235f4011d391bd63
|
|
5
5
|
//
|
|
6
6
|
// The sandbox↔SDK wire vocabulary (PLATFORM_LAYERING_SPEC §2 / S1). Import the
|
|
7
7
|
// constants instead of writing the string: a rename then has ONE edit site and
|
|
@@ -35,13 +35,13 @@ exports.DIAGNOSTICS = 'diagnostics';
|
|
|
35
35
|
exports.DND_CANCEL = 'dnd-cancel';
|
|
36
36
|
/** `dropped-item` — message · host->app. */
|
|
37
37
|
exports.DROPPED_ITEM = 'dropped-item';
|
|
38
|
-
/** `editor-context` — push · host->app. polled with `request-editor-context`.
|
|
38
|
+
/** `editor-context` — push · host->app. polled with `request-editor-context`. */
|
|
39
39
|
exports.EDITOR_CONTEXT = 'editor-context';
|
|
40
40
|
/** Read off this message today: `activeFile`, `dirtyPaths`, `openFiles`, `viewedFile`. */
|
|
41
41
|
/** `form-factor` — push · host->app. polled with `request-form-factor`. */
|
|
42
42
|
exports.FORM_FACTOR = 'form-factor';
|
|
43
43
|
/** Read off this message today: `formFactor`. */
|
|
44
|
-
/** `fs-change` — push · host->app.
|
|
44
|
+
/** `fs-change` — push · host->app. */
|
|
45
45
|
exports.FS_CHANGE = 'fs-change';
|
|
46
46
|
/** Read off this message today: `epoch`, `paths`. */
|
|
47
47
|
/** `invitations` — push · host->app. polled with `request-invitations`. */
|
|
@@ -118,7 +118,7 @@ exports.REQUEST_SESSION_MOUNTS = 'request-session-mounts';
|
|
|
118
118
|
exports.REQUEST_THEME = 'request-theme';
|
|
119
119
|
/** `request-vcs-state` — poll · app->host. */
|
|
120
120
|
exports.REQUEST_VCS_STATE = 'request-vcs-state';
|
|
121
|
-
/** `sdk-handshake` — message · app->host.
|
|
121
|
+
/** `sdk-handshake` — message · app->host. */
|
|
122
122
|
exports.SDK_HANDSHAKE = 'sdk-handshake';
|
|
123
123
|
/** `secrets-metadata` — push · host->app. polled with `request-secrets-metadata`. */
|
|
124
124
|
exports.SECRETS_METADATA = 'secrets-metadata';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@immediately-run/sandbox-protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The sandbox<->SDK wire protocol: ONE descriptor set, projected into the wire-name constants, the payload types, and the per-side snapshots both repos gate against (PLATFORM_LAYERING_SPEC S1). Consumed by sandbox and immediately-run-sdk so a wire change is a version bump, not a hand-copied file.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"types": "./dist/sdk.d.ts",
|
|
24
24
|
"default": "./dist/sdk.js"
|
|
25
25
|
},
|
|
26
|
+
"./fixtures": {
|
|
27
|
+
"types": "./dist/fixtures.d.ts",
|
|
28
|
+
"default": "./dist/fixtures.js"
|
|
29
|
+
},
|
|
26
30
|
"./snapshots/sandbox": "./snapshots/sandbox.json",
|
|
27
31
|
"./snapshots/sdk": "./snapshots/sdk.json",
|
|
28
32
|
"./package.json": "./package.json"
|
package/snapshots/sandbox.json
CHANGED
|
@@ -190,16 +190,13 @@
|
|
|
190
190
|
"fields": [
|
|
191
191
|
{
|
|
192
192
|
"name": "activeFile",
|
|
193
|
-
"optional":
|
|
193
|
+
"optional": false,
|
|
194
194
|
"union": [
|
|
195
195
|
{
|
|
196
196
|
"type": "null"
|
|
197
197
|
},
|
|
198
198
|
{
|
|
199
199
|
"type": "string"
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
"type": "undefined"
|
|
203
200
|
}
|
|
204
201
|
]
|
|
205
202
|
},
|
|
@@ -209,6 +206,25 @@
|
|
|
209
206
|
"array": {
|
|
210
207
|
"type": "string"
|
|
211
208
|
}
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"name": "openFiles",
|
|
212
|
+
"optional": false,
|
|
213
|
+
"array": {
|
|
214
|
+
"type": "string"
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"name": "viewedFile",
|
|
219
|
+
"optional": false,
|
|
220
|
+
"union": [
|
|
221
|
+
{
|
|
222
|
+
"type": "null"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"type": "string"
|
|
226
|
+
}
|
|
227
|
+
]
|
|
212
228
|
}
|
|
213
229
|
],
|
|
214
230
|
"reads": [
|
|
@@ -219,9 +235,7 @@
|
|
|
219
235
|
"sites": [
|
|
220
236
|
"src/editor/EditorContextService.ts",
|
|
221
237
|
"src/editor/editorContextState.ts"
|
|
222
|
-
]
|
|
223
|
-
"divergent": true,
|
|
224
|
-
"divergentNote": "declared-incomplete — the host (site-main channelBridge.ts) sends {dirtyPaths, openFiles, activeFile, viewedFile}; this side declares only {dirtyPaths, activeFile?} while the SDK reads all four. `viewedFile` (R3-268) and `openFiles` never entered this declaration. R3-274e picks one shape for both sides."
|
|
238
|
+
]
|
|
225
239
|
},
|
|
226
240
|
"evaluate": {
|
|
227
241
|
"kind": "message",
|
|
@@ -252,15 +266,28 @@
|
|
|
252
266
|
"kind": "message",
|
|
253
267
|
"direction": "host->app",
|
|
254
268
|
"payload": {
|
|
269
|
+
"fields": [
|
|
270
|
+
{
|
|
271
|
+
"name": "epoch",
|
|
272
|
+
"optional": false,
|
|
273
|
+
"type": "number"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"name": "paths",
|
|
277
|
+
"optional": false,
|
|
278
|
+
"array": {
|
|
279
|
+
"type": "string"
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
],
|
|
255
283
|
"reads": [
|
|
256
284
|
"paths"
|
|
257
285
|
]
|
|
258
286
|
},
|
|
259
287
|
"sites": [
|
|
260
|
-
"src/index.ts"
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
"divergentNote": "subset-reads with no declared owner on either side — the host sends {paths, epoch}; this side reads only `paths`, the SDK reads both. Nothing forces the two to agree, which is the divergence PLATFORM_LAYERING_SPEC §2 names as the exemplar. The `kind` also differs (message here, push channel in the SDK). R3-274e decides: keep `epoch` or drop it."
|
|
288
|
+
"src/index.ts",
|
|
289
|
+
"src/protocol/fsChange.ts"
|
|
290
|
+
]
|
|
264
291
|
},
|
|
265
292
|
"initialized": {
|
|
266
293
|
"kind": "message",
|
|
@@ -487,21 +514,45 @@
|
|
|
487
514
|
"fields": [
|
|
488
515
|
{
|
|
489
516
|
"name": "protocolVersion",
|
|
490
|
-
"optional":
|
|
491
|
-
"
|
|
517
|
+
"optional": true,
|
|
518
|
+
"union": [
|
|
519
|
+
{
|
|
520
|
+
"type": "string"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"type": "undefined"
|
|
524
|
+
}
|
|
525
|
+
]
|
|
492
526
|
},
|
|
493
527
|
{
|
|
494
528
|
"name": "sandboxProtocolVersion",
|
|
495
|
-
"optional":
|
|
496
|
-
"
|
|
529
|
+
"optional": true,
|
|
530
|
+
"union": [
|
|
531
|
+
{
|
|
532
|
+
"type": "string"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
"type": "undefined"
|
|
536
|
+
}
|
|
537
|
+
]
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
"name": "sdkVersion",
|
|
541
|
+
"optional": true,
|
|
542
|
+
"union": [
|
|
543
|
+
{
|
|
544
|
+
"type": "string"
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
"type": "undefined"
|
|
548
|
+
}
|
|
549
|
+
]
|
|
497
550
|
}
|
|
498
551
|
]
|
|
499
552
|
},
|
|
500
553
|
"sites": [
|
|
501
554
|
"src/index.ts"
|
|
502
|
-
]
|
|
503
|
-
"divergent": true,
|
|
504
|
-
"divergentNote": "divergent-declared — TWO producers of one name with different payloads: this frame announces {protocolVersion, sandboxProtocolVersion}, the SDK announces {protocolVersion, sdkVersion}. R3-274d gave the frame its own SANDBOX_PROTOCOL_VERSION (announced additively; the host logs it, fail-open) and retired the sibling-checkout read that used to source `protocolVersion`. R3-274e picks one shape."
|
|
555
|
+
]
|
|
505
556
|
},
|
|
506
557
|
"start": {
|
|
507
558
|
"kind": "message",
|
package/snapshots/sdk.json
CHANGED
|
@@ -416,9 +416,7 @@
|
|
|
416
416
|
},
|
|
417
417
|
"sites": [
|
|
418
418
|
"src/editorContext.ts"
|
|
419
|
-
]
|
|
420
|
-
"divergent": true,
|
|
421
|
-
"divergentNote": "declared-incomplete — the host (site-main channelBridge.ts) sends {dirtyPaths, openFiles, activeFile, viewedFile}; this side declares only {dirtyPaths, activeFile?} while the SDK reads all four. `viewedFile` (R3-268) and `openFiles` never entered this declaration. R3-274e picks one shape for both sides."
|
|
419
|
+
]
|
|
422
420
|
},
|
|
423
421
|
"form-factor": {
|
|
424
422
|
"kind": "push",
|
|
@@ -503,9 +501,7 @@
|
|
|
503
501
|
},
|
|
504
502
|
"sites": [
|
|
505
503
|
"src/onFsChange.ts"
|
|
506
|
-
]
|
|
507
|
-
"divergent": true,
|
|
508
|
-
"divergentNote": "subset-reads with no declared owner on either side — the host sends {paths, epoch}; this side reads only `paths`, the SDK reads both. Nothing forces the two to agree, which is the divergence PLATFORM_LAYERING_SPEC §2 names as the exemplar. The `kind` also differs (message here, push channel in the SDK). R3-274e decides: keep `epoch` or drop it."
|
|
504
|
+
]
|
|
509
505
|
},
|
|
510
506
|
"invitations": {
|
|
511
507
|
"kind": "push",
|
|
@@ -1715,21 +1711,45 @@
|
|
|
1715
1711
|
"fields": [
|
|
1716
1712
|
{
|
|
1717
1713
|
"name": "protocolVersion",
|
|
1718
|
-
"optional":
|
|
1719
|
-
"
|
|
1714
|
+
"optional": true,
|
|
1715
|
+
"union": [
|
|
1716
|
+
{
|
|
1717
|
+
"type": "string"
|
|
1718
|
+
},
|
|
1719
|
+
{
|
|
1720
|
+
"type": "undefined"
|
|
1721
|
+
}
|
|
1722
|
+
]
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
"name": "sandboxProtocolVersion",
|
|
1726
|
+
"optional": true,
|
|
1727
|
+
"union": [
|
|
1728
|
+
{
|
|
1729
|
+
"type": "string"
|
|
1730
|
+
},
|
|
1731
|
+
{
|
|
1732
|
+
"type": "undefined"
|
|
1733
|
+
}
|
|
1734
|
+
]
|
|
1720
1735
|
},
|
|
1721
1736
|
{
|
|
1722
1737
|
"name": "sdkVersion",
|
|
1723
|
-
"optional":
|
|
1724
|
-
"
|
|
1738
|
+
"optional": true,
|
|
1739
|
+
"union": [
|
|
1740
|
+
{
|
|
1741
|
+
"type": "string"
|
|
1742
|
+
},
|
|
1743
|
+
{
|
|
1744
|
+
"type": "undefined"
|
|
1745
|
+
}
|
|
1746
|
+
]
|
|
1725
1747
|
}
|
|
1726
1748
|
]
|
|
1727
1749
|
},
|
|
1728
1750
|
"sites": [
|
|
1729
1751
|
"src/runtime.ts"
|
|
1730
|
-
]
|
|
1731
|
-
"divergent": true,
|
|
1732
|
-
"divergentNote": "divergent-declared — TWO producers of one name with different payloads: this frame announces {protocolVersion, sandboxProtocolVersion}, the SDK announces {protocolVersion, sdkVersion}. R3-274d gave the frame its own SANDBOX_PROTOCOL_VERSION (announced additively; the host logs it, fail-open) and retired the sibling-checkout read that used to source `protocolVersion`. R3-274e picks one shape."
|
|
1752
|
+
]
|
|
1733
1753
|
},
|
|
1734
1754
|
"secrets-metadata": {
|
|
1735
1755
|
"kind": "push",
|