@pellux/goodvibes-tui 1.1.0 → 1.9.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 (267) hide show
  1. package/CHANGELOG.md +85 -21
  2. package/README.md +28 -18
  3. package/docs/foundation-artifacts/operator-contract.json +4045 -1763
  4. package/package.json +2 -2
  5. package/src/audio/spoken-turn-controller.ts +12 -2
  6. package/src/audio/spoken-turn-wiring.ts +2 -1
  7. package/src/cli/help.ts +8 -1
  8. package/src/cli/service-posture.ts +2 -1
  9. package/src/cli/status.ts +2 -1
  10. package/src/cli/surface-command.ts +2 -2
  11. package/src/core/alert-gating.ts +67 -0
  12. package/src/core/approval-alert.ts +72 -0
  13. package/src/core/budget-breach-notifier.ts +106 -0
  14. package/src/core/composer-state.ts +11 -3
  15. package/src/core/conversation-line-cache.ts +27 -3
  16. package/src/core/conversation-rendering.ts +90 -14
  17. package/src/core/conversation.ts +18 -0
  18. package/src/core/focus-tracker.ts +41 -0
  19. package/src/core/long-task-notifier.ts +33 -6
  20. package/src/core/stream-event-wiring.ts +20 -1
  21. package/src/core/system-message-noise.ts +87 -0
  22. package/src/core/system-message-router.ts +104 -51
  23. package/src/core/turn-cancellation.ts +25 -0
  24. package/src/core/turn-event-wiring.ts +72 -3
  25. package/src/daemon/cli.ts +29 -2
  26. package/src/daemon/handlers/register.ts +8 -1
  27. package/src/daemon/service-commands.ts +329 -0
  28. package/src/export/cost-utils.ts +36 -0
  29. package/src/input/autocomplete.ts +27 -1
  30. package/src/input/command-registry.ts +84 -5
  31. package/src/input/commands/checkpoint-runtime.ts +280 -0
  32. package/src/input/commands/codebase-runtime.ts +232 -0
  33. package/src/input/commands/config.ts +43 -3
  34. package/src/input/commands/eval.ts +1 -1
  35. package/src/input/commands/health-runtime.ts +10 -2
  36. package/src/input/commands/image-runtime.ts +112 -0
  37. package/src/input/commands/intelligence-runtime.ts +11 -1
  38. package/src/input/commands/local-auth-runtime.ts +4 -1
  39. package/src/input/commands/local-runtime.ts +9 -3
  40. package/src/input/commands/marketplace-runtime.ts +2 -2
  41. package/src/input/commands/memory.ts +73 -35
  42. package/src/input/commands/operator-panel-runtime.ts +71 -31
  43. package/src/input/commands/planning-runtime.ts +116 -4
  44. package/src/input/commands/platform-sandbox-runtime.ts +1 -6
  45. package/src/input/commands/plugin-runtime.ts +2 -2
  46. package/src/input/commands/policy-dispatch.ts +21 -0
  47. package/src/input/commands/provider-accounts-runtime.ts +1 -1
  48. package/src/input/commands/qrcode-runtime.ts +26 -6
  49. package/src/input/commands/recall-review.ts +35 -0
  50. package/src/input/commands/remote-runtime-setup.ts +5 -3
  51. package/src/input/commands/remote-runtime.ts +3 -3
  52. package/src/input/commands/runtime-services.ts +54 -13
  53. package/src/input/commands/services-runtime.ts +1 -1
  54. package/src/input/commands/session-content.ts +20 -9
  55. package/src/input/commands/session-workflow.ts +16 -1
  56. package/src/input/commands/settings-sync-runtime.ts +16 -4
  57. package/src/input/commands/shell-core.ts +25 -8
  58. package/src/input/commands/skills-runtime.ts +2 -8
  59. package/src/input/commands/subscription-runtime.ts +2 -2
  60. package/src/input/commands/test-runtime.ts +277 -0
  61. package/src/input/commands/websearch-runtime.ts +101 -0
  62. package/src/input/commands/work-plan-runtime.ts +36 -10
  63. package/src/input/commands/workstream-runtime.ts +488 -0
  64. package/src/input/commands.ts +12 -0
  65. package/src/input/config-modal-types.ts +175 -0
  66. package/src/input/config-modal.ts +592 -0
  67. package/src/input/feed-context-factory.ts +10 -8
  68. package/src/input/handler-command-route.ts +37 -20
  69. package/src/input/handler-content-actions.ts +17 -2
  70. package/src/input/handler-feed-routes.ts +74 -114
  71. package/src/input/handler-feed.ts +79 -27
  72. package/src/input/handler-interactions.ts +1 -3
  73. package/src/input/handler-modal-routes.ts +136 -6
  74. package/src/input/handler-modal-stack.ts +14 -7
  75. package/src/input/handler-modal-token-routes.ts +16 -49
  76. package/src/input/handler-onboarding-daemon-adopt.ts +149 -0
  77. package/src/input/handler-onboarding.ts +71 -59
  78. package/src/input/handler-picker-routes.ts +26 -102
  79. package/src/input/handler-shortcuts.ts +74 -14
  80. package/src/input/handler-types.ts +2 -6
  81. package/src/input/handler-ui-state.ts +10 -22
  82. package/src/input/handler.ts +12 -29
  83. package/src/input/keybindings.ts +23 -8
  84. package/src/input/model-picker-types.ts +24 -6
  85. package/src/input/model-picker.ts +77 -2
  86. package/src/input/onboarding/onboarding-runtime-status.ts +10 -1
  87. package/src/input/onboarding/onboarding-wizard-apply.ts +8 -1
  88. package/src/input/onboarding/onboarding-wizard-constants.ts +4 -1
  89. package/src/input/onboarding/onboarding-wizard-network-adopt.ts +136 -0
  90. package/src/input/onboarding/onboarding-wizard-steps.ts +9 -6
  91. package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
  92. package/src/input/panel-integration-actions.ts +9 -170
  93. package/src/input/panel-mouse-geometry.ts +97 -0
  94. package/src/input/panel-paste-flood-guard.ts +86 -0
  95. package/src/input/selection-modal.ts +11 -0
  96. package/src/input/session-picker-modal.ts +44 -4
  97. package/src/input/settings-modal-data.ts +146 -2
  98. package/src/input/settings-modal-mutations.ts +6 -4
  99. package/src/input/settings-modal-types.ts +4 -2
  100. package/src/main.ts +49 -51
  101. package/src/panels/agent-inspector-shared.ts +2 -1
  102. package/src/panels/base-panel.ts +22 -1
  103. package/src/panels/builtin/agent.ts +21 -107
  104. package/src/panels/builtin/development.ts +15 -61
  105. package/src/panels/builtin/knowledge.ts +8 -32
  106. package/src/panels/builtin/operations.ts +84 -428
  107. package/src/panels/builtin/session.ts +21 -112
  108. package/src/panels/builtin/shared.ts +18 -46
  109. package/src/panels/builtin-modals.ts +218 -0
  110. package/src/panels/builtin-panels.ts +5 -0
  111. package/src/panels/cost-tracker-panel.ts +36 -10
  112. package/src/panels/diff-panel.ts +12 -43
  113. package/src/panels/eval-registry.ts +60 -0
  114. package/src/panels/fleet-deep-link.ts +31 -0
  115. package/src/panels/fleet-panel-format.ts +62 -0
  116. package/src/panels/fleet-panel-worktree-detail.ts +48 -0
  117. package/src/panels/fleet-panel.ts +758 -0
  118. package/src/panels/fleet-read-model.ts +520 -0
  119. package/src/panels/fleet-steer.ts +125 -0
  120. package/src/panels/fleet-stop.ts +153 -0
  121. package/src/panels/fleet-tabs.ts +230 -0
  122. package/src/panels/fleet-transcript.ts +356 -0
  123. package/src/panels/index.ts +7 -31
  124. package/src/panels/modals/hooks-modal.ts +187 -0
  125. package/src/panels/modals/keybindings-modal.ts +166 -0
  126. package/src/panels/modals/knowledge-modal.ts +158 -0
  127. package/src/panels/modals/local-auth-modal.ts +132 -0
  128. package/src/panels/modals/marketplace-modal.ts +218 -0
  129. package/src/panels/modals/memory-modal.ts +180 -0
  130. package/src/panels/modals/modal-surface-helpers.ts +54 -0
  131. package/src/panels/modals/modal-theme.ts +42 -0
  132. package/src/panels/modals/pairing-modal.ts +163 -0
  133. package/src/panels/modals/planning-modal.ts +304 -0
  134. package/src/panels/modals/plugins-modal.ts +174 -0
  135. package/src/panels/modals/policy-modal.ts +256 -0
  136. package/src/panels/modals/provider-health-modal.ts +136 -0
  137. package/src/panels/modals/remote-modal.ts +115 -0
  138. package/src/panels/modals/sandbox-modal.ts +150 -0
  139. package/src/panels/modals/security-modal.ts +217 -0
  140. package/src/panels/modals/services-modal.ts +179 -0
  141. package/src/panels/modals/settings-sync-modal.ts +142 -0
  142. package/src/panels/modals/skills-modal.ts +189 -0
  143. package/src/panels/modals/subscription-modal.ts +172 -0
  144. package/src/panels/modals/work-plan-modal.ts +177 -0
  145. package/src/panels/panel-confirm-overlay.ts +72 -0
  146. package/src/panels/panel-manager.ts +123 -9
  147. package/src/panels/polish-core.ts +38 -25
  148. package/src/panels/project-planning-answer-actions.ts +8 -11
  149. package/src/panels/skills-panel.ts +7 -51
  150. package/src/panels/types.ts +37 -0
  151. package/src/permissions/hunk-selection.ts +179 -0
  152. package/src/permissions/prompt.ts +216 -13
  153. package/src/renderer/autocomplete-overlay.ts +28 -2
  154. package/src/renderer/compaction-history-modal.ts +19 -3
  155. package/src/renderer/compaction-preview.ts +13 -2
  156. package/src/renderer/compaction-quality.ts +100 -0
  157. package/src/renderer/compositor.ts +2 -3
  158. package/src/renderer/config-modal.ts +95 -0
  159. package/src/renderer/conversation-overlays.ts +10 -17
  160. package/src/renderer/fleet-tab-strip.ts +56 -0
  161. package/src/renderer/footer-tips.ts +15 -3
  162. package/src/renderer/fullscreen-primitives.ts +32 -22
  163. package/src/renderer/git-status.ts +43 -1
  164. package/src/renderer/help-overlay.ts +2 -2
  165. package/src/renderer/layout.ts +0 -4
  166. package/src/renderer/markdown.ts +7 -3
  167. package/src/renderer/modal-factory.ts +25 -20
  168. package/src/renderer/model-workspace.ts +62 -4
  169. package/src/renderer/overlay-box.ts +21 -17
  170. package/src/renderer/panel-workspace-bar.ts +8 -2
  171. package/src/renderer/process-indicator.ts +14 -3
  172. package/src/renderer/selection-modal-overlay.ts +6 -1
  173. package/src/renderer/session-picker-modal.ts +196 -3
  174. package/src/renderer/settings-modal-helpers.ts +2 -0
  175. package/src/renderer/settings-modal.ts +7 -0
  176. package/src/renderer/shell-surface.ts +8 -1
  177. package/src/renderer/status-glyphs.ts +14 -15
  178. package/src/renderer/system-message.ts +15 -3
  179. package/src/renderer/terminal-bg-probe.ts +339 -0
  180. package/src/renderer/terminal-escapes.ts +20 -0
  181. package/src/renderer/theme-mode-config.ts +67 -0
  182. package/src/renderer/theme.ts +91 -1
  183. package/src/renderer/thinking.ts +11 -3
  184. package/src/renderer/tool-call.ts +15 -9
  185. package/src/renderer/tool-result-summary.ts +148 -0
  186. package/src/renderer/turn-injection.ts +133 -0
  187. package/src/renderer/ui-factory.ts +154 -85
  188. package/src/renderer/ui-primitives.ts +30 -129
  189. package/src/runtime/bootstrap-command-context.ts +27 -1
  190. package/src/runtime/bootstrap-command-parts.ts +41 -10
  191. package/src/runtime/bootstrap-core.ts +47 -15
  192. package/src/runtime/bootstrap-hook-bridge.ts +7 -0
  193. package/src/runtime/bootstrap-shell.ts +48 -17
  194. package/src/runtime/bootstrap.ts +129 -22
  195. package/src/runtime/code-index-services.ts +135 -0
  196. package/src/runtime/legacy-daemon-migration.ts +516 -0
  197. package/src/runtime/memory-fold.ts +26 -0
  198. package/src/runtime/onboarding/derivation.ts +7 -2
  199. package/src/runtime/onboarding/snapshot.ts +27 -1
  200. package/src/runtime/onboarding/types.ts +31 -1
  201. package/src/runtime/operator-token-cleanup.ts +82 -1
  202. package/src/runtime/orchestrator-core-services.ts +59 -0
  203. package/src/runtime/process-lifecycle.ts +3 -1
  204. package/src/runtime/resume-notice.ts +209 -0
  205. package/src/runtime/services.ts +98 -46
  206. package/src/runtime/session-inbound-inputs.ts +252 -0
  207. package/src/runtime/session-spine-transport.ts +64 -0
  208. package/src/runtime/terminal-output-guard.ts +15 -8
  209. package/src/runtime/ui-services.ts +27 -3
  210. package/src/runtime/workstream-services.ts +327 -0
  211. package/src/runtime/wrfc-persistence.ts +124 -17
  212. package/src/shell/blocking-input.ts +68 -4
  213. package/src/shell/recovery-input-helpers.ts +170 -1
  214. package/src/shell/ui-openers.ts +171 -26
  215. package/src/utils/format-duration.ts +8 -18
  216. package/src/utils/splash-lines.ts +1 -1
  217. package/src/utils/terminal-width.ts +52 -0
  218. package/src/version.ts +1 -1
  219. package/src/panels/agent-inspector-panel.ts +0 -786
  220. package/src/panels/approval-panel.ts +0 -252
  221. package/src/panels/automation-control-panel.ts +0 -479
  222. package/src/panels/cockpit-panel.ts +0 -481
  223. package/src/panels/cockpit-read-model.ts +0 -238
  224. package/src/panels/communication-panel.ts +0 -256
  225. package/src/panels/control-plane-panel.ts +0 -470
  226. package/src/panels/debug-panel.ts +0 -615
  227. package/src/panels/docs-panel.ts +0 -384
  228. package/src/panels/eval-panel.ts +0 -627
  229. package/src/panels/file-explorer-panel.ts +0 -673
  230. package/src/panels/file-preview-panel.ts +0 -517
  231. package/src/panels/hooks-panel.ts +0 -401
  232. package/src/panels/incident-review-panel.ts +0 -406
  233. package/src/panels/intelligence-panel.ts +0 -383
  234. package/src/panels/knowledge-graph-panel.ts +0 -515
  235. package/src/panels/marketplace-panel.ts +0 -399
  236. package/src/panels/memory-panel.ts +0 -558
  237. package/src/panels/ops-control-panel.ts +0 -329
  238. package/src/panels/ops-strategy-panel.ts +0 -321
  239. package/src/panels/orchestration-panel.ts +0 -465
  240. package/src/panels/panel-list-panel.ts +0 -566
  241. package/src/panels/plan-dashboard-panel.ts +0 -707
  242. package/src/panels/policy-panel.ts +0 -517
  243. package/src/panels/project-planning-panel.ts +0 -731
  244. package/src/panels/provider-health-panel.ts +0 -678
  245. package/src/panels/provider-health-tracker.ts +0 -310
  246. package/src/panels/provider-health-views.ts +0 -567
  247. package/src/panels/qr-panel.ts +0 -280
  248. package/src/panels/remote-panel.ts +0 -534
  249. package/src/panels/routes-panel.ts +0 -241
  250. package/src/panels/sandbox-panel.ts +0 -456
  251. package/src/panels/security-panel.ts +0 -447
  252. package/src/panels/services-panel.ts +0 -329
  253. package/src/panels/session-browser-panel.ts +0 -496
  254. package/src/panels/settings-sync-panel.ts +0 -398
  255. package/src/panels/subscription-panel.ts +0 -342
  256. package/src/panels/symbol-outline-panel.ts +0 -619
  257. package/src/panels/system-messages-panel.ts +0 -364
  258. package/src/panels/tasks-panel.ts +0 -608
  259. package/src/panels/thinking-panel.ts +0 -333
  260. package/src/panels/tool-inspector-panel.ts +0 -537
  261. package/src/panels/work-plan-panel.ts +0 -540
  262. package/src/panels/worktree-panel.ts +0 -360
  263. package/src/panels/wrfc-panel.ts +0 -790
  264. package/src/renderer/agent-detail-modal.ts +0 -466
  265. package/src/renderer/live-tail-modal.ts +0 -156
  266. package/src/renderer/process-modal.ts +0 -671
  267. package/src/renderer/qr-renderer.ts +0 -120
