Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/skill-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Skill Review
on:
pull_request:
paths: ['**/SKILL.md']
jobs:
review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: tesslio/skill-review@22e928dd837202b2b1d1397e0114c92e0fae5ead # main
58 changes: 58 additions & 0 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,64 @@ enum ServiceError: LocalizedError, Sendable {
| Combine to async | `publisher.sinkSingleValue() async throws` |
| Custom defaults | `@DefaultValue<T>` property wrapper |

## Key Patterns

### Actor Definition

```swift
actor DataStore {
private var cache: [String: Data] = [:]

func fetch(_ key: String) async throws -> Data {
if let cached = cache[key] { return cached }
let data = try await URLSession.shared.data(from: endpoint(for: key)).0
cache[key] = data
return data
}
}
```

### @MainActor ViewModel

```swift
@MainActor
final class ItemListViewModel: ObservableObject {
@Published private(set) var items: [Item] = []
@Published private(set) var isLoading = false
private let store: DataStore

init(store: DataStore) { self.store = store }

func load() async {
isLoading = true
defer { isLoading = false }
items = (try? await store.fetchItems()) ?? []
}
}
```

### AsyncStream Usage

```swift
func progressUpdates() -> AsyncStream<Float> {
AsyncStream { continuation in
let observer = progress.observe(\.fractionCompleted) { p, _ in
continuation.yield(Float(p.fractionCompleted))
if p.isFinished { continuation.finish() }
}
continuation.onTermination = { _ in observer.invalidate() }
}
}
```

### Swift 6 Strict Concurrency Workflow

1. Enable in `Package.swift`: `swiftSettings: [.enableExperimentalFeature("StrictConcurrency")]`
2. Build β€” fix `Sendable` warnings: mark value types `Sendable`, use `@MainActor` for UI state
3. Isolate shared mutable state in `actor` types or `Mutex<T>`
4. Ensure closures crossing isolation boundaries are `@Sendable`
5. Verify: build with no warnings β†’ run tests β†’ check for runtime isolation violations in Console

## Detailed References

- **swift-concurrency.md** β€” Swift 6 concurrency patterns: actors, Sendable, AsyncSequence, task cancellation, synchronization, state machines, reactive patterns, generics, persistence, networking, testing, diagnostics
Expand Down