@lattices/cli 0.4.1 → 0.4.5

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 (71) hide show
  1. package/README.md +3 -0
  2. package/app/Info.plist +2 -2
  3. package/app/Lattices.app/Contents/Info.plist +2 -2
  4. package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
  5. package/app/Package.swift +6 -0
  6. package/app/Sources/ActionRow.swift +43 -26
  7. package/app/Sources/App.swift +10 -0
  8. package/app/Sources/AppDelegate.swift +91 -30
  9. package/app/Sources/AppShellView.swift +2 -0
  10. package/app/Sources/AppTypeClassifier.swift +36 -0
  11. package/app/Sources/AppUpdater.swift +92 -0
  12. package/app/Sources/CheatSheetHUD.swift +1 -0
  13. package/app/Sources/CliActionLauncher.swift +50 -0
  14. package/app/Sources/CommandModeView.swift +4 -24
  15. package/app/Sources/CompanionActivityLog.swift +70 -0
  16. package/app/Sources/CompanionKeyboardController.swift +141 -0
  17. package/app/Sources/DesktopModel.swift +4 -0
  18. package/app/Sources/HandsOffSession.swift +53 -16
  19. package/app/Sources/HomeDashboardView.swift +18 -10
  20. package/app/Sources/HotkeyStore.swift +8 -5
  21. package/app/Sources/IntentEngine.swift +7 -1
  22. package/app/Sources/LatticesApi.swift +125 -4
  23. package/app/Sources/LatticesCompanionBridgeServer.swift +438 -0
  24. package/app/Sources/LatticesCompanionCockpit.swift +555 -0
  25. package/app/Sources/LatticesCompanionSecurityCoordinator.swift +594 -0
  26. package/app/Sources/LatticesCompanionTrackpadController.swift +204 -0
  27. package/app/Sources/LatticesDeckHost.swift +1463 -0
  28. package/app/Sources/LatticesRuntime.swift +61 -0
  29. package/app/Sources/MainView.swift +398 -186
  30. package/app/Sources/MouseFinder.swift +335 -30
  31. package/app/Sources/MouseGestureConfig.swift +364 -0
  32. package/app/Sources/MouseGestureController.swift +1203 -0
  33. package/app/Sources/MouseInputDeviceStore.swift +98 -0
  34. package/app/Sources/MouseInputEventViewer.swift +272 -0
  35. package/app/Sources/MouseShortcutStore.swift +107 -0
  36. package/app/Sources/OmniSearchView.swift +136 -2
  37. package/app/Sources/OmniSearchWindow.swift +65 -5
  38. package/app/Sources/OnboardingView.swift +30 -16
  39. package/app/Sources/PaletteCommand.swift +26 -6
  40. package/app/Sources/PermissionChecker.swift +76 -2
  41. package/app/Sources/PiAuthNextStepCard.swift +148 -0
  42. package/app/Sources/PiAuthPromptCard.swift +90 -0
  43. package/app/Sources/PiChatDock.swift +137 -74
  44. package/app/Sources/PiChatSession.swift +608 -108
  45. package/app/Sources/PiInstallCallout.swift +86 -0
  46. package/app/Sources/PiProviderSetupCallout.swift +99 -0
  47. package/app/Sources/PiWorkspaceView.swift +174 -77
  48. package/app/Sources/Preferences.swift +78 -0
  49. package/app/Sources/ScreenMapState.swift +91 -31
  50. package/app/Sources/ScreenMapView.swift +510 -524
  51. package/app/Sources/ScreenMapWindowController.swift +12 -4
  52. package/app/Sources/SettingsView.swift +869 -152
  53. package/app/Sources/SystemTelemetryMonitor.swift +273 -0
  54. package/app/Sources/VoiceCommandWindow.swift +23 -2
  55. package/app/Sources/WindowDragSnapController.swift +628 -0
  56. package/app/Sources/WindowTiler.swift +328 -65
  57. package/app/Sources/WorkspaceManager.swift +288 -0
  58. package/bin/assistant-intelligence.ts +874 -0
  59. package/bin/handsoff-infer.ts +16 -209
  60. package/bin/handsoff-worker.ts +45 -258
  61. package/bin/lattices-app.ts +65 -1
  62. package/bin/lattices-dev +4 -0
  63. package/bin/lattices.ts +125 -14
  64. package/docs/agents.md +14 -0
  65. package/docs/api.md +55 -0
  66. package/docs/app.md +3 -0
  67. package/docs/companion-deck.md +180 -0
  68. package/docs/config.md +25 -0
  69. package/docs/tiling-reference.md +55 -0
  70. package/docs/voice-error-model.md +73 -0
  71. package/package.json +4 -2
