@pygmalionjs/pygmalion 0.7.4 → 0.8.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.
Files changed (133) hide show
  1. package/README.ko.md +17 -2
  2. package/README.md +18 -2
  3. package/dist-lib/CameraLayer-nkNrazn8.js +159 -0
  4. package/dist-lib/pygmalion.js +14628 -16995
  5. package/dist-lib/runtime-DdYnT6k4.js +19705 -0
  6. package/dist-lib/style.css +1 -1
  7. package/dist-lib/testing.js +20 -21
  8. package/dist-lib/types/EditorShell.d.ts +1 -1
  9. package/dist-lib/types/canvas/CameraLayer.d.ts +3 -3
  10. package/dist-lib/types/canvas/Canvas.d.ts +2 -2
  11. package/dist-lib/types/canvas/FrameLabelBanner.d.ts +1 -1
  12. package/dist-lib/types/canvas/FrameView.d.ts +8 -2
  13. package/dist-lib/types/canvas/FrozenRoutePreview.d.ts +1 -1
  14. package/dist-lib/types/canvas/InspectOverlay.d.ts +4 -2
  15. package/dist-lib/types/canvas/LightweightCanvas.d.ts +1 -1
  16. package/dist-lib/types/canvas/SectionBoxes.d.ts +1 -1
  17. package/dist-lib/types/canvas/ShadowRoutePreview.d.ts +2 -2
  18. package/dist-lib/types/canvas/useFlowSession.d.ts +1 -1
  19. package/dist-lib/types/canvas/useFrameLod.d.ts +1 -1
  20. package/dist-lib/types/contract/transport.d.ts +5 -5
  21. package/dist-lib/types/contract/types.d.ts +1 -1
  22. package/dist-lib/types/contract/validate.d.ts +3 -3
  23. package/dist-lib/types/core/context.d.ts +2 -2
  24. package/dist-lib/types/core/debug.d.ts +14 -14
  25. package/dist-lib/types/core/hostBindings.d.ts +2 -2
  26. package/dist-lib/types/core/runtime.d.ts +34 -3
  27. package/dist-lib/types/core/runtimeContext.d.ts +3 -3
  28. package/dist-lib/types/core/schedulers.d.ts +67 -0
  29. package/dist-lib/types/editor/assetEditing.d.ts +2 -2
  30. package/dist-lib/types/editor/automaticMotion.d.ts +0 -11
  31. package/dist-lib/types/editor/automaticPseudoStates.d.ts +8 -2
  32. package/dist-lib/types/editor/captureSupply.d.ts +16 -7
  33. package/dist-lib/types/editor/catalog.d.ts +2 -2
  34. package/dist-lib/types/editor/codegen.d.ts +6 -3
  35. package/dist-lib/types/editor/componentConnections.d.ts +13 -8
  36. package/dist-lib/types/editor/componentInstances.d.ts +2 -2
  37. package/dist-lib/types/editor/declarations.d.ts +107 -0
  38. package/dist-lib/types/editor/designCompiler.d.ts +9 -4
  39. package/dist-lib/types/editor/designImport.d.ts +48 -12
  40. package/dist-lib/types/editor/documentSync.d.ts +28 -25
  41. package/dist-lib/types/editor/domImport.d.ts +2 -2
  42. package/dist-lib/types/editor/fiberMap.d.ts +1 -1
  43. package/dist-lib/types/editor/flowSessionScheduler.d.ts +106 -159
  44. package/dist-lib/types/editor/flowSessions.d.ts +147 -84
  45. package/dist-lib/types/editor/frameInteraction.d.ts +22 -32
  46. package/dist-lib/types/editor/frameLabels.d.ts +11 -5
  47. package/dist-lib/types/editor/frameLanes.d.ts +14 -17
  48. package/dist-lib/types/editor/frameLod.d.ts +17 -0
  49. package/dist-lib/types/editor/frameLodRuntime.d.ts +38 -38
  50. package/dist-lib/types/editor/framePreviewKeys.d.ts +14 -5
  51. package/dist-lib/types/editor/frozenImport.d.ts +13 -14
  52. package/dist-lib/types/editor/heldPseudoStates.d.ts +1 -1
  53. package/dist-lib/types/editor/host.d.ts +10 -55
  54. package/dist-lib/types/editor/implementationSourceMap.d.ts +2 -2
  55. package/dist-lib/types/editor/importFidelity.d.ts +1 -1
  56. package/dist-lib/types/editor/inspect.d.ts +7 -2
  57. package/dist-lib/types/editor/interactiveSessionSurface.d.ts +26 -34
  58. package/dist-lib/types/editor/interactiveStates.d.ts +12 -10
  59. package/dist-lib/types/editor/livePreviewInstances.d.ts +13 -3
  60. package/dist-lib/types/editor/liveScreens.d.ts +25 -16
  61. package/dist-lib/types/editor/mountScheduler.d.ts +8 -11
  62. package/dist-lib/types/editor/nodeSelector.d.ts +1 -1
  63. package/dist-lib/types/editor/pendingSourceChanges.d.ts +19 -0
  64. package/dist-lib/types/editor/previewBootstrap.d.ts +12 -22
  65. package/dist-lib/types/editor/previewCaptureProgress.d.ts +10 -6
  66. package/dist-lib/types/editor/previewEnvironmentControls.d.ts +14 -17
  67. package/dist-lib/types/editor/previewIntent.d.ts +11 -16
  68. package/dist-lib/types/editor/previewSweep.d.ts +7 -3
  69. package/dist-lib/types/editor/previewWarmup.d.ts +19 -7
  70. package/dist-lib/types/editor/projectRuntime.d.ts +2 -2
  71. package/dist-lib/types/editor/registry.d.ts +6 -2
  72. package/dist-lib/types/editor/revisionCatalog.d.ts +19 -19
  73. package/dist-lib/types/editor/revisionCatalogInstall.d.ts +18 -17
  74. package/dist-lib/types/editor/routePreview.d.ts +85 -139
  75. package/dist-lib/types/editor/scenarioCoverage.d.ts +52 -20
  76. package/dist-lib/types/editor/screenCards.d.ts +10 -6
  77. package/dist-lib/types/editor/screenDimensions.d.ts +9 -5
  78. package/dist-lib/types/editor/screenFlows.d.ts +8 -5
  79. package/dist-lib/types/editor/screenInteractions.d.ts +9 -1
  80. package/dist-lib/types/editor/screenLists.d.ts +8 -4
  81. package/dist-lib/types/editor/screenStateGroups.d.ts +1 -1
  82. package/dist-lib/types/editor/sectionHeaders.d.ts +10 -6
  83. package/dist-lib/types/editor/sessionPresets.d.ts +12 -32
  84. package/dist-lib/types/editor/shadowPreview.d.ts +7 -10
  85. package/dist-lib/types/editor/sharedSource.d.ts +4 -2
  86. package/dist-lib/types/editor/sourceChangeSummary.d.ts +1 -1
  87. package/dist-lib/types/editor/sourceJournal.d.ts +2 -2
  88. package/dist-lib/types/editor/stateSwitchMetrics.d.ts +68 -82
  89. package/dist-lib/types/editor/store.d.ts +88 -22
  90. package/dist-lib/types/editor/storyboardAuthored.d.ts +2 -2
  91. package/dist-lib/types/editor/storyboardDiscovery.d.ts +4 -3
  92. package/dist-lib/types/editor/storyboardEnvironment.d.ts +9 -5
  93. package/dist-lib/types/editor/storyboardGraph.d.ts +1 -1
  94. package/dist-lib/types/editor/storyboardGraphRuntime.d.ts +8 -10
  95. package/dist-lib/types/editor/storyboardGraphView.d.ts +1 -1
  96. package/dist-lib/types/editor/storyboardJourney.d.ts +1 -1
  97. package/dist-lib/types/editor/surfaceDemands.d.ts +196 -31
  98. package/dist-lib/types/editor/tokens.d.ts +24 -25
  99. package/dist-lib/types/editor/variantAxes.d.ts +70 -0
  100. package/dist-lib/types/editor/variantPrefetch.d.ts +26 -43
  101. package/dist-lib/types/editor/viewportPresets.d.ts +6 -6
  102. package/dist-lib/types/editor/visualQa.d.ts +2 -2
  103. package/dist-lib/types/lib.d.ts +104 -108
  104. package/dist-lib/types/shell/CatalogAssetPanel.d.ts +1 -1
  105. package/dist-lib/types/shell/CodePanel.d.ts +1 -1
  106. package/dist-lib/types/shell/ComponentStateControls.d.ts +7 -53
  107. package/dist-lib/types/shell/FrameInspector.d.ts +17 -0
  108. package/dist-lib/types/shell/FrameReviewDetails.d.ts +28 -0
  109. package/dist-lib/types/shell/LayerTree.d.ts +1 -1
  110. package/dist-lib/types/shell/StoryboardGraphPanel.d.ts +2 -2
  111. package/dist-lib/types/shell/VariantPanel.d.ts +23 -0
  112. package/dist-lib/types/shell/inspectorControls.d.ts +34 -0
  113. package/dist-lib/types/shell/qaPresentation.d.ts +1 -1
  114. package/dist-lib/types/testing.d.ts +5 -6
  115. package/dist-lib/types/ui/SourceRefControl.d.ts +1 -1
  116. package/docs/coverage-contracts.md +431 -0
  117. package/docs/screen-state-contract.md +14 -16
  118. package/node/component-branches.mjs +7 -13
  119. package/node/design-session.mjs +3 -5
  120. package/node/dev-mirror.mjs +9 -6
  121. package/node/envelope.mjs +43 -0
  122. package/node/impact-frames.mjs +94 -0
  123. package/node/inspect-plugin.mjs +12 -6
  124. package/node/preview-artifact-plugin.mjs +3 -9
  125. package/node/qa-capture-plugin.mjs +3 -6
  126. package/node/source-graph.mjs +1 -0
  127. package/node/storyboard-environment.mjs +33 -6
  128. package/node/vite.mjs +1 -0
  129. package/package.json +7 -2
  130. package/dist-lib/CameraLayer-D2wrEPwG.js +0 -415
  131. package/dist-lib/frameLodRuntime-CU0IYaSu.js +0 -272
  132. package/dist-lib/runtime-DRkTU9eq.js +0 -16195
  133. package/dist-lib/types/core/defaultRuntime.d.ts +0 -3
