@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.
Files changed (111) hide show
  1. package/README.md +85 -9
  2. package/app/Info.plist +30 -0
  3. package/app/Lattices.app/Contents/Info.plist +8 -2
  4. package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
  5. package/app/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
  6. package/app/Lattices.app/Contents/Resources/tap.wav +0 -0
  7. package/app/Lattices.app/Contents/_CodeSignature/CodeResources +139 -0
  8. package/app/Lattices.entitlements +15 -0
  9. package/app/Package.swift +8 -1
  10. package/app/Resources/tap.wav +0 -0
  11. package/app/Sources/AdvisorLearningStore.swift +90 -0
  12. package/app/Sources/AgentSession.swift +377 -0
  13. package/app/Sources/AppDelegate.swift +45 -12
  14. package/app/Sources/AppShellView.swift +81 -8
  15. package/app/Sources/AudioProvider.swift +386 -0
  16. package/app/Sources/CheatSheetHUD.swift +261 -19
  17. package/app/Sources/DaemonProtocol.swift +13 -0
  18. package/app/Sources/DaemonServer.swift +8 -0
  19. package/app/Sources/DesktopModel.swift +189 -6
  20. package/app/Sources/DesktopModelTypes.swift +2 -0
  21. package/app/Sources/DiagnosticLog.swift +104 -2
  22. package/app/Sources/EventBus.swift +1 -0
  23. package/app/Sources/HUDBottomBar.swift +279 -0
  24. package/app/Sources/HUDController.swift +1158 -0
  25. package/app/Sources/HUDLeftBar.swift +849 -0
  26. package/app/Sources/HUDMinimap.swift +179 -0
  27. package/app/Sources/HUDRightBar.swift +774 -0
  28. package/app/Sources/HUDState.swift +367 -0
  29. package/app/Sources/HUDTopBar.swift +243 -0
  30. package/app/Sources/HandsOffSession.swift +802 -0
  31. package/app/Sources/HomeDashboardView.swift +125 -0
  32. package/app/Sources/HotkeyManager.swift +2 -0
  33. package/app/Sources/HotkeyStore.swift +49 -9
  34. package/app/Sources/IntentEngine.swift +962 -0
  35. package/app/Sources/Intents/CreateLayerIntent.swift +54 -0
  36. package/app/Sources/Intents/DistributeIntent.swift +56 -0
  37. package/app/Sources/Intents/FocusIntent.swift +69 -0
  38. package/app/Sources/Intents/HelpIntent.swift +41 -0
  39. package/app/Sources/Intents/KillIntent.swift +47 -0
  40. package/app/Sources/Intents/LatticeIntent.swift +78 -0
  41. package/app/Sources/Intents/LaunchIntent.swift +67 -0
  42. package/app/Sources/Intents/ListSessionsIntent.swift +32 -0
  43. package/app/Sources/Intents/ListWindowsIntent.swift +30 -0
  44. package/app/Sources/Intents/ScanIntent.swift +52 -0
  45. package/app/Sources/Intents/SearchIntent.swift +190 -0
  46. package/app/Sources/Intents/SwitchLayerIntent.swift +50 -0
  47. package/app/Sources/Intents/TileIntent.swift +61 -0
  48. package/app/Sources/LatticesApi.swift +1275 -30
  49. package/app/Sources/LauncherHUD.swift +348 -0
  50. package/app/Sources/MainView.swift +147 -44
  51. package/app/Sources/MouseFinder.swift +222 -0
  52. package/app/Sources/OcrModel.swift +34 -1
  53. package/app/Sources/OmniSearchState.swift +99 -102
  54. package/app/Sources/OnboardingView.swift +457 -0
  55. package/app/Sources/PermissionChecker.swift +2 -12
  56. package/app/Sources/PiChatDock.swift +454 -0
  57. package/app/Sources/PiChatSession.swift +815 -0
  58. package/app/Sources/PiWorkspaceView.swift +364 -0
  59. package/app/Sources/PlacementSpec.swift +195 -0
  60. package/app/Sources/Preferences.swift +59 -0
  61. package/app/Sources/ProjectScanner.swift +58 -45
  62. package/app/Sources/ScreenMapState.swift +701 -55
  63. package/app/Sources/ScreenMapView.swift +843 -103
  64. package/app/Sources/ScreenMapWindowController.swift +22 -0
  65. package/app/Sources/SessionLayerStore.swift +285 -0
  66. package/app/Sources/SessionManager.swift +4 -1
  67. package/app/Sources/SettingsView.swift +186 -3
  68. package/app/Sources/Theme.swift +9 -8
  69. package/app/Sources/TmuxModel.swift +7 -0
  70. package/app/Sources/TmuxQuery.swift +27 -3
  71. package/app/Sources/VoiceChatView.swift +192 -0
  72. package/app/Sources/VoiceCommandWindow.swift +1594 -0
  73. package/app/Sources/VoiceIntentResolver.swift +671 -0
  74. package/app/Sources/VoxClient.swift +454 -0
  75. package/app/Sources/WindowTiler.swift +348 -87
  76. package/app/Sources/WorkspaceManager.swift +127 -18
  77. package/app/Tests/StageDragTests.swift +333 -0
  78. package/app/Tests/StageJoinTests.swift +313 -0
  79. package/app/Tests/StageManagerTests.swift +280 -0
  80. package/app/Tests/StageTileTests.swift +353 -0
  81. package/assets/AppIcon.icns +0 -0
  82. package/bin/client.ts +16 -0
  83. package/bin/{daemon-client.js → daemon-client.ts} +49 -30
  84. package/bin/handsoff-infer.ts +280 -0
  85. package/bin/handsoff-worker.ts +740 -0
  86. package/bin/lattices-app.ts +338 -0
  87. package/bin/lattices-dev +208 -0
  88. package/bin/{lattices.js → lattices.ts} +777 -140
  89. package/bin/project-twin.ts +645 -0
  90. package/docs/agent-execution-plan.md +562 -0
  91. package/docs/agent-layer-guide.md +207 -0
  92. package/docs/agents.md +142 -0
  93. package/docs/api.md +153 -34
  94. package/docs/app.md +29 -1
  95. package/docs/config.md +5 -1
  96. package/docs/handsoff-test-scenarios.md +84 -0
  97. package/docs/layers.md +20 -20
  98. package/docs/ocr.md +14 -5
  99. package/docs/overview.md +5 -1
  100. package/docs/presentation-execution-review.md +491 -0
  101. package/docs/prompts/hands-off-system.md +374 -0
  102. package/docs/prompts/hands-off-turn.md +30 -0
  103. package/docs/prompts/voice-advisor.md +31 -0
  104. package/docs/prompts/voice-fallback.md +23 -0
  105. package/docs/tiling-reference.md +167 -0
  106. package/docs/twins.md +138 -0
  107. package/docs/voice-command-protocol.md +278 -0
  108. package/docs/voice.md +219 -0
  109. package/package.json +29 -11
  110. package/bin/client.js +0 -4
  111. package/bin/lattices-app.js +0 -221
