@arach/lattices 0.2.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +144 -69
  3. package/apps/mac/Info.plist +43 -0
  4. package/apps/mac/Lattices.app/Contents/Info.plist +43 -0
  5. package/apps/mac/Lattices.app/Contents/MacOS/Lattices +0 -0
  6. package/apps/mac/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
  7. package/apps/mac/Lattices.app/Contents/Resources/docs/assistant-knowledge.md +130 -0
  8. package/apps/mac/Lattices.app/Contents/Resources/tap.wav +0 -0
  9. package/apps/mac/Lattices.app/Contents/_CodeSignature/CodeResources +150 -0
  10. package/apps/mac/Lattices.entitlements +21 -0
  11. package/apps/mac/Resources/Pets/assistant-spark/pet.json +62 -0
  12. package/apps/mac/Resources/Pets/assistant-spark/spritesheet.webp +0 -0
  13. package/apps/mac/Resources/Pets/scout-ranger/pet.json +6 -0
  14. package/apps/mac/Resources/Pets/scout-ranger/spritesheet.webp +0 -0
  15. package/apps/mac/Resources/tap.wav +0 -0
  16. package/assets/AppIcon.icns +0 -0
  17. package/bin/assistant-intelligence.ts +912 -0
  18. package/bin/cli/capture.ts +252 -0
  19. package/bin/cli/daemon.ts +22 -0
  20. package/bin/cli/helpers.ts +105 -0
  21. package/bin/cli/layer.ts +178 -0
  22. package/bin/cli/runs.ts +43 -0
  23. package/bin/cli/search.ts +141 -0
  24. package/bin/cli/session.ts +32 -0
  25. package/bin/client.ts +17 -0
  26. package/bin/cua.ts +26 -0
  27. package/bin/{daemon-client.js → daemon-client.ts} +49 -30
  28. package/bin/handsoff-infer.ts +96 -0
  29. package/bin/handsoff-worker.ts +531 -0
  30. package/bin/infer.ts +424 -0
  31. package/bin/keychain.ts +75 -0
  32. package/bin/lattices-app.ts +655 -0
  33. package/bin/lattices-build +125 -0
  34. package/bin/lattices-build-env.ts +77 -0
  35. package/bin/lattices-dev +362 -0
  36. package/bin/lattices.ts +3260 -0
  37. package/bin/project-twin.ts +645 -0
  38. package/docs/agent-execution-plan.md +562 -0
  39. package/docs/agent-layer-guide.md +207 -0
  40. package/docs/agents.md +233 -0
  41. package/docs/ai-chat-ux-review.md +416 -0
  42. package/docs/api.md +1041 -47
  43. package/docs/app.md +96 -13
  44. package/docs/assistant-knowledge.md +130 -0
  45. package/docs/companion-deck.md +209 -0
  46. package/docs/component-extraction-roadmap.md +392 -0
  47. package/docs/concepts.md +13 -12
  48. package/docs/config.md +83 -10
  49. package/docs/gesture-customization-proposal.md +520 -0
  50. package/docs/handsoff-test-scenarios.md +84 -0
  51. package/docs/hyperspace-grid-snappiness.md +210 -0
  52. package/docs/layers.md +176 -28
  53. package/docs/mouse-gestures.md +244 -0
  54. package/docs/ocr.md +21 -9
  55. package/docs/overview.md +42 -23
  56. package/docs/presentation-execution-review.md +491 -0
  57. package/docs/prompts/hands-off-system.md +382 -0
  58. package/docs/prompts/hands-off-turn.md +30 -0
  59. package/docs/prompts/voice-advisor.md +31 -0
  60. package/docs/prompts/voice-fallback.md +23 -0
  61. package/docs/proposals/LAT-001-gesture-visual-customization.md +522 -0
  62. package/docs/proposals/LAT-002-shared-overlay-canvas.md +353 -0
  63. package/docs/proposals/LAT-003-menu-bar-controller-architecture.md +291 -0
  64. package/docs/proposals/LAT-004-interactive-overlay-actors.md +534 -0
  65. package/docs/proposals/LAT-005-action-runtime-product-spine.md +914 -0
  66. package/docs/proposals/LAT-006-followup-gaps.md +103 -0
  67. package/docs/proposals/LAT-006-runs-and-capture-in-lattices.md +566 -0
  68. package/docs/proposals/LAT-007-unified-app-shell.md +128 -0
  69. package/docs/quickstart.md +8 -12
  70. package/docs/reference/dewey.config.ts +74 -0
  71. package/docs/reference/install-agent.md +79 -0
  72. package/docs/release.md +172 -0
  73. package/docs/repo-structure.md +100 -0
  74. package/docs/terminal-kit.md +87 -0
  75. package/docs/tiling-reference.md +224 -0
  76. package/docs/twins.md +138 -0
  77. package/docs/voice-command-protocol.md +278 -0
  78. package/docs/voice-error-model.md +73 -0
  79. package/docs/voice.md +221 -0
  80. package/package.json +69 -16
  81. package/packages/npm/sdk/cua.d.mts +1 -0
  82. package/packages/npm/sdk/cua.d.ts +188 -0
  83. package/packages/npm/sdk/cua.mjs +376 -0
  84. package/app/Lattices.app/Contents/Info.plist +0 -24
  85. package/app/Package.swift +0 -13
  86. package/app/Sources/ActionRow.swift +0 -61
  87. package/app/Sources/App.swift +0 -10
  88. package/app/Sources/AppDelegate.swift +0 -234
  89. package/app/Sources/AppShellView.swift +0 -62
  90. package/app/Sources/AppTypeClassifier.swift +0 -70
  91. package/app/Sources/AppWindowShell.swift +0 -63
  92. package/app/Sources/CheatSheetHUD.swift +0 -332
  93. package/app/Sources/CommandModeState.swift +0 -1362
  94. package/app/Sources/CommandModeView.swift +0 -1405
  95. package/app/Sources/CommandModeWindow.swift +0 -192
  96. package/app/Sources/CommandPaletteView.swift +0 -307
  97. package/app/Sources/CommandPaletteWindow.swift +0 -134
  98. package/app/Sources/DaemonProtocol.swift +0 -101
  99. package/app/Sources/DaemonServer.swift +0 -414
  100. package/app/Sources/DesktopModel.swift +0 -121
  101. package/app/Sources/DesktopModelTypes.swift +0 -71
  102. package/app/Sources/DiagnosticLog.swift +0 -271
  103. package/app/Sources/EventBus.swift +0 -30
  104. package/app/Sources/HotkeyManager.swift +0 -250
  105. package/app/Sources/HotkeyStore.swift +0 -338
  106. package/app/Sources/InventoryManager.swift +0 -35
  107. package/app/Sources/InventoryPath.swift +0 -43
  108. package/app/Sources/KeyRecorderView.swift +0 -210
  109. package/app/Sources/LatticesApi.swift +0 -1125
  110. package/app/Sources/MainView.swift +0 -467
  111. package/app/Sources/MainWindow.swift +0 -83
  112. package/app/Sources/OcrModel.swift +0 -309
  113. package/app/Sources/OcrStore.swift +0 -295
  114. package/app/Sources/OmniSearchState.swift +0 -283
  115. package/app/Sources/OmniSearchView.swift +0 -288
  116. package/app/Sources/OmniSearchWindow.swift +0 -105
  117. package/app/Sources/OrphanRow.swift +0 -129
  118. package/app/Sources/PaletteCommand.swift +0 -419
  119. package/app/Sources/PermissionChecker.swift +0 -125
  120. package/app/Sources/Preferences.swift +0 -92
  121. package/app/Sources/ProcessModel.swift +0 -199
  122. package/app/Sources/ProcessQuery.swift +0 -151
  123. package/app/Sources/Project.swift +0 -28
  124. package/app/Sources/ProjectRow.swift +0 -368
  125. package/app/Sources/ProjectScanner.swift +0 -121
  126. package/app/Sources/ScreenMapState.swift +0 -2387
  127. package/app/Sources/ScreenMapView.swift +0 -2820
  128. package/app/Sources/ScreenMapWindowController.swift +0 -89
  129. package/app/Sources/SessionManager.swift +0 -72
  130. package/app/Sources/SettingsView.swift +0 -1053
  131. package/app/Sources/SettingsWindow.swift +0 -20
  132. package/app/Sources/TabGroupRow.swift +0 -178
  133. package/app/Sources/Terminal.swift +0 -259
  134. package/app/Sources/TerminalQuery.swift +0 -156
  135. package/app/Sources/TerminalSynthesizer.swift +0 -200
  136. package/app/Sources/Theme.swift +0 -163
  137. package/app/Sources/TilePickerView.swift +0 -209
  138. package/app/Sources/TmuxModel.swift +0 -53
  139. package/app/Sources/TmuxQuery.swift +0 -81
  140. package/app/Sources/WindowTiler.swift +0 -1755
  141. package/app/Sources/WorkspaceManager.swift +0 -434
  142. package/bin/lattices-app.js +0 -221
  143. package/bin/lattices.js +0 -1418