@@ -81,6 +81,56 @@ typed placement model internally:
81
81
 
82
82
  That is what keeps CLI, daemon, voice, and hands-off execution aligned.
83
83
 
84
+ ## Drag Snap Zones
85
+
86
+ The menu bar app can also use placement specs as drag-to-snap targets.
87
+ When you drag a window, Lattices shows faint landing zones plus a live
88
+ preview of the resulting frame. Releasing over a zone tiles the dragged
89
+ window to that placement. Hold `Command` while dragging to reveal snap
90
+ mode, and release `Command` to drop back to a normal free drag without
91
+ ending the gesture.
92
+
93
+ The recommended agent-owned config lives in `~/.lattices/snap-zones.json`:
94
+
95
+ ```json
96
+ {
97
+ "enabled": true,
98
+ "modifier": "command",
99
+ "zoneOpacity": 0.08,
100
+ "highlightOpacity": 0.18,
101
+ "previewOpacity": 0.14,
102
+ "rules": [
103
+ {
104
+ "id": "left-edge",
105
+ "label": "Left",
106
+ "placement": "left",
107
+ "trigger": { "x": 0.0, "y": 0.18, "w": 0.12, "h": 0.64 },
108
+ "priority": 10
109
+ },
110
+ {
111
+ "id": "notes-rail",
112
+ "label": "Notes",
113
+ "placement": { "x": 0.68, "y": 0.0, "w": 0.32, "h": 1.0 },
114
+ "trigger": { "x": 0.88, "y": 0.18, "w": 0.12, "h": 0.64 },
115
+ "priority": 30
116
+ }
117
+ ]
118
+ }
119
+ ```
120
+
121
+ Notes:
122
+
123
+ - `rules` is the preferred list key. `zones` is still accepted for backward compatibility.
124
+ - `modifier` accepts `command`, `option`, `control`, or `shift`.
125
+ - `placement` can be a named placement/preset string or raw fractions.
126
+ - `trigger` uses normalized `(x, y, w, h)` fractions of the screen's
127
+ visible area, with `y = 0` at the top.
128
+ - `priority` breaks ties when trigger regions overlap.
129
+ - `trigger` can also be a named placement or preset string if you want
130
+ the trigger region itself to reuse an existing tile definition.
131
+ - The older `~/.lattices/grid.json` `snapZones` section still works, but
132
+ `~/.lattices/snap-zones.json` is the cleaner file for agents to edit.
133
+
84
134
  ## Execution Paths
85
135
 
86
136
  The old split-brain tiling logic has been collapsed toward a shared path.
@@ -146,6 +196,11 @@ These are composed from multiple `tile_window` actions:
146
196
  | Eight-up (4×2) | All eight `*-*-fourth` positions |
147
197
  | Distribute | Single `distribute` intent (auto-grid) |
148
198
 
199
+ CLI shortcuts compile into the same distributor:
200
+
201
+ - `lattices tile family` → smart-grid the frontmost app's visible windows
202
+ - `lattices distribute iTerm2 right` → smart-grid visible iTerm windows inside the right half
203
+
149
204
  ## HandsOff Smart Distribution
150
205
 
151
206
  When the LLM sends multiple `tile_window` actions targeting the **same position**, `HandsOffSession.distributeTileActions()` subdivides:
