@lattices/cli 0.4.10 → 0.4.11

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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -13
  3. package/{app → apps/mac}/Lattices.app/Contents/Info.plist +10 -2
  4. package/{app → apps/mac}/Lattices.app/Contents/MacOS/Lattices +0 -0
  5. package/{app → apps/mac}/Package.swift +2 -1
  6. package/apps/mac/Resources/Pets/assistant-spark/pet.json +62 -0
  7. package/apps/mac/Resources/Pets/assistant-spark/spritesheet.webp +0 -0
  8. package/apps/mac/Resources/Pets/scout-ranger/pet.json +6 -0
  9. package/apps/mac/Resources/Pets/scout-ranger/spritesheet.webp +0 -0
  10. package/apps/mac/Sources/AppShell/AppActivationCoordinator.swift +27 -0
  11. package/apps/mac/Sources/AppShell/AppDelegate.swift +189 -0
  12. package/apps/mac/Sources/AppShell/AppServicesBootstrap.swift +25 -0
  13. package/{app → apps/mac}/Sources/AppShell/AppShellView.swift +18 -3
  14. package/{app → apps/mac}/Sources/AppShell/AppUpdater.swift +4 -3
  15. package/apps/mac/Sources/AppShell/HotkeyBootstrap.swift +87 -0
  16. package/{app → apps/mac}/Sources/AppShell/LatticesRuntime.swift +43 -0
  17. package/{app → apps/mac}/Sources/AppShell/MainView.swift +116 -63
  18. package/apps/mac/Sources/AppShell/MenuBarController.swift +177 -0
  19. package/{app → apps/mac}/Sources/AppShell/OnboardingView.swift +72 -60
  20. package/apps/mac/Sources/AppShell/PermissionsAssistantView.swift +366 -0
  21. package/apps/mac/Sources/AppShell/PermissionsAssistantWindow.swift +70 -0
  22. package/{app → apps/mac}/Sources/AppShell/Preferences.swift +37 -2
  23. package/{app → apps/mac}/Sources/AppShell/SettingsView.swift +815 -156
  24. package/{app → apps/mac}/Sources/AppShell/SettingsWindow.swift +10 -0
  25. package/apps/mac/Sources/AppShell/WorkspaceInspectorPresenter.swift +13 -0
  26. package/{app → apps/mac}/Sources/Core/Actions/HotkeyStore.swift +6 -1
  27. package/{app → apps/mac}/Sources/Core/Actions/IntentEngine.swift +2 -0
  28. package/{app → apps/mac}/Sources/Core/Daemon/DaemonServer.swift +5 -0
  29. package/{app → apps/mac}/Sources/Core/Daemon/LatticesApi.swift +365 -0
  30. package/{app → apps/mac}/Sources/Core/Desktop/OcrModel.swift +17 -13
  31. package/apps/mac/Sources/Core/Desktop/WindowCapture.swift +33 -0
  32. package/{app → apps/mac}/Sources/Core/Desktop/WindowDragSnapController.swift +18 -217
  33. package/{app → apps/mac}/Sources/Core/Desktop/WindowPreviewStore.swift +4 -5
  34. package/{app → apps/mac}/Sources/Core/Desktop/WindowTiler.swift +19 -13
  35. package/apps/mac/Sources/Core/Input/EventTapBreaker.swift +124 -0
  36. package/apps/mac/Sources/Core/Input/EventTapThread.swift +54 -0
  37. package/apps/mac/Sources/Core/Input/InputCaptureResetCenter.swift +20 -0
  38. package/apps/mac/Sources/Core/Input/KeyboardRemapController.swift +335 -0
  39. package/apps/mac/Sources/Core/Input/KeyboardRemapStore.swift +141 -0
  40. package/{app → apps/mac}/Sources/Core/Input/MouseGestureConfig.swift +155 -20
  41. package/apps/mac/Sources/Core/Input/MouseGestureController.swift +2259 -0
  42. package/apps/mac/Sources/Core/Input/MouseShortcutStore.swift +170 -0
  43. package/apps/mac/Sources/Core/Input/SecureEventInputMonitor.swift +39 -0
  44. package/apps/mac/Sources/Core/Input/ShapeRecognizer.swift +624 -0
  45. package/apps/mac/Sources/Core/Input/TapBudgetMeter.swift +56 -0
  46. package/{app → apps/mac}/Sources/Core/Overlays/ScreenMap/ScreenMapState.swift +8 -8
  47. package/apps/mac/Sources/Core/Overlays/ScreenOverlayCanvasController.swift +1240 -0
  48. package/{app → apps/mac}/Sources/Core/Overlays/Voice/VoiceCommandWindow.swift +11 -23
  49. package/{app → apps/mac}/Sources/Core/Pi/PiChatDock.swift +90 -43
  50. package/{app → apps/mac}/Sources/Core/Pi/PiChatSession.swift +676 -43
  51. package/{app → apps/mac}/Sources/Core/Pi/PiProviderSetupCallout.swift +5 -5
  52. package/{app → apps/mac}/Sources/Core/Pi/PiWorkspaceView.swift +93 -44
  53. package/apps/mac/Sources/Core/System/Capability.swift +79 -0
  54. package/{app → apps/mac}/Sources/Core/System/PermissionChecker.swift +43 -8
  55. package/{app → apps/mac}/Sources/Core/Voice/AudioProvider.swift +225 -56
  56. package/bin/handsoff-infer.ts +14 -5
  57. package/bin/handsoff-worker.ts +11 -7
  58. package/bin/infer.ts +406 -0
  59. package/bin/lattices-app.ts +57 -7
  60. package/bin/lattices-dev +40 -1
  61. package/bin/lattices.ts +1 -1
  62. package/docs/agent-execution-plan.md +9 -9
  63. package/docs/api.md +119 -0
  64. package/docs/app.md +1 -0
  65. package/docs/companion-deck.md +1 -1
  66. package/docs/gesture-customization-proposal.md +520 -0
  67. package/docs/mouse-gestures.md +79 -0
  68. package/docs/overview.md +2 -2
  69. package/docs/presentation-execution-review.md +9 -9
  70. package/docs/proposals/LAT-001-gesture-visual-customization.md +522 -0
  71. package/docs/proposals/LAT-002-shared-overlay-canvas.md +353 -0
  72. package/docs/proposals/LAT-003-menu-bar-controller-architecture.md +291 -0
  73. package/docs/proposals/LAT-004-interactive-overlay-actors.md +534 -0
  74. package/docs/reference/dewey.config.ts +74 -0
  75. package/docs/reference/install-agent.md +79 -0
  76. package/docs/repo-structure.md +100 -0
  77. package/docs/voice-error-model.md +7 -7
  78. package/docs/voice.md +18 -0
  79. package/package.json +23 -13
  80. package/swift/Package.swift +20 -0
  81. package/swift/Sources/DeckKit/DeckAction.swift +51 -0
  82. package/swift/Sources/DeckKit/DeckBridgeSecurity.swift +152 -0
  83. package/swift/Sources/DeckKit/DeckCockpit.swift +82 -0
  84. package/swift/Sources/DeckKit/DeckHost.swift +7 -0
  85. package/swift/Sources/DeckKit/DeckManifest.swift +145 -0
  86. package/swift/Sources/DeckKit/DeckRuntimeSnapshot.swift +533 -0
  87. package/swift/Sources/DeckKit/DeckTrackpad.swift +63 -0
  88. package/swift/Sources/DeckKit/DeckValue.swift +93 -0
  89. package/swift/Sources/DeckKit/DeckVoiceError.swift +88 -0
  90. package/swift/Tests/DeckKitTests/DeckKitTests.swift +286 -0
  91. package/app/Sources/AppShell/AppDelegate.swift +0 -408
  92. package/app/Sources/Core/Input/KeyboardRemapController.swift +0 -184
  93. package/app/Sources/Core/Input/KeyboardRemapStore.swift +0 -84
  94. package/app/Sources/Core/Input/MouseGestureController.swift +0 -1203
  95. package/app/Sources/Core/Input/MouseShortcutStore.swift +0 -107
  96. /package/{app → apps/mac}/Info.plist +0 -0
  97. /package/{app → apps/mac}/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
  98. /package/{app → apps/mac}/Lattices.app/Contents/Resources/tap.wav +0 -0
  99. /package/{app → apps/mac}/Lattices.app/Contents/_CodeSignature/CodeResources +0 -0
  100. /package/{app → apps/mac}/Lattices.entitlements +0 -0
  101. /package/{app → apps/mac}/Resources/tap.wav +0 -0
  102. /package/{app → apps/mac}/Sources/AppShell/App.swift +0 -0
  103. /package/{app → apps/mac}/Sources/AppShell/CliActionLauncher.swift +0 -0
  104. /package/{app → apps/mac}/Sources/AppShell/HomeDashboardView.swift +0 -0
  105. /package/{app → apps/mac}/Sources/AppShell/KeyRecorderView.swift +0 -0
  106. /package/{app → apps/mac}/Sources/AppShell/MainWindow.swift +0 -0
  107. /package/{app → apps/mac}/Sources/Core/Actions/HotkeyManager.swift +0 -0
  108. /package/{app → apps/mac}/Sources/Core/Actions/IntentSchema.swift +0 -0
  109. /package/{app → apps/mac}/Sources/Core/Actions/Intents/CreateLayerIntent.swift +0 -0
  110. /package/{app → apps/mac}/Sources/Core/Actions/Intents/DistributeIntent.swift +0 -0
  111. /package/{app → apps/mac}/Sources/Core/Actions/Intents/FocusIntent.swift +0 -0
  112. /package/{app → apps/mac}/Sources/Core/Actions/Intents/HelpIntent.swift +0 -0
  113. /package/{app → apps/mac}/Sources/Core/Actions/Intents/KillIntent.swift +0 -0
  114. /package/{app → apps/mac}/Sources/Core/Actions/Intents/LatticeIntent.swift +0 -0
  115. /package/{app → apps/mac}/Sources/Core/Actions/Intents/LaunchIntent.swift +0 -0
  116. /package/{app → apps/mac}/Sources/Core/Actions/Intents/ListSessionsIntent.swift +0 -0
  117. /package/{app → apps/mac}/Sources/Core/Actions/Intents/ListWindowsIntent.swift +0 -0
  118. /package/{app → apps/mac}/Sources/Core/Actions/Intents/ScanIntent.swift +0 -0
  119. /package/{app → apps/mac}/Sources/Core/Actions/Intents/SearchIntent.swift +0 -0
  120. /package/{app → apps/mac}/Sources/Core/Actions/Intents/SwitchLayerIntent.swift +0 -0
  121. /package/{app → apps/mac}/Sources/Core/Actions/Intents/TileIntent.swift +0 -0
  122. /package/{app → apps/mac}/Sources/Core/Actions/PaletteCommand.swift +0 -0
  123. /package/{app → apps/mac}/Sources/Core/Actions/VoiceIntentResolver.swift +0 -0
  124. /package/{app → apps/mac}/Sources/Core/Companion/CompanionActivityLog.swift +0 -0
  125. /package/{app → apps/mac}/Sources/Core/Companion/CompanionKeyboardController.swift +0 -0
  126. /package/{app → apps/mac}/Sources/Core/Companion/LatticesCompanionBridgeServer.swift +0 -0
  127. /package/{app → apps/mac}/Sources/Core/Companion/LatticesCompanionCockpit.swift +0 -0
  128. /package/{app → apps/mac}/Sources/Core/Companion/LatticesCompanionSecurityCoordinator.swift +0 -0
  129. /package/{app → apps/mac}/Sources/Core/Companion/LatticesCompanionTrackpadController.swift +0 -0
  130. /package/{app → apps/mac}/Sources/Core/Companion/LatticesDeckHost.swift +0 -0
  131. /package/{app → apps/mac}/Sources/Core/Daemon/DaemonProtocol.swift +0 -0
  132. /package/{app → apps/mac}/Sources/Core/Desktop/AccessibilityTextExtractor.swift +0 -0
  133. /package/{app → apps/mac}/Sources/Core/Desktop/AppTypeClassifier.swift +0 -0
  134. /package/{app → apps/mac}/Sources/Core/Desktop/DesktopModel.swift +0 -0
  135. /package/{app → apps/mac}/Sources/Core/Desktop/DesktopModelTypes.swift +0 -0
  136. /package/{app → apps/mac}/Sources/Core/Desktop/InventoryManager.swift +0 -0
  137. /package/{app → apps/mac}/Sources/Core/Desktop/InventoryPath.swift +0 -0
  138. /package/{app → apps/mac}/Sources/Core/Desktop/MouseFinder.swift +0 -0
  139. /package/{app → apps/mac}/Sources/Core/Desktop/OcrStore.swift +0 -0
  140. /package/{app → apps/mac}/Sources/Core/Desktop/PlacementSpec.swift +0 -0
  141. /package/{app → apps/mac}/Sources/Core/Desktop/SessionWindowLocator.swift +0 -0
  142. /package/{app → apps/mac}/Sources/Core/Desktop/TilePickerView.swift +0 -0
  143. /package/{app → apps/mac}/Sources/Core/Desktop/WindowPreviewCard.swift +0 -0
  144. /package/{app → apps/mac}/Sources/Core/Desktop/WindowSelectionStore.swift +0 -0
  145. /package/{app → apps/mac}/Sources/Core/Input/KeyboardRemapConfig.swift +0 -0
  146. /package/{app → apps/mac}/Sources/Core/Input/MouseInputDeviceStore.swift +0 -0
  147. /package/{app → apps/mac}/Sources/Core/Input/MouseInputEventViewer.swift +0 -0
  148. /package/{app → apps/mac}/Sources/Core/Overlays/AppWindowShell.swift +0 -0
  149. /package/{app → apps/mac}/Sources/Core/Overlays/CommandMode/CommandModeState.swift +0 -0
  150. /package/{app → apps/mac}/Sources/Core/Overlays/CommandMode/CommandModeView.swift +0 -0
  151. /package/{app → apps/mac}/Sources/Core/Overlays/CommandMode/CommandModeWindow.swift +0 -0
  152. /package/{app → apps/mac}/Sources/Core/Overlays/CommandPalette/CommandPaletteView.swift +0 -0
  153. /package/{app → apps/mac}/Sources/Core/Overlays/CommandPalette/CommandPaletteWindow.swift +0 -0
  154. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/CheatSheetHUD.swift +0 -0
  155. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/HUDBottomBar.swift +0 -0
  156. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/HUDController.swift +0 -0
  157. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/HUDLeftBar.swift +0 -0
  158. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/HUDMinimap.swift +0 -0
  159. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/HUDRightBar.swift +0 -0
  160. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/HUDState.swift +0 -0
  161. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/HUDTopBar.swift +0 -0
  162. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/LauncherHUD.swift +0 -0
  163. /package/{app → apps/mac}/Sources/Core/Overlays/HUD/LayerBezel.swift +0 -0
  164. /package/{app → apps/mac}/Sources/Core/Overlays/OmniSearch/OmniSearchState.swift +0 -0
  165. /package/{app → apps/mac}/Sources/Core/Overlays/OmniSearch/OmniSearchView.swift +0 -0
  166. /package/{app → apps/mac}/Sources/Core/Overlays/OmniSearch/OmniSearchWindow.swift +0 -0
  167. /package/{app → apps/mac}/Sources/Core/Overlays/OverlayPanelShell.swift +0 -0
  168. /package/{app → apps/mac}/Sources/Core/Overlays/ScreenMap/ScreenMapView.swift +0 -0
  169. /package/{app → apps/mac}/Sources/Core/Overlays/ScreenMap/ScreenMapWindowController.swift +0 -0
  170. /package/{app → apps/mac}/Sources/Core/Pi/PiAuthNextStepCard.swift +0 -0
  171. /package/{app → apps/mac}/Sources/Core/Pi/PiAuthPromptCard.swift +0 -0
  172. /package/{app → apps/mac}/Sources/Core/Pi/PiInstallCallout.swift +0 -0
  173. /package/{app → apps/mac}/Sources/Core/System/DiagnosticLog.swift +0 -0
  174. /package/{app → apps/mac}/Sources/Core/System/EventBus.swift +0 -0
  175. /package/{app → apps/mac}/Sources/Core/System/ProcessModel.swift +0 -0
  176. /package/{app → apps/mac}/Sources/Core/System/ProcessQuery.swift +0 -0
  177. /package/{app → apps/mac}/Sources/Core/System/SystemTelemetryMonitor.swift +0 -0
  178. /package/{app → apps/mac}/Sources/Core/Voice/AdvisorLearningStore.swift +0 -0
  179. /package/{app → apps/mac}/Sources/Core/Voice/AgentSession.swift +0 -0
  180. /package/{app → apps/mac}/Sources/Core/Voice/HandsOffSession.swift +0 -0
  181. /package/{app → apps/mac}/Sources/Core/Voice/VoiceChatView.swift +0 -0
  182. /package/{app → apps/mac}/Sources/Core/Voice/VoxClient.swift +0 -0
  183. /package/{app → apps/mac}/Sources/Core/Workspace/Project.swift +0 -0
  184. /package/{app → apps/mac}/Sources/Core/Workspace/ProjectScanner.swift +0 -0
  185. /package/{app → apps/mac}/Sources/Core/Workspace/SessionLayerStore.swift +0 -0
  186. /package/{app → apps/mac}/Sources/Core/Workspace/SessionManager.swift +0 -0
  187. /package/{app → apps/mac}/Sources/Core/Workspace/Terminal/Terminal.swift +0 -0
  188. /package/{app → apps/mac}/Sources/Core/Workspace/Terminal/TerminalQuery.swift +0 -0
  189. /package/{app → apps/mac}/Sources/Core/Workspace/Terminal/TerminalSynthesizer.swift +0 -0
  190. /package/{app → apps/mac}/Sources/Core/Workspace/Tmux/TmuxModel.swift +0 -0
  191. /package/{app → apps/mac}/Sources/Core/Workspace/Tmux/TmuxQuery.swift +0 -0
  192. /package/{app → apps/mac}/Sources/Core/Workspace/WorkspaceManager.swift +0 -0
  193. /package/{app → apps/mac}/Sources/UI/ActionRow.swift +0 -0
  194. /package/{app → apps/mac}/Sources/UI/OrphanRow.swift +0 -0
  195. /package/{app → apps/mac}/Sources/UI/ProjectRow.swift +0 -0
  196. /package/{app → apps/mac}/Sources/UI/TabGroupRow.swift +0 -0
  197. /package/{app → apps/mac}/Sources/UI/Theme.swift +0 -0
  198. /package/{app → apps/mac}/Tests/StageDragTests.swift +0 -0
  199. /package/{app → apps/mac}/Tests/StageJoinTests.swift +0 -0
  200. /package/{app → apps/mac}/Tests/StageManagerTests.swift +0 -0
  201. /package/{app → apps/mac}/Tests/StageTileTests.swift +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arach Tchoupani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  <picture>
