@lattices/cli 0.3.0 → 0.4.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/README.md +85 -9
- package/app/Info.plist +30 -0
- package/app/Lattices.app/Contents/Info.plist +8 -2
- package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/app/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
- package/app/Lattices.app/Contents/Resources/tap.wav +0 -0
- package/app/Lattices.app/Contents/_CodeSignature/CodeResources +139 -0
- package/app/Lattices.entitlements +15 -0
- package/app/Package.swift +8 -1
- package/app/Resources/tap.wav +0 -0
- package/app/Sources/AdvisorLearningStore.swift +90 -0
- package/app/Sources/AgentSession.swift +377 -0
- package/app/Sources/AppDelegate.swift +45 -12
- package/app/Sources/AppShellView.swift +81 -8
- package/app/Sources/AudioProvider.swift +386 -0
- package/app/Sources/CheatSheetHUD.swift +261 -19
- package/app/Sources/DaemonProtocol.swift +13 -0
- package/app/Sources/DaemonServer.swift +8 -0
- package/app/Sources/DesktopModel.swift +189 -6
- package/app/Sources/DesktopModelTypes.swift +2 -0
- package/app/Sources/DiagnosticLog.swift +104 -2
- package/app/Sources/EventBus.swift +1 -0
- package/app/Sources/HUDBottomBar.swift +279 -0
- package/app/Sources/HUDController.swift +1158 -0
- package/app/Sources/HUDLeftBar.swift +849 -0
- package/app/Sources/HUDMinimap.swift +179 -0
- package/app/Sources/HUDRightBar.swift +774 -0
- package/app/Sources/HUDState.swift +367 -0
- package/app/Sources/HUDTopBar.swift +243 -0
- package/app/Sources/HandsOffSession.swift +802 -0
- package/app/Sources/HomeDashboardView.swift +125 -0
- package/app/Sources/HotkeyManager.swift +2 -0
- package/app/Sources/HotkeyStore.swift +49 -9
- package/app/Sources/IntentEngine.swift +962 -0
- package/app/Sources/Intents/CreateLayerIntent.swift +54 -0
- package/app/Sources/Intents/DistributeIntent.swift +56 -0
- package/app/Sources/Intents/FocusIntent.swift +69 -0
- package/app/Sources/Intents/HelpIntent.swift +41 -0
- package/app/Sources/Intents/KillIntent.swift +47 -0
- package/app/Sources/Intents/LatticeIntent.swift +78 -0
- package/app/Sources/Intents/LaunchIntent.swift +67 -0
- package/app/Sources/Intents/ListSessionsIntent.swift +32 -0
- package/app/Sources/Intents/ListWindowsIntent.swift +30 -0
- package/app/Sources/Intents/ScanIntent.swift +52 -0
- package/app/Sources/Intents/SearchIntent.swift +190 -0
- package/app/Sources/Intents/SwitchLayerIntent.swift +50 -0
- package/app/Sources/Intents/TileIntent.swift +61 -0
- package/app/Sources/LatticesApi.swift +1275 -30
- package/app/Sources/LauncherHUD.swift +348 -0
- package/app/Sources/MainView.swift +147 -44
- package/app/Sources/MouseFinder.swift +222 -0
- package/app/Sources/OcrModel.swift +34 -1
- package/app/Sources/OmniSearchState.swift +99 -102
- package/app/Sources/OnboardingView.swift +457 -0
- package/app/Sources/PermissionChecker.swift +2 -12
- package/app/Sources/PiChatDock.swift +454 -0
- package/app/Sources/PiChatSession.swift +815 -0
- package/app/Sources/PiWorkspaceView.swift +364 -0
- package/app/Sources/PlacementSpec.swift +195 -0
- package/app/Sources/Preferences.swift +59 -0
- package/app/Sources/ProjectScanner.swift +58 -45
- package/app/Sources/ScreenMapState.swift +701 -55
- package/app/Sources/ScreenMapView.swift +843 -103
- package/app/Sources/ScreenMapWindowController.swift +22 -0
- package/app/Sources/SessionLayerStore.swift +285 -0
- package/app/Sources/SessionManager.swift +4 -1
- package/app/Sources/SettingsView.swift +186 -3
- package/app/Sources/Theme.swift +9 -8
- package/app/Sources/TmuxModel.swift +7 -0
- package/app/Sources/TmuxQuery.swift +27 -3
- package/app/Sources/VoiceChatView.swift +192 -0
- package/app/Sources/VoiceCommandWindow.swift +1594 -0
- package/app/Sources/VoiceIntentResolver.swift +671 -0
- package/app/Sources/VoxClient.swift +454 -0
- package/app/Sources/WindowTiler.swift +348 -87
- package/app/Sources/WorkspaceManager.swift +127 -18
- package/app/Tests/StageDragTests.swift +333 -0
- package/app/Tests/StageJoinTests.swift +313 -0
- package/app/Tests/StageManagerTests.swift +280 -0
- package/app/Tests/StageTileTests.swift +353 -0
- package/assets/AppIcon.icns +0 -0
- package/bin/client.ts +16 -0
- package/bin/{daemon-client.js → daemon-client.ts} +49 -30
- package/bin/handsoff-infer.ts +280 -0
- package/bin/handsoff-worker.ts +740 -0
- package/bin/lattices-app.ts +338 -0
- package/bin/lattices-dev +208 -0
- package/bin/{lattices.js → lattices.ts} +777 -140
- 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 +142 -0
- package/docs/api.md +153 -34
- package/docs/app.md +29 -1
- package/docs/config.md +5 -1
- package/docs/handsoff-test-scenarios.md +84 -0
- package/docs/layers.md +20 -20
- package/docs/ocr.md +14 -5
- package/docs/overview.md +5 -1
- package/docs/presentation-execution-review.md +491 -0
- package/docs/prompts/hands-off-system.md +374 -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/tiling-reference.md +167 -0
- package/docs/twins.md +138 -0
- package/docs/voice-command-protocol.md +278 -0
- package/docs/voice.md +219 -0
- package/package.json +29 -11
- package/bin/client.js +0 -4
- package/bin/lattices-app.js +0 -221
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
# Presentation And Execution Review
|
|
2
|
+
|
|
3
|
+
This note reviews the current Lattices presentation layer, the tiling and intent-to-outcome pipeline behind it, and a direction for tightening execution logic. It also pulls in relevant ideas from Hyprland and Wayland, using primary sources only.
|
|
4
|
+
|
|
5
|
+
## Why this document exists
|
|
6
|
+
|
|
7
|
+
Lattices already has strong operator-facing surfaces:
|
|
8
|
+
|
|
9
|
+
- HUD and keyboard-driven interaction
|
|
10
|
+
- local voice mode
|
|
11
|
+
- hands-off voice mode
|
|
12
|
+
- command palette
|
|
13
|
+
- desktop inventory and search
|
|
14
|
+
|
|
15
|
+
What is still under-shaped is the execution core behind those surfaces. Today the UX is ahead of the action model.
|
|
16
|
+
|
|
17
|
+
The root issue is not "tiling quality" in isolation. The deeper issue is that Lattices has multiple control surfaces, multiple intent grammars, and multiple direct execution paths that do not converge on a single canonical planner/executor.
|
|
18
|
+
|
|
19
|
+
## Review scope
|
|
20
|
+
|
|
21
|
+
This review is based on:
|
|
22
|
+
|
|
23
|
+
- `app/Sources/WindowTiler.swift`
|
|
24
|
+
- `app/Sources/WorkspaceManager.swift`
|
|
25
|
+
- `app/Sources/IntentEngine.swift`
|
|
26
|
+
- `app/Sources/VoiceIntentResolver.swift`
|
|
27
|
+
- `app/Sources/LatticesApi.swift`
|
|
28
|
+
- `app/Sources/PaletteCommand.swift`
|
|
29
|
+
- `app/Sources/HUDController.swift`
|
|
30
|
+
- `app/Sources/DesktopModel.swift`
|
|
31
|
+
- `app/Sources/HandsOffSession.swift`
|
|
32
|
+
- `docs/voice-command-protocol.md`
|
|
33
|
+
|
|
34
|
+
## Current Architecture
|
|
35
|
+
|
|
36
|
+
### 1. Presentation surfaces are rich, but execution is fragmented
|
|
37
|
+
|
|
38
|
+
Lattices currently has at least five operator surfaces:
|
|
39
|
+
|
|
40
|
+
| Surface | Main files | How it resolves intent | How it executes |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| Command palette | `PaletteCommand.swift`, `CommandPaletteView.swift` | No semantic resolution | Calls `SessionManager`, `WindowTiler`, `WorkspaceManager` directly |
|
|
43
|
+
| HUD | `HUDController.swift` | Hardcoded key routing | Calls `WindowTiler` and `HandsOffSession` directly |
|
|
44
|
+
| Local voice | `VoiceCommandWindow.swift`, `VoiceIntentResolver.swift`, `IntentEngine.swift` | NL embedding + heuristics + slot extraction | Mix of `LatticesApi` dispatch and direct `WindowTiler` calls |
|
|
45
|
+
| Hands-off voice | `HandsOffSession.swift` | External worker returns action list | Replays actions through `PhraseMatcher` / `IntentEngine` |
|
|
46
|
+
| Daemon / API | `LatticesApi.swift`, `DaemonServer.swift` | Structured request only | Calls subsystems directly |
|
|
47
|
+
|
|
48
|
+
The result is a split brain:
|
|
49
|
+
|
|
50
|
+
- presentation is centralized in the app
|
|
51
|
+
- execution is not centralized in one action engine
|
|
52
|
+
|
|
53
|
+
### 2. Tiling itself is reasonably capable
|
|
54
|
+
|
|
55
|
+
`WindowTiler.swift` already has solid building blocks:
|
|
56
|
+
|
|
57
|
+
- named positions from halves up through sixths and eighths
|
|
58
|
+
- generic `grid:CxR:C,R` support
|
|
59
|
+
- frame derivation against `visibleFrame`
|
|
60
|
+
- fast path via `DesktopModel`
|
|
61
|
+
- AX fallback
|
|
62
|
+
- AppleScript fallback
|
|
63
|
+
- batch moves and raises
|
|
64
|
+
- space discovery and limited space movement
|
|
65
|
+
|
|
66
|
+
That is a good substrate. The problem is not the absence of tiling primitives. The problem is that these primitives are reached through different decision systems.
|
|
67
|
+
|
|
68
|
+
### 3. Layer tiling is the closest thing to an orchestrator
|
|
69
|
+
|
|
70
|
+
`WorkspaceManager.tileLayer(...)` is the most complete execution pipeline in the app today. It already does:
|
|
71
|
+
|
|
72
|
+
1. inventory refresh
|
|
73
|
+
2. classification of running vs missing windows
|
|
74
|
+
3. batched moves for known windows
|
|
75
|
+
4. fallbacks for untracked windows
|
|
76
|
+
5. launch queue for missing projects/apps
|
|
77
|
+
6. delayed post-launch tiling
|
|
78
|
+
|
|
79
|
+
This is useful, but it is still a per-feature orchestrator, not the shared execution model for the whole product.
|
|
80
|
+
|
|
81
|
+
### 4. Intent conversion currently exists in multiple incompatible forms
|
|
82
|
+
|
|
83
|
+
There are several distinct ways to convert a user goal into motion:
|
|
84
|
+
|
|
85
|
+
- HUD key map in `HUDController`
|
|
86
|
+
- local voice extraction in `VoiceIntentResolver`
|
|
87
|
+
- intent handlers in `IntentEngine`
|
|
88
|
+
- direct daemon calls in `LatticesApi`
|
|
89
|
+
- hands-off worker action generation in `HandsOffSession`
|
|
90
|
+
|
|
91
|
+
These systems overlap, but they are not the same system.
|
|
92
|
+
|
|
93
|
+
## Root-Cause Findings
|
|
94
|
+
|
|
95
|
+
### 1. There is no canonical action schema
|
|
96
|
+
|
|
97
|
+
The core missing layer is a first-class action model. Right now Lattices mostly jumps from:
|
|
98
|
+
|
|
99
|
+
- UI event -> subsystem method
|
|
100
|
+
|
|
101
|
+
instead of:
|
|
102
|
+
|
|
103
|
+
- UI event -> canonical action -> planner -> validated execution -> result
|
|
104
|
+
|
|
105
|
+
That is why each surface grows its own grammar and shortcuts.
|
|
106
|
+
|
|
107
|
+
### 2. Intent resolution and execution are coupled too early
|
|
108
|
+
|
|
109
|
+
`IntentEngine` mixes:
|
|
110
|
+
|
|
111
|
+
- slot validation
|
|
112
|
+
- target resolution
|
|
113
|
+
- direct side effects
|
|
114
|
+
|
|
115
|
+
That makes it harder to:
|
|
116
|
+
|
|
117
|
+
- preview what will happen
|
|
118
|
+
- batch actions coherently
|
|
119
|
+
- deduplicate targets
|
|
120
|
+
- rollback or retry
|
|
121
|
+
- explain why a request failed before side effects begin
|
|
122
|
+
|
|
123
|
+
### 3. Presentation layers still own execution semantics
|
|
124
|
+
|
|
125
|
+
Examples:
|
|
126
|
+
|
|
127
|
+
- command palette actions directly call `WindowTiler` / `SessionManager`
|
|
128
|
+
- HUD tile mode computes its own ad hoc grid and applies it immediately
|
|
129
|
+
- local voice can go through `LatticesApi` or bypass it
|
|
130
|
+
- hands-off voice replays actions one by one rather than committing a single execution plan
|
|
131
|
+
|
|
132
|
+
This means the product does not yet have one source of truth for "what operation means" or "what order side effects should occur in."
|
|
133
|
+
|
|
134
|
+
### 4. The system is not transactional
|
|
135
|
+
|
|
136
|
+
Wayland's most useful idea here is not Linux-specific rendering. It is commit discipline.
|
|
137
|
+
|
|
138
|
+
Lattices currently performs many operations incrementally:
|
|
139
|
+
|
|
140
|
+
- poll desktop
|
|
141
|
+
- start moving known windows
|
|
142
|
+
- navigate to missing windows
|
|
143
|
+
- launch apps
|
|
144
|
+
- tile launched apps later
|
|
145
|
+
|
|
146
|
+
That produces useful behavior, but not an explicit transaction model. The user intent is "arrange my workspace", but implementation today is "execute a staggered set of best-effort side effects."
|
|
147
|
+
|
|
148
|
+
### 5. Window identity is still mostly heuristic
|
|
149
|
+
|
|
150
|
+
The current system relies on:
|
|
151
|
+
|
|
152
|
+
- `[lattices:session-name]` title tags for terminal windows
|
|
153
|
+
- `app + title substring` matching for non-terminal windows
|
|
154
|
+
- a `DesktopModel` cache plus CG/AX fallbacks
|
|
155
|
+
|
|
156
|
+
This is workable, but it is not yet elevated into a durable target-resolution layer with confidence, ambiguity handling, or plan-time diagnostics.
|
|
157
|
+
|
|
158
|
+
### 6. The product has multiple position grammars
|
|
159
|
+
|
|
160
|
+
At minimum there are separate position systems in:
|
|
161
|
+
|
|
162
|
+
- `TilePosition`
|
|
163
|
+
- `parseGridString(...)`
|
|
164
|
+
- `VoiceIntentResolver.resolvePosition(...)`
|
|
165
|
+
- HUD key routing
|
|
166
|
+
- hands-off worker output
|
|
167
|
+
- daemon `window.tile`
|
|
168
|
+
|
|
169
|
+
The existence of `TilePosition` suggests there should be one canonical placement language. In practice there are several.
|
|
170
|
+
|
|
171
|
+
## What Hyprland Gets Right
|
|
172
|
+
|
|
173
|
+
### 1. One mutation surface: dispatchers
|
|
174
|
+
|
|
175
|
+
Hyprland exposes a consistent mutation model: `hyprctl dispatch ...` calls compositor dispatchers rather than inventing a new command path for each UI. That is the right mental model for Lattices too.
|
|
176
|
+
|
|
177
|
+
For Lattices, the equivalent should be:
|
|
178
|
+
|
|
179
|
+
- one canonical action registry
|
|
180
|
+
- many presentation surfaces
|
|
181
|
+
- one executor
|
|
182
|
+
|
|
183
|
+
### 2. Separate control from live observation
|
|
184
|
+
|
|
185
|
+
Hyprland separates:
|
|
186
|
+
|
|
187
|
+
- control/info requests via `hyprctl` / request socket
|
|
188
|
+
- live events via `socket2`
|
|
189
|
+
|
|
190
|
+
That split is useful for Lattices. The app already has an `EventBus`, but execution still often assumes fresh polling instead of treating live state and mutations as distinct first-class channels.
|
|
191
|
+
|
|
192
|
+
### 3. Rules are first-class, not hidden glue
|
|
193
|
+
|
|
194
|
+
Hyprland's window rules are useful not because Lattices should copy them literally, but because they formalize policy:
|
|
195
|
+
|
|
196
|
+
- what should open where
|
|
197
|
+
- when rules are evaluated
|
|
198
|
+
- which rules are static vs dynamic
|
|
199
|
+
|
|
200
|
+
Lattices currently has pieces of this spread across:
|
|
201
|
+
|
|
202
|
+
- layer project specs
|
|
203
|
+
- companion `windows` entries
|
|
204
|
+
- session naming
|
|
205
|
+
- title matching
|
|
206
|
+
- ad hoc fallback behavior
|
|
207
|
+
|
|
208
|
+
These want to become an explicit rule engine.
|
|
209
|
+
|
|
210
|
+
### 4. Layout engines are explicit and addressable
|
|
211
|
+
|
|
212
|
+
Hyprland treats layout strategy as a named concept:
|
|
213
|
+
|
|
214
|
+
- `master`
|
|
215
|
+
- `dwindle`
|
|
216
|
+
- per-layout config
|
|
217
|
+
- layout-specific dispatchers / layout messages
|
|
218
|
+
|
|
219
|
+
Lattices currently has positions, grids, layer tiling, and distribute logic, but not named layout engines with their own semantics. That is why many arrangements still feel like clever commands rather than stable workspace behaviors.
|
|
220
|
+
|
|
221
|
+
## What Wayland Gets Right
|
|
222
|
+
|
|
223
|
+
### 1. Clear object roles
|
|
224
|
+
|
|
225
|
+
Wayland's `wl_surface` becomes meaningful through roles such as toplevel and popup. That separation matters.
|
|
226
|
+
|
|
227
|
+
Lattices needs the same distinction between:
|
|
228
|
+
|
|
229
|
+
- raw windows
|
|
230
|
+
- lattices session windows
|
|
231
|
+
- companion app windows
|
|
232
|
+
- HUD utility windows
|
|
233
|
+
- layout targets
|
|
234
|
+
- execution results
|
|
235
|
+
|
|
236
|
+
Right now these concepts are present, but not formalized strongly enough in the execution model.
|
|
237
|
+
|
|
238
|
+
### 2. Requests and events are different things
|
|
239
|
+
|
|
240
|
+
Wayland's protocol model is built around objects with requests and events. Lattices should mirror that more explicitly:
|
|
241
|
+
|
|
242
|
+
- requests mutate state
|
|
243
|
+
- events report state changes
|
|
244
|
+
- snapshots are derived, not the mutation API
|
|
245
|
+
|
|
246
|
+
Today those concerns blur together in some places.
|
|
247
|
+
|
|
248
|
+
### 3. Pending state vs applied state
|
|
249
|
+
|
|
250
|
+
This is the biggest transferable idea.
|
|
251
|
+
|
|
252
|
+
Wayland's surface lifecycle makes state changes pending until commit. Lattices should adopt the same pattern for workspace arrangement:
|
|
253
|
+
|
|
254
|
+
- resolve targets
|
|
255
|
+
- compute plan
|
|
256
|
+
- validate plan
|
|
257
|
+
- commit plan
|
|
258
|
+
- publish result
|
|
259
|
+
|
|
260
|
+
Without this, "organize my windows" will always be less predictable than it should be.
|
|
261
|
+
|
|
262
|
+
### 4. Configure / acknowledge / commit
|
|
263
|
+
|
|
264
|
+
Wayland's configure-and-ack flow is a good model for coordination between planner and executor:
|
|
265
|
+
|
|
266
|
+
- planner proposes a layout/result
|
|
267
|
+
- executor acknowledges what can be applied
|
|
268
|
+
- final commit produces the visible outcome
|
|
269
|
+
|
|
270
|
+
For Lattices, this suggests explicit execution receipts, not just side effects plus logging.
|
|
271
|
+
|
|
272
|
+
## Proposed Direction For Lattices
|
|
273
|
+
|
|
274
|
+
### 1. Introduce a canonical action model
|
|
275
|
+
|
|
276
|
+
Every surface should emit the same internal action envelope:
|
|
277
|
+
|
|
278
|
+
```json
|
|
279
|
+
{
|
|
280
|
+
"intent": "window.tile",
|
|
281
|
+
"targets": [{ "kind": "wid", "value": 1234 }],
|
|
282
|
+
"args": { "position": "left" },
|
|
283
|
+
"source": "voice-local"
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Not all actions need to originate from voice. The important part is that command palette, HUD, daemon, and worker output all normalize into the same model.
|
|
288
|
+
|
|
289
|
+
### 2. Split the pipeline into four layers
|
|
290
|
+
|
|
291
|
+
### A. Interpretation
|
|
292
|
+
|
|
293
|
+
Converts user input into canonical actions.
|
|
294
|
+
|
|
295
|
+
Examples:
|
|
296
|
+
|
|
297
|
+
- keyboard chord -> action
|
|
298
|
+
- transcript -> action
|
|
299
|
+
- daemon JSON -> action
|
|
300
|
+
|
|
301
|
+
### B. Planning
|
|
302
|
+
|
|
303
|
+
Resolves targets and composes a layout plan.
|
|
304
|
+
|
|
305
|
+
Examples:
|
|
306
|
+
|
|
307
|
+
- which exact window does "Chrome" mean
|
|
308
|
+
- which screen should `left-third` land on
|
|
309
|
+
- whether a missing project should be launched
|
|
310
|
+
- whether multiple actions should be merged into one transaction
|
|
311
|
+
|
|
312
|
+
### C. Execution
|
|
313
|
+
|
|
314
|
+
Applies the plan through one executor.
|
|
315
|
+
|
|
316
|
+
Examples:
|
|
317
|
+
|
|
318
|
+
- batch move these windows
|
|
319
|
+
- focus this session
|
|
320
|
+
- launch these apps
|
|
321
|
+
- wait for these windows to appear
|
|
322
|
+
- commit final arrangement
|
|
323
|
+
|
|
324
|
+
### D. Presentation
|
|
325
|
+
|
|
326
|
+
Shows:
|
|
327
|
+
|
|
328
|
+
- preview
|
|
329
|
+
- progress
|
|
330
|
+
- result
|
|
331
|
+
- failure
|
|
332
|
+
|
|
333
|
+
The key point is that presentation should no longer define semantics.
|
|
334
|
+
|
|
335
|
+
### 3. Create a real arrangement transaction
|
|
336
|
+
|
|
337
|
+
Lattices should have a type along these lines:
|
|
338
|
+
|
|
339
|
+
- `ArrangementIntent`
|
|
340
|
+
- `ArrangementPlan`
|
|
341
|
+
- `ArrangementTransaction`
|
|
342
|
+
- `ArrangementResult`
|
|
343
|
+
|
|
344
|
+
An arrangement transaction should carry:
|
|
345
|
+
|
|
346
|
+
- requested actions
|
|
347
|
+
- resolved targets
|
|
348
|
+
- preconditions
|
|
349
|
+
- fallback strategy
|
|
350
|
+
- steps
|
|
351
|
+
- partial failures
|
|
352
|
+
- final applied state
|
|
353
|
+
|
|
354
|
+
That gives the app a place for:
|
|
355
|
+
|
|
356
|
+
- preview before commit
|
|
357
|
+
- retries
|
|
358
|
+
- rollback where possible
|
|
359
|
+
- voice confirmation
|
|
360
|
+
- better diagnostics than raw log lines
|
|
361
|
+
|
|
362
|
+
### 4. Unify the placement grammar
|
|
363
|
+
|
|
364
|
+
There should be exactly one placement language.
|
|
365
|
+
|
|
366
|
+
That language should cover:
|
|
367
|
+
|
|
368
|
+
- named positions
|
|
369
|
+
- grid cells
|
|
370
|
+
- screen/display selection
|
|
371
|
+
- optional grouping semantics
|
|
372
|
+
- optional relative semantics like "stack" or "master"
|
|
373
|
+
|
|
374
|
+
Everything else should compile into it, including:
|
|
375
|
+
|
|
376
|
+
- HUD keys
|
|
377
|
+
- voice phrases
|
|
378
|
+
- daemon requests
|
|
379
|
+
- future scripting
|
|
380
|
+
|
|
381
|
+
`VoiceIntentResolver` should not own a separate smaller placement universe.
|
|
382
|
+
|
|
383
|
+
### 5. Promote rules to a first-class subsystem
|
|
384
|
+
|
|
385
|
+
Lattices should formalize:
|
|
386
|
+
|
|
387
|
+
- static rules: applied on launch or first attach
|
|
388
|
+
- dynamic rules: re-evaluated when window properties or workspace state changes
|
|
389
|
+
|
|
390
|
+
Examples:
|
|
391
|
+
|
|
392
|
+
- project session window belongs on display 2 left half
|
|
393
|
+
- browser matching title X belongs beside project Y
|
|
394
|
+
- voice/HUD utility panels are never layout targets
|
|
395
|
+
- session windows for a layer open silently until plan commit
|
|
396
|
+
|
|
397
|
+
This is the clearest Hyprland-inspired gap in the current design.
|
|
398
|
+
|
|
399
|
+
### 6. Treat layout strategy as a pluggable engine
|
|
400
|
+
|
|
401
|
+
Instead of "tile to coordinates" being the only real abstraction, Lattices should support named layout engines, for example:
|
|
402
|
+
|
|
403
|
+
- `stack`
|
|
404
|
+
- `master`
|
|
405
|
+
- `grid`
|
|
406
|
+
- `bsp`
|
|
407
|
+
- `focus-ring`
|
|
408
|
+
- `review`
|
|
409
|
+
|
|
410
|
+
Each layout engine can expose:
|
|
411
|
+
|
|
412
|
+
- configuration
|
|
413
|
+
- planning logic
|
|
414
|
+
- compact mutation messages
|
|
415
|
+
|
|
416
|
+
That is the Hyprland lesson from `master`, `dwindle`, and `layoutmsg`: layout should be semantic, not just positional.
|
|
417
|
+
|
|
418
|
+
### 7. Make the daemon the canonical external executor boundary
|
|
419
|
+
|
|
420
|
+
The daemon already has enough shape to become the stable mutation boundary, but it should move from "RPC bag of commands" toward:
|
|
421
|
+
|
|
422
|
+
- state snapshot endpoints
|
|
423
|
+
- event stream
|
|
424
|
+
- action submission
|
|
425
|
+
- transaction status / receipts
|
|
426
|
+
|
|
427
|
+
The app can still call internals directly, but conceptually it should use the same execution core the daemon exposes.
|
|
428
|
+
|
|
429
|
+
## What This Means For Existing Features
|
|
430
|
+
|
|
431
|
+
### HUD
|
|
432
|
+
|
|
433
|
+
The HUD should remain fast and tactile, but its keys should emit canonical actions or layout messages, not direct tiler calls with private semantics.
|
|
434
|
+
|
|
435
|
+
### Local voice
|
|
436
|
+
|
|
437
|
+
Local voice should only do:
|
|
438
|
+
|
|
439
|
+
- transcript normalization
|
|
440
|
+
- action extraction
|
|
441
|
+
|
|
442
|
+
It should not decide execution policy inline.
|
|
443
|
+
|
|
444
|
+
### Hands-off voice
|
|
445
|
+
|
|
446
|
+
The worker should emit canonical actions only. Swift should not need to reinterpret those actions through a second matcher.
|
|
447
|
+
|
|
448
|
+
### Command palette
|
|
449
|
+
|
|
450
|
+
Palette commands should become thin wrappers over canonical actions, which makes them previewable and scriptable for free.
|
|
451
|
+
|
|
452
|
+
### Layers
|
|
453
|
+
|
|
454
|
+
`WorkspaceManager.tileLayer(...)` should evolve into a planner/executor user, not remain a special-case orchestration island.
|
|
455
|
+
|
|
456
|
+
## Concrete Recommendation
|
|
457
|
+
|
|
458
|
+
If I had to reduce this to one architectural move, it would be:
|
|
459
|
+
|
|
460
|
+
**Build a single action planner/executor and force every surface to go through it.**
|
|
461
|
+
|
|
462
|
+
That one move solves the deepest problems:
|
|
463
|
+
|
|
464
|
+
- duplicate intent logic
|
|
465
|
+
- duplicate position grammars
|
|
466
|
+
- direct UI-owned side effects
|
|
467
|
+
- lack of previews and execution receipts
|
|
468
|
+
- hard-to-reason-about batch behavior
|
|
469
|
+
|
|
470
|
+
## Suggested Implementation Order
|
|
471
|
+
|
|
472
|
+
1. Define canonical action and target schemas.
|
|
473
|
+
2. Extract a placement grammar module shared by voice, HUD, daemon, and layer logic.
|
|
474
|
+
3. Introduce `ArrangementPlan` plus an executor that can batch, defer, and report.
|
|
475
|
+
4. Migrate `window.tile`, `layout.distribute`, and layer switching onto that executor first.
|
|
476
|
+
5. Make local voice and hands-off worker emit canonical actions only.
|
|
477
|
+
6. Add preview/result receipts to HUD and voice surfaces.
|
|
478
|
+
7. Add first-class rules and named layout engines after the core path is stable.
|
|
479
|
+
|
|
480
|
+
## Primary References
|
|
481
|
+
|
|
482
|
+
- [Hyprland: Using hyprctl](https://wiki.hypr.land/Configuring/Using-hyprctl/)
|
|
483
|
+
- [Hyprland: IPC](https://wiki.hypr.land/0.54.0/IPC/)
|
|
484
|
+
- [Hyprland: Window Rules](https://wiki.hypr.land/0.51.0/Configuring/Window-Rules/)
|
|
485
|
+
- [Hyprland: Dwindle Layout](https://wiki.hypr.land/Configuring/Dwindle-Layout/)
|
|
486
|
+
- [Hyprland: Master Layout](https://wiki.hypr.land/Configuring/Master-Layout/)
|
|
487
|
+
- [Wayland project overview](https://wayland.freedesktop.org/index.html)
|
|
488
|
+
- [Wayland Book: Interfaces, requests, and events](https://wayland-book.com/protocol-design/interfaces-reqs-events.html)
|
|
489
|
+
- [Wayland Book: Surface lifecycle](https://wayland-book.com/surfaces-in-depth/lifecycle.html)
|
|
490
|
+
- [Wayland Book: XDG shell basics](https://wayland-book.com/xdg-shell-basics.html)
|
|
491
|
+
- [Wayland Book: Configuration & lifecycle](https://wayland-book.com/xdg-shell-in-depth/configuration.html)
|