@lattices/cli 0.3.0 → 0.4.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 (95) hide show
  1. package/README.md +85 -9
  2. package/app/Package.swift +8 -1
  3. package/app/Sources/AdvisorLearningStore.swift +90 -0
  4. package/app/Sources/AgentSession.swift +377 -0
  5. package/app/Sources/AppDelegate.swift +44 -12
  6. package/app/Sources/AppShellView.swift +81 -8
  7. package/app/Sources/AudioProvider.swift +386 -0
  8. package/app/Sources/CheatSheetHUD.swift +261 -19
  9. package/app/Sources/DaemonProtocol.swift +13 -0
  10. package/app/Sources/DaemonServer.swift +8 -0
  11. package/app/Sources/DesktopModel.swift +164 -5
  12. package/app/Sources/DesktopModelTypes.swift +2 -0
  13. package/app/Sources/DiagnosticLog.swift +104 -2
  14. package/app/Sources/EventBus.swift +1 -0
  15. package/app/Sources/HUDBottomBar.swift +279 -0
  16. package/app/Sources/HUDController.swift +1158 -0
  17. package/app/Sources/HUDLeftBar.swift +849 -0
  18. package/app/Sources/HUDMinimap.swift +179 -0
  19. package/app/Sources/HUDRightBar.swift +774 -0
  20. package/app/Sources/HUDState.swift +367 -0
  21. package/app/Sources/HUDTopBar.swift +243 -0
  22. package/app/Sources/HandsOffSession.swift +733 -0
  23. package/app/Sources/HomeDashboardView.swift +125 -0
  24. package/app/Sources/HotkeyManager.swift +2 -0
  25. package/app/Sources/HotkeyStore.swift +45 -9
  26. package/app/Sources/IntentEngine.swift +925 -0
  27. package/app/Sources/Intents/CreateLayerIntent.swift +54 -0
  28. package/app/Sources/Intents/DistributeIntent.swift +56 -0
  29. package/app/Sources/Intents/FocusIntent.swift +69 -0
  30. package/app/Sources/Intents/HelpIntent.swift +41 -0
  31. package/app/Sources/Intents/KillIntent.swift +47 -0
  32. package/app/Sources/Intents/LatticeIntent.swift +78 -0
  33. package/app/Sources/Intents/LaunchIntent.swift +67 -0
  34. package/app/Sources/Intents/ListSessionsIntent.swift +32 -0
  35. package/app/Sources/Intents/ListWindowsIntent.swift +30 -0
  36. package/app/Sources/Intents/ScanIntent.swift +52 -0
  37. package/app/Sources/Intents/SearchIntent.swift +190 -0
  38. package/app/Sources/Intents/SwitchLayerIntent.swift +50 -0
  39. package/app/Sources/Intents/TileIntent.swift +61 -0
  40. package/app/Sources/LatticesApi.swift +1235 -30
  41. package/app/Sources/LauncherHUD.swift +348 -0
  42. package/app/Sources/MainView.swift +147 -44
  43. package/app/Sources/OcrModel.swift +34 -1
  44. package/app/Sources/OmniSearchState.swift +99 -102
  45. package/app/Sources/OnboardingView.swift +457 -0
  46. package/app/Sources/PermissionChecker.swift +2 -12
  47. package/app/Sources/PiChatDock.swift +454 -0
  48. package/app/Sources/PiChatSession.swift +815 -0
  49. package/app/Sources/PiWorkspaceView.swift +364 -0
  50. package/app/Sources/PlacementSpec.swift +195 -0
  51. package/app/Sources/Preferences.swift +59 -0
  52. package/app/Sources/ProjectScanner.swift +1 -1
  53. package/app/Sources/ScreenMapState.swift +701 -55
  54. package/app/Sources/ScreenMapView.swift +843 -103
  55. package/app/Sources/ScreenMapWindowController.swift +22 -0
  56. package/app/Sources/SessionLayerStore.swift +285 -0
  57. package/app/Sources/SessionManager.swift +4 -1
  58. package/app/Sources/SettingsView.swift +186 -3
  59. package/app/Sources/Theme.swift +9 -8
  60. package/app/Sources/TmuxModel.swift +7 -0
  61. package/app/Sources/TmuxQuery.swift +27 -3
  62. package/app/Sources/VoiceChatView.swift +192 -0
  63. package/app/Sources/VoiceCommandWindow.swift +1594 -0
  64. package/app/Sources/VoiceIntentResolver.swift +671 -0
  65. package/app/Sources/VoxClient.swift +454 -0
  66. package/app/Sources/WindowTiler.swift +348 -87
  67. package/app/Sources/WorkspaceManager.swift +127 -18
  68. package/bin/client.ts +16 -0
  69. package/bin/{daemon-client.js → daemon-client.ts} +49 -30
  70. package/bin/handsoff-infer.ts +280 -0
  71. package/bin/handsoff-worker.ts +731 -0
  72. package/bin/{lattices-app.js → lattices-app.ts} +67 -32
  73. package/bin/lattices-dev +160 -0
  74. package/bin/{lattices.js → lattices.ts} +600 -137
  75. package/bin/project-twin.ts +645 -0
  76. package/docs/agent-execution-plan.md +562 -0
  77. package/docs/agents.md +142 -0
  78. package/docs/api.md +153 -34
  79. package/docs/app.md +29 -1
  80. package/docs/config.md +5 -1
  81. package/docs/handsoff-test-scenarios.md +84 -0
  82. package/docs/layers.md +20 -20
  83. package/docs/ocr.md +14 -5
  84. package/docs/overview.md +5 -1
  85. package/docs/presentation-execution-review.md +491 -0
  86. package/docs/prompts/hands-off-system.md +374 -0
  87. package/docs/prompts/hands-off-turn.md +30 -0
  88. package/docs/prompts/voice-advisor.md +31 -0
  89. package/docs/prompts/voice-fallback.md +23 -0
  90. package/docs/tiling-reference.md +167 -0
  91. package/docs/twins.md +138 -0
  92. package/docs/voice-command-protocol.md +278 -0
  93. package/docs/voice.md +219 -0
  94. package/package.json +21 -10
  95. package/bin/client.js +0 -4