@@ -0,0 +1,534 @@
1
+ # LAT-004: Generative Overlay UI
2
+
3
+ ## Status
4
+
5
+ Approved.
6
+
7
+ This document proposes a general generative overlay UI system for Lattices. The goal is not to build a mascot-specific feature. The goal is to let agents and local systems generate structured interface requests that Lattices renders as small, stateful, movable, clickable, native desktop surfaces.
8
+
9
+ ## Summary
10
+
11
+ Lattices now has the beginning of a shared screen overlay canvas and an agent-facing overlay API. That is enough for passive visuals: labels, highlights, toasts, and simple pet-style sprites.
12
+
13
+ The next step is interaction.
14
+
15
+ Agents and local systems need a way to surface attention requests without opening a full app window. Examples include:
16
+
17
+ - an agent asking for feedback
18
+ - a permission request that needs approval
19
+ - a build, merge, or review result
20
+ - a useful link to a PR, thread, workspace, or file
21
+ - a reminder that a background process is waiting
22
+ - a lightweight status surface that can be moved out of the way
23
+
24
+ The proposed primitive is an **overlay actor**: a small persistent or transient object on the desktop that can move, animate, change state, show attached information, expose click targets, accept drag/drop, and emit interaction events back to the daemon.
25
+
26
+ The broader product frame is **Generative Overlay UI**:
27
+
28
+ - callers generate intent and schema
29
+ - Lattices owns rendering, style, hit-testing, permissions, safety, and interaction behavior
30
+ - the desktop receives native contextual UI instead of arbitrary injected web content
31
+
32
+ Ranger or any pet-like asset can be one renderer for this system. A logo, status chip, icon, or minimal badge should be equally valid renderers.
33
+
34
+ ## Why Now
35
+
36
+ The shared overlay canvas gives Lattices a stable place to draw. The agent overlay API proves that outside processes can publish useful visual state.
37
+
38
+ The early pet experiments also exposed the missing pieces:
39
+
40
+ - WebSocket-driven position updates are too chunky for motion.
41
+ - Text needs crisp typography and carefully controlled translucent backing.
42
+ - Overlays must be easy to dismiss and should not linger accidentally.
43
+ - Some surfaces need real hit-testing, while the rest of the canvas must remain click-through.
44
+ - Agents need events when the user clicks, dismisses, drags, or chooses an action.
45
+
46
+ Those are general generative UI needs, not pet-specific needs.
47
+
48
+ ## Goals
49
+
50
+ - Provide a reusable model for small interactive overlay actors.
51
+ - Keep the canvas click-through except where an actor or attached surface explicitly opts into input.
52
+ - Let the app own animation timing, easing, and sprite state.
53
+ - Let agents express intent instead of manually streaming frames or coordinates.
54
+ - Render agent-generated UI from safe structured schemas instead of arbitrary HTML.
55
+ - Support crisp, minimal information presentation with optional translucent text/card backing.
56
+ - Support hover, click, drag, dismiss, drop, menu, and action-button interactions.
57
+ - Emit daemon events for user interactions.
58
+ - Keep all attention surfaces dismissible, snoozable, or moveable.
59
+ - Make sound possible but controlled by app settings and priority.
60
+
61
+ ## Non-Goals
62
+
63
+ This is not a replacement for the HUD, command palette, settings window, Screen Map, or menu bar app.
64
+
65
+ This is not a general webview or arbitrary HTML surface.
66
+
67
+ This is not a notification center clone. The system can present attention requests, but it should stay compact, contextual, and action-oriented.
68
+
69
+ This does not make every overlay interactive. Passive layers such as snap zones, gesture trails, and focus highlights should remain passive unless they have a clear reason to capture input.
70
+
71
+ ## Conceptual Model
72
+
73
+ ### Actor
74
+
75
+ An actor is the small visible object.
76
+
77
+ Examples:
78
+
79
+ - sprite asset
80
+ - app/service logo
81
+ - status chip
82
+ - progress puck
83
+ - minimal icon
84
+
85
+ An actor has:
86
+
87
+ - stable id
88
+ - renderer type
89
+ - asset id
90
+ - state
91
+ - position
92
+ - size or scale
93
+ - opacity
94
+ - optional pinned position
95
+ - input policy
96
+ - optional attached surface
97
+
98
+ ### Surface
99
+
100
+ A surface is information attached to an actor.
101
+
102
+ Examples:
103
+
104
+ - one-line message
105
+ - compact card
106
+ - action prompt
107
+ - link preview
108
+ - progress status
109
+ - permission request
110
+
111
+ The surface should support:
112
+
113
+ - title
114
+ - body
115
+ - severity/priority
116
+ - links
117
+ - buttons
118
+ - dismiss/snooze affordance
119
+ - optional timeout
120
+
121
+ Surfaces should be visually precise: crisp text, restrained translucent backing, thin edges when needed, no heavy blurry panel chrome.
122
+
123
+ ### Effect
124
+
125
+ An effect is visual or audio feedback that supports state.
126
+
127
+ Examples:
128
+
129
+ - hover lift/brightness
130
+ - pulse for waiting state
131
+ - success flash
132
+ - failure shake
133
+ - path trail during movement
134
+ - soft sound cue for attention
135
+
136
+ Effects should be optional and bounded. They should never become the core interaction contract.
137
+
138
+ ## Actor State
139
+
140
+ The system should define common states while allowing renderer-specific mapping.
141
+
142
+ Initial common states:
143
+
144
+ - `idle`
145
+ - `active`
146
+ - `moving`
147
+ - `waiting`
148
+ - `thinking`
149
+ - `success`
150
+ - `warning`
151
+ - `failed`
152
+ - `review`
153
+ - `muted`
154
+
155
+ Renderers can map these states to their own animation names. For example, a sprite renderer might map:
156
+
157
+ - `movingRight` -> `run_right`
158
+ - `movingLeft` -> `run_left`
159
+ - `waiting` -> `waiting`
160
+ - `failed` -> `failed`
161
+
162
+ The API should not require callers to know sprite rows or frame sizes.
163
+
164
+ ## Interaction Model
165
+
166
+ Actors should support explicit input capabilities:
167
+
168
+ - `hoverable`
169
+ - `clickable`
170
+ - `draggable`
171
+ - `droppable`
172
+ - `dismissible`
173
+ - `menuEnabled`
174
+
175
+ The default should be conservative:
176
+
177
+ - the canvas remains click-through
178
+ - only actor bounds and attached surface/button bounds capture input
179
+ - input capture should never cover the whole screen unless a modal feature explicitly owns that surface
180
+
181
+ Expected interactions:
182
+
183
+ - hover: brighten, lift, preview, or emit event
184
+ - click: primary action, open compact surface, or emit event
185
+ - double-click: optional secondary action
186
+ - drag: move actor and optionally pin final position
187
+ - right-click: close that actor without clearing other actors
188
+ - drop: emit dropped item payload if supported
189
+ - Escape: dismiss the active surface
190
+ - click-away: dismiss transient surfaces when appropriate
191
+ - context menu: mute, snooze, hide, settings, inspect source
192
+
193
+ Dismissal should normally dismiss the current message/surface, not delete the actor.
194
+ Persistent actors can be parked globally with the overlay actor hotkey
195
+ without clearing their ids or state. The initial shortcut is **Hyper+B**.
196
+
197
+ ## Motion
198
+
199
+ Motion should be renderer-owned, not API-spammed.
200
+
201
+ Callers should be able to say:
202
+
203
+ ```json
204
+ {
205
+ "id": "scout-ranger",
206
+ "position": { "x": 640, "y": 320 },
207
+ "durationMs": 700,
208
+ "easing": "spring"
209
+ }
210
+ ```
211
+
212
+ The app should:
213
+
214
+ - keep current position
215
+ - interpolate toward target position
216
+ - draw at display cadence
217
+ - update directional state during movement
218
+ - settle into the target state when complete
219
+
220
+ Initial easing modes:
221
+
222
+ - `linear`
223
+ - `easeInOut`
224
+ - `spring`
225
+
226
+ Path support can come later:
227
+
228
+ ```json
229
+ {
230
+ "id": "scout-ranger",
231
+ "path": [
232
+ { "x": 320, "y": 180 },
233
+ { "x": 540, "y": 230 },
234
+ { "x": 760, "y": 190 }
235
+ ],
236
+ "durationMs": 1400,
237
+ "easing": "spring"
238
+ }
239
+ ```
240
+
241
+ ## API Sketch
242
+
243
+ ### Create Or Update Actor
244
+
245
+ ```json
246
+ {
247
+ "method": "overlay.actor.publish",
248
+ "params": {
249
+ "id": "scout-ranger",
250
+ "renderer": "sprite",
251
+ "asset": "scout-ranger",
252
+ "state": "idle",
253
+ "position": {
254
+ "anchor": "bottomRight",
255
+ "x": -40,
256
+ "y": -40
257
+ },
258
+ "draggable": true,
259
+ "clickable": true,
260
+ "dismissible": true
261
+ }
262
+ }
263
+ ```
264
+
265
+ ### Set State
266
+
267
+ ```json
268
+ {
269
+ "method": "overlay.actor.setState",
270
+ "params": {
271
+ "id": "scout-ranger",
272
+ "state": "waiting",
273
+ "message": {
274
+ "title": "Agent needs feedback",
275
+ "body": "Review the proposed merge?",
276
+ "priority": "decision",
277
+ "actions": [
278
+ { "id": "approve", "label": "Approve", "style": "primary" },
279
+ { "id": "open", "label": "Open PR", "url": "https://github.com/arach/lattices/pull/31" },
280
+ { "id": "dismiss", "label": "Dismiss" }
281
+ ]
282
+ },
283
+ "sound": "attention-soft"
284
+ }
285
+ }
286
+ ```
287
+
288
+ ### Move Actor
289
+
290
+ ```json
291
+ {
292
+ "method": "overlay.actor.moveTo",
293
+ "params": {
294
+ "id": "scout-ranger",
295
+ "position": { "x": 640, "y": 320 },
296
+ "durationMs": 700,
297
+ "easing": "spring"
298
+ }
299
+ }
300
+ ```
301
+
302
+ ### Clear Actor Or Surface
303
+
304
+ ```json
305
+ {
306
+ "method": "overlay.actor.clear",
307
+ "params": {
308
+ "id": "scout-ranger",
309
+ "surfaceOnly": true
310
+ }
311
+ }
312
+ ```
313
+
314
+ ### Subscribe To Events
315
+
316
+ The daemon should emit events such as:
317
+
318
+ - `overlay.actor.hovered`
319
+ - `overlay.actor.clicked`
320
+ - `overlay.actor.doubleClicked`
321
+ - `overlay.actor.dragStarted`
322
+ - `overlay.actor.moved`
323
+ - `overlay.actor.dropped`
324
+ - `overlay.actor.dismissed`
325
+ - `overlay.actor.actionSelected`
326
+ - `overlay.actor.snoozed`
327
+
328
+ Example event:
329
+
330
+ ```json
331
+ {
332
+ "event": "overlay.actor.actionSelected",
333
+ "data": {
334
+ "actorId": "scout-ranger",
335
+ "surfaceId": "ask-123",
336
+ "actionId": "approve"
337
+ }
338
+ }
339
+ ```
340
+
341
+ ## Visual Rules
342
+
343
+ The visual system should stay quiet and exact.
344
+
345
+ - Prefer actor plus attached text over large panels.
346
+ - Use translucent backing only when it improves readability.
347
+ - Keep text crisp: system fonts, no excessive blur, no heavy shadows.
348
+ - Use thin strokes and hairlines when edges are needed.
349
+ - Avoid decorative opacity stacks that make the surface feel fuzzy.
350
+ - Avoid sticky surfaces unless the request truly needs a decision.
351
+ - Make hover/click affordances legible without shouting.
352
+
353
+ For text next to an actor, the baseline style should be:
354
+
355
+ - white text with high alpha
356
+ - subtle black text halo or small shadow
357
+ - optional dark wash at low alpha
358
+ - thin light edge if needed
359
+ - no large rounded card unless actions require it
360
+
361
+ ## Sound
362
+
363
+ Sound should be event-driven and user-controlled.
364
+
365
+ Initial cue types:
366
+
367
+ - `none`
368
+ - `attention-soft`
369
+ - `success-soft`
370
+ - `warning-soft`
371
+ - `failure-soft`
372
+
373
+ Rules:
374
+
375
+ - sound should default to quiet or disabled depending app settings
376
+ - priority should gate whether sound is allowed
377
+ - repeated sounds should be rate-limited
378
+ - dragging/hovering should not spam sounds
379
+ - all sounds should be suppressible globally and per actor/source
380
+
381
+ ## Architecture
382
+
383
+ Proposed components:
384
+
385
+ ### `OverlayActorStore`
386
+
387
+ Owns actor state:
388
+
389
+ - actors by id
390
+ - current position
391
+ - target position
392
+ - current state
393
+ - attached surface
394
+ - interaction policy
395
+ - pin/mute/snooze metadata
396
+
397
+ ### `OverlayActorAnimator`
398
+
399
+ Owns time-based interpolation:
400
+
401
+ - active motion records
402
+ - easing functions
403
+ - display-link or timer updates
404
+ - direction/state transitions during movement
405
+
406
+ ### `OverlayActorRenderer`
407
+
408
+ Draws actors and surfaces into the shared overlay canvas.
409
+
410
+ Renderer variants can include:
411
+
412
+ - sprite renderer
413
+ - logo renderer
414
+ - chip renderer
415
+ - progress renderer
416
+
417
+ ### `OverlayActorHitTester`
418
+
419
+ Tracks interactive regions:
420
+
421
+ - actor bounds
422
+ - attached card bounds
423
+ - action button bounds
424
+ - drag handles if needed
425
+
426
+ This component decides whether the overlay window should accept input at a given point.
427
+
428
+ ### `OverlayActorInteractionController`
429
+
430
+ Handles:
431
+
432
+ - hover state
433
+ - click/double-click
434
+ - drag/drop
435
+ - dismissal
436
+ - context menu
437
+ - event emission
438
+
439
+ ### `OverlayActorApi`
440
+
441
+ Adds daemon methods and schemas:
442
+
443
+ - `overlay.actor.publish`
444
+ - `overlay.actor.setState`
445
+ - `overlay.actor.moveTo`
446
+ - `overlay.actor.clear`
447
+ - `overlay.actor.list`
448
+
449
+ ## Relationship To `ScreenOverlayCanvas`
450
+
451
+ `ScreenOverlayCanvasController` should remain the rendering substrate.
452
+
453
+ Interactive actors may require the overlay window to stop ignoring mouse events in a very controlled way. The preferred approach is:
454
+
455
+ - keep the panel non-activating
456
+ - override hit-testing so only registered actor/surface regions return a view
457
+ - return `nil` for all other points so normal desktop clicks pass through
458
+ - avoid making the app active for simple hover/click where possible
459
+
460
+ The shared canvas can continue supporting passive layers alongside interactive actors.
461
+
462
+ ## Relationship To Existing Overlay API
463
+
464
+ The current `overlay.publish` API is still useful for simple passive layers:
465
+
466
+ - `toast`
467
+ - `label`
468
+ - `highlight`
469
+ - simple `pet`
470
+
471
+ The actor API should be added next to it rather than replacing it immediately.
472
+
473
+ Over time, `kind: "pet"` can become a compatibility wrapper around `overlay.actor.publish` for sprite actors.
474
+
475
+ ## Implementation Plan
476
+
477
+ ### Phase 1: Actor State And Rendering
478
+
479
+ - Add actor model types.
480
+ - Add actor payload to the screen overlay renderer.
481
+ - Support sprite assets, state mapping, and attached text wash.
482
+ - Add `overlay.actor.publish`.
483
+ - Keep interaction disabled except dismiss-on-click-away.
484
+
485
+ ### Phase 2: Smooth Motion
486
+
487
+ - Add current/target position state.
488
+ - Add display-cadence animation timer.
489
+ - Add `overlay.actor.moveTo`.
490
+ - Map direction to movement animation state where assets support it.
491
+
492
+ ### Phase 3: Hit-Testing And Drag
493
+
494
+ - Make the overlay window selectively interactive.
495
+ - Hit-test only actor and attached surface bounds.
496
+ - Support hover state.
497
+ - Support dragging to move/pin.
498
+ - Emit `overlay.actor.moved`.
499
+
500
+ ### Phase 4: Action Surfaces
501
+
502
+ - Add compact action cards.
503
+ - Support links and action buttons.
504
+ - Emit `overlay.actor.actionSelected`.
505
+ - Add dismiss and snooze behaviors.
506
+
507
+ ### Phase 5: Sound And Settings
508
+
509
+ - Add sound cue names.
510
+ - Add global overlay sound setting.
511
+ - Add rate limits.
512
+ - Add mute/snooze per source or actor.
513
+
514
+ ## Open Questions
515
+
516
+ - Should actors be global across Spaces, per Space, or configurable per actor?
517
+ - Should pinned actor positions be saved per display, per Space, or globally?
518
+ - What is the right default anchor for a persistent actor?
519
+ - Should action cards use AppKit drawing or a small SwiftUI-hosted island?
520
+ - How much interaction can a non-activating panel handle without surprising focus behavior?
521
+ - Should daemon events be broadcast to all clients or routed back to the caller that created the actor?
522
+ - How should drops be represented when users drag files, URLs, or text onto an actor?
523
+
524
+ ## First Useful Slice
525
+
526
+ The first useful implementation should be small:
527
+
528
+ 1. Add `overlay.actor.publish` for a sprite actor with state and attached message.
529
+ 2. Add smooth `overlay.actor.moveTo` with app-owned easing.
530
+ 3. Add selective hit-testing for hover and drag.
531
+ 4. Emit `overlay.actor.moved` and `overlay.actor.clicked`.
532
+ 5. Keep action cards and sound for the next slice.
533
+
534
+ That would make the system immediately feel different from passive overlays while keeping the surface area manageable.