@@ -1,7 +1,10 @@
1
- import { type DesignImportController, type DesignScreenCaptureSpec } from './designImport';
2
- import type { FlowSessionRunner, ResolvedFlowPath } from './flowSessions';
3
- import type { ScreenFlowPath } from './screenFlows';
4
- import type { EditorStore, PageModel } from './store';
1
+ import { type DesignImportController, type DesignScreenCaptureSpec } from './designImport.js';
2
+ import type { RoutePreviewCache } from './routePreview.js';
3
+ import type { FlowSessionRunner, FlowSessions, ResolvedFlowPath } from './flowSessions.js';
4
+ import { type InteractiveSessionSurfaces } from './interactiveSessionSurface.js';
5
+ import type { ScreenFlowPath } from './screenFlows.js';
6
+ import type { EditorStore, PageModel } from './store.js';
7
+ import type { EditorDeclarations } from './declarations.js';
5
8
  /** What the scheduler needs from an editor runtime; `EditorRuntime` satisfies it. */
6
9
  export interface FlowSessionRuntime {
7
10
  readonly store: EditorStore;
@@ -9,86 +12,12 @@ export interface FlowSessionRuntime {
9
12
  readonly appOrigin: string;
10
13
  readonly previewRevision: string;
11
14
  };
15
+ readonly previews: RoutePreviewCache;
16
+ readonly declarations: EditorDeclarations;
12
17
  }