@@ -0,0 +1,562 @@
1
+ # Agent Execution Plan
2
+
3
+ This document turns the architectural review into an implementation plan based on the current product priorities:
4
+
5
+ 1. Predictability
6
+ 2. Traceability
7
+ 3. Reversibility later, but not as the first constraint
8
+
9
+ It also fixes the initial migration target:
10
+
11
+ - first-class execution path = daemon API
12
+ - preferred operator surface = agentic voice
13
+ - first use case = dictation or agent command -> daemon action -> reliable window/layer/layout outcome
14
+
15
+ This is intentionally daemon-first. If the daemon becomes the canonical execution boundary, voice, HUD, command palette, and workers can all become thinner clients.
16
+
17
+ ## Product framing
18
+
19
+ There are three action families we need to support first.
20
+
21
+ ### 1. Window-specific actions
22
+
23
+ These target a specific window and a destination.
24
+
25
+ Examples:
26
+
27
+ - "Chrome to the top right corner"
28
+ - "Terminal to the right third"
29
+ - "Move Slack to the bottom quarter"
30
+ - "Put Xcode in the upper third"
31
+
32
+ Core shape:
33
+
34
+ - target window
35
+ - destination
36
+
37
+ ### 2. Layer-specific actions
38
+
39
+ These bring up an existing layer and arrange it coherently according to stored preferences.
40
+
41
+ Examples:
42
+
43
+ - "Bring up review"
44
+ - "Switch to mobile"
45
+ - "Open the web layer"
46
+
47
+ Expectation:
48
+
49
+ - honor existing layer and project preferences
50
+ - launch or focus what is needed
51
+ - tile the result coherently
52
+ - do not invent too much intelligence beyond declared preferences
53
+
54
+ ### 3. Space-optimization actions
55
+
56
+ These take the current set of visible or selected windows and make the desktop "nice."
57
+
58
+ Examples:
59
+
60
+ - "Make this nice"
61
+ - "Organize these windows"
62
+ - "Clean up the layout"
63
+ - "Arrange this space"
64
+
65
+ Expectation:
66
+
67
+ - produce a good mosaic or grid
68
+ - be deterministic
69
+ - explain why the chosen arrangement happened
70
+
71
+ ## Goals
72
+
73
+ ### Must-have
74
+
75
+ - Every execution path is predictable.
76
+ - Every execution returns a trace explaining what happened.
77
+ - Every action is represented in one canonical schema.
78
+ - Voice and agents submit structured actions to the daemon.
79
+
80
+ ### Nice-to-have later
81
+
82
+ - Undo
83
+ - Full transaction replay
84
+ - Layout previews before commit
85
+ - Smarter semantic layouts such as `review` or `focus`
86
+
87
+ ### Non-goal for v1
88
+
89
+ - Building a fully autonomous planner that improvises layouts beyond declared rules
90
+
91
+ ## Architecture decision
92
+
93
+ The daemon becomes the canonical mutation boundary.
94
+
95
+ That means:
96
+
97
+ - interpretation can happen anywhere
98
+ - planning and execution live behind the daemon
99
+ - all clients get the same semantics
100
+
101
+ In practice:
102
+
103
+ - local voice extracts actions, then calls daemon
104
+ - hands-off worker emits actions, then calls daemon
105
+ - HUD keys emit actions, then call daemon
106
+ - command palette emits actions, then calls daemon
107
+
108
+ This avoids multiple execution semantics in app code.
109
+
110
+ ## Canonical execution model
111
+
112
+ We should introduce four core types.
113
+
114
+ ### 1. `ActionRequest`
115
+
116
+ Represents what the operator asked for.
117
+
118
+ ```json
119
+ {
120
+ "id": "req_123",
121
+ "source": "voice",
122
+ "intent": "window.place",
123
+ "targets": [{ "kind": "window_ref", "value": "frontmost" }],
124
+ "args": {
125
+ "placement": "top-right"
126
+ },
127
+ "rawUtterance": "put this in the top right corner"
128
+ }
129
+ ```
130
+
131
+ ### 2. `ExecutionPlan`
132
+
133
+ Represents the resolved plan before mutation.
134
+
135
+ ```json
136
+ {
137
+ "id": "plan_123",
138
+ "requestId": "req_123",
139
+ "steps": [
140
+ {
141
+ "kind": "resolveWindow",
142
+ "result": { "wid": 38192, "app": "Google Chrome", "title": "Docs" }
143
+ },
144
+ {
145
+ "kind": "placeWindow",
146
+ "result": { "display": 0, "frame": { "x": 960, "y": 0, "w": 960, "h": 540 } }
147
+ }
148
+ ],
149
+ "explanation": [
150
+ "Resolved 'this' to the frontmost window",
151
+ "Mapped 'top-right' to the top-right quarter of display 1"
152
+ ]
153
+ }
154
+ ```
155
+
156
+ ### 3. `ExecutionReceipt`
157
+
158
+ Represents what actually happened.
159
+
160
+ ```json
161
+ {
162
+ "id": "exec_123",
163
+ "requestId": "req_123",
164
+ "status": "ok",
165
+ "applied": [
166
+ {
167
+ "kind": "window.place",
168
+ "wid": 38192,
169
+ "before": { "x": 120, "y": 80, "w": 1280, "h": 900 },
170
+ "after": { "x": 960, "y": 0, "w": 960, "h": 540 }
171
+ }
172
+ ],
173
+ "trace": [
174
+ "DesktopModel matched frontmost window",
175
+ "Window moved by AX batch path"
176
+ ]
177
+ }
178
+ ```
179
+
180
+ ### 4. `ExecutionTrace`
181
+
182
+ Represents the scrutable explanation layer.
183
+
184
+ This is the object the user should be able to inspect when they ask:
185
+
186
+ - why did you move that?
187
+ - why did you choose that layout?
188
+ - which rule applied?
189
+
190
+ This is separate from logging. It is product data.
191
+
192
+ ## Initial action vocabulary
193
+
194
+ The first version should stay intentionally small.
195
+
196
+ ### Window actions
197
+
198
+ - `window.place`
199
+ - `window.focus`
200
+ - `window.present`
201
+
202
+ `window.place` is the core mutation.
203
+
204
+ Arguments:
205
+
206
+ - `placement`
207
+ - optional `display`
208
+ - optional `strategy`
209
+
210
+ Targets:
211
+
212
+ - `wid`
213
+ - `session`
214
+ - `app_title`
215
+ - `frontmost`
216
+ - `selection`
217
+
218
+ ### Layer actions
219
+
220
+ - `layer.activate`
221
+
222
+ Arguments:
223
+
224
+ - `mode`: `focus` or `launch`
225
+ - optional `force`
226
+
227
+ This should wrap current `layer.switch` / `tileLayer(...)` semantics, but return an execution receipt instead of silently doing best-effort work.
228
+
229
+ ### Space actions
230
+
231
+ - `space.optimize`
232
+
233
+ Arguments:
234
+
235
+ - `scope`: `visible`, `selection`, `current_display`, `current_space`
236
+ - `strategy`: `mosaic`, `grid`, `balanced`
237
+
238
+ This wraps current `layout.distribute`, but with an explicit strategy and trace.
239
+
240
+ ## Placement grammar
241
+
242
+ We need one shared placement grammar for all clients.
243
+
244
+ ### v1 named placements
245
+
246
+ - `maximize`
247
+ - `center`
248
+ - `left`
249
+ - `right`
250
+ - `top`
251
+ - `bottom`
252
+ - `top-left`
253
+ - `top-right`
254
+ - `bottom-left`
255
+ - `bottom-right`
256
+ - `left-third`
257
+ - `center-third`
258
+ - `right-third`
259
+ - `top-third`
260
+ - `middle-third`
261
+ - `bottom-third`
262
+ - `left-quarter`
263
+ - `right-quarter`
264
+ - `top-quarter`
265
+ - `bottom-quarter`
266
+
267
+ Important note:
268
+
269
+ `top-third`, `middle-third`, and `bottom-third` should become real first-class placements, not inferred hacks. Right now the codebase has better support for vertical thirds than horizontal thirds. The grammar should fix that.
270
+
271
+ ### v1 generic placement form
272
+
273
+ - `grid:CxR:C,R`
274
+
275
+ Examples:
276
+
277
+ - `grid:3x1:2,0`
278
+ - `grid:1x3:0,0`
279
+ - `grid:4x2:3,1`
280
+
281
+ ### v1 display selector
282
+
283
+ Optional wrapper:
284
+
285
+ - `display:current:left`
286
+ - `display:2:grid:1x3:0,0`
287
+
288
+ If that wrapper feels too awkward for public API, keep it structured:
289
+
290
+ ```json
291
+ {
292
+ "placement": "grid:1x3:0,0",
293
+ "display": "current"
294
+ }
295
+ ```
296
+
297
+ ## Planning rules
298
+
299
+ Planning must be deterministic.
300
+
301
+ ### Rule 1. Resolve target before applying placement
302
+
303
+ No side effects should start until target resolution succeeds or a launch/fallback policy is chosen.
304
+
305
+ ### Rule 2. Return the matching reason
306
+
307
+ Every resolved target should include why it matched:
308
+
309
+ - frontmost
310
+ - exact session tag
311
+ - exact `wid`
312
+ - app + title match
313
+ - rule-based layer member
314
+
315
+ ### Rule 3. If ambiguous, fail clearly unless policy says otherwise
316
+
317
+ For example:
318
+
319
+ - "Chrome to the right" with 4 Chrome windows should fail or request disambiguation in agent mode unless a deterministic policy exists
320
+
321
+ Possible policy order:
322
+
323
+ 1. exact title match
324
+ 2. exact session match
325
+ 3. frontmost matching app
326
+ 4. z-order first visible matching app
327
+
328
+ But whichever order we pick must be explicit and returned in the trace.
329
+
330
+ ### Rule 4. Layer activation plans should be compositional
331
+
332
+ `layer.activate` should produce a plan containing:
333
+
334
+ - windows already running
335
+ - sessions to launch
336
+ - companion apps to launch
337
+ - placements to apply
338
+ - fallbacks for untracked windows
339
+
340
+ This is already partly present in `WorkspaceManager.tileLayer(...)`; the goal is to formalize it as plan data.
341
+
342
+ ### Rule 5. Space optimization must always declare its strategy
343
+
344
+ If the system chooses a mosaic, it must say why.
345
+
346
+ Examples:
347
+
348
+ - "Used 2x2 grid because 4 windows were in scope"
349
+ - "Used 3-column mosaic because 5 windows fit better in landscape"
350
+
351
+ ## Traceability design
352
+
353
+ Traceability is a product feature, not an internal debugging detail.
354
+
355
+ Every mutation endpoint should return:
356
+
357
+ - `request`
358
+ - `resolvedTargets`
359
+ - `appliedRules`
360
+ - `computedFrames`
361
+ - `executionPath`
362
+ - `failures`
363
+
364
+ ### Example trace fields
365
+
366
+ ```json
367
+ {
368
+ "resolvedTargets": [
369
+ {
370
+ "input": "Chrome",
371
+ "resolution": "wid",
372
+ "wid": 38192,
373
+ "reason": "frontmost app match"
374
+ }
375
+ ],
376
+ "appliedRules": [
377
+ "placement top-right -> grid 2x2 cell 1,0",
378
+ "display current"
379
+ ],
380
+ "executionPath": [
381
+ "DesktopModel",
382
+ "AX batch move"
383
+ ]
384
+ }
385
+ ```
386
+
387
+ ## Daemon changes
388
+
389
+ We should not immediately remove existing endpoints. We should add a new execution layer and gradually migrate callers.
390
+
391
+ ### New endpoints
392
+
393
+ ### `actions.execute`
394
+
395
+ Primary mutation endpoint.
396
+
397
+ Input:
398
+
399
+ - one action or a batch of actions
400
+
401
+ Output:
402
+
403
+ - execution receipt with trace
404
+
405
+ ### `actions.plan`
406
+
407
+ Dry-run planner.
408
+
409
+ Input:
410
+
411
+ - same as `actions.execute`
412
+
413
+ Output:
414
+
415
+ - execution plan with no side effects
416
+
417
+ This is critical for predictability and future previews.
418
+
419
+ ### `actions.history`
420
+
421
+ Recent receipts.
422
+
423
+ Output:
424
+
425
+ - recent execution receipts for scrutability
426
+
427
+ This is also the future basis for undo.
428
+
429
+ ### Existing endpoints to wrap first
430
+
431
+ These should internally route into the new planner/executor as early as possible:
432
+
433
+ - `window.tile`
434
+ - `window.present`
435
+ - `layout.distribute`
436
+ - `layer.switch`
437
+
438
+ Those existing RPC names can remain stable while their internals are replaced.
439
+
440
+ ## Migration order
441
+
442
+ ### Phase 1. Build the daemon execution core
443
+
444
+ Files likely involved:
445
+
446
+ - `app/Sources/LatticesApi.swift`
447
+ - new planner/executor files under `app/Sources/`
448
+ - `app/Sources/WindowTiler.swift`
449
+ - `app/Sources/WorkspaceManager.swift`
450
+
451
+ Deliverables:
452
+
453
+ - `ActionRequest`
454
+ - `ExecutionPlan`
455
+ - `ExecutionReceipt`
456
+ - shared placement parser
457
+ - `actions.plan`
458
+ - `actions.execute`
459
+
460
+ ### Phase 2. Migrate existing daemon mutations
461
+
462
+ Replace internal implementations for:
463
+
464
+ - `window.tile`
465
+ - `layout.distribute`
466
+ - `layer.switch`
467
+
468
+ Deliverables:
469
+
470
+ - stable behavior through old API names
471
+ - receipts and traces returned in responses
472
+
473
+ ### Phase 3. Make voice call the daemon directly
474
+
475
+ Files likely involved:
476
+
477
+ - `app/Sources/VoiceIntentResolver.swift`
478
+ - `app/Sources/IntentEngine.swift`
479
+ - `app/Sources/HandsOffSession.swift`
480
+
481
+ Deliverables:
482
+
483
+ - local voice emits canonical actions
484
+ - hands-off worker emits canonical actions
485
+ - no second interpretation pass for worker actions
486
+
487
+ ### Phase 4. Migrate HUD and command palette
488
+
489
+ Files likely involved:
490
+
491
+ - `app/Sources/HUDController.swift`
492
+ - `app/Sources/PaletteCommand.swift`
493
+
494
+ Deliverables:
495
+
496
+ - all surfaces use the same planner/executor
497
+ - same traces available no matter how action was triggered
498
+
499
+ ## Immediate implementation slice
500
+
501
+ The first practical slice should be:
502
+
503
+ 1. Add a shared placement parser with first-class support for:
504
+ - existing `TilePosition` names
505
+ - `grid:CxR:C,R`
506
+ - new `top-third`, `middle-third`, `bottom-third`
507
+ - new quarter aliases
508
+ 2. Add `actions.plan` and `actions.execute` for:
509
+ - `window.place`
510
+ - `space.optimize`
511
+ - `layer.activate`
512
+ 3. Reimplement `window.tile` as a wrapper around `window.place`
513
+ 4. Return a structured receipt from daemon mutations
514
+
515
+ That gives immediate product value:
516
+
517
+ - voice can target the daemon directly
518
+ - placement semantics stop drifting
519
+ - "why did you do that?" has a real answer
520
+
521
+ ## Example v1 utterance mappings
522
+
523
+ These should become golden examples for tests.
524
+
525
+ ### Window placement
526
+
527
+ - "Put Chrome in the top right corner" -> `window.place(target=Chrome, placement=top-right)`
528
+ - "Move Terminal to the right third" -> `window.place(target=Terminal, placement=right-third)`
529
+ - "Put this in the upper third" -> `window.place(target=frontmost, placement=top-third)`
530
+ - "Bottom quarter for Slack" -> `window.place(target=Slack, placement=bottom-quarter)`
531
+
532
+ ### Layer activation
533
+
534
+ - "Bring up review" -> `layer.activate(name=review, mode=launch)`
535
+ - "Switch to mobile" -> `layer.activate(name=mobile, mode=focus)`
536
+
537
+ ### Space optimization
538
+
539
+ - "Make this nice" -> `space.optimize(scope=visible, strategy=mosaic)`
540
+ - "Organize these windows" -> `space.optimize(scope=selection_or_visible, strategy=balanced)`
541
+
542
+ ## Definition of success
543
+
544
+ This initiative is successful when:
545
+
546
+ - the daemon can plan and execute all three action families
547
+ - voice can issue those actions without direct subsystem calls
548
+ - every execution returns a scrutable receipt
549
+ - placement vocabulary is shared across all clients
550
+ - layout outcomes stop depending on which interface triggered them
551
+
552
+ ## Recommendation
553
+
554
+ Start with daemon execution for `window.place`.
555
+
556
+ Why:
557
+
558
+ - it is the smallest useful vertical slice
559
+ - it serves voice immediately
560
+ - it forces the placement grammar to become canonical
561
+ - it establishes the receipt/trace model early
562
+ - it unlocks layer and optimize-space actions without rework
package/docs/agents.md ADDED
@@ -0,0 +1,142 @@
1
+ ---
2
+ title: Agent Guide
3
+ description: Canonical contracts for agents using docs URLs, CLI, voice, and the daemon API
4
+ order: 6
5
+ ---
6
+
7
+ Lattices exposes the same execution model through four surfaces:
8
+
9
+ - **Docs URLs** for discovery and citation
10
+ - **CLI** for shell-based agents
11
+ - **Daemon API** for typed programmatic control
12
+ - **Voice / hands-off / HUD** as clients of the same execution layer
13
+
14
+ The rule is simple: agents should learn the **canonical action model**
15
+ first, then choose the transport that fits the environment.
16
+
17
+ ## Canonical mutations
18
+
19
+ These are the preferred action identifiers:
20
+
21
+ | Action | Purpose | Preferred surface |
22
+ |--------|---------|-------------------|
23
+ | `window.place` | Place a window or session using a typed placement spec | Daemon API |
24
+ | `layer.activate` | Bring up a workspace layer with explicit activation mode | Daemon API |
25
+ | `space.optimize` | Rebalance a set of windows using an explicit scope and strategy | Daemon API |
26
+
27
+ Compatibility wrappers still exist:
28
+
29
+ | Legacy method | Canonical equivalent |
30
+ |---------------|----------------------|
31
+ | `window.tile` | `window.place` |
32
+ | `layer.switch` | `layer.activate` with `mode=launch` |
33
+ | `layout.distribute` | `space.optimize` with `scope=visible`, `strategy=balanced` |
34
+
35
+ ## Discoverability
36
+
37
+ Agents should use these paths in order:
38
+
39
+ 1. **API schema**: `lattices call api.schema`
40
+ 2. **Daemon reference**: [/docs/api](/docs/api)
41
+ 3. **Agent guide**: [/docs/agents](/docs/agents)
42
+ 4. **Voice model**: [/docs/voice](/docs/voice)
43
+ 5. **Concepts / config**: [/docs/concepts](/docs/concepts), [/docs/config](/docs/config)
44
+
45
+ Useful CLI discovery commands:
46
+
47
+ ```bash
48
+ lattices help
49
+ lattices call api.schema
50
+ lattices voice intents
51
+ ```
52
+
53
+ ## Placement contract
54
+
55
+ At the boundary, placements may be strings for convenience.
56
+ Inside the daemon, the canonical contract is typed.
57
+
58
+ String shorthand:
59
+
60
+ ```json
61
+ { "placement": "top-right" }
62
+ { "placement": "grid:3x2:2,0" }
63
+ ```
64
+
65
+ Typed placement objects:
66
+
67
+ ```json
68
+ { "placement": { "kind": "tile", "value": "top-third" } }
69
+ { "placement": { "kind": "grid", "columns": 3, "rows": 2, "column": 2, "row": 0 } }
70
+ { "placement": { "kind": "fractions", "x": 0.5, "y": 0, "w": 0.5, "h": 1 } }
71
+ ```
72
+
73
+ This lets voice stay natural while the executor stays explicit.
74
+
75
+ ## Choosing a surface
76
+
77
+ Use the **daemon API** when you need:
78
+
79
+ - typed receipts and traces
80
+ - explicit targeting by `wid`, `session`, or `app`
81
+ - composition across layers, windows, and optimization
82
+
83
+ Use the **CLI** when you need:
84
+
85
+ - one-shot shell execution
86
+ - quick discovery from inside an agent terminal
87
+ - compatibility with environments that already have `lattices`
88
+
89
+ Use **docs URLs** when an agent needs:
90
+
91
+ - a citeable contract
92
+ - a stable page to open in a browser or pass to another agent
93
+ - quick onboarding without reading source
94
+
95
+ ## Examples
96
+
97
+ Node.js:
98
+
99
+ ```js
100
+ import { daemonCall } from '@lattices/cli'
101
+
102
+ await daemonCall('session.launch', { path: '/Users/you/dev/frontend' })
103
+ await daemonCall('window.place', {
104
+ session: 'frontend-a1b2c3',
105
+ placement: { kind: 'tile', value: 'left' }
106
+ })
107
+ await daemonCall('layer.activate', { name: 'review', mode: 'launch' })
108
+ await daemonCall('space.optimize', { scope: 'visible', strategy: 'balanced' })
109
+ ```
110
+
111
+ CLI:
112
+
113
+ ```bash
114
+ lattices call api.schema
115
+ lattices call window.place '{"session":"frontend-a1b2c3","placement":"left"}'
116
+ lattices call layer.activate '{"name":"review","mode":"launch"}'
117
+ lattices call space.optimize '{"scope":"visible","strategy":"balanced"}'
118
+ ```
119
+
120
+ ## Receipts and traceability
121
+
122
+ Mutating daemon calls should return structured receipts when possible.
123
+ The important fields for agents are:
124
+
125
+ - resolved target
126
+ - resolved placement / scope / mode
127
+ - affected window IDs
128
+ - trace entries explaining why the daemon chose that path
129
+
130
+ This is what keeps voice, hands-off, and scripted execution scrutable.
131
+
132
+ ## Voice and hands-off
133
+
134
+ Voice is not a separate execution system. It should compile into the
135
+ same canonical actions:
136
+
137
+ - "put Terminal in the upper third" → `window.place`
138
+ - "bring up review" → `layer.activate`
139
+ - "make this nice" → `space.optimize`
140
+
141
+ That keeps the interaction layer flexible while the executor stays
142
+ predictable.