2
- <img alt="lattices" src="site/public/og.png" />
2
+ <img alt="lattices" src="apps/site/public/og.png" />
3
3
  </picture>
4
4
 
5
5
  # lattices
6
6
 
7
- The agentic window manager for macOS.
7
+ The agentic workspace manager for macOS.
8
8
 
9
- Tile windows with hotkeys, manage persistent tmux sessions, index screen
10
- text with OCR, and give AI agents a 35-method desktop API all from a
11
- native menu bar app and CLI.
9
+ Lattices turns your Mac workspace into a coherent API, so agents can see and
10
+ control windows, tmux sessions, screen text, and layouts. It also gives you
11
+ an assistant to control that workspace in plain language.
12
12
 
13
13
  **[lattices.dev](https://lattices.dev)** · [Docs](https://lattices.dev/docs/overview) · [Download](https://github.com/arach/lattices/releases/latest)
14
14
 
@@ -42,25 +42,25 @@ The CLI and app work independently — use either or both.
42
42
  git clone https://github.com/arach/lattices.git
43
43
  cd lattices
44
44
 
45
- # Build the menu bar app (requires Swift 5.9+ / Xcode 15+)
46
- cd app && swift build -c release && cd ..
45
+ # Build the menu bar app (requires Swift 6.2 / Xcode 26+)
46
+ cd apps/mac && swift build -c release && cd ../..
47
47
 
48
48
  # Install CLI dependencies
49
49
  npm install
50
50
 
51
51
  # Launch
52
- node bin/lattices-app.js build # bundle the .app
53
- node bin/lattices-app.js # launch it
52
+ bun bin/lattices-app.ts build # bundle the .app
53
+ bun bin/lattices-app.ts # launch it
54
54
  ```
55
55
 
56
56
  To build a signed, notarized DMG for distribution:
57
57
 
58
58
  ```sh
59
59
  # Requires a Developer ID certificate and notarytool keychain profile
60
- ./scripts/build-dmg.sh
60
+ ./tools/release/build-dmg.sh
61
61
 
62
62
  # Update v<package.json version> and upload the DMG to GitHub Releases
63
- ./scripts/ship.sh
63
+ ./tools/release/ship.sh
64
64
  ```
65
65
 
66
66
  ## Quick start
@@ -215,13 +215,13 @@ lattices help Show help
215
215
 
216
216
  ## Requirements
217
217
 
218
- - macOS 13.0+
218
+ - macOS 26.0+
219
219
  - Node.js 18+
220
220
 
221
221
  ### Optional
222
222
 
223
223
  - tmux for persistent terminal sessions (`brew install tmux`)
224
- - Swift 5.9+ to build the menu bar app from source
224
+ - Swift 6.2 / Xcode 26+ to build the menu bar app from source
225
225
 
226
226
  ## Docs
227
227
 
@@ -26,9 +26,17 @@
26
26
  </dict>
27
27
  </array>
28
28
  <key>CFBundleVersion</key>
29
- <string>0.4.10</string>
29
+ <string>0.4.11</string>
30
30
  <key>CFBundleShortVersionString</key>
31
- <string>0.4.10</string>
31
+ <string>0.4.11</string>
32
+ <key>LatticesBuildChannel</key>
33
+ <string>dev</string>
34
+ <key>LatticesBuildTrack</key>
35
+ <string>latest</string>
36
+ <key>LatticesBuildRevision</key>
37
+ <string>9ce9e1a</string>
38
+ <key>LatticesBuildTimestamp</key>
39
+ <string>2026-05-04T15:09:03Z</string>
32
40
  <key>LSMinimumSystemVersion</key>
33
41
  <string>13.0</string>
34
42
  <key>LSUIElement</key>
@@ -5,7 +5,7 @@ let package = Package(
5
5
  name: "Lattices",
6
6
  platforms: [.macOS(.v13)],
7
7
  dependencies: [
8
- .package(path: "../swift")
8
+ .package(path: "../../swift")
9
9
  ],
10
10
  targets: [
11
11
  .executableTarget(
@@ -16,6 +16,7 @@ let package = Package(
16
16
  path: "Sources",
17
17
  resources: [
18
18
  .copy("../Resources/tap.wav"),
19
+ .copy("../Resources/Pets"),
19
20
  ]
20
21
  ),
21
22
  .testTarget(
@@ -0,0 +1,62 @@
1
+ {
2
+ "id": "assistant-spark",
3
+ "displayName": "Assistant Spark",
4
+ "description": "A small luminous assistant companion for Codex sessions.",
5
+ "spritesheetPath": "spritesheet.webp",
6
+ "states": {
7
+ "idle": {
8
+ "row": 0,
9
+ "frames": 6,
10
+ "frameWidth": 192,
11
+ "frameHeight": 208
12
+ },
13
+ "run_right": {
14
+ "row": 1,
15
+ "frames": 8,
16
+ "frameWidth": 192,
17
+ "frameHeight": 208
18
+ },
19
+ "run_left": {
20
+ "row": 2,
21
+ "frames": 8,
22
+ "frameWidth": 192,
23
+ "frameHeight": 208
24
+ },
25
+ "waving": {
26
+ "row": 3,
27
+ "frames": 4,
28
+ "frameWidth": 192,
29
+ "frameHeight": 208
30
+ },
31
+ "jumping": {
32
+ "row": 4,
33
+ "frames": 5,
34
+ "frameWidth": 192,
35
+ "frameHeight": 208
36
+ },
37
+ "failed": {
38
+ "row": 5,
39
+ "frames": 8,
40
+ "frameWidth": 192,
41
+ "frameHeight": 208
42
+ },
43
+ "waiting": {
44
+ "row": 6,
45
+ "frames": 6,
46
+ "frameWidth": 192,
47
+ "frameHeight": 208
48
+ },
49
+ "running": {
50
+ "row": 7,
51
+ "frames": 6,
52
+ "frameWidth": 192,
53
+ "frameHeight": 208
54
+ },
55
+ "review": {
56
+ "row": 8,
57
+ "frames": 6,
58
+ "frameWidth": 192,
59
+ "frameHeight": 208
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "scout-ranger",
3
+ "displayName": "Scout Ranger",
4
+ "description": "A tiny chunky robot field-general companion for Scout and Codex sessions.",
5
+ "spritesheetPath": "spritesheet.webp"
6
+ }
@@ -0,0 +1,27 @@
1
+ import AppKit
2
+
3
+ final class AppActivationCoordinator {
4
+ static let shared = AppActivationCoordinator()
5
+
6
+ private var surfaceVisibilityProviders: [(id: String, isVisible: () -> Bool)] = []
7
+
8
+ private init() {}
9
+
10
+ func registerSurface(id: String, isVisible: @escaping () -> Bool) {
11
+ guard !surfaceVisibilityProviders.contains(where: { $0.id == id }) else { return }
12
+ surfaceVisibilityProviders.append((id: id, isVisible: isVisible))
13
+ }
14
+
15
+ func refresh() {
16
+ let hasVisibleWindow = surfaceVisibilityProviders.contains { provider in
17
+ provider.isVisible()
18
+ }
19
+ let desired: NSApplication.ActivationPolicy = hasVisibleWindow ? .regular : .accessory
20
+ if NSApp.activationPolicy() != desired {
21
+ NSApp.setActivationPolicy(desired)
22
+ if desired == .regular {
23
+ NSApp.activate(ignoringOtherApps: true)
24
+ }
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,189 @@
1
+ import AppKit
2
+ import Carbon
3
+
4
+ extension Notification.Name {
5
+ static let latticesPopoverWillShow = Notification.Name("latticesPopoverWillShow")
6
+ static let latticesShowGeneralSettings = Notification.Name("latticesShowGeneralSettings")
7
+ static let latticesShowAssistantSettings = Notification.Name("latticesShowAssistantSettings")
8
+ }
9
+
10
+ class AppDelegate: NSObject, NSApplicationDelegate {
11
+ private var notificationObservers: [NSObjectProtocol] = []
12
+
13
+ static func updateActivationPolicy() {
14
+ AppActivationCoordinator.shared.refresh()
15
+ }
16
+
17
+ func applicationDidFinishLaunching(_ notification: Notification) {
18
+ NSApp.setActivationPolicy(.accessory)
19
+ NSApp.appearance = NSAppearance(named: .darkAqua)
20
+ registerDeepLinkHandler()
21
+ installSystemInputBoundaryObservers()
22
+
23
+ MenuBarController.shared.start()
24
+ registerVisibleSurfaces()
25
+ HotkeyBootstrap.registerHotkeys()
26
+
27
+ DispatchQueue.main.async { HUDController.shared.warmUp() }
28
+ DispatchQueue.main.async { MenuBarController.shared.warmUpPopover() }
29
+ DispatchQueue.main.async { ScreenOverlayCanvasController.shared.warmUp() }
30
+
31
+ WindowDragSnapController.shared.start()
32
+ MouseGestureController.shared.start()
33
+ KeyboardRemapController.shared.start()
34
+ SecureEventInputMonitor.shared.start()
35
+
36
+ if !OnboardingWindowController.shared.showIfNeeded() {
37
+ PermissionChecker.shared.check()
38
+ }
39
+
40
+ AppServicesBootstrap.start()
41
+
42
+ Task {
43
+ await AppUpdater.shared.checkIfNeeded()
44
+ }
45
+
46
+ // --diagnostics flag: auto-open diagnostics panel on launch
47
+ if CommandLine.arguments.contains("--diagnostics") {
48
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
49
+ DiagnosticWindow.shared.show()
50
+ }
51
+ }
52
+
53
+ // --screen-map flag: auto-open layout on launch
54
+ if CommandLine.arguments.contains("--screen-map") {
55
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
56
+ ScreenMapWindowController.shared.showPage(.screenMap)
57
+ }
58
+ }
59
+
60
+ // Explicit preview entry point for development/demo flows. This still
61
+ // requires a launch argument; the assistant never opens automatically.
62
+ if CommandLine.arguments.contains("--permissions-assistant") {
63
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
64
+ PermissionsAssistantWindowController.shared.show()
65
+ }
66
+ }
67
+ }
68
+
69
+ func applicationWillTerminate(_ notification: Notification) {
70
+ removeSystemInputBoundaryObservers()
71
+ SecureEventInputMonitor.shared.stop()
72
+ KeyboardRemapController.shared.stop()
73
+ AppServicesBootstrap.stop()
74
+ }
75
+
76
+ func applicationDidBecomeActive(_ notification: Notification) {
77
+ resetInputCapture(reason: "app became active")
78
+ }
79
+
80
+ func applicationWillResignActive(_ notification: Notification) {
81
+ resetInputCapture(reason: "app resigned active")
82
+ }
83
+
84
+ private func registerVisibleSurfaces() {
85
+ let coordinator = AppActivationCoordinator.shared
86
+ coordinator.registerSurface(id: "menuBarPopover") { MenuBarController.shared.isPopoverShown }
87
+ coordinator.registerSurface(id: "commandMode") { CommandModeWindow.shared.isVisible }
88
+ coordinator.registerSurface(id: "commandPalette") { CommandPaletteWindow.shared.isVisible }
89
+ coordinator.registerSurface(id: "mainWindow") { MainWindow.shared.isVisible }
90
+ coordinator.registerSurface(id: "screenMap") { ScreenMapWindowController.shared.isVisible }
91
+ coordinator.registerSurface(id: "omniSearch") { OmniSearchWindow.shared.isVisible }
92
+ }
93
+
94
+ private func installSystemInputBoundaryObservers() {
95
+ let center = NSWorkspace.shared.notificationCenter
96
+ notificationObservers.append(center.addObserver(
97
+ forName: NSWorkspace.willSleepNotification,
98
+ object: nil,
99
+ queue: .main
100
+ ) { [weak self] _ in
101
+ self?.resetInputCapture(reason: "system will sleep")
102
+ })
103
+ notificationObservers.append(center.addObserver(
104
+ forName: NSWorkspace.didWakeNotification,
105
+ object: nil,
106
+ queue: .main
107
+ ) { [weak self] _ in
108
+ self?.resetInputCapture(reason: "system did wake")
109
+ })
110
+ notificationObservers.append(center.addObserver(
111
+ forName: NSWorkspace.screensDidWakeNotification,
112
+ object: nil,
113
+ queue: .main
114
+ ) { [weak self] _ in
115
+ self?.resetInputCapture(reason: "screens did wake")
116
+ })
117
+ notificationObservers.append(center.addObserver(
118
+ forName: NSWorkspace.screensDidSleepNotification,
119
+ object: nil,
120
+ queue: .main
121
+ ) { [weak self] _ in
122
+ self?.resetInputCapture(reason: "screens did sleep")
123
+ })
124
+ }
125
+
126
+ private func removeSystemInputBoundaryObservers() {
127
+ let center = NSWorkspace.shared.notificationCenter
128
+ for observer in notificationObservers {
129
+ center.removeObserver(observer)
130
+ }
131
+ notificationObservers.removeAll()
132
+ }
133
+
134
+ private func resetInputCapture(reason: String) {
135
+ InputCaptureResetCenter.reset(reason: reason)
136
+ }
137
+
138
+ // MARK: - Deep Links
139
+
140
+ private func registerDeepLinkHandler() {
141
+ NSAppleEventManager.shared().setEventHandler(
142
+ self,
143
+ andSelector: #selector(handleGetURLEvent(_:withReplyEvent:)),
144
+ forEventClass: AEEventClass(kInternetEventClass),
145
+ andEventID: AEEventID(kAEGetURL)
146
+ )
147
+ }
148
+
149
+ @objc private func handleGetURLEvent(
150
+ _ event: NSAppleEventDescriptor,
151
+ withReplyEvent replyEvent: NSAppleEventDescriptor
152
+ ) {
153
+ guard
154
+ let value = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue,
155
+ let url = URL(string: value)
156
+ else {
157
+ return
158
+ }
159
+ handleDeepLink(url)
160
+ }
161
+
162
+ private func handleDeepLink(_ url: URL) {
163
+ guard url.scheme?.localizedCaseInsensitiveCompare("lattices") == .orderedSame else {
164
+ return
165
+ }
166
+
167
+ let host = url.host?.lowercased()
168
+ let action = url.pathComponents
169
+ .first { $0 != "/" }?
170
+ .lowercased()
171
+
172
+ guard host == "companion" else {
173
+ SettingsWindowController.shared.show()
174
+ return
175
+ }
176
+
177
+ switch action {
178
+ case "enable", "start":
179
+ Preferences.shared.companionBridgeEnabled = true
180
+ SettingsWindowController.shared.showCompanion()
181
+ case "disable", "stop":
182
+ Preferences.shared.companionBridgeEnabled = false
183
+ SettingsWindowController.shared.showCompanion()
184
+ default:
185
+ SettingsWindowController.shared.showCompanion()
186
+ }
187
+ }
188
+
189
+ }
@@ -0,0 +1,25 @@
1
+ enum AppServicesBootstrap {
2
+ static func start() {
3
+ let diagnosticLog = DiagnosticLog.shared
4
+ let timedBoot = diagnosticLog.startTimed("Daemon services boot")
5
+ OcrStore.shared.open()
6
+ DesktopModel.shared.start()
7
+ OcrModel.shared.start()
8
+ TmuxModel.shared.start()
9
+ ProcessModel.shared.start()
10
+ LatticesApi.setup()
11
+ DaemonServer.shared.start()
12
+ if Preferences.shared.companionBridgeEnabled {
13
+ LatticesCompanionBridgeServer.shared.start()
14
+ } else {
15
+ diagnosticLog.info("CompanionBridge: disabled by preference")
16
+ }
17
+ AgentPool.shared.start()
18
+ diagnosticLog.finish(timedBoot)
19
+ }
20
+
21
+ static func stop() {
22
+ LatticesCompanionBridgeServer.shared.stop()
23
+ DaemonServer.shared.stop()
24
+ }
25
+ }
@@ -14,9 +14,9 @@ enum AppPage: String, CaseIterable {
14
14
  var label: String {
15
15
  switch self {
16
16
  case .home: return "Home"
17
- case .screenMap: return "Screen Map"
17
+ case .screenMap: return "Layout"
18
18
  case .desktopInventory: return "Desktop Inventory"
19
- case .pi: return "Pi"
19
+ case .pi: return "Assistant"
20
20
  case .settings: return "Settings"
21
21
  case .companionSettings:return "Settings"
22
22
  case .docs: return "Docs"
@@ -28,7 +28,7 @@ enum AppPage: String, CaseIterable {
28
28
  case .home: return "house"
29
29
  case .screenMap: return "rectangle.3.group"
30
30
  case .desktopInventory: return "macwindow.on.rectangle"
31
- case .pi: return "terminal"
31
+ case .pi: return "bubble.left.and.bubble.right"
32
32
  case .settings: return "gearshape"
33
33
  case .companionSettings:return "ipad.and.iphone"
34
34
  case .docs: return "book"
@@ -63,6 +63,21 @@ struct AppShellView: View {
63
63
  }
64
64
  .onChange(of: windowController.activePage) { page in
65
65
  syncPageState(page)
66
+ clearRelevantDismissals(for: page)
67
+ }
68
+ }
69
+
70
+ /// Entering a feature page clears its capability snooze — the user is
71
+ /// telling us they want this to work, so the banner can resurface.
72
+ private func clearRelevantDismissals(for page: AppPage) {
73
+ let prefs = Preferences.shared
74
+ switch page {
75
+ case .screenMap:
76
+ prefs.clearDismissal(Capability.windowControl.rawValue)
77
+ case .desktopInventory:
78
+ prefs.clearDismissal(Capability.screenSearch.rawValue)
79
+ default:
80
+ break
66
81
  }
67
82
  }
68
83
 
@@ -31,6 +31,7 @@ final class AppUpdater: ObservableObject {
31
31
  private init() {}
32
32
 
33
33
  var currentVersion: String { LatticesRuntime.appVersion }
34
+ var currentDisplayVersion: String { LatticesRuntime.appDisplayVersion }
34
35
 
35
36
  var canUpdate: Bool {
36
37
  LatticesRuntime.bunPath != nil && LatticesRuntime.appHelperScriptPath != nil
@@ -124,7 +125,7 @@ final class AppUpdater: ObservableObject {
124
125
  } else {
125
126
  presentAlert(
126
127
  title: "Lattices Is Up to Date",
127
- message: "You’re running \(currentVersion), which is the latest published release."
128
+ message: "You’re running \(currentDisplayVersion), which is the latest available build for this install."
128
129
  )
129
130
  }
130
131
  }
@@ -140,7 +141,7 @@ final class AppUpdater: ObservableObject {
140
141
  if let update = availableUpdate {
141
142
  alert.messageText = "Update Lattices?"
142
143
  alert.informativeText = """
143
- Current version: \(currentVersion)
144
+ Current version: \(currentDisplayVersion)
144
145
  New version: \(update.version)
145
146
 
146
147
  Lattices will download the signed release, quit briefly, replace the app, and relaunch when the update is ready.
@@ -148,7 +149,7 @@ final class AppUpdater: ObservableObject {
148
149
  } else {
149
150
  alert.messageText = "Check and update Lattices?"
150
151
  alert.informativeText = """
151
- Current version: \(currentVersion)
152
+ Current version: \(currentDisplayVersion)
152
153
  New version: latest published release
153
154
 
154
155
  Lattices will download the signed release, quit briefly, replace the app, and relaunch when the update is ready.
@@ -0,0 +1,87 @@
1
+ import AppKit
2
+
3
+ enum HotkeyBootstrap {
4
+ static func registerHotkeys() {
5
+ let scanner = ProjectScanner.shared
6
+ CommandPaletteWindow.shared.configure(scanner: scanner)
7
+
8
+ let store = HotkeyStore.shared
9
+ store.register(action: .palette) { CommandPaletteWindow.shared.toggle() }
10
+ store.register(action: .unifiedWindow) { ScreenMapWindowController.shared.toggle() }
11
+ store.register(action: .bezel) { WorkspaceInspectorPresenter.show() }
12
+ store.register(action: .cheatSheet) { SettingsWindowController.shared.show() }
13
+ store.register(action: .desktopInventory) {
14
+ DiagnosticLog.shared.info("Hotkey: desktopInventory triggered")
15
+ ScreenMapWindowController.shared.showPage(.desktopInventory)
16
+ }
17
+ store.register(action: .voiceCommand) {
18
+ DiagnosticLog.shared.info("Hotkey: voiceCommand triggered")
19
+ VoiceCommandWindow.shared.toggle()
20
+ }
21
+ store.register(action: .handsOff) {
22
+ DiagnosticLog.shared.info("Hotkey: handsOff triggered")
23
+ HandsOffSession.shared.toggle()
24
+ if HandsOffSession.shared.state != .idle {
25
+ HUDController.shared.showVoiceBar()
26
+ } else {
27
+ HUDController.shared.hideVoiceBar()
28
+ }
29
+ }
30
+ store.register(action: .hud) { HUDController.shared.toggle() }
31
+ store.register(action: .mouseFinder) { MouseFinder.shared.find() }
32
+ store.register(action: .overlayActors) { ScreenOverlayCanvasController.shared.toggleAgentActorsVisibility() }
33
+ store.register(action: .omniSearch) { OmniSearchWindow.shared.toggle() }
34
+
35
+ registerLayerHotkeys(store: store)
36
+ registerTilingHotkeys(store: store)
37
+ }
38
+
39
+ private static func registerLayerHotkeys(store: HotkeyStore) {
40
+ store.register(action: .layerNext) { SessionLayerStore.shared.cycleNext() }
41
+ store.register(action: .layerPrev) { SessionLayerStore.shared.cyclePrev() }
42
+ store.register(action: .layerTag) { SessionLayerStore.shared.tagFrontmostWindow() }
43
+
44
+ let workspace = WorkspaceManager.shared
45
+ let configLayerCount = (workspace.config?.layers ?? []).count
46
+ let maxLayers = max(configLayerCount, 9)
47
+ for (index, action) in HotkeyAction.layerActions.prefix(maxLayers).enumerated() {
48
+ store.register(action: action) {
49
+ let session = SessionLayerStore.shared
50
+ if !session.layers.isEmpty && index < session.layers.count {
51
+ session.switchTo(index: index)
52
+ } else {
53
+ workspace.focusLayer(index: index)
54
+ }
55
+ EventBus.shared.post(.layerSwitched(index: index))
56
+ }
57
+ }
58
+ }
59
+
60
+ private static func registerTilingHotkeys(store: HotkeyStore) {
61
+ let tileMap: [(HotkeyAction, TilePosition)] = [
62
+ (.tileLeft, .left), (.tileRight, .right),
63
+ (.tileMaximize, .maximize), (.tileCenter, .center),
64
+ (.tileTopLeft, .topLeft), (.tileTopRight, .topRight),
65
+ (.tileBottomLeft, .bottomLeft), (.tileBottomRight, .bottomRight),
66
+ (.tileTop, .top), (.tileBottom, .bottom),
67
+ (.tileLeftThird, .leftThird), (.tileCenterThird, .centerThird),
68
+ (.tileRightThird, .rightThird),
69
+ ]
70
+ for (action, position) in tileMap {
71
+ store.register(action: action) {
72
+ WindowTiler.tileFrontmostViaAX(to: position)
73
+ }
74
+ }
75
+ store.register(action: .tileDistribute) {
76
+ WindowTiler.distributeVisible(reactivateLattices: false)
77
+ }
78
+ store.register(action: .tileTypeGrid) {
79
+ WindowTiler.distributeVisibleByFrontmostType(reactivateLattices: false)
80
+ }
81
+ store.register(action: .tileOrganize) {
82
+ let appName = DesktopModel.shared.frontmostWindow()?.app
83
+ ?? NSWorkspace.shared.frontmostApplication?.localizedName
84
+ CommandModeWindow.shared.show(launchMode: .organize(appName: appName))
85
+ }
86
+ }
87
+ }
@@ -55,7 +55,50 @@ enum LatticesRuntime {
55
55
  ?? "unknown"
56
56
  }
57
57
 
58
+ static var appDisplayVersion: String {
59
+ let base = appVersion == "unknown" ? "unknown" : "v\(appVersion)"
60
+ guard isDevBuild else { return base }
61
+
62
+ let track = buildTrack ?? "latest"
63
+ return "\(base)-dev.\(track)"
64
+ }
65
+
66
+ static var buildChannel: String {
67
+ let raw = Bundle.main.infoDictionary?["LatticesBuildChannel"] as? String
68
+ return raw?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() ?? "release"
69
+ }
70
+
71
+ static var buildTrack: String? {
72
+ normalizedInfoValue("LatticesBuildTrack")
73
+ }
74
+
75
+ static var buildRevision: String? {
76
+ normalizedInfoValue("LatticesBuildRevision")
77
+ }
78
+
79
+ static var buildTimestamp: String? {
80
+ normalizedInfoValue("LatticesBuildTimestamp")
81
+ }
82
+
83
+ static var isDevBuild: Bool {
84
+ buildChannel == "dev"
85
+ }
86
+
87
+ static var buildStatusLabel: String {
88
+ isDevBuild ? "Latest local dev build" : "Signed release build"
89
+ }
90
+
91
+ static var buildChannelLabel: String {
92
+ isDevBuild ? "DEV" : "RELEASE"
93
+ }
94
+
58
95
  private static func hasAppHelper(in root: String) -> Bool {
59
96
  FileManager.default.fileExists(atPath: root + "/bin/lattices-app.ts")
60
97
  }
98
+
99
+ private static func normalizedInfoValue(_ key: String) -> String? {
100
+ guard let raw = Bundle.main.infoDictionary?[key] as? String else { return nil }
101
+ let value = raw.trimmingCharacters(in: .whitespacesAndNewlines)
102
+ return value.isEmpty || value == "unknown" ? nil : value
103
+ }
61
104
  }