Commit 778cded
authored
refactor: migrate to Swift 6 language mode with strict concurrency (farouqaldori#47)
* refactor(build): migrate to Swift 6 language mode
Enable Swift 6 with strict concurrency checking:
- Update SWIFT_VERSION from 5.0 to 6 in Debug and Release configs
- Add SWIFT_STRICT_CONCURRENCY = complete
- Add @preconcurrency imports for Sparkle and Markdown libraries
- Add @mainactor to AppDelegate class for global state isolation
Build errors are expected and will be fixed in subsequent commits.
* fix(concurrency): replace NSLock with Mutex for thread-safe task tracking
Migrate from NSLock to Swift 6 Synchronization.Mutex for the activeTasks
dictionary in ClaudeSessionMonitor. Mutex provides better ergonomics with
withLock closures and aligns with modern Swift concurrency patterns.
* fix(concurrency): convert ProcessExecutor from actor to struct
ProcessExecutor has no mutable state to protect - all methods dispatch
work to background queues and return results via async continuations.
Converting to a Sendable struct eliminates unnecessary actor isolation
overhead and simplifies cross-context access in Swift 6.
* fix(concurrency): use MainActor.assumeIsolated for event handlers
NSEvent monitor handlers and NotificationCenter handlers run on the main
thread by documentation. Replace DispatchQueue.main.async with
MainActor.assumeIsolated for better performance and to avoid Sendable
warnings when passing NSEvent across isolation boundaries.
Also add nonisolated(unsafe) to ScreenObserver properties that are only
written during init (on MainActor) and read from deinit.
* fix(concurrency): fix MainActor isolation for timer callbacks and loggers
- Wrap Sparkle update check in Timer callback with Task { @mainactor }
to ensure SPUUpdater methods are called on MainActor
- Mark global Logger instances as nonisolated(unsafe) for cross-context
access from actors and nonisolated functions
* fix(concurrency): add nonisolated annotations for Sendable types
Add explicit nonisolated markers to methods, computed properties, and
static functions on Sendable value types. Swift 6 strict concurrency
requires these when accessed from non-isolated contexts:
- SessionPhase: init, isWaitingForApproval, matches(), allowedTransitions()
- SessionState: ToolTracker and SubagentState methods
- ToolResultData: MCPResult and GenericResult with nonisolated(unsafe) for
[String: Any] properties and nonisolated == operators
- ChatItemFactory: all static factory methods
- ToolResultParser: all static parsing methods
- TerminalAppRegistry: static properties and methods
- EventMonitor: stopInternal() for deinit access
* fix(deprecation): update deprecated API calls
- Replace NSRunningApplication.activate(options:) with activate() as the
options parameter is deprecated in macOS 14+
- Silence unused result warning for NSSound.play() with explicit discard
* fix(lint): remove redundant conditional casts in HookInstaller
Simplify array iteration by removing unnecessary conditional casts.
Since the arrays are already typed as [[String: Any]], re-casting
each element is redundant and triggers Swift 6 warnings.
* fix(concurrency): make file watcher classes @unchecked Sendable
AgentFileWatcher and JSONLInterruptWatcher use their own DispatchQueues
for serialization rather than MainActor. Mark them as @unchecked Sendable
with nonisolated methods and nonisolated(unsafe) properties to satisfy
Swift 6 strict concurrency checking.
- Add final class with @unchecked Sendable conformance
- Mark all methods as nonisolated
- Mark mutable properties as nonisolated(unsafe) (protected by queue)
- Add nonisolated(unsafe) to file-level logger (MainActor inference workaround)
* fix(concurrency): make HookSocketServer @unchecked Sendable with explicit Codable
HookSocketServer uses its own DispatchQueue and NSLock for thread safety.
Mark it as @unchecked Sendable with proper nonisolated annotations for
Swift 6 strict concurrency.
- Add final class with @unchecked Sendable conformance
- Mark all public and private methods as nonisolated
- Mark mutable properties as nonisolated(unsafe) (protected by queue/locks)
- Add explicit nonisolated Codable conformance for HookEvent and HookResponse
to avoid MainActor-isolated synthesized conformance
- Add nonisolated(unsafe) to file-level logger (MainActor inference workaround)
* fix(concurrency): replace nonisolated(unsafe) with nonisolated for Sendable constants
Move module-level loggers inside their types as `nonisolated static let`
per SE-0434. Sendable constants don't need the `unsafe` qualifier since
they're inherently thread-safe. This eliminates 7 compiler warnings.
* fix(concurrency): make ScreenObserver @unchecked Sendable
Add @unchecked Sendable conformance to ScreenObserver for consistency
with other classes using nonisolated(unsafe) properties (AgentFileWatcher,
JSONLInterruptWatcher). Thread safety is managed via main thread notification
delivery and debounced DispatchWorkItem execution.
* refactor(concurrency): migrate HookSocketServer from NSLock to Mutex
Replace legacy NSLock + nonisolated(unsafe) pattern with modern
Synchronization.Mutex for thread-safe state management.
- Add PermissionsState and CacheState structs for Mutex-protected state
- Replace permissionsLock/cacheLock NSLock with Mutex instances
- Convert all critical sections to use withLock closures
- Add TimeoutResult and PermissionLookupResult enums for clean
multi-guard early returns outside lock scope
- Convert markPermissionResponded to nonisolated static helper
* fix(concurrency): address race conditions and Swift 6 isolation
- Move acceptSource mutations into queue.sync in stop() to avoid data races
- Remove unnecessary MainActor hop in scheduleRetry() to prevent deadlock
- Use explicit MainActor isolation for delegate callbacks in file watchers1 parent 3cc15b7 commit 778cded
23 files changed
Lines changed: 530 additions & 408 deletions
File tree
- ClaudeIsland.xcodeproj
- ClaudeIsland
- App
- Events
- Models
- Services
- Hooks
- Session
- State
- Update
- Window
- UI
- Components
- Views
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
306 | 306 | | |
307 | 307 | | |
308 | 308 | | |
309 | | - | |
| 309 | + | |
| 310 | + | |
310 | 311 | | |
311 | 312 | | |
312 | 313 | | |
| |||
341 | 342 | | |
342 | 343 | | |
343 | 344 | | |
344 | | - | |
| 345 | + | |
| 346 | + | |
345 | 347 | | |
346 | 348 | | |
347 | 349 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| 11 | + | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
| |||
68 | 70 | | |
69 | 71 | | |
70 | 72 | | |
71 | | - | |
72 | | - | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
73 | 77 | | |
74 | 78 | | |
75 | 79 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
11 | 13 | | |
12 | 14 | | |
13 | 15 | | |
| |||
21 | 23 | | |
22 | 24 | | |
23 | 25 | | |
24 | | - | |
25 | | - | |
26 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
27 | 33 | | |
28 | 34 | | |
29 | 35 | | |
| |||
35 | 41 | | |
36 | 42 | | |
37 | 43 | | |
38 | | - | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
39 | 47 | | |
40 | 48 | | |
41 | 49 | | |
| |||
53 | 61 | | |
54 | 62 | | |
55 | 63 | | |
56 | | - | |
| 64 | + | |
57 | 65 | | |
58 | 66 | | |
59 | 67 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
62 | | - | |
| 62 | + | |
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
11 | 21 | | |
12 | 22 | | |
13 | 23 | | |
| |||
33 | 43 | | |
34 | 44 | | |
35 | 45 | | |
36 | | - | |
37 | | - | |
38 | | - | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
39 | 49 | | |
40 | | - | |
| 50 | + | |
41 | 51 | | |
42 | 52 | | |
43 | 53 | | |
44 | 54 | | |
45 | 55 | | |
46 | 56 | | |
47 | | - | |
48 | | - | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
49 | 60 | | |
50 | 61 | | |
51 | 62 | | |
52 | 63 | | |
53 | 64 | | |
54 | | - | |
| 65 | + | |
55 | 66 | | |
56 | 67 | | |
57 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| |||
150 | 150 | | |
151 | 151 | | |
152 | 152 | | |
153 | | - | |
| 153 | + | |
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
| |||
197 | 197 | | |
198 | 198 | | |
199 | 199 | | |
200 | | - | |
| 200 | + | |
201 | 201 | | |
202 | 202 | | |
203 | 203 | | |
| |||
213 | 213 | | |
214 | 214 | | |
215 | 215 | | |
216 | | - | |
| 216 | + | |
217 | 217 | | |
218 | 218 | | |
219 | 219 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
234 | 234 | | |
235 | 235 | | |
236 | 236 | | |
237 | | - | |
| 237 | + | |
238 | 238 | | |
239 | 239 | | |
240 | 240 | | |
241 | 241 | | |
242 | | - | |
| 242 | + | |
243 | 243 | | |
244 | 244 | | |
245 | 245 | | |
246 | 246 | | |
247 | | - | |
| 247 | + | |
248 | 248 | | |
249 | 249 | | |
250 | 250 | | |
| |||
255 | 255 | | |
256 | 256 | | |
257 | 257 | | |
258 | | - | |
| 258 | + | |
259 | 259 | | |
260 | 260 | | |
261 | 261 | | |
| |||
304 | 304 | | |
305 | 305 | | |
306 | 306 | | |
307 | | - | |
| 307 | + | |
308 | 308 | | |
309 | 309 | | |
310 | 310 | | |
311 | 311 | | |
312 | | - | |
| 312 | + | |
313 | 313 | | |
314 | 314 | | |
315 | 315 | | |
| |||
320 | 320 | | |
321 | 321 | | |
322 | 322 | | |
323 | | - | |
| 323 | + | |
324 | 324 | | |
325 | 325 | | |
326 | 326 | | |
327 | 327 | | |
328 | | - | |
| 328 | + | |
329 | 329 | | |
330 | 330 | | |
331 | 331 | | |
332 | 332 | | |
333 | 333 | | |
334 | 334 | | |
335 | 335 | | |
336 | | - | |
| 336 | + | |
337 | 337 | | |
338 | 338 | | |
339 | 339 | | |
340 | 340 | | |
341 | | - | |
| 341 | + | |
342 | 342 | | |
343 | 343 | | |
344 | 344 | | |
345 | 345 | | |
346 | | - | |
| 346 | + | |
347 | 347 | | |
348 | 348 | | |
349 | 349 | | |
| |||
354 | 354 | | |
355 | 355 | | |
356 | 356 | | |
357 | | - | |
| 357 | + | |
358 | 358 | | |
359 | 359 | | |
360 | 360 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
247 | 247 | | |
248 | 248 | | |
249 | 249 | | |
250 | | - | |
| 250 | + | |
| 251 | + | |
251 | 252 | | |
252 | | - | |
| 253 | + | |
253 | 254 | | |
254 | 255 | | |
255 | 256 | | |
| |||
260 | 261 | | |
261 | 262 | | |
262 | 263 | | |
263 | | - | |
| 264 | + | |
| 265 | + | |
264 | 266 | | |
265 | | - | |
| 267 | + | |
266 | 268 | | |
267 | 269 | | |
268 | 270 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
228 | 228 | | |
229 | 229 | | |
230 | 230 | | |
231 | | - | |
232 | | - | |
| 231 | + | |
| 232 | + | |
233 | 233 | | |
234 | | - | |
235 | | - | |
| 234 | + | |
| 235 | + | |
236 | 236 | | |
237 | 237 | | |
238 | 238 | | |
| |||
0 commit comments