@@ -0,0 +1,73 @@
1
+ # Voice Error Model
2
+
3
+ ## Goal + anchors
4
+
5
+ Use one error vocabulary for Mac voice capture/execution and iPad relay/status. The canonical protocol says Lattices borrows Vox for capture and never owns the mic directly (`docs/voice-command-protocol.md:5-7`), but the shared runtime already has a cross-platform `DeckVoiceState` slot (`swift/Sources/DeckKit/DeckRuntimeSnapshot.swift:49-68`). Current Mac code exposes local strings (`VoxError`, `executionResult`) instead of structured errors (`app/Sources/VoxClient.swift:43-59`, `app/Sources/AudioProvider.swift:343-349`); iPad has only a generic `errorMessage` (`iOS/LatticesCompanion/Sources/DeckStore.swift:18`). Normalize at DeckKit, then let each surface render the same object.
6
+
7
+ ## Error structure
8
+
9
+ Prefer `DeckVoiceError` now; if later reused for trackpad/deck actions, lift the same shape to `LatsError`.
10
+
11
+ ```swift
12
+ public struct DeckVoiceError: Codable, Equatable, Identifiable, Sendable {
13
+ public var id: String // uuid or request id
14
+ public var code: DeckVoiceErrorCode
15
+ public var severity: DeckErrorSeverity
16
+ public var recoverable: Bool
17
+ public var retry: DeckRetryHint?
18
+ public var source: DeckErrorSource // mac, ipad, vox, daemon, intent, bridge
19
+ public var owner: String? // e.g. "Vox", "Lattices", "Bridge"
20
+ public var message: String // cockpit copy, already human-readable
21
+ public var remediation: DeckRemediationAction?
22
+ public var occurredAt: Date
23
+ public var detail: String? // diagnostic-only
24
+ }
25
+
26
+ public enum DeckVoiceErrorCode: String, Codable, Sendable { case vox_unreachable, daemon_unreachable, network, connection_lost, mic_denied, accessibility_denied, mic_busy, no_active_target, vox_not_running, vox_loading, intent_unresolved, action_failed, transcription_failed, empty_transcript, language_unsupported }
27
+ public enum DeckErrorSeverity: String, Codable, Sendable { case info, warning, error, blocked }
28
+ public enum DeckRetryHint: String, Codable, Sendable { case silent, immediate, afterLaunch, userAction }
29
+ public enum DeckErrorSource: String, Codable, Sendable { case mac, ipad, vox, daemon, intent, bridge }
30
+ public enum DeckRemediationAction: Codable, Equatable, Sendable {
31
+ case openVox, openSystemSettings(kind: String), retryVoice, openDiagnostics, chooseTarget
32
+ }
33
+ ```
34
+
35
+ Add `var error: DeckVoiceError?` and optionally `var lastError: DeckVoiceError?` to `DeckVoiceState`, preserving existing `phase`, transcript, and provider fields (`swift/Sources/DeckKit/DeckRuntimeSnapshot.swift:49-68`). Codes should stay stable string raw values for JSON logs and iPad bridge snapshots.
36
+
37
+ ## Categories
38
+
39
+ | Category | Codes | Recovery rule |
40
+ |---|---|---|
41
+ | Connection | `vox_unreachable`, `daemon_unreachable`, `network`, `connection_lost` | Recoverable unless active capture was lost. Silent reconnect when idle; visible banner during `listening`/`transcribing`. |
42
+ | Permission | `mic_denied`, `accessibility_denied` | Needs user action. `mic_denied` is Mac/Vox-owned; iPad only relays it. `accessibility_denied` blocks execution/navigation. |
43
+ | State | `mic_busy { owner }`, `no_active_target`, `vox_not_running`, `vox_loading` | Usually recoverable. `mic_busy` waits for owner; `vox_not_running` supports launch-on-demand. |
44
+ | Execution | `intent_unresolved`, `action_failed`, `transcription_failed` | Recoverable by retry or edited command; escalate to log if repeated. |
45
+ | Validation | `empty_transcript`, `language_unsupported` | Recoverable; no scary chrome. Treat as a missed command, not a crash. |
46
+
47
+ Copy examples: `Mic in use by Vox — finish memo first`, `No target window`, `Vox offline — starting`, `Connection lost — press again`, `Intent not found`.
48
+
49
+ ## Presentation patterns
50
+
51
+ **Mac VoiceCommandWindow.** Keep the three-column cockpit. The top mic bar already owns live state (`connecting...`, `processing...`; `app/Sources/VoiceCommandWindow.swift:692-719`); render the active error as a compact red/amber status chip there. The center column uses `commandSection` cards (`app/Sources/VoiceCommandWindow.swift:1287-1304`): show a single `blocked`/`needs action` card only when the user can do something. The footer already has key chips (`app/Sources/VoiceCommandWindow.swift:1308-1348`); replace the generic command list with contextual remediation: `⌥ Retry`, `Return Open Vox`, `⌘, Permissions`. Logs stay in the right rail, using existing level colors (`app/Sources/VoiceCommandWindow.swift:1112-1150`).
52
+
53
+ **Mac HUD.** `HUDTopBar.voiceStatus` already has dot, label, transcript, response (`app/Sources/HUDTopBar.swift:134-198`). Add severity tint: green idle/listening, amber connecting/recoverable, red blocked. For active voice errors, HUD shows a one-line banner in the top bar; no sheet.
54
+
55
+ **iPad Home.** Add `HomeVoiceOverlay` as the full voice modal for active relay: title row `VOICE`, phase, transcript, Mac owner, and one remediation button. The bottom bar already has dense status slots and `hold·space` (`iOS/LatticesCompanion/Sources/Home/HomeBottomBar.swift:58-68`, `iOS/LatticesCompanion/Sources/Home/HomeBottomBar.swift:129-148`); render idle/recoverable errors inline there (`voice · reconnecting`, `voice · Vox offline`). Use a deck overlay banner only when an issued iPad action failed. Use sheets only for permissions/pairing because they need human action. This follows the chrome rule: do not remove noisy UI; replace it with state that answers “what am I controlling, who is listening, what failed?” (`/Users/arach/.claude/projects/-Users-arach-dev-lattices/memory/feedback_chrome_design.md:11-13`).
56
+
57
+ ## Unhappy-path prescriptions
58
+
59
+ **Launch Vox on demand.** Spec flow is detect installed/not running, open Vox, show `Starting Vox...`, wait up to 10s, retry `startDictation`, then fail with manual-open copy (`docs/voice-command-protocol.md:73-89`). Current Mac waits 2s after `connect()` (`app/Sources/VoiceCommandWindow.swift:290-313`); design target is `vox_not_running` → `vox_loading` → retry → either clear error or `vox_unreachable` with `openVox`.
60
+
61
+ **Mic busy.** Preserve owner attribution from protocol (`docs/voice-command-protocol.md:127-135`). `mic_busy(owner: "Vox")` is warning, recoverable, retry hint `userAction`; message: `Mic in use by Vox — finish memo first`. If owner is unknown: `Mic busy — wait for current recording`.
62
+
63
+ **Connection recovery.** If idle, reconnect silently and write log only. If active, show red `Connection lost`; do not auto-retry captured audio because Vox cancels dropped sockets (`docs/voice-command-protocol.md:174-188`). iPad shows `Mac voice link lost` if bridge lost, not `network` unless the iPad transport failed.
64
+
65
+ **JSONL.** Add `~/.lattices/voice.jsonl` beside `lattices.log` (current log path is `~/.lattices/lattices.log`; `app/Sources/DiagnosticLog.swift:40-59`). Shape:
66
+
67
+ ```json
68
+ {"ts":"2026-04-27T14:03:11.120Z","platform":"mac","sessionId":"...","phase":"listening","event":"error","error":{"code":"mic_busy","severity":"warning","recoverable":true,"source":"vox","owner":"Vox","message":"Mic in use by Vox — finish memo first"},"transcript":null,"intent":null,"durationMs":820}
69
+ ```
70
+
71
+ ## Cross-platform conventions
72
+
73
+ Tone: terse cockpit, no apologies. Prefer noun-state-action: `Vox offline — starting`, `No target — pick window`, `Access denied — enable Accessibility`. Tint maps to existing palettes: Mac `Palette.detach` amber and `Palette.kill` red (`app/Sources/Theme.swift:19-23`); iPad `LatsPalette.amber/red` (`iOS/LatticesCompanion/Sources/LatsDeckScreen.swift:19-25`). Icons: `mic.fill` live, `mic.slash` denied, `waveform.badge.exclamationmark` transcription, `bolt.trianglebadge.exclamationmark` execution, `wifi.exclamationmark` connection, `scope` target. Ownership: Mac owns Vox, mic, Accessibility, intent execution, and JSONL. iPad owns relay/bridge/network presentation and never claims direct mic capture.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lattices/cli",
3
- "version": "0.4.1",
3
+ "version": "0.4.5",
4
4
  "description": "Agentic window manager for macOS — programmable workspace, smart layouts, managed tmux sessions, and a 35+-method agent API",
5
5
  "bin": {
6
6
  "lattices": "./bin/lattices.ts",
@@ -22,6 +22,7 @@
22
22
  "license": "MIT",
23
23
  "exports": {
24
24
  ".": "./bin/client.ts",
25
+ "./assistant-intelligence": "./bin/assistant-intelligence.ts",
25
26
  "./daemon-client": "./bin/daemon-client.ts",
26
27
  "./project-twin": "./bin/project-twin.ts"
27
28
  },
@@ -55,6 +56,7 @@
55
56
  "@ai-sdk/openai": "^3.0.41",
56
57
  "@ai-sdk/xai": "^3.0.67",
57
58
  "@arach/speakeasy": "^0.2.8",
58
- "ai": "^6.0.116"
59
+ "ai": "^6.0.116",
60
+ "zod": "^3.25.76"
59
61
  }
60
62
  }