13
18
  /** Applies the active frame's own boot condition to a path-specific session. */
14
- export declare function resolveActivePagePath(resolved: ResolvedFlowPath, path: ScreenFlowPath, page: PageModel, appOrigin: string): ResolvedFlowPath;
19
+ export declare function resolveActivePagePath(declarations: Pick<EditorDeclarations, 'getStoryboardBaselineEnvironment' | 'getPreviewEnvironmentOverride'>, resolved: ResolvedFlowPath, path: ScreenFlowPath, page: PageModel, appOrigin: string): ResolvedFlowPath;
15
20
  /** Diagnostic counters for the headless debug surface. */
16
- export declare const __flowSchedulerDebug: {
17
- calls: number;
18
- lastCanvas: string;
19
- lastFlows: number;
20
- lastCandidates: number;
21
- lastQueued: number;
22
- };
23
- /**
24
- * Materializes the flow-declared screens of one canvas that still lack a
25
- * frozen snapshot. Paths delivering the active frame's screen run first.
26
- * Returns the number of paths queued.
27
- */
28
- export declare function materializeCanvasFlows(runtime: FlowSessionRuntime, input: {
29
- canvas: string;
30
- previewRevision: string;
31
- /**
32
- * Only paths that deliver one of these screens. The worker-first supply
33
- * hands the walking supply exactly the screens the worker could not answer;
34
- * without a filter every path on the canvas is a candidate.
35
- */
36
- screenIds?: ReadonlySet<string>;
37
- }): number;
38
- /** Session delivery state for one page, keyed by its catalog screen id. */
39
- export declare function flowSessionWillDeliverPage(page: {
40
- importPageId?: string;
41
- id: string;
42
- }): boolean;
43
- /**
44
- * Walks an instance to the active frame's screen in the background and parks
45
- * it, unless a parked instance already serves that path. Returns true when a
46
- * warming walk was queued.
47
- */
48
- export declare function warmActiveFrameInstance(runtime: FlowSessionRuntime, page: PageModel, previewRevision: string): boolean;
49
- /** Diagnostic counters for activation warming. */
50
- export declare const __warmingDebug: {
51
- requested: number;
52
- noPath: number;
53
- resolvedNull: number;
54
- alreadyWarm: number;
55
- queued: number;
56
- };
57
- /**
58
- * Materializes one screen at an explicit viewport through its flow path.
59
- * Prefix waypoints walk as pass-through (steps only); the target publishes
60
- * under the page's recipe key at that viewport — the key its frame reads
61
- * after the size change commits. Returns false when no flow claims the
62
- * screen (the live re-import fallback stays for those).
63
- */
64
- export declare function materializePageViewport(runtime: FlowSessionRuntime, page: PageModel, viewport: {
65
- width: number;
66
- height: number;
67
- }, previewRevision: string): boolean;
68
- /** True while a viewport-variant session still owes this page's snapshot. */
69
- export declare function viewportSessionWillDeliver(page: {
70
- importPageId?: string;
71
- id: string;
72
- }, viewport: {
73
- width: number;
74
- height: number;
75
- }): boolean;
76
- /** Subscribe to viewport-variant delivery changes. */
77
- export declare function subscribeViewportSessions(listener: () => void): () => void;
78
- type InteractivePreparationController = Pick<DesignImportController, 'prepareScreenCapture' | 'prepareScreenState'>;
79
- /**
80
- * Reproduces an editor-controlled state without capture-only quiescence.
81
- * Direct desired state is presented as soon as the host commits React; replay
82
- * states remain hidden until their gestures finish. Frozen persistence may
83
- * continue afterward without delaying either live presentation path.
84
- */
85
- export declare function prepareInteractiveSessionState(iframe: HTMLIFrameElement, spec: DesignScreenCaptureSpec, controller?: InteractivePreparationController | null, onStateReady?: () => void): Promise<import("./designImport").DesignScreenCaptureReport>;
86
- /**
87
- * Test seam: replaces the interactive runner with one whose boot/prepare/
88
- * publish are injected fakes, so the variant-and-repark queueing can run
89
- * headless. Passing null restores the default runner on next use.
90
- */
91
- export declare function __setInteractiveSessionRunnerForTests(runner: FlowSessionRunner | null): void;
92
21
  export declare function interactiveSessionScreenId(page: {
93
22
  id: string;
94
23
  interactiveStateId?: string;
@@ -103,85 +32,103 @@ export declare function interactiveSessionSurfaceId(page: {
103
32
  interactiveOptionIds?: readonly string[];
104
33
  interactiveStateUsesDesiredState?: boolean;
105
34
  }): string;
106
- /**
107
- * Materializes one screen in its declared interactive state through the
108
- * screen's flow path. The prefix walks as pass-through; the target publishes
109
- * under the page's own recipe key, which already includes the option's steps
110
- * (the store appends them to the recipe, and resolvePath replays them).
111
- * Returns false when no flow claims the screen — those frames keep the live
112
- * boot fallback.
113
- */
114
- export declare function materializePageInteractiveState(runtime: FlowSessionRuntime, page: PageModel, previewRevision: string, targetCacheKey?: string): boolean;
115
- /** True while an interactive-state session still owes this page its snapshot. */
116
- export declare function interactiveSessionWillDeliver(page: {
117
- id: string;
118
- interactiveStateId?: string;
119
- interactiveOptionId?: string;
120
- interactiveOptionIds?: readonly string[];
121
- interactiveStateUsesDesiredState?: boolean;
122
- }, targetCacheKey?: string): boolean;
123
- /** Subscribe to interactive-state delivery changes. */
124
- export declare function subscribeInteractiveSessions(listener: () => void): () => void;
125
- /** How one speculative enqueue attempt ended. */
126
35
  export type InteractiveVariantPrefetchOutcome = 'queued' | 'busy' | 'tracked' | 'unavailable';
127
- /** True when the interactive runner has nothing queued or walking. */
128
- export declare function interactiveSessionRunnerIsIdle(): boolean;
129
- /**
130
- * True when the interactive runner already tracks this variant's delivery in
131
- * any status. Unlike interactiveSessionWillDeliver, an untracked variant
132
- * reads as false here: the prefetch policy asks "is anyone already on it",
133
- * not "should the frame wait".
134
- */
135
- export declare function interactiveSessionTracksVariant(variantPage: {
136
- importPageId?: string;
137
- id: string;
138
- interactiveStateId?: string;
139
- interactiveOptionId?: string;
140
- }): boolean;
36
+ export interface FlowSessionSchedulerDeps {
37
+ /** This runtime's warm pool, runner factory, and canonical runner. */
38
+ sessions: FlowSessions;
39
+ /** This runtime's session surfaces; the direct-state handlers go on them. */
40
+ surfaces: InteractiveSessionSurfaces;
41
+ }
141
42
  /**
142
- * Queues one speculative walk for a hypothetical variant identity — a shallow
143
- * page clone carrying the interactions/environment/state fields the store's
144
- * applyInteractiveState would produce for the option (variantPrefetch.ts
145
- * derives it). Sibling of materializePageInteractiveState, kept separate so
146
- * speculation never changes the real request path.
147
- *
148
- * The user must never wait behind speculation: the runner is concurrency-1
149
- * FIFO, so this enqueues only into an EMPTY runner ('busy' otherwise). At
150
- * most one speculative walk is therefore ever queued or running, and a real
151
- * selection made meanwhile queues behind that single walk at worst.
43
+ * One editor's flow-session scheduling: the canvas fill, the activation warm,
44
+ * the viewport and interactive runners with their delivery states, the
45
+ * direct-state paths, and the counters the debug surface reads. Bound to one
46
+ * runtime, so it reads that runtime's store, host, and preview cache and
47
+ * installs its direct-state handlers on that runtime's surfaces.
152
48
  */
153
- export declare function prefetchPageInteractiveVariant(runtime: FlowSessionRuntime, variantPage: PageModel, previewRevision: string): InteractiveVariantPrefetchOutcome;
154
- /** Diagnostic counters for the interactive-state path. */
155
- export declare const __interactiveSessionDebug: {
156
- requested: number;
157
- noPath: number;
158
- resolvedNull: number;
159
- queued: number;
160
- /** Base-prefix re-park warming walks queued behind variant deliveries. */
161
- reparkQueued: number;
162
- /** Re-parks skipped because a parked base instance already serves the prefix. */
163
- reparkAlreadyParked: number;
164
- /** Re-parks skipped because the option adds no steps over the base screen. */
165
- reparkNoExtraSteps: number;
166
- };
167
- /** Interactive-runner delivery states for the headless debug surface. */
168
- export declare function __debugInteractiveSessionStates(): Record<string, unknown>;
169
- /** Diagnostic counters for the viewport-commit path. */
170
- export declare const __viewportCommitDebug: {
171
- requested: number;
172
- resolvedNull: number;
173
- controllerMissing: number;
174
- markerGone: number;
175
- editsWon: number;
176
- captureNull: number;
177
- committed: number;
49
+ export declare function createFlowSessionScheduler(runtime: FlowSessionRuntime, deps: FlowSessionSchedulerDeps): {
50
+ __flowSchedulerDebug: {
51
+ calls: number;
52
+ lastCanvas: string;
53
+ lastFlows: number;
54
+ lastCandidates: number;
55
+ lastQueued: number;
56
+ };
57
+ materializeCanvasFlows: (input: {
58
+ canvas: string;
59
+ previewRevision: string;
60
+ /**
61
+ * Only paths that deliver one of these screens. The worker-first supply
62
+ * hands the walking supply exactly the screens the worker could not answer;
63
+ * without a filter every path on the canvas is a candidate.
64
+ */
65
+ screenIds?: ReadonlySet<string>;
66
+ }) => number;
67
+ flowSessionWillDeliverPage: (page: {
68
+ importPageId?: string;
69
+ id: string;
70
+ }) => boolean;
71
+ warmActiveFrameInstance: (page: PageModel, previewRevision: string) => boolean;
72
+ __warmingDebug: {
73
+ requested: number;
74
+ noPath: number;
75
+ resolvedNull: number;
76
+ alreadyWarm: number;
77
+ queued: number;
78
+ };
79
+ materializePageViewport: (page: PageModel, viewport: {
80
+ width: number;
81
+ height: number;
82
+ }, previewRevision: string) => boolean;
83
+ viewportSessionWillDeliver: (page: {
84
+ importPageId?: string;
85
+ id: string;
86
+ }, viewport: {
87
+ width: number;
88
+ height: number;
89
+ }) => boolean;
90
+ subscribeViewportSessions: (listener: () => void) => () => void;
91
+ prepareInteractiveSessionState: (iframe: HTMLIFrameElement, spec: DesignScreenCaptureSpec, controller?: Pick<DesignImportController, "prepareScreenCapture" | "prepareScreenState"> | null, onStateReady?: () => void) => Promise<import("./designImport.js").DesignScreenCaptureReport>;
92
+ __setInteractiveSessionRunnerForTests: (runner: FlowSessionRunner | null) => void;
93
+ materializePageInteractiveState: (page: PageModel, previewRevision: string, targetCacheKey?: string) => boolean;
94
+ interactiveSessionWillDeliver: (previews: Pick<RoutePreviewCache, "hasExactRoutePreviewSnapshot">, page: {
95
+ id: string;
96
+ interactiveStateId?: string;
97
+ interactiveOptionId?: string;
98
+ interactiveOptionIds?: readonly string[];
99
+ interactiveStateUsesDesiredState?: boolean;
100
+ }, targetCacheKey?: string) => boolean;
101
+ subscribeInteractiveSessions: (listener: () => void) => () => void;
102
+ interactiveSessionRunnerIsIdle: () => boolean;
103
+ interactiveSessionTracksVariant: (variantPage: {
104
+ importPageId?: string;
105
+ id: string;
106
+ interactiveStateId?: string;
107
+ interactiveOptionId?: string;
108
+ }) => boolean;
109
+ prefetchPageInteractiveVariant: (variantPage: PageModel, previewRevision: string) => InteractiveVariantPrefetchOutcome;
110
+ __interactiveSessionDebug: {
111
+ requested: number;
112
+ noPath: number;
113
+ resolvedNull: number;
114
+ queued: number;
115
+ /** Base-prefix re-park warming walks queued behind variant deliveries. */
116
+ reparkQueued: number;
117
+ /** Re-parks skipped because a parked base instance already serves the prefix. */
118
+ reparkAlreadyParked: number;
119
+ /** Re-parks skipped because the option adds no steps over the base screen. */
120
+ reparkNoExtraSteps: number;
121
+ };
122
+ __debugInteractiveSessionStates: () => Record<string, unknown>;
123
+ __viewportCommitDebug: {
124
+ requested: number;
125
+ resolvedNull: number;
126
+ controllerMissing: number;
127
+ markerGone: number;
128
+ editsWon: number;
129
+ captureNull: number;
130
+ committed: number;
131
+ };
132
+ __debugViewportSessionStates: () => Record<string, unknown>;
178
133
  };
179
- /** Viewport-runner delivery states for the headless debug surface. */
180
- export declare function __debugViewportSessionStates(): Record<string, unknown>;
181
- /**
182
- * Installs the direct-state handlers for one runtime and returns their
183
- * remover. Called from `runtime.attach()`, so a mounted editor owns them and
184
- * an unmounted one releases them.
185
- */
186
- export declare function installDirectInteractiveStateHandlers(runtime: FlowSessionRuntime): () => void;
187
- export {};
134
+ export type FlowSessionScheduler = ReturnType<typeof createFlowSessionScheduler>;
@@ -1,4 +1,7 @@
1
- import type { DesignScreenAssertion, DesignScreenCaptureReport, DesignScreenDesiredState, DesignScreenInteraction, DesignScreenPreset } from './designImport';
1
+ import type { DesignScreenAssertion, DesignScreenCaptureReport, DesignScreenDesiredState, DesignScreenInteraction, DesignScreenPreset } from './designImport.js';
2
+ import type { RoutePreviewCache } from './routePreview.js';
3
+ import { type StateSwitchMetrics } from './stateSwitchMetrics.js';
4
+ import type { EditorDeclarations } from './declarations.js';
2
5
  export interface ResolvedFlowWaypoint {
3
6
  screenId: string;
4
7
  /**
@@ -107,6 +110,13 @@ export interface FlowSessionRunnerOptions {
107
110
  settle?: (iframe: HTMLIFrameElement, ms: number) => Promise<void>;
108
111
  /** Layout-stability wait before serializing. Defaults to waitForGeometryStability. */
109
112
  waitForStability?: (iframe: HTMLIFrameElement) => Promise<void>;
113
+ /**
114
+ * The preview cache a walked screen is published into. Required unless
115
+ * both `serialize` and `publish` are supplied, as tests do.
116
+ */
117
+ previews?: Pick<RoutePreviewCache, 'serializeRoutePreview' | 'setRoutePreviewSnapshot'>;
118
+ /** Where walk phases are recorded; the runtime passes its own metrics. */
119
+ metrics?: Pick<StateSwitchMetrics, 'beginStateSwitchWalk' | 'beginStateSwitchWaypoint' | 'markStateSwitchPhase' | 'recordStateSwitchPhase' | 'endStateSwitchWalk'>;
110
120
  serialize?: (iframe: HTMLIFrameElement, fallbackUrl: string) => string | null;
111
121
  /** Writes one waypoint snapshot into the route preview store. */
112
122
  publish?: (cacheKey: string, snapshot: string) => boolean;
@@ -130,89 +140,142 @@ export interface FlowSessionRunnerOptions {
130
140
  */
131
141
  export declare function waitForGeometryStability(iframe: HTMLIFrameElement, timeoutMs?: number): Promise<void>;
132
142
  export declare function createFlowSessionIframe(): HTMLIFrameElement;
133
- /** Test/tuning hook for how long a parked instance stays claimable. */
134
- export declare function setFlowSessionWarmTtl(ms: number): void;
135
- /** Warm-pool counters for the headless debug surface. */
136
- export declare const __flowSessionWarmDebug: {
137
- boots: number;
138
- reuses: number;
139
- parks: number;
140
- evictions: number;
141
- /** Warming walks answered by renewing an already-parked instance's lease. */
142
- refreshes: number;
143
- /** Which supply booted, so a stray second boot is attributable. */
144
- bootsByRunner: Record<string, number>;
145
- };
146
- /** Drops parked instances globally, or only those owned by one runner. */
147
- export declare function evictFlowSessionWarmInstances(ownerLabel?: string, options?: {
148
- preservePinned?: boolean;
149
- }): void;
143
+ export interface FlowSessionsDeps {
144
+ /** The cache every runner of this editor publishes into unless told otherwise. */
145
+ previews?: FlowSessionRunnerOptions['previews'];
146
+ /** Where every runner of this editor records its walk phases. */
147
+ metrics?: FlowSessionRunnerOptions['metrics'];
148
+ /** The host declarations a runner prepares waypoints against. */
149
+ declarations?: EditorDeclarations;
150
+ }
150
151
  /**
151
- * True when a walk of this path would resume on a parked instance. Activation
152
- * warming reads it to decide whether the frame already has a resumable
153
- * instance or one has to be walked in the background.
152
+ * One editor's flow sessions: the warm pool of parked application instances
153
+ * every runner shares, the runner factory bound to that pool, and the
154
+ * canonical runner that fills the canvas. Every runtime owns one.
154
155
  */
155
- export declare function warmInstanceServesPath(path: ResolvedFlowPath): boolean;
156
- /** Returns an idle document already parked at this path's exact endpoint. */
157
- export declare function warmInstanceAtPathEnd(path: ResolvedFlowPath): HTMLIFrameElement | null;
158
- export declare function createFlowSessionRunner(options?: FlowSessionRunnerOptions): {
159
- /**
160
- * Queues paths for materialization. Screens already delivered, failed, or
161
- * claimed by a queued path are skipped — callers re-request freely.
162
- */
163
- materialize(paths: readonly ResolvedFlowPath[]): number;
164
- /**
165
- * Applies a path's terminal state on a known live document. The caller
166
- * guarantees that this iframe already reached the path's route and base
167
- * prefix; all gesture steps are therefore skipped and only the target's
168
- * complete desired-state map is prepared. FIFO ordering keeps a document
169
- * exposed by the current walk from being mutated until that walk finishes.
170
- */
171
- materializeOnInstance(path: ResolvedFlowPath, iframe: HTMLIFrameElement): number;
172
- /**
173
- * Drops queued paths the predicate rejects, releasing their pending
174
- * screens so a later materialize can queue them again. Running walks are
175
- * untouched. Called when the designer moves to another canvas: the
176
- * paths of the canvas they left should not run ahead of the one they
177
- * are looking at.
178
- */
179
- pruneQueue(keep: (path: ResolvedFlowPath) => boolean): number;
180
- /** Live instances that may walk at once; takes effect at the next pump. */
181
- setConcurrency(next: number): void;
182
- /** Session state of one screen, or null when no session claims it. */
183
- screenState(screenId: string): FlowScreenState | null;
184
- /**
185
- * Forgets a terminal delivery whose external snapshot was evicted. A
186
- * running or queued screen keeps its claim and cannot be invalidated.
187
- */
188
- forgetScreen(screenId: string): boolean;
189
- /** True while the session still owes this screen its snapshot. */
190
- willDeliver(screenId: string): boolean;
191
- /**
192
- * True when nothing is queued or walking. Speculative callers read this
193
- * before enqueueing: the runner is FIFO, so speculative work queued ahead
194
- * of a designer's real request would delay it speculation may only
195
- * enter an empty runner.
196
- */
197
- isIdle(): boolean;
198
- subscribe(listener: () => void): () => void;
199
- /**
200
- * Drops all session state. Running paths notice the round change at their
201
- * next waypoint boundary and stop; their remaining screens re-queue on
202
- * the next materialize call.
203
- */
204
- reset(): void;
205
- /** Test/diagnostic snapshot of every tracked screen. */
206
- debugScreenStates(): Record<string, FlowScreenState>;
207
- /** How many finished walks currently have an instance parked for reuse. */
208
- debugWarmInstancesParked(): number;
156
+ export declare function createFlowSessions(deps?: FlowSessionsDeps): {
157
+ setFlowSessionWarmTtl: (ms: number) => void;
158
+ __flowSessionWarmDebug: {
159
+ boots: number;
160
+ reuses: number;
161
+ parks: number;
162
+ evictions: number;
163
+ /** Warming walks answered by renewing an already-parked instance's lease. */
164
+ refreshes: number;
165
+ /** Which supply booted, so a stray second boot is attributable. */
166
+ bootsByRunner: Record<string, number>;
167
+ };
168
+ evictFlowSessionWarmInstances: (ownerLabel?: string, options?: {
169
+ preservePinned?: boolean;
170
+ }) => void;
171
+ warmInstanceServesPath: (path: ResolvedFlowPath) => boolean;
172
+ warmInstanceAtPathEnd: (path: ResolvedFlowPath) => HTMLIFrameElement | null;
173
+ createFlowSessionRunner: (options?: FlowSessionRunnerOptions) => {
174
+ /**
175
+ * Queues paths for materialization. Screens already delivered, failed, or
176
+ * claimed by a queued path are skipped callers re-request freely.
177
+ */
178
+ materialize(paths: readonly ResolvedFlowPath[]): number;
179
+ /**
180
+ * Applies a path's terminal state on a known live document. The caller
181
+ * guarantees that this iframe already reached the path's route and base
182
+ * prefix; all gesture steps are therefore skipped and only the target's
183
+ * complete desired-state map is prepared. FIFO ordering keeps a document
184
+ * exposed by the current walk from being mutated until that walk finishes.
185
+ */
186
+ materializeOnInstance(path: ResolvedFlowPath, iframe: HTMLIFrameElement): number;
187
+ /**
188
+ * Drops queued paths the predicate rejects, releasing their pending
189
+ * screens so a later materialize can queue them again. Running walks are
190
+ * untouched. Called when the designer moves to another canvas: the
191
+ * paths of the canvas they left should not run ahead of the one they
192
+ * are looking at.
193
+ */
194
+ pruneQueue(keep: (path: ResolvedFlowPath) => boolean): number;
195
+ /** Live instances that may walk at once; takes effect at the next pump. */
196
+ setConcurrency(next: number): void;
197
+ /** Session state of one screen, or null when no session claims it. */
198
+ screenState(screenId: string): FlowScreenState | null;
199
+ /**
200
+ * Forgets a terminal delivery whose external snapshot was evicted. A
201
+ * running or queued screen keeps its claim and cannot be invalidated.
202
+ */
203
+ forgetScreen(screenId: string): boolean;
204
+ /** True while the session still owes this screen its snapshot. */
205
+ willDeliver(screenId: string): boolean;
206
+ /**
207
+ * True when nothing is queued or walking. Speculative callers read this
208
+ * before enqueueing: the runner is FIFO, so speculative work queued ahead
209
+ * of a designer's real request would delay it — speculation may only
210
+ * enter an empty runner.
211
+ */
212
+ isIdle(): boolean;
213
+ subscribe(listener: () => void): () => void;
214
+ /**
215
+ * Drops all session state. Running paths notice the round change at their
216
+ * next waypoint boundary and stop; their remaining screens re-queue on
217
+ * the next materialize call.
218
+ */
219
+ reset(): void;
220
+ /** Test/diagnostic snapshot of every tracked screen. */
221
+ debugScreenStates(): Record<string, FlowScreenState>;
222
+ /** How many finished walks currently have an instance parked for reuse. */
223
+ debugWarmInstancesParked(): number;
224
+ };
225
+ getFlowSessionRunner: () => ReturnType<(options?: FlowSessionRunnerOptions) => {
226
+ /**
227
+ * Queues paths for materialization. Screens already delivered, failed, or
228
+ * claimed by a queued path are skipped — callers re-request freely.
229
+ */
230
+ materialize(paths: readonly ResolvedFlowPath[]): number;
231
+ /**
232
+ * Applies a path's terminal state on a known live document. The caller
233
+ * guarantees that this iframe already reached the path's route and base
234
+ * prefix; all gesture steps are therefore skipped and only the target's
235
+ * complete desired-state map is prepared. FIFO ordering keeps a document
236
+ * exposed by the current walk from being mutated until that walk finishes.
237
+ */
238
+ materializeOnInstance(path: ResolvedFlowPath, iframe: HTMLIFrameElement): number;
239
+ /**
240
+ * Drops queued paths the predicate rejects, releasing their pending
241
+ * screens so a later materialize can queue them again. Running walks are
242
+ * untouched. Called when the designer moves to another canvas: the
243
+ * paths of the canvas they left should not run ahead of the one they
244
+ * are looking at.
245
+ */
246
+ pruneQueue(keep: (path: ResolvedFlowPath) => boolean): number;
247
+ /** Live instances that may walk at once; takes effect at the next pump. */
248
+ setConcurrency(next: number): void;
249
+ /** Session state of one screen, or null when no session claims it. */
250
+ screenState(screenId: string): FlowScreenState | null;
251
+ /**
252
+ * Forgets a terminal delivery whose external snapshot was evicted. A
253
+ * running or queued screen keeps its claim and cannot be invalidated.
254
+ */
255
+ forgetScreen(screenId: string): boolean;
256
+ /** True while the session still owes this screen its snapshot. */
257
+ willDeliver(screenId: string): boolean;
258
+ /**
259
+ * True when nothing is queued or walking. Speculative callers read this
260
+ * before enqueueing: the runner is FIFO, so speculative work queued ahead
261
+ * of a designer's real request would delay it — speculation may only
262
+ * enter an empty runner.
263
+ */
264
+ isIdle(): boolean;
265
+ subscribe(listener: () => void): () => void;
266
+ /**
267
+ * Drops all session state. Running paths notice the round change at their
268
+ * next waypoint boundary and stop; their remaining screens re-queue on
269
+ * the next materialize call.
270
+ */
271
+ reset(): void;
272
+ /** Test/diagnostic snapshot of every tracked screen. */
273
+ debugScreenStates(): Record<string, FlowScreenState>;
274
+ /** How many finished walks currently have an instance parked for reuse. */
275
+ debugWarmInstancesParked(): number;
276
+ }>;
277
+ setFlowSessionConcurrency: (concurrency: number) => void;
278
+ resetFlowSessionRunner: () => void;
209
279
  };
210
- export type FlowSessionRunner = ReturnType<typeof createFlowSessionRunner>;
211
- export declare function getFlowSessionRunner(): FlowSessionRunner;
212
- /**
213
- * How many walks the canonical supply runs at once. The host declares it,
214
- * because only the host knows whether its mocked backends survive two
215
- * sessions; the default of one is the safe choice.
216
- */
217
- export declare function setFlowSessionConcurrency(concurrency: number): void;
218
- export declare function resetFlowSessionRunner(): void;
280
+ export type FlowSessions = ReturnType<typeof createFlowSessions>;
281
+ export type FlowSessionRunner = ReturnType<FlowSessions['createFlowSessionRunner']>;
@@ -34,39 +34,29 @@ export interface FrameInteractionEntryContext {
34
34
  export declare function canBeginFrameInteraction({ editMode, tool, hasRoute, liveOriginReady, backgroundOnly, }: FrameInteractionEntryContext): boolean;
35
35
  /** Keeps canvas tools authoritative except during selection or live input. */
36
36
  export declare function canvasFramePointerEventsEnabled(editMode: boolean, tool: string, interactionActive: boolean): boolean;
37
- /** Starts a transient live-input session for one code-backed frame. */
38
- export declare function beginFrameInteraction(frameId: string): void;
39
- /** Ends the current session. A frame id prevents stale cleanups from ending a newer one. */
40
- export declare function exitFrameInteraction(frameId?: string): boolean;
41
- /**
42
- * Keeps interaction scoped to the selected frame and to view-only/select mode.
43
- * Returns true when a session was closed.
44
- */
45
- export declare function reconcileFrameInteractionScope(activeFrameId: string | null, enabled: boolean): boolean;
46
- export declare function getFrameInteractionSnapshot(): FrameInteractionSnapshot;
47
- export declare function subscribeFrameInteraction(listener: () => void): () => void;
48
- /**
49
- * Connects the running preview viewport once its declared screen state arrives.
50
- * The bridge is deliberately imperative: a side panel can read and set scroll
51
- * without learning whether the running surface is an iframe or another host.
52
- */
53
- export declare function connectFrameInteractionViewport(frameId: string, adapter: FrameInteractionViewportAdapter): () => void;
54
- /**
55
- * Makes the frozen DOM useful immediately while its live React document warms.
56
- * The preview is a scroll-only bridge: navigation and form submission stay
57
- * contained, and the live iframe later replaces it without ending the session.
58
- */
59
- export declare function connectFrameInteractionPreview(frameId: string, root: ShadowRoot, contentElement: HTMLElement): () => void;
60
- /** Scrolls the running frame viewport and immediately republishes its reading. */
61
- export declare function setFrameInteractionScroll(position: {
62
- x?: number;
63
- y?: number;
64
- }): boolean;
65
37
  /** Hash and query changes stay in the same screen; another path leaves it. */
66
38
  export declare function frameInteractionNavigationStaysInFrame(baselineHref: string, nextHref: string): boolean;
67
39
  /** Blocks document navigation while leaving ordinary in-screen events intact. */
68
40
  export declare function installFrameInteractionNavigationGuard(view: Window, document: Document): () => void;
69
- /** Connects a same-origin live iframe, including Escape and nested scroll tracking. */
70
- export declare function connectFrameInteractionIframe(frameId: string, iframe: HTMLIFrameElement): () => void;
71
- /** Test seam for independent runtime cases. */
72
- export declare function resetFrameInteraction(): void;
41
+ /**
42
+ * The per-runtime live-input session: the frame in live input, its phase and
43
+ * scroll reading, the connected viewport bridge, and the listeners the shell
44
+ * and panels subscribe through. The bodies below are the former module-level
45
+ * functions, closed over instance state instead of module state.
46
+ */
47
+ export declare function createFrameInteraction(): {
48
+ beginFrameInteraction: (frameId: string) => void;
49
+ exitFrameInteraction: (frameId?: string) => boolean;
50
+ reconcileFrameInteractionScope: (activeFrameId: string | null, enabled: boolean) => boolean;
51
+ getFrameInteractionSnapshot: () => FrameInteractionSnapshot;
52
+ subscribeFrameInteraction: (listener: () => void) => () => void;
53
+ connectFrameInteractionViewport: (frameId: string, adapter: FrameInteractionViewportAdapter) => () => void;
54
+ connectFrameInteractionPreview: (frameId: string, root: ShadowRoot, contentElement: HTMLElement) => () => void;
55
+ setFrameInteractionScroll: (position: {
56
+ x?: number;
57
+ y?: number;
58
+ }) => boolean;
59
+ connectFrameInteractionIframe: (frameId: string, iframe: HTMLIFrameElement) => () => void;
60
+ resetFrameInteraction: () => void;
61
+ };
62
+ export type FrameInteraction = ReturnType<typeof createFrameInteraction>;
@@ -1,4 +1,4 @@
1
- import type { PageModel } from './store';
1
+ import type { PageModel } from './store.js';
2
2
  /**
3
3
  * Host-declared presentation of one branch kind.
4
4
  *
@@ -97,6 +97,8 @@ export declare const FRAME_LABEL_STYLE: {
97
97
  readonly pillSize: 12;
98
98
  readonly pillPaddingY: 4;
99
99
  readonly pillPaddingX: 10;
100
+ /** Text of the unclassified-surfaces badge: a warning tint on the dark surface. */
101
+ readonly unclassified: "#f5c86b";
100
102
  /** Bottom margin between the label and its frame. */
101
103
  readonly marginBottom: 8;
102
104
  readonly surface: "#343441";
@@ -127,7 +129,11 @@ export declare const FRAME_LABEL_OVERLAY_CLEARANCE: number;
127
129
  * of sixty frames reads as a coloured structure instead of grey mush.
128
130
  */
129
131
  export declare const FRAME_LABEL_COMPACT_ZOOM = 0.35;
130
- export declare function setFrameBranchKinds(defs: readonly FrameBranchKindDef[], labels?: FrameLabelLabels): void;
131
- export declare function getFrameBranchKinds(): readonly FrameBranchKindDef[];
132
- export declare function getFrameLabelLabels(): FrameLabelLabels | undefined;
133
- export declare function frameBranchKindFor(kind: string): FrameBranchKindDef;
132
+ /** One editor's declared frame branch kinds and label labels. */
133
+ export declare function createFrameLabels(): {
134
+ setFrameBranchKinds: (defs: readonly FrameBranchKindDef[], labels?: FrameLabelLabels) => void;
135
+ getFrameBranchKinds: () => readonly FrameBranchKindDef[];
136
+ getFrameLabelLabels: () => FrameLabelLabels | undefined;
137
+ frameBranchKindFor: (kind: string) => FrameBranchKindDef;
138
+ };
139
+ export type FrameLabels = ReturnType<typeof createFrameLabels>;