@vibecook/ice 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 +37 -2
- package/dist/chunk-2GUYATUM.js +643 -0
- package/dist/chunk-2GUYATUM.js.map +1 -0
- package/dist/{chunk-5S7GSXJG.js → chunk-5QY7HK6G.js} +3145 -1306
- package/dist/chunk-5QY7HK6G.js.map +1 -0
- package/dist/{chunk-BCJ47SX7.js → chunk-OR5FNVUE.js} +460 -1
- package/dist/chunk-OR5FNVUE.js.map +1 -0
- package/dist/{chunk-FIAXPNNY.js → chunk-PKK6GLSA.js} +143 -551
- package/dist/chunk-PKK6GLSA.js.map +1 -0
- package/dist/devtools.js +508 -372
- package/dist/devtools.js.map +1 -1
- package/dist/dom.js +3 -11
- package/dist/ground.js +715 -0
- package/dist/ground.js.map +1 -0
- package/dist/index.js +80 -2
- package/dist/kernel.js +31 -1
- package/dist/r3f.js +605 -62
- package/dist/r3f.js.map +1 -1
- package/dist/react.js +36 -418
- package/dist/react.js.map +1 -1
- package/dist/types/packages/core/src/catalog/camera-derived.d.ts +65 -3
- package/dist/types/packages/core/src/catalog/gesture.d.ts +40 -4
- package/dist/types/packages/core/src/catalog/graph.d.ts +7 -6
- package/dist/types/packages/core/src/catalog/index.d.ts +1 -0
- package/dist/types/packages/core/src/catalog/insert.d.ts +31 -0
- package/dist/types/packages/core/src/catalog/pointer.d.ts +11 -0
- package/dist/types/packages/core/src/catalog/scene.d.ts +37 -4
- package/dist/types/packages/core/src/catalog/selection-presence.d.ts +7 -0
- package/dist/types/packages/core/src/catalog/settings-resources.d.ts +21 -0
- package/dist/types/packages/core/src/doc/autosave.d.ts +49 -2
- package/dist/types/packages/core/src/doc/bootstrap.d.ts +29 -0
- package/dist/types/packages/core/src/doc/channels.d.ts +9 -0
- package/dist/types/packages/core/src/doc/doc-commit-sink.d.ts +2 -1
- package/dist/types/packages/core/src/doc/doc-kit.d.ts +16 -1
- package/dist/types/packages/core/src/doc/envelope.d.ts +2 -1
- package/dist/types/packages/core/src/doc/migrate.d.ts +8 -6
- package/dist/types/packages/core/src/doc/schema-migrate.d.ts +50 -0
- package/dist/types/packages/core/src/doc/version-gate.d.ts +3 -0
- package/dist/types/packages/core/src/engine/commit-sink.d.ts +24 -2
- package/dist/types/packages/core/src/engine/engine.d.ts +11 -0
- package/dist/types/packages/core/src/engine/frame-control.d.ts +71 -0
- package/dist/types/packages/core/src/engine/frame-info.d.ts +16 -1
- package/dist/types/packages/core/src/facade/create-canvas-engine.d.ts +79 -6
- package/dist/types/packages/core/src/guards/guarded-tx.d.ts +4 -2
- package/dist/types/packages/core/src/helpers/churn-guard.d.ts +40 -0
- package/dist/types/packages/core/src/index.d.ts +15 -7
- package/dist/types/packages/core/src/input/queue.d.ts +11 -0
- package/dist/types/packages/core/src/interaction/gesture-status.d.ts +13 -0
- package/dist/types/packages/core/src/nav/nested-canvas.d.ts +47 -11
- package/dist/types/packages/core/src/ops/arrange.d.ts +15 -0
- package/dist/types/packages/core/src/ops/insert.d.ts +62 -0
- package/dist/types/packages/core/src/ops/point-pick.d.ts +11 -7
- package/dist/types/packages/core/src/ops/sibling-order.d.ts +70 -0
- package/dist/types/packages/core/src/schema/meta.d.ts +1 -0
- package/dist/types/packages/core/src/settings/defaults.d.ts +45 -0
- package/dist/types/packages/core/src/settings/ground-config.d.ts +55 -0
- package/dist/types/packages/core/src/systems/chrome.d.ts +6 -2
- package/dist/types/packages/core/src/systems/insert-ghost.d.ts +25 -0
- package/dist/types/packages/core/src/systems/l1-pick.d.ts +25 -11
- package/dist/types/packages/core/src/systems/l2-recognize.d.ts +10 -4
- package/dist/types/packages/core/src/systems/l3-behave.d.ts +6 -4
- package/dist/types/packages/core/src/systems/l3-claim.d.ts +7 -3
- package/dist/types/packages/core/src/systems/l3-drop.d.ts +3 -1
- package/dist/types/packages/core/src/systems/l3-resize.d.ts +3 -1
- package/dist/types/packages/core/src/systems/l3-snap.d.ts +25 -7
- package/dist/types/packages/core/src/systems/nav-flight.d.ts +95 -0
- package/dist/types/packages/core/src/widget/define-widget.d.ts +39 -0
- package/dist/types/packages/core/src/widget/mount-store.d.ts +11 -3
- package/dist/types/packages/core/src/widget/set-props.d.ts +16 -0
- package/dist/types/packages/core/src/widget/spawn.d.ts +21 -1
- package/dist/types/packages/devtools/src/attach.d.ts +77 -0
- package/dist/types/packages/devtools/src/dock.d.ts +38 -0
- package/dist/types/packages/devtools/src/gl-panel.d.ts +69 -0
- package/dist/types/packages/devtools/src/index.d.ts +8 -6
- package/dist/types/packages/dom/src/index.d.ts +1 -3
- package/dist/types/packages/dom/src/loop.d.ts +11 -0
- package/dist/types/packages/dom/src/measure-wiring.d.ts +2 -2
- package/dist/types/packages/dom/src/pointer-adapter.d.ts +21 -1
- package/dist/types/packages/dom/src/reflectors/dom-widgets.d.ts +5 -0
- package/dist/types/packages/ground/src/index.d.ts +52 -0
- package/dist/types/packages/ground/src/layer.d.ts +40 -0
- package/dist/types/packages/ground/src/pass.d.ts +41 -0
- package/dist/types/packages/ground/src/passes/grid.d.ts +21 -0
- package/dist/types/packages/ground/src/passes/guides-collect.d.ts +14 -0
- package/dist/types/packages/ground/src/passes/guides.d.ts +3 -0
- package/dist/types/packages/ground/src/passes/soup-collect.d.ts +35 -0
- package/dist/types/packages/ground/src/passes/soup-mesh.d.ts +8 -0
- package/dist/types/packages/ground/src/passes/wires-collect.d.ts +31 -0
- package/dist/types/packages/ground/src/passes/wires.d.ts +10 -0
- package/dist/types/packages/ground/src/renderer.d.ts +15 -0
- package/dist/types/packages/ice/src/ground.d.ts +1 -0
- package/dist/types/packages/kernel/src/bezier.d.ts +15 -0
- package/dist/types/packages/kernel/src/coords.d.ts +15 -0
- package/dist/types/packages/kernel/src/easing.d.ts +11 -0
- package/dist/types/packages/kernel/src/index.d.ts +3 -0
- package/dist/types/packages/kernel/src/layout.d.ts +118 -0
- package/dist/types/packages/kernel/src/nav-flight.d.ts +93 -0
- package/dist/types/packages/r3f/src/bridge.d.ts +73 -12
- package/dist/types/packages/r3f/src/composite-material.d.ts +9 -0
- package/dist/types/packages/r3f/src/compositor-pass.d.ts +22 -0
- package/dist/types/packages/r3f/src/gl-root.d.ts +76 -1
- package/dist/types/packages/r3f/src/gl-router.d.ts +10 -0
- package/dist/types/packages/r3f/src/index.d.ts +3 -2
- package/dist/types/packages/r3f/src/island-state.d.ts +44 -0
- package/dist/types/packages/r3f/src/preview-capture.d.ts +19 -0
- package/dist/types/packages/r3f/src/self-sustain.d.ts +39 -0
- package/dist/types/packages/r3f/src/use-island-frame.d.ts +16 -1
- package/dist/types/packages/react/src/engine-context.d.ts +21 -0
- package/dist/types/packages/react/src/index.d.ts +4 -2
- package/dist/types/packages/react/src/infinite-canvas.d.ts +40 -6
- package/dist/types/packages/react/src/preview-snapshots.d.ts +17 -0
- package/dist/types/packages/react/src/widget-preview.d.ts +14 -0
- package/package.json +32 -61
- package/dist/chunk-5S7GSXJG.js.map +0 -1
- package/dist/chunk-BCJ47SX7.js.map +0 -1
- package/dist/chunk-FIAXPNNY.js.map +0 -1
- package/dist/types/packages/devtools/src/panel.d.ts +0 -48
- package/dist/types/packages/dom/src/reflectors/grid.d.ts +0 -63
- package/dist/types/packages/dom/src/reflectors/wires.d.ts +0 -88
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recognizers & gestures — the L2 runtime recognizer prefabs (design-001 §5.5,
|
|
3
|
+
* design-003 §4).
|
|
4
|
+
*
|
|
5
|
+
* Identity is the KIND component (its presence is the kind; its fields are the
|
|
6
|
+
* working value). Phase is a tag-of-set flipped by the engine PhaseSet helper
|
|
7
|
+
* (strata has no one-of primitive; `Pending` was dropped as dead machinery). All
|
|
8
|
+
* in-flight state lives on the recognizer entity or the grabbed widgets — no
|
|
9
|
+
* singleton trackers — so N concurrent same-kind gestures are structural.
|
|
10
|
+
*
|
|
11
|
+
* Field set for each kind matches design-003 §4.2's revised table (which adds
|
|
12
|
+
* `zoomAtClaim` to Drag and Pinch over design-001 §5.5).
|
|
13
|
+
*
|
|
14
|
+
* Defaults policy (see catalog/index.ts): kind components and per-frame working
|
|
15
|
+
* riders are runtime scratch spawned/written by systems, so they carry full
|
|
16
|
+
* zero/identity defaults (ergonomic `ctx.spawn`). Origin-latch riders that MUST
|
|
17
|
+
* carry real values (Grab, Down) stay bare so a defaulted origin can't silently
|
|
18
|
+
* corrupt a cancel-restore.
|
|
19
|
+
*/
|
|
20
|
+
import { type Entity } from "@vibecook/strata-ecs";
|
|
1
21
|
/** Continuous drag. Origin from dead-zone exit; totals/velocities accumulate; `zoomAtClaim` anchors widget-move math. */
|
|
2
22
|
export declare const Drag: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
3
23
|
readonly startX: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
@@ -95,7 +115,7 @@ export declare const WheelZoom: import("@vibecook/strata-ecs").Component<import(
|
|
|
95
115
|
* `Sequence`/`RequiresFail` edge. NEVER reaped; exempt from integrity's watched-pointer
|
|
96
116
|
* count (a pending multi-tap legitimately outlives its lifted touch pointer).
|
|
97
117
|
*/
|
|
98
|
-
export declare const GesturePhases: import("..").PhaseSet<"
|
|
118
|
+
export declare const GesturePhases: import("..").PhaseSet<"Active" | "Possible" | "Pending" | "Recognized" | "Ended" | "Failed" | "Cancelled">;
|
|
99
119
|
/** Recognizer alive, not yet claiming. */
|
|
100
120
|
export declare const GesturePossible: import("@vibecook/strata-ecs").Tag;
|
|
101
121
|
/** Continuous kinds' claiming phase + per-frame work gate. */
|
|
@@ -168,23 +188,39 @@ export declare const Drags: import("@vibecook/strata-ecs").Relation;
|
|
|
168
188
|
export declare const ClaimedBy: import("@vibecook/strata-ecs").Relation;
|
|
169
189
|
/** recognizer → candidate container under the dragged bounds (design-003 §5 dropSystem). */
|
|
170
190
|
export declare const DropTarget: import("@vibecook/strata-ecs").Relation;
|
|
191
|
+
/**
|
|
192
|
+
* "None" sentinel for Grab's eid fields — strata's reserved null handle
|
|
193
|
+
* (entity 0 is never live; generations start at 1).
|
|
194
|
+
*/
|
|
195
|
+
export declare const NO_ENTITY: Entity;
|
|
171
196
|
/**
|
|
172
197
|
* Per-dragged-widget origin, attached at claim time with the CURRENT transform embedded
|
|
173
198
|
* (design-001 §3, design-003 §4.5). Bare on purpose: a defaulted zero origin would corrupt
|
|
174
|
-
* the cancel-restore of Position
|
|
199
|
+
* the cancel-restore of Position and sibling order.
|
|
200
|
+
*
|
|
201
|
+
* `parent`/`prev`/`ord` are the ORDER MEMO (petition 8) — the claim-time
|
|
202
|
+
* elevate is `moveRelation(w, ChildOf, "last")`, so cancel/fly-back must
|
|
203
|
+
* remember where the widget SAT: its `ChildOf` parent (NO_ENTITY = no edge —
|
|
204
|
+
* legacy world, nothing to restore), its nearest non-dragged predecessor
|
|
205
|
+
* sibling (NO_ENTITY = it was first), and its original sibling index (`ord` —
|
|
206
|
+
* the members' relative order at reinsert; see l3-behave's restore walk).
|
|
175
207
|
*/
|
|
176
208
|
export declare const Grab: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
177
209
|
readonly x: "f64";
|
|
178
210
|
readonly y: "f64";
|
|
179
211
|
readonly w: "f32";
|
|
180
212
|
readonly h: "f32";
|
|
181
|
-
readonly
|
|
213
|
+
readonly parent: "eid";
|
|
214
|
+
readonly prev: "eid";
|
|
215
|
+
readonly ord: "f64";
|
|
182
216
|
}>, {
|
|
183
217
|
readonly x: "f64";
|
|
184
218
|
readonly y: "f64";
|
|
185
219
|
readonly w: "f32";
|
|
186
220
|
readonly h: "f32";
|
|
187
|
-
readonly
|
|
221
|
+
readonly parent: "eid";
|
|
222
|
+
readonly prev: "eid";
|
|
223
|
+
readonly ord: "f64";
|
|
188
224
|
}>;
|
|
189
225
|
/** Snap offset — in the Drag prefab's essential set (present from spawn, zeroed — writers never race an attach). */
|
|
190
226
|
export declare const SnapState: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
@@ -15,11 +15,11 @@ export declare const WirePorts: import("@vibecook/strata-ecs").Component<import(
|
|
|
15
15
|
/** A widget port descriptor — spawned only for interaction (connect tool / hover proximity). */
|
|
16
16
|
export declare const Port: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
17
17
|
readonly id: "string";
|
|
18
|
-
readonly side: import("@vibecook/strata-ecs").EnumType<"
|
|
18
|
+
readonly side: import("@vibecook/strata-ecs").EnumType<"s" | "w" | "n" | "e">;
|
|
19
19
|
readonly index: import("@vibecook/strata-ecs").FieldSpec<"u8", true>;
|
|
20
20
|
}>, {
|
|
21
21
|
readonly id: "string";
|
|
22
|
-
readonly side: import("@vibecook/strata-ecs").EnumType<"
|
|
22
|
+
readonly side: import("@vibecook/strata-ecs").EnumType<"s" | "w" | "n" | "e">;
|
|
23
23
|
readonly index: import("@vibecook/strata-ecs").FieldSpec<"u8", true>;
|
|
24
24
|
}>;
|
|
25
25
|
/** port → widget. */
|
|
@@ -47,9 +47,10 @@ export declare const Provides: import("@vibecook/strata-ecs").Component<import("
|
|
|
47
47
|
readonly list: import("@vibecook/strata-ecs").FieldSpec<"string", true>;
|
|
48
48
|
}>;
|
|
49
49
|
/**
|
|
50
|
-
* The durable wire prefab (design-001 §5.3):
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
50
|
+
* The durable wire prefab (design-001 §5.3): WirePorts + the Wire tag +
|
|
51
|
+
* eligible WireFrom/WireTo edges — the COMPLETE contract, so the doc commit
|
|
52
|
+
* sink spawns through the paved `tx.spawnPrefab` path instead of a raw spawn
|
|
53
|
+
* that bypassed eligibility checks (2026-07-13 review). Registered here so the
|
|
54
|
+
* version gate stamps `engine.pack.wire.<v>` like every durable pack.
|
|
54
55
|
*/
|
|
55
56
|
export declare const WirePrefab: import("..").Prefab;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ghost marker + its promote payload, attached at `ops.insertByDrag`:
|
|
3
|
+
* `type`/`props` (JSON) rebuild the widget in the commit's `CommitCreate`;
|
|
4
|
+
* `screenX/screenY` remember the tray press point IN SCREEN SPACE so the
|
|
5
|
+
* cancel fly-back re-projects it through the CURRENT camera — the ghost
|
|
6
|
+
* returns to the tray on screen even if the user zoomed mid-drag.
|
|
7
|
+
*/
|
|
8
|
+
export declare const InsertGhost: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
9
|
+
readonly type: "string";
|
|
10
|
+
readonly props: import("@vibecook/strata-ecs").FieldSpec<"string", true>;
|
|
11
|
+
readonly screenX: "f32";
|
|
12
|
+
readonly screenY: "f32";
|
|
13
|
+
}>, {
|
|
14
|
+
readonly type: "string";
|
|
15
|
+
readonly props: import("@vibecook/strata-ecs").FieldSpec<"string", true>;
|
|
16
|
+
readonly screenX: "f32";
|
|
17
|
+
readonly screenY: "f32";
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Set by moveBehavior when the ghost's gesture committed its `create` intent.
|
|
21
|
+
* The reap system despawns the ghost ONE tick later — the projected twin lands
|
|
22
|
+
* at the next sync, so the swap happens inside a single reflect flush (no
|
|
23
|
+
* one-frame blink of neither).
|
|
24
|
+
*/
|
|
25
|
+
export declare const GhostCommitted: import("@vibecook/strata-ecs").Tag;
|
|
26
|
+
/**
|
|
27
|
+
* Set on the cancel / rejected-drop paths together with the fly-back
|
|
28
|
+
* `TransformTween`: the reap system despawns the ghost when the tween lands
|
|
29
|
+
* (component removed on arrival — camera-sim).
|
|
30
|
+
*/
|
|
31
|
+
export declare const GhostRetiring: import("@vibecook/strata-ecs").Tag;
|
|
@@ -66,6 +66,17 @@ export declare const WentUp: import("@vibecook/strata-ecs").Tag;
|
|
|
66
66
|
export declare const WentCancelled: import("@vibecook/strata-ecs").Tag;
|
|
67
67
|
/** The down was consumed by a widget's own DOM handler — recognizers skip it. */
|
|
68
68
|
export declare const HandledByWidget: import("@vibecook/strata-ecs").Tag;
|
|
69
|
+
/**
|
|
70
|
+
* PERSISTENT (not one-tick): the pointer is hovering content that would opt a
|
|
71
|
+
* down out — a native interactive / `[data-canvas-interactive]` (DOM) or
|
|
72
|
+
* claim-capable island content (GL). Written change-only by ingest from the
|
|
73
|
+
* adapters' hover-time `overInteractive` fact (design-002 §8 amendment,
|
|
74
|
+
* 2026-07-18) and held across ticks with no fresh hover information (wheel,
|
|
75
|
+
* blur). Presentation-grade truth — cursor affordances telegraph "the widget
|
|
76
|
+
* owns your input here" BEFORE the down; recognizers never read it (the
|
|
77
|
+
* gesture gate stays `HandledByWidget`).
|
|
78
|
+
*/
|
|
79
|
+
export declare const OverInteractive: import("@vibecook/strata-ecs").Tag;
|
|
69
80
|
/** Marks the local device's pointer(s) (vs. presence projections). */
|
|
70
81
|
export declare const LocalPointer: import("@vibecook/strata-ecs").Tag;
|
|
71
82
|
/** Derive-owned world position — screen × camera, recomputed every tick. */
|
|
@@ -20,15 +20,48 @@ export declare const Rotation: import("@vibecook/strata-ecs").Component<import("
|
|
|
20
20
|
}>, {
|
|
21
21
|
readonly r: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
22
22
|
}>;
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Optional-eligible widget opacity, 0..1 (design-004 §3: `{opacity}` is the
|
|
25
|
+
* neutral composite's WHOLE per-widget fact). Reflected by the dom host
|
|
26
|
+
* (style.opacity) and the gl composite quad (uOpacity) alike; absent = 1.
|
|
27
|
+
* Identity default so a bare attach is ergonomic.
|
|
28
|
+
*/
|
|
29
|
+
export declare const Opacity: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
30
|
+
readonly a: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
31
|
+
}>, {
|
|
32
|
+
readonly a: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* LEGACY (petition 8, engineSchema 2): scalar stacking order, superseded by ordered `ChildOf`
|
|
36
|
+
* sibling sequences. Stays REGISTERED so v1 docs' z cells keep projecting — the schema
|
|
37
|
+
* migration sorts by them, and a v1 doc opened read-only still paints z-correct through the
|
|
38
|
+
* renderers' legacy fallback. Never written for new entities; no new reader outside the
|
|
39
|
+
* migration and the read-only sort fallback.
|
|
40
|
+
*/
|
|
24
41
|
export declare const StackZ: import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
25
42
|
readonly z: "f64";
|
|
26
43
|
}>, {
|
|
27
44
|
readonly z: "f64";
|
|
28
45
|
}>;
|
|
29
46
|
/**
|
|
30
|
-
* child → parent frame (durable-eligible)
|
|
31
|
-
* children
|
|
32
|
-
*
|
|
47
|
+
* child → parent frame (durable-eligible), ORDERED (petition 8): each parent's `getReverse` is
|
|
48
|
+
* its children in SIBLING ORDER — paint/pick order within a frame IS this sequence (the
|
|
49
|
+
* per-frame sibling-order law; design-004 §1 amendment). Placement rides
|
|
50
|
+
* `setRelation(child, ChildOf, parent, place)` / `moveRelation`; order converges
|
|
51
|
+
* collaboratively (CRDT movable list). Children-of-x = `Related(ChildOf, x)`; ancestor walk =
|
|
52
|
+
* forward `getRelation`; engine cascade walks `getReverse(e, ChildOf)` (see ops/cascade.ts).
|
|
33
53
|
*/
|
|
34
54
|
export declare const ChildOf: import("@vibecook/strata-ecs").Relation;
|
|
55
|
+
/**
|
|
56
|
+
* The BOARD ROOT (petition 8): the componentless durable entity every root-level widget hangs
|
|
57
|
+
* its `ChildOf` edge on, so the root frame has a sibling sequence like any container. Minted
|
|
58
|
+
* once per document (key recorded first-writer-wins in the meta map, `engine.boardRoot`);
|
|
59
|
+
* componentless BY LAW — it must dodge every widget/pick/cull query. This RUNTIME resource
|
|
60
|
+
* names it post-attach; absent = a pre-schema-2 read-only doc (renderers fall back to the
|
|
61
|
+
* legacy StackZ sort).
|
|
62
|
+
*/
|
|
63
|
+
export declare const BoardRoot: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
|
|
64
|
+
readonly root: "eid";
|
|
65
|
+
}>, {
|
|
66
|
+
readonly root: "eid";
|
|
67
|
+
}>;
|
|
@@ -5,6 +5,13 @@ export declare const Movable: import("@vibecook/strata-ecs").Tag;
|
|
|
5
5
|
export declare const Resizable: import("@vibecook/strata-ecs").Tag;
|
|
6
6
|
export declare const SnapSource: import("@vibecook/strata-ecs").Tag;
|
|
7
7
|
export declare const SnapTarget: import("@vibecook/strata-ecs").Tag;
|
|
8
|
+
/**
|
|
9
|
+
* Comment-box group drag (2026-07-18, James: the UE-Blueprint comment): a
|
|
10
|
+
* move claim on this widget ALSO claims every widget fully inside its bounds
|
|
11
|
+
* at claim time — spatial membership, never reparenting (that's the folder
|
|
12
|
+
* path). Drag a member out and it simply stops being inside.
|
|
13
|
+
*/
|
|
14
|
+
export declare const SweepsContained: import("@vibecook/strata-ecs").Tag;
|
|
8
15
|
/**
|
|
9
16
|
* Marks an ephemeral presence-peer entity (design-001 §5.6). Rides the presence
|
|
10
17
|
* blob so remote peers project it — a peer query is `[PresencePeer, Not(Local)]`
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Selection-chrome live mirror (2026-07-17): `liftScale` = the app's visual
|
|
3
|
+
* drag-lift scale factor; `selectionChrome` inflates a Grab-bed member's rect
|
|
4
|
+
* by it (about the rect center) so the union box always wraps the card the
|
|
5
|
+
* user SEES, not just its ECS footprint.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ChromeSettings: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
|
|
8
|
+
readonly liftScale: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
9
|
+
}>, {
|
|
10
|
+
readonly liftScale: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
11
|
+
}>;
|
|
1
12
|
/** Recognizer timing/slop live mirror (design-003 §4.2 kind table; inertia constants §5 item 9). */
|
|
2
13
|
export declare const GestureSettings: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
|
|
3
14
|
readonly tapMaxMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
@@ -11,6 +22,8 @@ export declare const GestureSettings: import("@vibecook/strata-ecs").Resource<im
|
|
|
11
22
|
readonly inertiaDecayMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
12
23
|
readonly multiTapWindowMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
13
24
|
readonly multiTapSlopPx: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
25
|
+
readonly wheelZoomSensitivity: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
26
|
+
readonly wheelZoomMaxStep: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
14
27
|
}>, {
|
|
15
28
|
readonly tapMaxMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
16
29
|
readonly tapSlopPx: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
@@ -23,6 +36,8 @@ export declare const GestureSettings: import("@vibecook/strata-ecs").Resource<im
|
|
|
23
36
|
readonly inertiaDecayMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
24
37
|
readonly multiTapWindowMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
25
38
|
readonly multiTapSlopPx: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
39
|
+
readonly wheelZoomSensitivity: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
40
|
+
readonly wheelZoomMaxStep: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
26
41
|
}>;
|
|
27
42
|
/** Pick radii + retarget dead-band live mirror (design-003 §3 L1 targeting). */
|
|
28
43
|
export declare const PointerSettings: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
|
|
@@ -44,3 +59,9 @@ export declare const CameraLimits: import("@vibecook/strata-ecs").Resource<impor
|
|
|
44
59
|
readonly minZoom: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
45
60
|
readonly maxZoom: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
46
61
|
}>;
|
|
62
|
+
/** Nav-transition spring response live mirror (design-006 §4; navFlight consumes). */
|
|
63
|
+
export declare const NavTransitionSettings: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
|
|
64
|
+
readonly responseMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
65
|
+
}>, {
|
|
66
|
+
readonly responseMs: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
67
|
+
}>;
|
|
@@ -1,9 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The autosave kit (design-005 §6.6; design-001 §6.5 envelope-at-rest).
|
|
3
|
+
*
|
|
4
|
+
* Persists a `DocSession` to app-owned storage on a debounce (default 800 ms)
|
|
5
|
+
* with a max-wait ceiling (default 10 s), DEFERRED while the user is mid-gesture
|
|
6
|
+
* so a save never captures a half-applied interaction. What it writes is an
|
|
7
|
+
* ENVELOPE (`session.exportEnvelope(savedAt)`) — never raw Loro bytes — so the
|
|
8
|
+
* restore path can read the header and gate/quarantine BEFORE any import.
|
|
9
|
+
*
|
|
10
|
+
* CHANGE-SUBSCRIPTION SURFACE: two triggers, plus an initial arm.
|
|
11
|
+
* - `DurableStore.subscribeOutbound` (durable-store.ts) fires SYNCHRONOUSLY on
|
|
12
|
+
* each sealed LOCAL commit and never on remote imports.
|
|
13
|
+
* - `DocSession.subscribeRemote` (doc-kit) fires after each successful
|
|
14
|
+
* `applyRemote`. The original design left remote changes to "whichever peer
|
|
15
|
+
* originated them" — but that peer persists to ITS storage, not this one's:
|
|
16
|
+
* a joiner that received edits and closed restored a STALE local backup
|
|
17
|
+
* (2026-07-13 review). Local autosave must reflect the last-seen document.
|
|
18
|
+
* - Autosave starts DIRTY: state that predates startAutosave() (a seeded or
|
|
19
|
+
* freshly-joined doc) reaches storage after the first debounce, not only
|
|
20
|
+
* after the next edit (same review — a seeded doc could close unsaved).
|
|
21
|
+
* No polling — the design's `store.exportSnapshot()` length/frontier poll is
|
|
22
|
+
* the last-resort fallback and is not needed here.
|
|
23
|
+
*
|
|
24
|
+
* Clock and scheduler are injectable so tests are deterministic with NO real
|
|
25
|
+
* timers; the design's `requestIdleCallback` optimization is just an alternate
|
|
26
|
+
* `schedule` an app can pass. `flush()` forces an awaited save; `close()`
|
|
27
|
+
* captures and durably serializes the final revision; `stop()` explicitly
|
|
28
|
+
* discards pending state.
|
|
29
|
+
*
|
|
30
|
+
* RESTORE (`restoreAutosave`): reads storage → `openDocSession`. Incompatible or
|
|
31
|
+
* corrupt bytes NEVER throw and NEVER brick boot (the M5 exit criterion) —
|
|
32
|
+
* they come back as `{ status: "quarantined", reason, bytes }` so the app can
|
|
33
|
+
* stash the bytes aside and start fresh.
|
|
34
|
+
*/
|
|
1
35
|
import type { World } from "@vibecook/strata-ecs";
|
|
2
36
|
import { type DocSession, type DocSessionOpts } from "./doc-kit";
|
|
3
37
|
import type { DocVersionReport } from "./version-gate";
|
|
4
38
|
/** The app-owned write side of storage (localStorage, IndexedDB, fs, cloud — WHERE is app-owned). */
|
|
5
39
|
export interface AutosaveStorageWrite {
|
|
6
40
|
put(bytes: Uint8Array): Promise<void> | void;
|
|
41
|
+
/** Optional opaque Loro-update journal. `put` replaces the checkpoint and
|
|
42
|
+
* clears its journal; `append` durably extends the current checkpoint. */
|
|
43
|
+
append?(bytes: Uint8Array): Promise<void> | void;
|
|
7
44
|
}
|
|
8
45
|
/** The app-owned read side of storage (restore path). */
|
|
9
46
|
export interface AutosaveStorageRead {
|
|
@@ -23,6 +60,10 @@ export interface AutosaveOpts {
|
|
|
23
60
|
readonly now?: () => number;
|
|
24
61
|
/** Timer factory; return a canceller (default `setTimeout`/`clearTimeout`). */
|
|
25
62
|
readonly schedule?: (fn: () => void, ms: number) => CancelScheduled;
|
|
63
|
+
/** Compact after this many journal records (default 64). */
|
|
64
|
+
readonly checkpointEvery?: number;
|
|
65
|
+
/** Compact before the journal exceeds this many bytes (default 4 MiB). */
|
|
66
|
+
readonly maxJournalBytes?: number;
|
|
26
67
|
}
|
|
27
68
|
export type AutosaveStatus = "idle" | "pending" | "deferred" | "saving" | "saved" | "error";
|
|
28
69
|
export interface AutosaveState {
|
|
@@ -33,9 +74,15 @@ export interface AutosaveState {
|
|
|
33
74
|
readonly pending: boolean;
|
|
34
75
|
}
|
|
35
76
|
export interface Autosave {
|
|
36
|
-
/** Force a save of the current document now and await it
|
|
77
|
+
/** Force a save of the current document now and await it. Rejects when persistence fails. */
|
|
37
78
|
flush(): Promise<void>;
|
|
38
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Capture the final document synchronously, serialize it behind any in-flight
|
|
81
|
+
* write, and stop only after storage acknowledges it. Rejects on failure and
|
|
82
|
+
* may be retried; no document mutation should occur after close begins.
|
|
83
|
+
*/
|
|
84
|
+
close(): Promise<void>;
|
|
85
|
+
/** Discard pending state immediately. Idempotent; never use for a normal close. */
|
|
39
86
|
stop(): void;
|
|
40
87
|
/** A pull-based status read for a per-frame HUD (design demo). */
|
|
41
88
|
state(): AutosaveState;
|
|
@@ -59,14 +59,43 @@ export interface JoinDocOpts {
|
|
|
59
59
|
readonly presence?: PresenceSession;
|
|
60
60
|
/** Surfaced when a re-bootstrap (after a PendingImportError) itself fails, or a base import fails post-join. */
|
|
61
61
|
readonly onError?: (err: unknown) => void;
|
|
62
|
+
/**
|
|
63
|
+
* Abort the join: tears the room down (channel unsubscribed, session closed)
|
|
64
|
+
* and rejects the promise if it hasn't resolved yet. The facade aborts its
|
|
65
|
+
* pending join when another document supersedes it — a resolution-time check
|
|
66
|
+
* alone cannot stop a mid-handshake join from attaching to the world.
|
|
67
|
+
*/
|
|
68
|
+
readonly signal?: AbortSignal;
|
|
69
|
+
/**
|
|
70
|
+
* Live-session transitions: fired at every activation (including the first,
|
|
71
|
+
* just before the promise resolves) and with `undefined` when an internal
|
|
72
|
+
* re-bootstrap tears the quarantined session down. The facade re-targets its
|
|
73
|
+
* forwarding sink here — without it, callers keep committing into a session
|
|
74
|
+
* `rebootstrap()` already closed.
|
|
75
|
+
*/
|
|
76
|
+
readonly onSession?: (session: DocSession | undefined) => void;
|
|
62
77
|
}
|
|
63
78
|
export interface JoinResult {
|
|
64
79
|
/** "seeder" = we created the doc (timed out); "joiner" = we imported a peer's base. */
|
|
65
80
|
readonly role: "seeder" | "joiner";
|
|
81
|
+
/** LIVE (a getter): after an internal re-bootstrap this is the replacement session. */
|
|
66
82
|
readonly session: DocSession;
|
|
67
83
|
/** Stop relaying, unsubscribe the channel, and close the session. Idempotent. */
|
|
68
84
|
leave(): void;
|
|
69
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Re-offer this session's document to the room (design-005 §6.5 amendment,
|
|
88
|
+
* 2026-07-20 — the lossy-transport repair). Broadcasts the base as an
|
|
89
|
+
* UN-addressed SNAPSHOT_OFFER — exactly the frame a joiner broadcasts after
|
|
90
|
+
* importing its base — so the protocol already defines every receiver's move:
|
|
91
|
+
* an ACTIVE peer MERGES it (loro dedupes; increments the outage dropped are
|
|
92
|
+
* subsumed by the full document), a BUFFERING peer OPENS it as its causal base.
|
|
93
|
+
* Call it when a lossy transport BEHIND a still-live channel heals (an Electron
|
|
94
|
+
* main's mesh link bounced; the IPC channel object never died). A channel that
|
|
95
|
+
* itself died (a closed socket) needs a fresh `joinDoc` instead — offers ride
|
|
96
|
+
* the channel, and a dead one drops them silently.
|
|
97
|
+
*/
|
|
98
|
+
export declare function offerBase(channel: ByteChannel, session: DocSession): void;
|
|
70
99
|
/**
|
|
71
100
|
* Join (or found) the room's document over `channel`. Resolves once we go active —
|
|
72
101
|
* as a "joiner" (imported a peer's base) or a "seeder" (timed out and created one).
|
|
@@ -16,6 +16,15 @@ export interface ByteChannel {
|
|
|
16
16
|
send(bytes: Uint8Array): void;
|
|
17
17
|
/** Deliver every inbound frame to `fn`. Returns an unsubscribe. */
|
|
18
18
|
subscribe(fn: (bytes: Uint8Array) => void): () => void;
|
|
19
|
+
/**
|
|
20
|
+
* OPTIONAL readiness: resolves once the transport can actually transmit,
|
|
21
|
+
* rejects if it never will. `joinDoc` gates its hello + the seed-silence
|
|
22
|
+
* window on this — a queue-until-open transport otherwise lets a slow
|
|
23
|
+
* connect elapse the window and seed a DIVERGENT second doc offline
|
|
24
|
+
* (2026-07-13 review). Synchronous transports (BroadcastChannel, in-memory
|
|
25
|
+
* buses) simply omit it.
|
|
26
|
+
*/
|
|
27
|
+
ready?(): Promise<void>;
|
|
19
28
|
}
|
|
20
29
|
/** A `ByteChannel` that owns a resource (a BroadcastChannel) and can release it. */
|
|
21
30
|
export interface OwnedByteChannel extends ByteChannel {
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* cancel, and a DEV warn says why.
|
|
16
16
|
*/
|
|
17
17
|
import type { DurableStore } from "@vibecook/strata-ecs/durable";
|
|
18
|
-
import type { World } from "@vibecook/strata-ecs";
|
|
18
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
19
19
|
import type { CommitSink } from "../engine/commit-sink";
|
|
20
|
+
export declare function drainCreatedSelections(world: World): Entity[];
|
|
20
21
|
export declare function createDocCommitSink(store: DurableStore, world: World): CommitSink;
|
|
21
22
|
/** The version-gate's read-only posture: gestures run, nothing commits. */
|
|
22
23
|
export declare function createReadOnlyCommitSink(): CommitSink;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { World } from "@vibecook/strata-ecs";
|
|
2
|
-
import type { DurableStore } from "@vibecook/strata-ecs/durable";
|
|
2
|
+
import type { Attachment, DurableStore } from "@vibecook/strata-ecs/durable";
|
|
3
3
|
import type { CommitSink } from "../engine/commit-sink";
|
|
4
4
|
import { type LiveWriter } from "../guards/live-writer";
|
|
5
5
|
import { type DocVersionReport, type GateVerdict } from "./version-gate";
|
|
@@ -18,6 +18,12 @@ export interface DocSessionOpts {
|
|
|
18
18
|
export interface DocSession {
|
|
19
19
|
readonly store: DurableStore;
|
|
20
20
|
readonly sink: CommitSink;
|
|
21
|
+
/**
|
|
22
|
+
* The strata attachment — a read-only INSPECTION seam: its `baseline` feeds
|
|
23
|
+
* the observer devtools' durable tab (runtime-vs-baseline = the un-agreed
|
|
24
|
+
* sync delta). Never a sync path; `close()` owns its lifecycle.
|
|
25
|
+
*/
|
|
26
|
+
readonly attachment: Attachment;
|
|
21
27
|
readonly readOnly: boolean;
|
|
22
28
|
/**
|
|
23
29
|
* The design-001 §3 step-2 DEV guard, wired to THIS doc: userland live
|
|
@@ -33,6 +39,15 @@ export interface DocSession {
|
|
|
33
39
|
/** Relay passthroughs (M5 dumb relay; M9 brings the bootstrap protocol). */
|
|
34
40
|
exportSnapshot(): Uint8Array;
|
|
35
41
|
applyRemote(bytes: Uint8Array): void;
|
|
42
|
+
/**
|
|
43
|
+
* Fires after each successful `applyRemote` on THIS session (strata's
|
|
44
|
+
* `subscribeOutbound` is local-commits-only by design, so remote imports are
|
|
45
|
+
* otherwise unobservable). Autosave rides this so a peer's local backup
|
|
46
|
+
* reflects the last-seen document, not just what it authored (2026-07-13
|
|
47
|
+
* review). A transport writing through `store.applyRemote` directly bypasses
|
|
48
|
+
* it — engine paths (bootstrap, broadcast relay) all go through the session.
|
|
49
|
+
*/
|
|
50
|
+
subscribeRemote(fn: (bytes: Uint8Array) => void): () => void;
|
|
36
51
|
/** cancel gestures → detach → world reset in place → respawn the anchor. */
|
|
37
52
|
close(): void;
|
|
38
53
|
}
|
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export declare const ENVELOPE_MAGIC = "ICE1";
|
|
18
18
|
export declare const ENVELOPE_VERSION = 1;
|
|
19
|
+
export declare const MAX_ENVELOPE_HEADER_BYTES: number;
|
|
19
20
|
/** The document-format version this build writes (gate compares against it). */
|
|
20
|
-
export declare const ENGINE_SCHEMA_VERSION =
|
|
21
|
+
export declare const ENGINE_SCHEMA_VERSION = 2;
|
|
21
22
|
export interface EnvelopeHeader {
|
|
22
23
|
readonly engineSchema: number;
|
|
23
24
|
/** Per-prefab pack versions at save time ({ [prefabId]: version }). */
|
|
@@ -59,11 +59,13 @@ export interface MigrationOutcome {
|
|
|
59
59
|
readonly skipped: string[];
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
* Run every applicable per-type migration against an ATTACHED doc.
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
62
|
+
* Run every applicable per-type migration against an ATTACHED doc. ALL types
|
|
63
|
+
* are planned (read + transform-fold) BEFORE anything is written — a throwing
|
|
64
|
+
* transform on the Nth type therefore aborts with the document untouched,
|
|
65
|
+
* never with types 1..N-1 permanently migrated and the rest old (2026-07-13
|
|
66
|
+
* review). Each type then writes one non-undoable transaction and stamps its
|
|
67
|
+
* marker. Never throws for a merely-un-migratable type (missing widget /
|
|
68
|
+
* gappy chain → skipped); a genuine fault (a throwing transform) propagates so
|
|
69
|
+
* the caller can fall back read-only.
|
|
68
70
|
*/
|
|
69
71
|
export declare function runMigrations(ctx: MigrationCtx, report: DocVersionReport): MigrationOutcome;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STRUCTURAL schema migrations (petition 8; engineSchema 1 → 2).
|
|
3
|
+
*
|
|
4
|
+
* The per-prefab runner (migrate.ts) folds per-entity group values — it cannot spawn entities,
|
|
5
|
+
* see siblings, write relations, or stamp `engine.schema`, so a schema-version bump used to
|
|
6
|
+
* leave old docs read-only FOREVER (the gate re-ran, saw docSchema < local, and nothing ever
|
|
7
|
+
* advanced it). This module is the missing half: whole-document transforms keyed by the schema
|
|
8
|
+
* version they migrate FROM, run at open on a "migrate" verdict BEFORE the pack runner, each
|
|
9
|
+
* stamping `engine.schema.<n+1>` on success.
|
|
10
|
+
*
|
|
11
|
+
* SINGLE-WRITER LAW: a structural migration may only run when this peer is the document's sole
|
|
12
|
+
* occupant — the local open path (autosave restore, file open). A LIVE-ROOM JOINER MUST NOT
|
|
13
|
+
* migrate (bootstrap passes `migrate: false`): the room's peers are still writing the old
|
|
14
|
+
* shape, sync never re-gates, and a mid-room migration split-brains the doc (old peers write
|
|
15
|
+
* scalar z the new shape ignores, and vice versa). An old-schema doc joined live is read-only
|
|
16
|
+
* until it is opened solo by a current build.
|
|
17
|
+
*
|
|
18
|
+
* Step 1→2 — ordered relations:
|
|
19
|
+
* 1. BOARD ROOT: mint the componentless durable entity root-level widgets hang `ChildOf` on
|
|
20
|
+
* ({@link ensureBoardRoot}); its key is recorded first-writer-wins in the meta map.
|
|
21
|
+
* 2. StackZ → sibling order: every durable widget is grouped by parent scope (existing
|
|
22
|
+
* `ChildOf` target, else the board root), each group sorted by `(z asc, entityKey asc)`,
|
|
23
|
+
* and re-linked in that order with `tx.setRelation(e, ChildOf, parent, "last")` — a
|
|
24
|
+
* same-target re-set WITH a place is a move, so applying in sorted order lands the sorted
|
|
25
|
+
* sequence; root-level widgets gain their first edge the same way. ONE non-undoable
|
|
26
|
+
* transaction; absolute, idempotent, convergent (same doc → same sort → same sequence).
|
|
27
|
+
* 3. The legacy `StackZ` CELLS ARE KEPT: an old build opening the migrated doc read-only
|
|
28
|
+
* (docSchema newer than local) still paints z-correct from them. New entities never write
|
|
29
|
+
* StackZ; the cells are simply never read by current builds outside the legacy fallback.
|
|
30
|
+
*/
|
|
31
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
32
|
+
import type { DurableStore } from "@vibecook/strata-ecs/durable";
|
|
33
|
+
import type { MigrationCtx } from "./migrate";
|
|
34
|
+
import type { DocVersionReport } from "./version-gate";
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the document's board root, minting it if absent (create path + step 1→2). The mint
|
|
37
|
+
* is a componentless `tx.spawn()` in a non-undoable transaction; the key is recorded in meta
|
|
38
|
+
* first-writer-wins and re-read after the write so a raced winner is honored (the single-writer
|
|
39
|
+
* law makes a race unreachable in practice — belt and braces). Returns the LIVE handle.
|
|
40
|
+
*/
|
|
41
|
+
export declare function ensureBoardRoot(world: World, store: DurableStore): Entity;
|
|
42
|
+
/** Read the board-root handle WITHOUT minting — read-only opens and post-attach lookups. */
|
|
43
|
+
export declare function resolveBoardRoot(world: World, store: DurableStore): Entity | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Run the structural chain `docSchema → … → localSchema`, stamping `engine.schema.<n+1>` after
|
|
46
|
+
* each step. A gap (missing step) stops the walk — the caller's re-gate keeps the doc
|
|
47
|
+
* read-only, exactly like a gappy pack chain. A docSchema of 0 is the gate's "reject" domain
|
|
48
|
+
* and never reaches here. Returns true when the doc reached the local schema version.
|
|
49
|
+
*/
|
|
50
|
+
export declare function runSchemaMigrations(ctx: MigrationCtx, report: DocVersionReport): boolean;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import type { LoroDoc } from "loro-crdt";
|
|
25
25
|
import type { DurableStore } from "@vibecook/strata-ecs/durable";
|
|
26
|
+
import { type EnvelopeHeader } from "./envelope";
|
|
26
27
|
export interface DocVersionReport {
|
|
27
28
|
/** Highest engine.schema.<n> marker present (0 = unstamped/pre-engine doc). */
|
|
28
29
|
readonly docSchema: number;
|
|
@@ -45,5 +46,7 @@ export type GateVerdict = "ok" | "readOnly" | "migrate" | "reject";
|
|
|
45
46
|
export declare function stampEngineMeta(store: DurableStore): void;
|
|
46
47
|
/** Read the marker keys off a raw (imported, unattached) doc and compare. */
|
|
47
48
|
export declare function readDocVersionReport(doc: LoroDoc): DocVersionReport;
|
|
49
|
+
/** Build the same comparison report from an envelope header, before Loro import. */
|
|
50
|
+
export declare function readEnvelopeVersionReport(header: EnvelopeHeader): DocVersionReport;
|
|
48
51
|
/** The default M5 policy. A facade policy hook may override (design-005 §6.3). */
|
|
49
52
|
export declare function gateVerdict(report: DocVersionReport): GateVerdict;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* The seam is deliberately dumb data: no callbacks into behaviors, no partial
|
|
13
13
|
* application — a whole gesture outcome in one value.
|
|
14
14
|
*/
|
|
15
|
-
import type { Component, Entity } from "@vibecook/strata-ecs";
|
|
15
|
+
import type { Component, Entity, OrderPlace } from "@vibecook/strata-ecs";
|
|
16
16
|
/** One absolute component write inside a commit (whole-value, design-001 §2). */
|
|
17
17
|
export interface CommitWrite {
|
|
18
18
|
readonly entity: Entity;
|
|
@@ -24,6 +24,17 @@ export interface CommitReparent {
|
|
|
24
24
|
readonly entity: Entity;
|
|
25
25
|
readonly container: Entity;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* An ordered-relation placement riding a commit (petition 8): the gesture's
|
|
29
|
+
* final sibling position lands IN the gesture's single transaction — one
|
|
30
|
+
* gesture stays one undo step. `parent` is re-asserted absolutely (a
|
|
31
|
+
* same-target `setRelation` WITH a place is a move, never a duplicate).
|
|
32
|
+
*/
|
|
33
|
+
export interface CommitOrder {
|
|
34
|
+
readonly entity: Entity;
|
|
35
|
+
readonly parent: Entity;
|
|
36
|
+
readonly place: OrderPlace;
|
|
37
|
+
}
|
|
27
38
|
/**
|
|
28
39
|
* A wire creation riding a connect outcome (design-003 §5.8; design-001
|
|
29
40
|
* §5.3): wires bind WIDGET entities + port IDS — never port entities.
|
|
@@ -34,13 +45,23 @@ export interface CommitWireSpawn {
|
|
|
34
45
|
readonly fromPort: string;
|
|
35
46
|
readonly toPort: string;
|
|
36
47
|
}
|
|
37
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* A widget creation riding a create outcome (draw tool, design-005 §3;
|
|
50
|
+
* tray-insert promote, 2026-07-19). `props`/`parent` extend the draw shape for
|
|
51
|
+
* ghost promotes: prop overrides rebuild the tray instance, `parent` lands a
|
|
52
|
+
* consume-into-container insert (x/y are container-LOCAL then, matching the
|
|
53
|
+
* reparent convention). `select` asks the sink to hand the projected twin to
|
|
54
|
+
* the reap system's selection transfer — the tray's select-on-drop.
|
|
55
|
+
*/
|
|
38
56
|
export interface CommitCreate {
|
|
39
57
|
readonly type: string;
|
|
40
58
|
readonly x: number;
|
|
41
59
|
readonly y: number;
|
|
42
60
|
readonly w: number;
|
|
43
61
|
readonly h: number;
|
|
62
|
+
readonly props?: Readonly<Record<string, unknown>>;
|
|
63
|
+
readonly parent?: Entity;
|
|
64
|
+
readonly select?: boolean;
|
|
44
65
|
}
|
|
45
66
|
export interface CommitIntent {
|
|
46
67
|
/** Outcome kind — traces assert on it. */
|
|
@@ -49,6 +70,7 @@ export interface CommitIntent {
|
|
|
49
70
|
readonly gesture: Entity;
|
|
50
71
|
readonly writes: readonly CommitWrite[];
|
|
51
72
|
readonly reparents?: readonly CommitReparent[];
|
|
73
|
+
readonly orders?: readonly CommitOrder[];
|
|
52
74
|
readonly wires?: readonly CommitWireSpawn[];
|
|
53
75
|
readonly creates?: readonly CommitCreate[];
|
|
54
76
|
}
|