@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.
- package/LICENSE +21 -0
- package/README.md +144 -69
- package/apps/mac/Info.plist +43 -0
- package/apps/mac/Lattices.app/Contents/Info.plist +43 -0
- package/apps/mac/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/apps/mac/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
- package/apps/mac/Lattices.app/Contents/Resources/docs/assistant-knowledge.md +130 -0
- package/apps/mac/Lattices.app/Contents/Resources/tap.wav +0 -0
- package/apps/mac/Lattices.app/Contents/_CodeSignature/CodeResources +150 -0
- package/apps/mac/Lattices.entitlements +21 -0
- package/apps/mac/Resources/Pets/assistant-spark/pet.json +62 -0
- package/apps/mac/Resources/Pets/assistant-spark/spritesheet.webp +0 -0
- package/apps/mac/Resources/Pets/scout-ranger/pet.json +6 -0
- package/apps/mac/Resources/Pets/scout-ranger/spritesheet.webp +0 -0
- package/apps/mac/Resources/tap.wav +0 -0
- package/assets/AppIcon.icns +0 -0
- package/bin/assistant-intelligence.ts +912 -0
- package/bin/cli/capture.ts +252 -0
- package/bin/cli/daemon.ts +22 -0
- package/bin/cli/helpers.ts +105 -0
- package/bin/cli/layer.ts +178 -0
- package/bin/cli/runs.ts +43 -0
- package/bin/cli/search.ts +141 -0
- package/bin/cli/session.ts +32 -0
- package/bin/client.ts +17 -0
- package/bin/cua.ts +26 -0
- package/bin/{daemon-client.js → daemon-client.ts} +49 -30
- package/bin/handsoff-infer.ts +96 -0
- package/bin/handsoff-worker.ts +531 -0
- package/bin/infer.ts +424 -0
- package/bin/keychain.ts +75 -0
- package/bin/lattices-app.ts +655 -0
- package/bin/lattices-build +125 -0
- package/bin/lattices-build-env.ts +77 -0
- package/bin/lattices-dev +362 -0
- package/bin/lattices.ts +3260 -0
- package/bin/project-twin.ts +645 -0
- package/docs/agent-execution-plan.md +562 -0
- package/docs/agent-layer-guide.md +207 -0
- package/docs/agents.md +233 -0
- package/docs/ai-chat-ux-review.md +416 -0
- package/docs/api.md +1041 -47
- package/docs/app.md +96 -13
- package/docs/assistant-knowledge.md +130 -0
- package/docs/companion-deck.md +209 -0
- package/docs/component-extraction-roadmap.md +392 -0
- package/docs/concepts.md +13 -12
- package/docs/config.md +83 -10
- package/docs/gesture-customization-proposal.md +520 -0
- package/docs/handsoff-test-scenarios.md +84 -0
- package/docs/hyperspace-grid-snappiness.md +210 -0
- package/docs/layers.md +176 -28
- package/docs/mouse-gestures.md +244 -0
- package/docs/ocr.md +21 -9
- package/docs/overview.md +42 -23
- package/docs/presentation-execution-review.md +491 -0
- package/docs/prompts/hands-off-system.md +382 -0
- package/docs/prompts/hands-off-turn.md +30 -0
- package/docs/prompts/voice-advisor.md +31 -0
- package/docs/prompts/voice-fallback.md +23 -0
- package/docs/proposals/LAT-001-gesture-visual-customization.md +522 -0
- package/docs/proposals/LAT-002-shared-overlay-canvas.md +353 -0
- package/docs/proposals/LAT-003-menu-bar-controller-architecture.md +291 -0
- package/docs/proposals/LAT-004-interactive-overlay-actors.md +534 -0
- package/docs/proposals/LAT-005-action-runtime-product-spine.md +914 -0
- package/docs/proposals/LAT-006-followup-gaps.md +103 -0
- package/docs/proposals/LAT-006-runs-and-capture-in-lattices.md +566 -0
- package/docs/proposals/LAT-007-unified-app-shell.md +128 -0
- package/docs/quickstart.md +8 -12
- package/docs/reference/dewey.config.ts +74 -0
- package/docs/reference/install-agent.md +79 -0
- package/docs/release.md +172 -0
- package/docs/repo-structure.md +100 -0
- package/docs/terminal-kit.md +87 -0
- package/docs/tiling-reference.md +224 -0
- package/docs/twins.md +138 -0
- package/docs/voice-command-protocol.md +278 -0
- package/docs/voice-error-model.md +73 -0
- package/docs/voice.md +221 -0
- package/package.json +69 -16
- package/packages/npm/sdk/cua.d.mts +1 -0
- package/packages/npm/sdk/cua.d.ts +188 -0
- package/packages/npm/sdk/cua.mjs +376 -0
- package/app/Lattices.app/Contents/Info.plist +0 -24
- package/app/Package.swift +0 -13
- package/app/Sources/ActionRow.swift +0 -61
- package/app/Sources/App.swift +0 -10
- package/app/Sources/AppDelegate.swift +0 -234
- package/app/Sources/AppShellView.swift +0 -62
- package/app/Sources/AppTypeClassifier.swift +0 -70
- package/app/Sources/AppWindowShell.swift +0 -63
- package/app/Sources/CheatSheetHUD.swift +0 -332
- package/app/Sources/CommandModeState.swift +0 -1362
- package/app/Sources/CommandModeView.swift +0 -1405
- package/app/Sources/CommandModeWindow.swift +0 -192
- package/app/Sources/CommandPaletteView.swift +0 -307
- package/app/Sources/CommandPaletteWindow.swift +0 -134
- package/app/Sources/DaemonProtocol.swift +0 -101
- package/app/Sources/DaemonServer.swift +0 -414
- package/app/Sources/DesktopModel.swift +0 -121
- package/app/Sources/DesktopModelTypes.swift +0 -71
- package/app/Sources/DiagnosticLog.swift +0 -271
- package/app/Sources/EventBus.swift +0 -30
- package/app/Sources/HotkeyManager.swift +0 -250
- package/app/Sources/HotkeyStore.swift +0 -338
- package/app/Sources/InventoryManager.swift +0 -35
- package/app/Sources/InventoryPath.swift +0 -43
- package/app/Sources/KeyRecorderView.swift +0 -210
- package/app/Sources/LatticesApi.swift +0 -1125
- package/app/Sources/MainView.swift +0 -467
- package/app/Sources/MainWindow.swift +0 -83
- package/app/Sources/OcrModel.swift +0 -309
- package/app/Sources/OcrStore.swift +0 -295
- package/app/Sources/OmniSearchState.swift +0 -283
- package/app/Sources/OmniSearchView.swift +0 -288
- package/app/Sources/OmniSearchWindow.swift +0 -105
- package/app/Sources/OrphanRow.swift +0 -129
- package/app/Sources/PaletteCommand.swift +0 -419
- package/app/Sources/PermissionChecker.swift +0 -125
- package/app/Sources/Preferences.swift +0 -92
- package/app/Sources/ProcessModel.swift +0 -199
- package/app/Sources/ProcessQuery.swift +0 -151
- package/app/Sources/Project.swift +0 -28
- package/app/Sources/ProjectRow.swift +0 -368
- package/app/Sources/ProjectScanner.swift +0 -121
- package/app/Sources/ScreenMapState.swift +0 -2387
- package/app/Sources/ScreenMapView.swift +0 -2820
- package/app/Sources/ScreenMapWindowController.swift +0 -89
- package/app/Sources/SessionManager.swift +0 -72
- package/app/Sources/SettingsView.swift +0 -1053
- package/app/Sources/SettingsWindow.swift +0 -20
- package/app/Sources/TabGroupRow.swift +0 -178
- package/app/Sources/Terminal.swift +0 -259
- package/app/Sources/TerminalQuery.swift +0 -156
- package/app/Sources/TerminalSynthesizer.swift +0 -200
- package/app/Sources/Theme.swift +0 -163
- package/app/Sources/TilePickerView.swift +0 -209
- package/app/Sources/TmuxModel.swift +0 -53
- package/app/Sources/TmuxQuery.swift +0 -81
- package/app/Sources/WindowTiler.swift +0 -1755
- package/app/Sources/WorkspaceManager.swift +0 -434
- package/bin/lattices-app.js +0 -221
- package/bin/lattices.js +0 -1418
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
# LAT-001: Gesture Visual Customization and Renderer Hooks
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Proposal for maintainers.
|
|
6
|
+
|
|
7
|
+
This is the first Lattices engineering proposal in the `LAT-00n` series, following the same proposal-numbering spirit as the `SCO-00n` documents used for Scout/OpenScout planning.
|
|
8
|
+
|
|
9
|
+
This document covers how to productize the recent mouse gesture and visual customization prototypes without letting decoration leak into the recognition or action-dispatch fast path.
|
|
10
|
+
|
|
11
|
+
## Summary
|
|
12
|
+
|
|
13
|
+
Lattices now has the bones of a gesture system that feels unusually alive for a macOS workspace tool: low-level mouse capture, shape recognition, shortcut matching, immediate native action dispatch, and a fallback overlay that can draw paths, markers, and result labels.
|
|
14
|
+
|
|
15
|
+
The next question is whether customization should become a supported product surface. The answer proposed here is yes, but with a hard boundary:
|
|
16
|
+
|
|
17
|
+
- gesture recognition and action dispatch remain native, synchronous, and fast
|
|
18
|
+
- custom rendering is declarative, best-effort, and optional
|
|
19
|
+
- user assets and external renderers never block or decide actions
|
|
20
|
+
- normal customization should not require recompiling the app
|
|
21
|
+
|
|
22
|
+
The first supported model should be a declarative `visual` block on mouse shortcut rules, backed by native theme presets and marker-to-animation mappings. Real Lottie playback can follow once the configuration model is stable. A plugin or XPC renderer can come later, after the native path has proven the contract.
|
|
23
|
+
|
|
24
|
+
## Current Gesture Pipeline
|
|
25
|
+
|
|
26
|
+
The gesture pipeline lives mainly in:
|
|
27
|
+
|
|
28
|
+
- `apps/mac/Sources/Core/Input/MouseGestureController.swift`
|
|
29
|
+
- `apps/mac/Sources/Core/Input/MouseGestureConfig.swift`
|
|
30
|
+
- `apps/mac/Sources/Core/Input/MouseShortcutStore.swift`
|
|
31
|
+
- `apps/mac/Sources/Core/Input/ShapeRecognizer.swift`
|
|
32
|
+
|
|
33
|
+
The current/prototyped flow is:
|
|
34
|
+
|
|
35
|
+
1. A CG event tap captures mouse button and movement events.
|
|
36
|
+
2. `MouseGestureController` starts and updates gesture sessions, tracking button state, phase, and path points.
|
|
37
|
+
3. Movement points are fed to `ShapeRecognizer`, which compresses raw motion into direction runs.
|
|
38
|
+
4. Recognized shapes such as `l-shape-down-right` become trigger facts.
|
|
39
|
+
5. `MouseShortcutStore` matches a `MouseShortcutTriggerEvent` against enabled `MouseShortcutRule` entries.
|
|
40
|
+
6. The matched rule dispatches its native action immediately.
|
|
41
|
+
7. `MouseGestureOverlay` and `MouseGestureOverlayView`, currently nested in `MouseGestureController.swift`, render the fallback/native gesture feedback.
|
|
42
|
+
|
|
43
|
+
The important split is already visible: input capture, recognition, rule matching, and action dispatch form the control path. Overlay drawing is feedback.
|
|
44
|
+
|
|
45
|
+
## What Was Prototyped
|
|
46
|
+
|
|
47
|
+
Recent prototype work explored both input semantics and visual expression.
|
|
48
|
+
|
|
49
|
+
Input and matching:
|
|
50
|
+
|
|
51
|
+
- shape triggers
|
|
52
|
+
- right, back, forward, and middle button handling
|
|
53
|
+
- MX back/forward aliases
|
|
54
|
+
- a back-button L shape that activates iTerm
|
|
55
|
+
- native action dispatch that stays immediate
|
|
56
|
+
|
|
57
|
+
Visual feedback:
|
|
58
|
+
|
|
59
|
+
- path drawing instead of a single direction arrow
|
|
60
|
+
- Bezier/graffiti trail rendering
|
|
61
|
+
- guide dots inspired by Android pattern lock
|
|
62
|
+
- satisfying result labels such as `iTerm FOCUSED`
|
|
63
|
+
- a `visual` block on shortcut rules
|
|
64
|
+
- a native stand-in for a custom animated character
|
|
65
|
+
|
|
66
|
+
The visual customization proof of concept added optional rule metadata:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"visual": {
|
|
71
|
+
"renderer": "lottie",
|
|
72
|
+
"asset": "~/.lattices/gesture-assets/cat.json",
|
|
73
|
+
"character": "cat",
|
|
74
|
+
"events": {
|
|
75
|
+
"updated": "follow",
|
|
76
|
+
"recognized:l-shape-down-right": "pounce",
|
|
77
|
+
"completed.success": "celebrate",
|
|
78
|
+
"completed.failure": "confused"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Today, `renderer: "lottie"` is a shim/POC name, not a real Lottie dependency. The native renderer draws a small reactive cat/avatar as a stand-in for an eventual Lottie asset.
|
|
85
|
+
|
|
86
|
+
That is a good prototype shape because it tests the user-facing contract without prematurely committing to a rendering engine.
|
|
87
|
+
|
|
88
|
+
## Architecture Principle
|
|
89
|
+
|
|
90
|
+
Recognition and action dispatch are the fast path. They must never wait on:
|
|
91
|
+
|
|
92
|
+
- custom rendering
|
|
93
|
+
- scripts
|
|
94
|
+
- Lottie playback
|
|
95
|
+
- XPC processes
|
|
96
|
+
- user-provided assets
|
|
97
|
+
- filesystem reads after gesture start
|
|
98
|
+
- network access
|
|
99
|
+
|
|
100
|
+
Visual customization is decorative. It can make gestures more legible, delightful, and personal, but it cannot become part of whether a gesture succeeds.
|
|
101
|
+
|
|
102
|
+
In practical terms:
|
|
103
|
+
|
|
104
|
+
- if a renderer fails, the action still runs
|
|
105
|
+
- if an asset is missing, the native fallback overlay appears
|
|
106
|
+
- if an external renderer is slow, it drops frames or misses the gesture
|
|
107
|
+
- if config is invalid, the rule can still match using native trigger/action fields
|
|
108
|
+
- action success/failure is reported from the action layer, not inferred from animation state
|
|
109
|
+
|
|
110
|
+
This boundary should be visible in the code. The gesture controller can emit visual events, but renderers should consume snapshots or markers asynchronously. They should not own recognition state.
|
|
111
|
+
|
|
112
|
+
## Proposed Customization Model
|
|
113
|
+
|
|
114
|
+
### 1. Declarative `visual` block first
|
|
115
|
+
|
|
116
|
+
Mouse shortcut rules should support a stable optional `visual` block:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"id": "back-l-iterm",
|
|
121
|
+
"enabled": true,
|
|
122
|
+
"device": "any",
|
|
123
|
+
"trigger": {
|
|
124
|
+
"button": "back",
|
|
125
|
+
"kind": "shape",
|
|
126
|
+
"shape": "l-shape-down-right"
|
|
127
|
+
},
|
|
128
|
+
"action": {
|
|
129
|
+
"type": "app.activate",
|
|
130
|
+
"app": "iTerm"
|
|
131
|
+
},
|
|
132
|
+
"visual": {
|
|
133
|
+
"renderer": "native",
|
|
134
|
+
"theme": "graffiti",
|
|
135
|
+
"markers": {
|
|
136
|
+
"updated": "follow",
|
|
137
|
+
"recognized:l-shape-down-right": "commit",
|
|
138
|
+
"completed.success": "success",
|
|
139
|
+
"completed.failure": "error"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The `visual` block should be optional and ignored by older versions where possible. Its first stable fields should be:
|
|
146
|
+
|
|
147
|
+
| Field | Type | Purpose |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `renderer` | string | Selects renderer family: `native`, later `lottie`, later `external` |
|
|
150
|
+
| `theme` | string? | Native preset name such as `minimal`, `graffiti`, `pattern`, `avatar` |
|
|
151
|
+
| `asset` | string? | Local asset reference for renderer families that need it |
|
|
152
|
+
| `character` | string? | Optional named character/avatar inside a renderer or asset pack |
|
|
153
|
+
| `markers` or `events` | object | Maps gesture markers to renderer actions |
|
|
154
|
+
|
|
155
|
+
The POC uses `events`; the product model should choose one name. `markers` is slightly clearer because the keys are not all raw system events. They are renderer-facing semantic markers derived from gesture state.
|
|
156
|
+
|
|
157
|
+
### 2. Theme presets
|
|
158
|
+
|
|
159
|
+
Before exposing arbitrary assets as the main path, ship native presets:
|
|
160
|
+
|
|
161
|
+
- `minimal`: simple path and endpoint feedback
|
|
162
|
+
- `graffiti`: Bezier trail with energetic completion burst
|
|
163
|
+
- `pattern`: guide dots and shape lock-in feedback
|
|
164
|
+
- `avatar`: native character-style feedback, similar to the POC cat
|
|
165
|
+
- `quiet`: subtle feedback for users who want confirmation without flourish
|
|
166
|
+
|
|
167
|
+
Presets give users customization without loading code or assets. They also give maintainers a reference for the renderer contract.
|
|
168
|
+
|
|
169
|
+
### 3. Marker mapping
|
|
170
|
+
|
|
171
|
+
Renderer-facing markers should be small, named, and phase-based:
|
|
172
|
+
|
|
173
|
+
| Marker | Meaning |
|
|
174
|
+
|---|---|
|
|
175
|
+
| `started` | Gesture session began |
|
|
176
|
+
| `updated` | Path changed |
|
|
177
|
+
| `recognized:<shape>` | Recognizer has a likely shape |
|
|
178
|
+
| `matched:<rule-id>` | Rule matched |
|
|
179
|
+
| `completed.success` | Action completed successfully |
|
|
180
|
+
| `completed.failure` | Action failed or no rule matched |
|
|
181
|
+
| `cancelled` | Gesture was cancelled |
|
|
182
|
+
|
|
183
|
+
Renderers can map these to animation names, effects, or state transitions:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"markers": {
|
|
188
|
+
"started": "wake",
|
|
189
|
+
"updated": "follow",
|
|
190
|
+
"recognized:l-shape-down-right": "pounce",
|
|
191
|
+
"completed.success": "celebrate",
|
|
192
|
+
"completed.failure": "confused",
|
|
193
|
+
"cancelled": "hide"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The control path emits facts. The renderer interprets those facts.
|
|
199
|
+
|
|
200
|
+
### 4. Asset references
|
|
201
|
+
|
|
202
|
+
Asset references should be local file paths or app-bundled names:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"visual": {
|
|
207
|
+
"renderer": "lottie",
|
|
208
|
+
"asset": "~/.lattices/gesture-assets/cat.json",
|
|
209
|
+
"markers": {
|
|
210
|
+
"updated": "follow",
|
|
211
|
+
"completed.success": "celebrate"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Rules:
|
|
218
|
+
|
|
219
|
+
- expand `~` explicitly
|
|
220
|
+
- resolve relative paths relative to `~/.lattices/`, not the current project
|
|
221
|
+
- do not fetch remote URLs
|
|
222
|
+
- validate extension and size before loading
|
|
223
|
+
- cache parsed assets outside the gesture hot path
|
|
224
|
+
- fall back to `native` if loading fails
|
|
225
|
+
|
|
226
|
+
### 5. Real Lottie player later
|
|
227
|
+
|
|
228
|
+
The current native shim should not pretend to be production Lottie. The roadmap should be:
|
|
229
|
+
|
|
230
|
+
1. stabilize the rule schema and marker model
|
|
231
|
+
2. ship native presets
|
|
232
|
+
3. add a real Lottie player behind the same renderer protocol
|
|
233
|
+
4. keep Lottie playback isolated from recognition and action dispatch
|
|
234
|
+
|
|
235
|
+
This avoids coupling the configuration surface to the first graphics library chosen.
|
|
236
|
+
|
|
237
|
+
### 6. Optional external renderer or XPC later
|
|
238
|
+
|
|
239
|
+
External renderers are powerful, but they are also where latency, crash, and security complexity enters. They should be a later feature, probably via XPC rather than arbitrary process execution.
|
|
240
|
+
|
|
241
|
+
The contract should look like a one-way visual event stream:
|
|
242
|
+
|
|
243
|
+
- Lattices sends gesture snapshots and markers.
|
|
244
|
+
- The renderer returns nothing that affects recognition or actions.
|
|
245
|
+
- The renderer may request drawing surfaces only through a narrow API.
|
|
246
|
+
- Timeouts and crashes are expected and non-fatal.
|
|
247
|
+
|
|
248
|
+
The open source nature of Lattices means users can always recompile experiments. Product customization should be easier and safer than that.
|
|
249
|
+
|
|
250
|
+
## Config Examples
|
|
251
|
+
|
|
252
|
+
### Back Button L to iTerm with Native Visual Markers
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"id": "back-l-iterm",
|
|
257
|
+
"enabled": true,
|
|
258
|
+
"device": "any",
|
|
259
|
+
"trigger": {
|
|
260
|
+
"button": "back",
|
|
261
|
+
"kind": "shape",
|
|
262
|
+
"shape": "l-shape-down-right"
|
|
263
|
+
},
|
|
264
|
+
"action": {
|
|
265
|
+
"type": "app.activate",
|
|
266
|
+
"app": "iTerm"
|
|
267
|
+
},
|
|
268
|
+
"visual": {
|
|
269
|
+
"renderer": "native",
|
|
270
|
+
"theme": "pattern",
|
|
271
|
+
"markers": {
|
|
272
|
+
"started": "show-guides",
|
|
273
|
+
"updated": "draw-path",
|
|
274
|
+
"recognized:l-shape-down-right": "lock-shape",
|
|
275
|
+
"completed.success": "success-label",
|
|
276
|
+
"completed.failure": "miss-label"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Back Button L to iTerm with Future Lottie Asset
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
{
|
|
286
|
+
"id": "back-l-iterm",
|
|
287
|
+
"enabled": true,
|
|
288
|
+
"device": "any",
|
|
289
|
+
"trigger": {
|
|
290
|
+
"button": "back",
|
|
291
|
+
"kind": "shape",
|
|
292
|
+
"shape": "l-shape-down-right"
|
|
293
|
+
},
|
|
294
|
+
"action": {
|
|
295
|
+
"type": "app.activate",
|
|
296
|
+
"app": "iTerm"
|
|
297
|
+
},
|
|
298
|
+
"visual": {
|
|
299
|
+
"renderer": "lottie",
|
|
300
|
+
"asset": "~/.lattices/gesture-assets/cat.json",
|
|
301
|
+
"character": "cat",
|
|
302
|
+
"markers": {
|
|
303
|
+
"started": "wake",
|
|
304
|
+
"updated": "follow",
|
|
305
|
+
"recognized:l-shape-down-right": "pounce",
|
|
306
|
+
"completed.success": "celebrate",
|
|
307
|
+
"completed.failure": "confused",
|
|
308
|
+
"cancelled": "hide"
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Quiet Native Preset
|
|
315
|
+
|
|
316
|
+
```json
|
|
317
|
+
{
|
|
318
|
+
"id": "middle-l-palette",
|
|
319
|
+
"enabled": true,
|
|
320
|
+
"trigger": {
|
|
321
|
+
"button": "middle",
|
|
322
|
+
"kind": "shape",
|
|
323
|
+
"shape": "l-shape-down-right"
|
|
324
|
+
},
|
|
325
|
+
"action": {
|
|
326
|
+
"type": "palette.open"
|
|
327
|
+
},
|
|
328
|
+
"visual": {
|
|
329
|
+
"renderer": "native",
|
|
330
|
+
"theme": "quiet"
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Latency Considerations
|
|
336
|
+
|
|
337
|
+
Gesture UX is latency-sensitive in two places:
|
|
338
|
+
|
|
339
|
+
- recognition should keep up with pointer movement
|
|
340
|
+
- action dispatch should happen as soon as the gesture commits
|
|
341
|
+
|
|
342
|
+
Renderer latency is allowed to be worse than action latency. The user should never feel that an animation is in charge of the system.
|
|
343
|
+
|
|
344
|
+
Implementation guidelines:
|
|
345
|
+
|
|
346
|
+
- use immutable gesture snapshots for renderer updates
|
|
347
|
+
- throttle rendering updates independently from event capture
|
|
348
|
+
- pre-load and validate assets when config changes, not when the gesture begins
|
|
349
|
+
- cap path point history passed to renderers
|
|
350
|
+
- drop visual frames under pressure
|
|
351
|
+
- keep completion labels tied to action receipts, not animation callbacks
|
|
352
|
+
|
|
353
|
+
Target behavior:
|
|
354
|
+
|
|
355
|
+
- action dispatch remains effectively immediate after match
|
|
356
|
+
- native visual feedback tracks the pointer smoothly
|
|
357
|
+
- custom renderer failure is invisible except for fallback visuals or debug logs
|
|
358
|
+
|
|
359
|
+
## Stability Considerations
|
|
360
|
+
|
|
361
|
+
The gesture system sits near global input, so failure modes must be boring.
|
|
362
|
+
|
|
363
|
+
Renderer failures should not:
|
|
364
|
+
|
|
365
|
+
- disable the event tap
|
|
366
|
+
- wedge gesture state
|
|
367
|
+
- prevent shortcut matching
|
|
368
|
+
- crash the app
|
|
369
|
+
- leave persistent overlay windows stuck on screen
|
|
370
|
+
|
|
371
|
+
Recommended boundaries:
|
|
372
|
+
|
|
373
|
+
- a `GestureVisualRenderer` protocol with small methods such as `start`, `update`, `mark`, `complete`, `cancel`
|
|
374
|
+
- a native fallback renderer that is always available
|
|
375
|
+
- renderer selection that can fail closed to `native`
|
|
376
|
+
- defensive validation of unknown marker names
|
|
377
|
+
- debug logging for invalid visuals, but no noisy user-facing alerts during gestures
|
|
378
|
+
|
|
379
|
+
## Security Considerations
|
|
380
|
+
|
|
381
|
+
Even though Lattices is open source, normal customization should not require recompilation. That means configuration and assets become part of the product surface and need constraints.
|
|
382
|
+
|
|
383
|
+
For MVP:
|
|
384
|
+
|
|
385
|
+
- no remote asset URLs
|
|
386
|
+
- no shell commands in `visual`
|
|
387
|
+
- no arbitrary scripts
|
|
388
|
+
- no executable plugins
|
|
389
|
+
- local assets only
|
|
390
|
+
- size limits for loaded assets
|
|
391
|
+
- clear fallback when assets are missing or invalid
|
|
392
|
+
|
|
393
|
+
For a future external renderer:
|
|
394
|
+
|
|
395
|
+
- prefer XPC over raw process execution
|
|
396
|
+
- use a narrow, documented message protocol
|
|
397
|
+
- treat renderer output as pixels or visual state only
|
|
398
|
+
- never accept action decisions from the renderer
|
|
399
|
+
- add a user-visible trust/install flow if third-party renderer bundles are supported
|
|
400
|
+
|
|
401
|
+
## Proposed Internal Shape
|
|
402
|
+
|
|
403
|
+
The implementation should keep the current architecture but name the boundary more explicitly.
|
|
404
|
+
|
|
405
|
+
Possible types:
|
|
406
|
+
|
|
407
|
+
```swift
|
|
408
|
+
struct GestureVisualConfig {
|
|
409
|
+
let renderer: GestureVisualRendererID
|
|
410
|
+
let theme: String?
|
|
411
|
+
let asset: String?
|
|
412
|
+
let character: String?
|
|
413
|
+
let markers: [String: String]
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
struct GestureVisualSnapshot {
|
|
417
|
+
let sessionID: UUID
|
|
418
|
+
let phase: GesturePhase
|
|
419
|
+
let button: MouseShortcutButton
|
|
420
|
+
let points: [CGPoint]
|
|
421
|
+
let recognizedShape: String?
|
|
422
|
+
let matchedRuleID: String?
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
protocol GestureVisualRenderer {
|
|
426
|
+
func start(_ snapshot: GestureVisualSnapshot, config: GestureVisualConfig)
|
|
427
|
+
func update(_ snapshot: GestureVisualSnapshot)
|
|
428
|
+
func mark(_ marker: String, snapshot: GestureVisualSnapshot)
|
|
429
|
+
func complete(_ marker: String, snapshot: GestureVisualSnapshot)
|
|
430
|
+
func cancel(_ snapshot: GestureVisualSnapshot)
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
The exact Swift names can differ. The important part is that renderers consume snapshots and markers; they do not mutate recognition state or decide actions.
|
|
435
|
+
|
|
436
|
+
## Phased Roadmap
|
|
437
|
+
|
|
438
|
+
### Phase 0: POC Cleanup
|
|
439
|
+
|
|
440
|
+
Goal: make the prototype understandable and safe to keep iterating.
|
|
441
|
+
|
|
442
|
+
- keep native avatar/Lottie shim clearly labeled as POC
|
|
443
|
+
- document current supported marker keys
|
|
444
|
+
- ensure missing or invalid visual config falls back to native overlay
|
|
445
|
+
- verify back/forward button aliases and shape matching remain independent from visuals
|
|
446
|
+
|
|
447
|
+
### Phase 1: MVP Native Customization
|
|
448
|
+
|
|
449
|
+
Goal: support real user customization without external dependencies.
|
|
450
|
+
|
|
451
|
+
- stabilize the `visual` schema
|
|
452
|
+
- support `renderer: "native"`
|
|
453
|
+
- ship a small set of native themes
|
|
454
|
+
- support marker mapping for native themes
|
|
455
|
+
- load visual config from normal shortcut config
|
|
456
|
+
- add diagnostics for invalid visuals
|
|
457
|
+
- keep existing native overlay as fallback
|
|
458
|
+
|
|
459
|
+
### Phase 2: Real Lottie Integration
|
|
460
|
+
|
|
461
|
+
Goal: make `renderer: "lottie"` honest.
|
|
462
|
+
|
|
463
|
+
- add a real Lottie player dependency or embedded playback implementation
|
|
464
|
+
- validate and cache Lottie assets outside the gesture hot path
|
|
465
|
+
- map markers to animation segments or named states
|
|
466
|
+
- enforce size and complexity limits
|
|
467
|
+
- provide at least one bundled example asset
|
|
468
|
+
|
|
469
|
+
### Phase 3: Renderer Hooks and XPC
|
|
470
|
+
|
|
471
|
+
Goal: enable deeper experiments without compromising the app.
|
|
472
|
+
|
|
473
|
+
- define a one-way renderer event protocol
|
|
474
|
+
- run external renderers out of process
|
|
475
|
+
- add crash and timeout handling
|
|
476
|
+
- add user trust/install UX for third-party renderers
|
|
477
|
+
- keep all action decisions inside Lattices
|
|
478
|
+
|
|
479
|
+
## Open Questions
|
|
480
|
+
|
|
481
|
+
- Should the field be named `events` to match the prototype, or `markers` to better describe the stable concept?
|
|
482
|
+
- Should visual config live only on individual rules, or should users be able to define reusable named visual profiles?
|
|
483
|
+
- How much of `MouseGestureOverlay` should become a renderer implementation versus remaining a fallback shell?
|
|
484
|
+
- Should marker names be fully free-form, or should unknown keys be rejected during config validation?
|
|
485
|
+
- Do we want app-level theme defaults, per-device defaults, or only per-rule visuals for MVP?
|
|
486
|
+
- Should `completed.failure` mean "no rule matched", "action failed", or both with more specific submarkers?
|
|
487
|
+
- Where should user assets live: `~/.lattices/gesture-assets/`, app support, or both?
|
|
488
|
+
|
|
489
|
+
## Acceptance Criteria
|
|
490
|
+
|
|
491
|
+
For the MVP:
|
|
492
|
+
|
|
493
|
+
- A shortcut rule can include a `visual` block without changing trigger or action behavior.
|
|
494
|
+
- A back-button `l-shape-down-right` rule can activate iTerm and show native marker-based feedback.
|
|
495
|
+
- Invalid visual config falls back to the native overlay and does not prevent the action.
|
|
496
|
+
- Missing assets do not crash the app or delay gesture completion.
|
|
497
|
+
- Recognition and action dispatch do not wait on renderer work.
|
|
498
|
+
- Native themes can render started, updated, recognized, success, failure, and cancelled states.
|
|
499
|
+
- The config format is documented with at least one complete example.
|
|
500
|
+
- Debug diagnostics make renderer fallback understandable to maintainers.
|
|
501
|
+
|
|
502
|
+
For later Lottie support:
|
|
503
|
+
|
|
504
|
+
- `renderer: "lottie"` uses a real Lottie player, not the native shim.
|
|
505
|
+
- Lottie assets are validated and cached before gesture start.
|
|
506
|
+
- Marker mappings can target named animations or segments.
|
|
507
|
+
- Lottie renderer failure falls back to native rendering without affecting actions.
|
|
508
|
+
|
|
509
|
+
## Recommendation
|
|
510
|
+
|
|
511
|
+
Productize visual customization, but productize it as a renderer contract rather than as a graphics feature.
|
|
512
|
+
|
|
513
|
+
The useful product surface is not "play a cat animation." It is:
|
|
514
|
+
|
|
515
|
+
- gestures have stable semantic markers
|
|
516
|
+
- users can bind visual feedback to those markers
|
|
517
|
+
- Lattices keeps input and action dispatch fast
|
|
518
|
+
- renderers are replaceable decoration
|
|
519
|
+
|
|
520
|
+
That gives maintainers room to ship the fun parts without letting them become load-bearing.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Hands-Off Mode — Test Scenarios
|
|
2
|
+
|
|
3
|
+
Press Ctrl+Cmd+M, say the phrase, press Ctrl+Cmd+M again. Check the result.
|
|
4
|
+
|
|
5
|
+
## 1. Basic awareness
|
|
6
|
+
|
|
7
|
+
| # | Say | Expected | Check |
|
|
8
|
+
|---|-----|----------|-------|
|
|
9
|
+
| 1.1 | "What's the frontmost window?" | Names the app + project/title, no wid | Correct window? No numbers? |
|
|
10
|
+
| 1.2 | "How many monitors do I have?" | Correct count + sizes | Matches reality? |
|
|
11
|
+
| 1.3 | "What terminals do I have open?" | Lists terminals with projects/cwds | Does it know the projects? |
|
|
12
|
+
| 1.4 | "Which ones are running Claude Code?" | Lists only Claude terminals + their projects | Correct? Uses hasClaude? |
|
|
13
|
+
| 1.5 | "What's on my second monitor?" | Describes windows on the non-main display | Correct display? |
|
|
14
|
+
|
|
15
|
+
## 2. Simple tiling
|
|
16
|
+
|
|
17
|
+
| # | Say | Expected | Check |
|
|
18
|
+
|---|-----|----------|-------|
|
|
19
|
+
| 2.1 | "Tile Chrome left" | Chrome moves to left half | Did it move? Spoken confirmation? |
|
|
20
|
+
| 2.2 | "Put iTerm on the right" | iTerm moves to right half | Correct window? |
|
|
21
|
+
| 2.3 | "Maximize this window" | Frontmost window maximizes | Right window? |
|
|
22
|
+
| 2.4 | "Center the Finder window" | Finder centers | Correct? |
|
|
23
|
+
|
|
24
|
+
## 3. Multi-window layouts
|
|
25
|
+
|
|
26
|
+
| # | Say | Expected | Check |
|
|
27
|
+
|---|-----|----------|-------|
|
|
28
|
+
| 3.1 | "Split Chrome and iTerm" | Chrome left, iTerm right | Both move? Spoken narration? |
|
|
29
|
+
| 3.2 | "Put everything in a grid" | distribute intent fires | Windows arrange? |
|
|
30
|
+
| 3.3 | "Thirds with Chrome, iTerm, and Finder" | Three apps in left/center/right thirds | Correct apps + positions? |
|
|
31
|
+
| 3.4 | "Quadrants" | Four windows in corners | Reasonable choices? |
|
|
32
|
+
|
|
33
|
+
## 4. Focus + switching
|
|
34
|
+
|
|
35
|
+
| # | Say | Expected | Check |
|
|
36
|
+
|---|-----|----------|-------|
|
|
37
|
+
| 4.1 | "Focus on Slack" | Slack comes to front | Did it switch? |
|
|
38
|
+
| 4.2 | "Switch to Chrome" | Chrome comes to front | Correct? |
|
|
39
|
+
| 4.3 | "Go to the lattices terminal" | Focuses the iTerm in ~/dev/lattices | Right terminal? |
|
|
40
|
+
| 4.4 | "Show me the Hudson Claude Code" | Focuses iTerm with hasClaude + cwd hudson | Correct? |
|
|
41
|
+
|
|
42
|
+
## 5. Conversational context
|
|
43
|
+
|
|
44
|
+
| # | Say | Expected | Check |
|
|
45
|
+
|---|-----|----------|-------|
|
|
46
|
+
| 5.1 | "Tile Chrome left" then "Now put iTerm on the right" | Two separate turns, both work | Context from turn 1 used? |
|
|
47
|
+
| 5.2 | "Tile Chrome left" then "Swap them" | Chrome right, iTerm left | Understood "them"? |
|
|
48
|
+
| 5.3 | "What terminals do I have?" then "Organize those" | Lists, then distributes the terminals | Connected the turns? |
|
|
49
|
+
| 5.4 | "Put it back" (after any tiling) | Reverses last action | Worked? (may not be supported yet) |
|
|
50
|
+
|
|
51
|
+
## 6. Intelligence
|
|
52
|
+
|
|
53
|
+
| # | Say | Expected | Check |
|
|
54
|
+
|---|-----|----------|-------|
|
|
55
|
+
| 6.1 | "Set up for coding" | Intelligent layout based on visible apps | Reasonable? Explained reasoning? |
|
|
56
|
+
| 6.2 | "I'm going to do a code review" | Suggests/applies review layout | Smart choice? |
|
|
57
|
+
| 6.3 | "Clean up my desktop" | Distributes or suggests organization | Actionable? |
|
|
58
|
+
| 6.4 | "Too many windows, simplify" | Suggests hiding some, focuses key ones | Reasonable? |
|
|
59
|
+
|
|
60
|
+
## 7. Error handling
|
|
61
|
+
|
|
62
|
+
| # | Say | Expected | Check |
|
|
63
|
+
|---|-----|----------|-------|
|
|
64
|
+
| 7.1 | "Focus on Firefox" | "I don't see Firefox. You have Chrome and Safari." | Honest? Names real apps? |
|
|
65
|
+
| 7.2 | "Tile the Photoshop window" | "Photoshop isn't open right now." | No hallucination? |
|
|
66
|
+
| 7.3 | (mumble something unclear) | "I didn't catch that. Can you say it again?" | Graceful? |
|
|
67
|
+
|
|
68
|
+
## 8. Actions actually execute
|
|
69
|
+
|
|
70
|
+
| # | Say | Expected | Check |
|
|
71
|
+
|---|-----|----------|-------|
|
|
72
|
+
| 8.1 | "Distribute my windows" | spoken + distribute action | Actions array not empty? |
|
|
73
|
+
| 8.2 | "Organize my terminals" | spoken + distribute or tile actions | Actions actually fire? |
|
|
74
|
+
| 8.3 | Any action command | Hear narration BEFORE windows move | Sequence correct? |
|
|
75
|
+
|
|
76
|
+
## Scoring
|
|
77
|
+
|
|
78
|
+
For each test:
|
|
79
|
+
- ✅ Works correctly
|
|
80
|
+
- ⚠️ Partially works (note what's wrong)
|
|
81
|
+
- ❌ Broken (note error)
|
|
82
|
+
- 🔇 No audio feedback
|
|
83
|
+
|
|
84
|
+
Track in a copy of this file or in the terminal.
|