@@ -15,53 +15,66 @@ class ProjectScanner: ObservableObject {
15
15
  self.scanRoot = root
16
16
  }
17
17
 
18
+ private static let scanQueue = DispatchQueue(label: "com.lattices.project-scanner", qos: .userInitiated)
19
+ private var scanInFlight = false
20
+
18
21
  func scan() {
19
- let diag = DiagnosticLog.shared
22
+ guard !scanInFlight else { return }
23
+ scanInFlight = true
24
+ let root = scanRoot
25
+
26
+ Self.scanQueue.async { [weak self] in
27
+ guard let self else { return }
28
+ let diag = DiagnosticLog.shared
29
+
30
+ // Use find to locate all .lattices.json files — no manual directory walking
31
+ let tFind = diag.startTimed("ProjectScanner: find .lattices.json")
32
+ let task = Process()
33
+ task.executableURL = URL(fileURLWithPath: "/usr/bin/find")
34
+ task.arguments = [root, "-name", ".lattices.json", "-maxdepth", "3", "-not", "-path", "*/.git/*", "-not", "-path", "*/node_modules/*"]
35
+ let pipe = Pipe()
36
+ task.standardOutput = pipe
37
+ task.standardError = FileHandle.nullDevice
38
+ try? task.run()
39
+ task.waitUntilExit()
40
+ diag.finish(tFind)
41
+
42
+ let data = pipe.fileHandleForReading.readDataToEndOfFile()
43
+ let output = String(data: data, encoding: .utf8) ?? ""
44
+ let configPaths = output.split(separator: "\n").map(String.init).filter { !$0.isEmpty }
45
+
46
+ let tParse = diag.startTimed("ProjectScanner: parse \(configPaths.count) configs")
47
+ var found: [Project] = []
48
+
49
+ for configPath in configPaths.sorted() {
50
+ let projectPath = (configPath as NSString).deletingLastPathComponent
51
+ let name = (projectPath as NSString).lastPathComponent
52
+ let (devCmd, pm) = self.detectDevCommand(at: projectPath)
53
+ let paneInfo = self.readPaneInfo(at: configPath)
54
+
55
+ var project = Project(
56
+ id: projectPath,
57
+ path: projectPath,
58
+ name: name,
59
+ devCommand: devCmd,
60
+ packageManager: pm,
61
+ hasConfig: true,
62
+ paneCount: paneInfo.count,
63
+ paneNames: paneInfo.names,
64
+ paneSummary: paneInfo.summary,
65
+ isRunning: false
66
+ )
67
+ project.isRunning = self.isSessionRunning(project.sessionName)
68
+ found.append(project)
69
+ }
70
+ diag.finish(tParse)
20
71
 
21
- // Use find to locate all .lattices.json files — no manual directory walking
22
- let tFind = diag.startTimed("ProjectScanner: find .lattices.json")
23
- let task = Process()
24
- task.executableURL = URL(fileURLWithPath: "/usr/bin/find")
25
- task.arguments = [scanRoot, "-name", ".lattices.json", "-maxdepth", "3", "-not", "-path", "*/.git/*", "-not", "-path", "*/node_modules/*"]
26
- let pipe = Pipe()
27
- task.standardOutput = pipe
28
- task.standardError = FileHandle.nullDevice
29
- try? task.run()
30
- task.waitUntilExit()
31
- diag.finish(tFind)
32
-
33
- let data = pipe.fileHandleForReading.readDataToEndOfFile()
34
- let output = String(data: data, encoding: .utf8) ?? ""
35
- let configPaths = output.split(separator: "\n").map(String.init).filter { !$0.isEmpty }
36
-
37
- let tParse = diag.startTimed("ProjectScanner: parse \(configPaths.count) configs")
38
- var found: [Project] = []
39
-
40
- for configPath in configPaths.sorted() {
41
- let projectPath = (configPath as NSString).deletingLastPathComponent
42
- let name = (projectPath as NSString).lastPathComponent
43
- let (devCmd, pm) = detectDevCommand(at: projectPath)
44
- let paneInfo = readPaneInfo(at: configPath)
45
-
46
- var project = Project(
47
- id: projectPath,
48
- path: projectPath,
49
- name: name,
50
- devCommand: devCmd,
51
- packageManager: pm,
52
- hasConfig: true,
53
- paneCount: paneInfo.count,
54
- paneNames: paneInfo.names,
55
- paneSummary: paneInfo.summary,
56
- isRunning: false
57
- )
58
- project.isRunning = isSessionRunning(project.sessionName)
59
- found.append(project)
72
+ diag.info("ProjectScanner: found \(found.count) projects (\(found.filter(\.isRunning).count) running)")
73
+ DispatchQueue.main.async {
74
+ self.projects = found
75
+ self.scanInFlight = false
76
+ }
60
77
  }
61
- diag.finish(tParse)
62
-
63
- diag.info("ProjectScanner: found \(found.count) projects (\(found.filter(\.isRunning).count) running)")
64
- DispatchQueue.main.async { self.projects = found }
65
78
  }
66
79
 
67
80
  func refreshStatus() {
@@ -113,7 +126,7 @@ class ProjectScanner: ObservableObject {
113
126
  return (panes.count, labels, labels.joined(separator: " · "))
114
127
  }
115
128
 
116
- private static let tmuxPath = "/opt/homebrew/bin/tmux"
129
+ private static var tmuxPath: String { TmuxQuery.resolvedPath ?? "/opt/homebrew/bin/tmux" }
117
130
 
118
131
  private func isSessionRunning(_ name: String) -> Bool {
119
132
  let task = Process()