@@ -0,0 +1,175 @@
1
+ import type { ModalSectionStyle } from '../renderer/modal-factory.ts';
2
+
3
+ /**
4
+ * Config-modal host — the shared seam every W6.1 MIGRATE-TO-MODAL surface
5
+ * (provider-health, services, subscription, remote, local-auth, settings-sync,
6
+ * sandbox, and the WO-B ecosystem/governance set) is expressed through.
7
+ *
8
+ * A surface is PURE DATA + ACTIONS: it hands the host a `buildView()` that maps
9
+ * live read-models to a tabbed, list-structured view, plus a declarative action
10
+ * table. The host owns all key routing (tab switch, list nav, Esc, confirm) and
11
+ * the stable-layout liveness contract — the surface never touches the input
12
+ * system directly (the charter's "do not invent a parallel input system").
13
+ *
14
+ * Liveness doctrine (charter: "live data, stable layout"): `buildView()` is
15
+ * called every render tick so values (latency, status, counts) update in place,
16
+ * but the host renders against the row/tab STRUCTURE captured at the last
17
+ * interaction boundary (open, or a key press). Rows never reflow under the
18
+ * cursor mid-interaction; a structural change (a row appears/disappears) is
19
+ * deferred until the next key press. See ConfigModal for the mechanism.
20
+ */
21
+
22
+ /** A single row within a tab. Identity is `id` (structural); `label` is live. */
23
+ export interface ConfigModalRow {
24
+ /**
25
+ * Stable identity across live-refresh ticks. The liveness contract keys
26
+ * structural stability off this: two builds with the same ordered id set are
27
+ * "structurally identical" and repaint values in place; a differing id set is
28
+ * a structural change, deferred to the next interaction boundary.
29
+ */
30
+ readonly id: string;
31
+ /** Display label. MAY embed live value fields (latency, status dot, counts). */
32
+ readonly label: string;
33
+ /** Optional per-row style (e.g. bad/warn tone for an errored row). */
34
+ readonly style?: ModalSectionStyle;
35
+ /**
36
+ * Non-selectable informational row (sub-header, spacer text). Skipped by
37
+ * up/down navigation and never receives an action. Defaults to selectable.
38
+ */
39
+ readonly selectable?: boolean;
40
+ }
41
+
42
+ /** One tab (section) of a surface. Tabs are switched with left/right or Tab. */
43
+ export interface ConfigModalTab {
44
+ /** Stable id — preserves the active tab across refresh + re-open. */
45
+ readonly id: string;
46
+ /** Tab-strip label. */
47
+ readonly label: string;
48
+ /** Live status/posture lines rendered above the list (non-selectable). */
49
+ readonly header?: readonly string[];
50
+ /** Selectable/informational rows. */
51
+ readonly rows: readonly ConfigModalRow[];
52
+ /** Honest empty-state text shown when `rows` is empty. */
53
+ readonly emptyText?: string;
54
+ /** Footer hints specific to this tab, appended after the surface hints. */
55
+ readonly hints?: readonly string[];
56
+ }
57
+
58
+ /** The whole surface view for one render tick. */
59
+ export interface ConfigModalView {
60
+ /** Live title (may change tick-to-tick; not structural). */
61
+ readonly title: string;
62
+ readonly tabs: readonly ConfigModalTab[];
63
+ /**
64
+ * Non-null when the read-model is unavailable/degraded — the host renders a
65
+ * banner and still shows whatever tabs/rows are present (honest degraded
66
+ * state rather than a blank or a throw).
67
+ */
68
+ readonly degraded?: string;
69
+ /** Base footer hints (Esc close is always appended by the host). */
70
+ readonly hints?: readonly string[];
71
+ }
72
+
73
+ /** Context handed to a surface's action handler when an action key fires. */
74
+ export interface ConfigModalActionContext {
75
+ /** The selected row the action targets (null when the active tab has none). */
76
+ readonly row: ConfigModalRow | null;
77
+ /** The active tab's id. */
78
+ readonly tabId: string;
79
+ /** Print a line to the conversation transcript. */
80
+ readonly print: (message: string) => void;
81
+ /**
82
+ * Execute a slash command — the same seam panels used via
83
+ * `PanelIntegrationContext.executeCommand`. This is how a migrated action
84
+ * preserves parity: the mutation still runs through its existing, tested
85
+ * command (e.g. `/settings-sync resolve`, `/local-auth delete-user`).
86
+ */
87
+ readonly executeCommand?: (name: string, args: string[]) => Promise<unknown>;
88
+ /** Open another named modal surface (cross-surface navigation, e.g. the
89
+ * services surface jumping to the subscription surface). Swaps the active
90
+ * surface in place — the same seam ctx.openModal uses. */
91
+ readonly openModal?: (name: string) => void;
92
+ /**
93
+ * Submit text to the chat/model as a real user turn — the same composer
94
+ * submission seam `handleUserInput` uses (threaded from CommandContext.submitInput).
95
+ * Generic across surfaces (any modal may hand free-form input to the model).
96
+ *
97
+ * ORDERING GUARD: a turn must never start while a modal owns the keyboard —
98
+ * that is the modal-liveness hazard (a live turn painting under a modal that
99
+ * still captures keys). Callers MUST `close()` the modal BEFORE invoking
100
+ * `submitInput`. The planning modal's free-form submit follows this ordering.
101
+ */
102
+ readonly submitInput?: (text: string) => void;
103
+ /** Request a re-render. */
104
+ readonly requestRender: () => void;
105
+ /** Set the modal's transient status line (e.g. a result or error message). */
106
+ readonly setStatus: (message: string) => void;
107
+ /** Close the modal (focus returns to whatever opened it). */
108
+ readonly close: () => void;
109
+ }
110
+
111
+ /** A declarative action bound to a key. */
112
+ export interface ConfigModalAction {
113
+ /**
114
+ * Trigger key: a single printable char ('r', 'd') or a named key ('enter').
115
+ * Must not collide with the host-reserved nav keys (up/down/left/right/tab/
116
+ * j/k/escape/'/') — those are consumed by the host before actions are
117
+ * consulted. '/' arms the host's type-to-filter (DEBT-5 item 1); while
118
+ * filtering, EVERY printable key (not just j/k) is captured by the query
119
+ * instead of firing an action — see handleConfigModalToken.
120
+ */
121
+ readonly key: string;
122
+ /** Action id passed to `onAction`. */
123
+ readonly id: string;
124
+ /** Short verb for the footer hint (e.g. "refresh", "delete user"). */
125
+ readonly label: string;
126
+ /**
127
+ * Destructive: require an explicit second press of the same key to fire
128
+ * (the host shows "press <key> again to <label>" between presses). Matches
129
+ * the session-picker delete-confirm precedent.
130
+ */
131
+ readonly confirm?: boolean;
132
+ /**
133
+ * When set, the action is only offered while the selected row's id satisfies
134
+ * this predicate (e.g. sandbox "stop" only on a session row). Rows failing
135
+ * the predicate neither show the hint nor fire the action.
136
+ */
137
+ readonly enabledFor?: (row: ConfigModalRow | null, tabId: string) => boolean;
138
+ }
139
+
140
+ /**
141
+ * A named config-modal surface. Pure seam — the host knows nothing about the
142
+ * surface's data. Built once (closing over its read-models) and registered on
143
+ * PanelManager via `registerModalSurface`; opened by name from a panel-id
144
+ * redirect hit or `ctx.openModal(name)`.
145
+ */
146
+ export interface ConfigModalSurface {
147
+ /** Modal name — the key `registerModalRedirect` / `ctx.openModal` use. */
148
+ readonly name: string;
149
+ /** Fallback title (buildView().title wins per tick). */
150
+ readonly title: string;
151
+ /**
152
+ * Build the current view from live read-models. Called on open, on every
153
+ * interaction boundary, AND on every render tick. MUST be pure and cheap —
154
+ * snapshot reads only, no async, no mutation.
155
+ */
156
+ buildView(): ConfigModalView;
157
+ /** Declarative action table (optional — a read-only surface has none). */
158
+ readonly actions?: readonly ConfigModalAction[];
159
+ /** Handle an action fired by its key. */
160
+ onAction?(actionId: string, ctx: ConfigModalActionContext): void;
161
+ /**
162
+ * Optional lifecycle: called when the modal opens this surface and when it
163
+ * closes. A live surface uses `onOpen` to subscribe to its read-model/events
164
+ * (calling the provided `requestRender` on change so live values refresh
165
+ * between key presses) and `onClose` to unsubscribe. The host guarantees
166
+ * `onClose` runs exactly once per `onOpen`.
167
+ */
168
+ onOpen?(requestRender: () => void): void;
169
+ onClose?(): void;
170
+ }
171
+
172
+ /** Read-only registry the host consults to resolve a modal name to a surface. */
173
+ export interface ConfigModalSurfaceRegistry {
174
+ getModalSurface(name: string): ConfigModalSurface | undefined;
175
+ }