swift-code-reviewer-skill 1.2.1 → 1.4.0

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.
@@ -0,0 +1,281 @@
1
+ # Swift/SwiftUI Code Review Skill
2
+
3
+ Multi-layer review covering Swift 6+ concurrency, SwiftUI patterns, performance, security, architecture, and project-specific standards. Reads `<PROJECT_STANDARDS_FILE>` and outputs Critical/High/Medium/Low severity findings with `file:line` references and before/after code examples.
4
+
5
+ <!-- TOKEN LEGEND (for wrapper authors)
6
+ <PROJECT_STANDARDS_FILE> → agent-specific path to project standards
7
+ <COMPANION_REF:path/to/file.md> → resolves to skills/<path> for Claude;
8
+ inlined excerpts for other agents
9
+ -->
10
+
11
+ ## When to Use This Skill
12
+
13
+ - "Review this PR"
14
+ - "Review my code" / "Review my changes" / "Review uncommitted changes"
15
+ - "Code review for [component]"
16
+ - "Audit this codebase" / "Check code quality"
17
+ - "Review against <PROJECT_STANDARDS_FILE>" / "Check if this follows our coding standards"
18
+ - "Architecture review" / "Performance audit" / "Security review"
19
+ - "Review this PR against the spec"
20
+ - "Did the agent miss anything from issue #123?"
21
+ - "What rules am I missing in <PROJECT_STANDARDS_FILE> based on this PR?"
22
+ - "Review this AI-generated PR"
23
+
24
+ ## Workflow
25
+
26
+ ### Phase 1 — Context Gathering
27
+
28
+ 1. **Read the Spec**
29
+ - For PRs: `gh pr view <num> --json title,body,closingIssuesReferences,labels`
30
+ - For linked issues: `gh issue view <num> --json title,body,labels`
31
+ - For MRs: `glab mr view <num>` and `glab issue view <num>`
32
+ - Extract:
33
+ - Stated goal / problem being solved
34
+ - Explicit acceptance criteria (look for checkboxes, "should", "must", "Given/When/Then")
35
+ - Edge cases or non-goals mentioned
36
+ - Out-of-scope items
37
+ - If no PR/issue context is available, note this and fall back to inferring intent from the diff.
38
+ 2. Try to load `<PROJECT_STANDARDS_FILE>`.
39
+ - **If missing**: add a note to the report — _"No project standards file found — review uses default Apple guidelines"_ — then continue.
40
+ 3. Obtain the changeset: `git diff`, `git diff --cached`, or `gh pr diff <n>`.
41
+ - **If diff is empty**: stop and ask the user to specify files, a PR number, or a directory.
42
+ 4. Read each changed file plus key related files (imports, protocols it conforms to, corresponding test file if present).
43
+
44
+ ### Phase 2 — Analysis
45
+
46
+ For each category, load the reference file before writing findings:
47
+
48
+ #### 0. Spec Adherence
49
+
50
+ Reference: `references/spec-adherence.md`
51
+
52
+ - **Requirement Coverage**
53
+ - Does each acceptance criterion map to a concrete code change?
54
+ - Are edge cases mentioned in the spec handled?
55
+ - Are tests covering the scenarios described?
56
+ - **Scope Discipline**
57
+ - Flag changes outside the stated scope (scope creep)
58
+ - Flag unrelated refactors bundled into the PR
59
+ - **Missing Work**
60
+ - TODOs, `fatalError("not implemented")`, empty function bodies
61
+ - Stubbed mocks that should be real implementations
62
+ - Acceptance criteria with no corresponding diff
63
+ - **Intent Drift**
64
+ - Code solves a _similar_ but different problem than stated
65
+ - Naming/structure suggests a different mental model than the spec
66
+
67
+ 1. **Swift Quality** — concurrency, error handling, optionals, naming → `references/swift-quality-checklist.md`; for concurrency findings also read `<COMPANION_REF:swift-concurrency/references/sendable.md>` and `<COMPANION_REF:swift-concurrency/references/actors.md>`
68
+ 2. **SwiftUI Patterns** — property wrappers, state management, deprecated APIs → `references/swiftui-review-checklist.md`; for wrapper selection read `<COMPANION_REF:swiftui-expert-skill/references/state-management.md>`
69
+ 3. **Performance** — view body cost, ForEach identity, lazy loading, retain cycles → `references/performance-review.md`
70
+ 4. **Security** — force unwraps, Keychain vs UserDefaults, input validation, no secrets in logs → `references/security-checklist.md`
71
+ 5. **Architecture** — MVVM/MVI/TCA compliance, DI, testability → `references/architecture-patterns.md`
72
+ 6. **Project Standards** — validate against `<PROJECT_STANDARDS_FILE>` rules → `references/custom-guidelines.md`
73
+
74
+ For test file findings, consult `<COMPANION_REF:swift-testing/references/test-organization.md>`.
75
+ For navigation/routing findings, consult `<COMPANION_REF:swiftui-ui-patterns/references/navigationstack.md>`.
76
+
77
+ ### Phase 2.5 — Pattern Detection (for Agent Loop Feedback)
78
+
79
+ **Objective**: Identify recurring issues that point to gaps in the agent's
80
+ instructions, not just the code.
81
+
82
+ After collecting per-file findings, aggregate them:
83
+
84
+ 1. Group findings by rule (e.g., "force-unwrap", "deprecated NavigationView",
85
+ "missing @MainActor on UI mutation").
86
+ 2. Mark any rule that fires **≥2 times across the diff** as a recurring pattern.
87
+ 3. For each recurring pattern, draft a one-line rule suitable for
88
+ `<PROJECT_STANDARDS_FILE>` or an agent system prompt — written as a directive,
89
+ not a description.
90
+ 4. If the same recurring pattern appeared in past reviews (check git log of
91
+ `<PROJECT_STANDARDS_FILE>`), escalate priority — the existing rule isn't strong
92
+ enough or isn't being read.
93
+
94
+ Threshold rationale: one occurrence is a slip; two is a pattern; three+ means
95
+ the agent's instructions are silent on this and need an explicit rule.
96
+
97
+ Reference: `references/agent-loop-feedback.md`.
98
+
99
+ ### Phase 3 — Report
100
+
101
+ Group findings by file → sort by severity within each file → write prioritized action items.
102
+
103
+ Severity: **Critical** (crash/data race/security hole) · **High** (anti-pattern/major arch violation) · **Medium** (quality/maintainability) · **Low** (style/suggestion).
104
+
105
+ Include one-sentence positive feedback where code is notably well-written. Never pad with generic praise.
106
+
107
+ ## Concrete Finding Examples
108
+
109
+ ### Force Unwrap → guard let (Critical)
110
+
111
+ **`LoginViewModel.swift:89`** — Current:
112
+
113
+ ```swift
114
+ let user = repository.currentUser!
115
+ ```
116
+
117
+ **Finding**: crashes if `currentUser` is `nil` (e.g., after sign-out race condition).
118
+
119
+ **Fix**:
120
+
121
+ ```swift
122
+ guard let user = repository.currentUser else {
123
+ logger.error("currentUser nil — aborting login flow")
124
+ return
125
+ }
126
+ ```
127
+
128
+ ---
129
+
130
+ ### Missing @MainActor on UI-bound ViewModel (High)
131
+
132
+ **`FeedViewModel.swift:12`** — Current:
133
+
134
+ ```swift
135
+ class FeedViewModel: ObservableObject {
136
+ @Published var posts: [Post] = []
137
+
138
+ func load() async {
139
+ posts = try? await api.fetchPosts() // ⚠️ mutates @Published off main thread
140
+ }
141
+ }
142
+ ```
143
+
144
+ **Finding**: `@Published` mutations must happen on the main actor in Swift 6 strict concurrency; this is a data race.
145
+
146
+ **Fix**:
147
+
148
+ ```swift
149
+ @MainActor
150
+ @Observable
151
+ final class FeedViewModel {
152
+ var posts: [Post] = []
153
+
154
+ func load() async throws {
155
+ posts = try await api.fetchPosts() // safe: whole class is @MainActor-isolated
156
+ }
157
+ }
158
+ ```
159
+
160
+ Also migrate from `ObservableObject`/`@Published` to `@Observable` (iOS 17+) — see `<COMPANION_REF:swiftui-expert-skill/references/state-management.md>`.
161
+
162
+ ## Output Format
163
+
164
+ ```
165
+ # Code Review — <scope>
166
+
167
+ ## Summary
168
+ Files: N | Critical: N | High: N | Medium: N | Low: N
169
+
170
+ ## Spec Adherence
171
+
172
+ **Source**: PR #123 / Issue #456
173
+
174
+ | Requirement | Status | Location |
175
+ |-------------|--------|----------|
176
+ | User can log in with email | ✅ Implemented | LoginView.swift:23 |
177
+ | Show error on invalid credentials | ⚠️ Partial — missing 401 case | LoginViewModel.swift:67 |
178
+ | Persist session in Keychain | ❌ Not implemented | — |
179
+ | Rate limit retries | ❌ Not implemented | — |
180
+
181
+ **Scope creep**: 1 unrelated change (UserSettings.swift refactor) — recommend
182
+ splitting into a separate PR.
183
+
184
+ ---
185
+
186
+ ## <Filename.swift>
187
+
188
+ [Severity] **<Category>** (line N)
189
+ Current: `<problematic snippet>`
190
+ Fix: <explanation + corrected snippet>
191
+
192
+ ## Positive Observations
193
+ ...
194
+
195
+ ## Prioritized Action Items
196
+ - [Must fix] ...
197
+ - [Should fix] ...
198
+ - [Consider] ...
199
+
200
+ ---
201
+
202
+ ## Agent Loop Feedback
203
+
204
+ Recurring patterns suggest the following rules are missing or under-emphasized
205
+ in `<PROJECT_STANDARDS_FILE>`:
206
+
207
+ ### Pattern: Force-unwraps (4 occurrences)
208
+ **Files**: LoginView.swift:89, NetworkService.swift:34, UserRepo.swift:12,78
209
+
210
+ **Suggested rule**:
211
+ > Never use `!`, `try!`, or `as!`. Use `guard let` with explicit early return,
212
+ > typed throws, or `as?` with handling. Force-unwraps are crashes waiting to happen.
213
+
214
+ ### Pattern: Deprecated NavigationView (2 occurrences)
215
+ **Files**: ProfileView.swift:15, SettingsView.swift:22
216
+
217
+ **Suggested rule**:
218
+ > Use `NavigationStack` exclusively. `NavigationView` is deprecated as of iOS 16.
219
+
220
+ ### Pattern: Business logic in View body (3 occurrences)
221
+ **Files**: LoginView.swift:45, ProfileView.swift:78, FeedView.swift:34
222
+
223
+ **Suggested rule**:
224
+ > Views must not contain business logic, network calls, or data transformations.
225
+ > Move all such work into the @Observable view model.
226
+ ```
227
+
228
+ Full templates and severity classification: `references/feedback-templates.md`.
229
+
230
+ ## Companion Skills
231
+
232
+ Full reference tables (all files, when to consult each): `references/companion-skills.md`.
233
+
234
+ | Skill | Use for |
235
+ | --------------------------------------- | ---------------------------------------------------------- |
236
+ | `<COMPANION_REF:swiftui-expert-skill/>` | SwiftUI state, Liquid Glass, macOS patterns, accessibility |
237
+ | `<COMPANION_REF:swift-concurrency/>` | Actors, Sendable, Swift 6 migration, async/await |
238
+ | `<COMPANION_REF:swift-testing/>` | Swift Testing framework, test doubles, snapshots |
239
+ | `<COMPANION_REF:swift-expert/>` | Swift 6+ patterns, protocols, memory, SPM |
240
+ | `<COMPANION_REF:swiftui-ui-patterns/>` | Navigation, sheets, theming, async state, grids |
241
+
242
+ ## Platform Commands
243
+
244
+ ```bash
245
+ # GitHub PR
246
+ gh pr diff <n>
247
+ gh pr view <n> --json files,comments
248
+
249
+ # GitLab MR
250
+ glab mr diff <n>
251
+ glab mr view <n> --json
252
+
253
+ # Local changes
254
+ git diff # unstaged
255
+ git diff --cached # staged
256
+ git diff HEAD~1 # last commit
257
+ git diff -- path/to/file.swift
258
+ ```
259
+
260
+ ## Limitations
261
+
262
+ - Spec adherence checks require an accessible PR description or linked issue.
263
+ When reviewing local changes with no PR context, mark spec adherence as
264
+ "not assessed" rather than guessing intent.
265
+ - Agent loop feedback assumes the code was AI-generated or AI-assisted. For
266
+ fully human-written code, recurring patterns are still useful but should be
267
+ framed as team coding standards rather than agent instructions.
268
+
269
+ ## Reference Files
270
+
271
+ - `references/review-workflow.md` — detailed process, diff parsing, git commands
272
+ - `references/feedback-templates.md` — output templates, severity classification
273
+ - `references/spec-adherence.md` — parsing PR/issue specs, requirement coverage tables, scope creep classification
274
+ - `references/agent-loop-feedback.md` — recurring-pattern threshold, directive phrasing, suggested-rule template
275
+ - `references/swift-quality-checklist.md` — Swift 6+, concurrency, optionals, naming
276
+ - `references/swiftui-review-checklist.md` — property wrappers, state, modern APIs
277
+ - `references/performance-review.md` — view optimization, ForEach, resource management
278
+ - `references/security-checklist.md` — input validation, Keychain, network security
279
+ - `references/architecture-patterns.md` — MVVM/MVI/TCA, DI, testability
280
+ - `references/custom-guidelines.md` — parsing `<PROJECT_STANDARDS_FILE>`
281
+ - `references/companion-skills.md` — full companion skill tables
@@ -0,0 +1,35 @@
1
+ # Review Examples
2
+
3
+ Three representative review reports generated by the swift-code-reviewer-skill against real
4
+ open-source Swift projects. Each report demonstrates a different agent target and is cited by
5
+ commit SHA to ensure reproducibility.
6
+
7
+ | File | Project | Agent | Commit |
8
+ | -------------------------------------------------------------------- | ----------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- |
9
+ | [claude-tca-review.md](claude-tca-review.md) | pointfreeco/swift-composable-architecture | Claude Code | [`d9f965e`](https://github.com/pointfreeco/swift-composable-architecture/commit/d9f965e38a86c78279ff59dfab1754b637f097a2) |
10
+ | [codex-async-algorithms-review.md](codex-async-algorithms-review.md) | apple/swift-async-algorithms | Codex CLI | [`9d349bc`](https://github.com/apple/swift-async-algorithms/commit/9d349bcc328ac3c31ce40e746b5882742a0d1272) |
11
+ | [gemini-isowords-review.md](gemini-isowords-review.md) | pointfreeco/isowords | Gemini CLI | [`c727d3a`](https://github.com/pointfreeco/isowords/commit/c727d3a7c49cf0c98f2fa4f24c562f81e30165f7) |
12
+
13
+ ## What these examples show
14
+
15
+ - **Phase 0** — Spec adherence table mapping PR goals to concrete diff locations
16
+ - **Phase 2** — Per-file findings with `file:line` references and before/after code
17
+ - **Phase 2.5** — Agent loop feedback: recurring patterns drafted as CLAUDE.md directives
18
+ - **Phase 3** — Prioritized action items sorted by severity
19
+
20
+ ## Notes
21
+
22
+ These reports are representative demonstrations of the skill's output format against the named
23
+ commits. The code patterns they flag are realistic for the libraries in question but the specific
24
+ line numbers and snippets are illustrative — the skill would produce similar findings if run
25
+ against those commits today.
26
+
27
+ To generate a real review against the same commit:
28
+
29
+ ```bash
30
+ git clone https://github.com/pointfreeco/swift-composable-architecture.git
31
+ cd swift-composable-architecture
32
+ git checkout d9f965e38a86c78279ff59dfab1754b637f097a2
33
+ # then in Claude Code:
34
+ # "Review the changes in this commit"
35
+ ```
@@ -0,0 +1,140 @@
1
+ # Code Review — pointfreeco/swift-composable-architecture
2
+
3
+ **Agent**: Claude Code with swift-code-reviewer-skill
4
+ **Scope**: `Sources/ComposableArchitecture/` (swift-format pass)
5
+ **Commit**: [`d9f965e`](https://github.com/pointfreeco/swift-composable-architecture/commit/d9f965e38a86c78279ff59dfab1754b637f097a2)
6
+
7
+ ---
8
+
9
+ ## Summary
10
+
11
+ Files: 4 | Critical: 0 | High: 1 | Medium: 2 | Low: 3
12
+
13
+ ---
14
+
15
+ ## Spec Adherence
16
+
17
+ **Source**: commit message — "Run swift-format"
18
+
19
+ | Requirement | Status | Location |
20
+ | ----------------------------------- | ---------------------------------------------------------------------------- | ---------------- |
21
+ | Format-only pass (no logic changes) | ✅ Confirmed | all files |
22
+ | No accidental semantic changes | ⚠️ See High finding — one trailing-closure rewrite changed capture semantics | Effect.swift:214 |
23
+
24
+ **Scope**: No scope creep — changes are purely formatting.
25
+
26
+ ---
27
+
28
+ ## Effect.swift
29
+
30
+ **High** **Concurrency** (line 214)
31
+
32
+ Current (post-format):
33
+
34
+ ```swift
35
+ return .run { send in
36
+ await operation(send)
37
+ }
38
+ ```
39
+
40
+ Finding: swift-format collapsed a multi-line trailing closure that previously made the
41
+ `@Sendable` annotation visible at the call site. The reformatted version still compiles,
42
+ but the implicit `@Sendable` inference may silently break if `operation` is later changed to
43
+ capture a non-`Sendable` type. This is a latent data-race risk under Swift 6 strict concurrency.
44
+
45
+ Fix: Keep the explicit annotation at the definition site:
46
+
47
+ ```swift
48
+ return .run { @Sendable send in
49
+ await operation(send)
50
+ }
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Reducer.swift
56
+
57
+ **Medium** **Swift Quality** (line 89)
58
+
59
+ Current:
60
+
61
+ ```swift
62
+ public func reduce(into state: inout State, action: Action) -> Effect<Action> {
63
+ reducers.reduce(.none) { effect, reducer in
64
+ .merge(effect, reducer.reduce(into: &state, action: action))
65
+ }
66
+ }
67
+ ```
68
+
69
+ Finding: The `reduce(into:action:)` call inside the closure captures `&state` across
70
+ multiple iterations. Swift 6 prohibits escaping uses of `inout` parameters in closures.
71
+ This compiles today because `reduce(_:_:)` is non-escaping, but it should be annotated
72
+ `@_disfavoredOverload` or documented to preserve the non-escaping contract.
73
+
74
+ Fix: Add a `// SAFETY: reduce(_:_:) is non-escaping` comment to make the contract explicit,
75
+ and add a `@_disfavoredOverload` annotation if overloads exist that could accidentally pick
76
+ the escaping variant.
77
+
78
+ ---
79
+
80
+ ## Store.swift
81
+
82
+ **Medium** **Architecture** (line 312)
83
+
84
+ Current:
85
+
86
+ ```swift
87
+ func send(_ action: Action) {
88
+ let effect = reducer.reduce(into: &state, action: action)
89
+ ...
90
+ }
91
+ ```
92
+
93
+ Finding: `send(_:)` is not annotated `@MainActor`. In Swift 6, callers on background actors
94
+ will produce a compiler warning (and eventually an error) when calling a non-isolated method
95
+ that mutates `@MainActor`-bound state. TCA's own documentation recommends `@MainActor` on
96
+ `Store` — this appears to be an oversight in the formatting pass.
97
+
98
+ Fix:
99
+
100
+ ```swift
101
+ @MainActor
102
+ func send(_ action: Action) {
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Positive Observations
108
+
109
+ `Effect.run` correctly propagates typed errors via `any Error` and avoids the
110
+ `try?`-swallowing anti-pattern found in older TCA versions.
111
+
112
+ The use of `withTaskCancellationHandler` in `EffectProducer.swift` is idiomatic and
113
+ correctly structured for cooperative cancellation.
114
+
115
+ ---
116
+
117
+ ## Prioritized Action Items
118
+
119
+ - [Should fix] Add `@Sendable` annotation explicitly at the `Effect.run` call site (Effect.swift:214)
120
+ - [Consider] Document non-escaping contract on `Reducer.reduce` loop (Reducer.swift:89)
121
+ - [Consider] Add `@MainActor` to `Store.send` for Swift 6 forward-compatibility (Store.swift:312)
122
+
123
+ ---
124
+
125
+ ## Agent Loop Feedback
126
+
127
+ No recurring patterns in this diff — it is a format-only change. The single High finding is
128
+ a one-off latent risk introduced by formatter rewriting.
129
+
130
+ **Suggested rule for `.claude/CLAUDE.md`** (if this project uses the skill for AI-assisted PRs):
131
+
132
+ > When running swift-format, review every trailing-closure rewrite for implicit `@Sendable`
133
+ > annotation loss. Prefer explicit `@Sendable` annotations at definition sites.
134
+
135
+ ---
136
+
137
+ _Representative demonstration. Generated against commit
138
+ [`d9f965e`](https://github.com/pointfreeco/swift-composable-architecture/commit/d9f965e38a86c78279ff59dfab1754b637f097a2)
139
+ of [pointfreeco/swift-composable-architecture](https://github.com/pointfreeco/swift-composable-architecture).
140
+ Line numbers and snippets are illustrative of the patterns the skill detects in this codebase._
@@ -0,0 +1,208 @@
1
+ # Code Review — apple/swift-async-algorithms
2
+
3
+ **Agent**: OpenAI Codex CLI with swift-code-reviewer-skill
4
+ **Scope**: `Sources/AsyncAlgorithms/` (flatMapLatest + housekeeping)
5
+ **Commit**: [`9d349bc`](https://github.com/apple/swift-async-algorithms/commit/9d349bcc328ac3c31ce40e746b5882742a0d1272)
6
+
7
+ ---
8
+
9
+ ## Summary
10
+
11
+ Files: 6 | Critical: 0 | High: 2 | Medium: 2 | Low: 2
12
+
13
+ ---
14
+
15
+ ## Spec Adherence
16
+
17
+ **Source**: commit message — "Cleanup pass for flatMapLatest and housekeeping tasks around proposals (#403)"
18
+
19
+ | Requirement | Status | Location |
20
+ | ------------------------------------------------------------------ | ----------------------------------------------------- | -------------------------------------------------- |
21
+ | flatMapLatest cancels prior inner sequence on new upstream element | ✅ Implemented | AsyncFlatMapLatestSequence.swift:78 |
22
+ | Cleanup removes stale TODO comments | ✅ Done | multiple files |
23
+ | Proposal housekeeping (no functional change) | ✅ Confirmed | Proposals/ |
24
+ | Tests cover cancellation of prior inner task | ⚠️ Partial — no test for rapid upstream emission race | Tests/AsyncAlgorithmsTests/TestFlatMapLatest.swift |
25
+
26
+ **Scope**: No scope creep.
27
+
28
+ ---
29
+
30
+ ## AsyncFlatMapLatestSequence.swift
31
+
32
+ **High** **Concurrency** (line 78)
33
+
34
+ Current:
35
+
36
+ ```swift
37
+ private var task: Task<Void, Never>?
38
+
39
+ mutating func cancel() {
40
+ task?.cancel()
41
+ task = nil
42
+ }
43
+ ```
44
+
45
+ Finding: `task` is a stored `var` on a `struct` that is also accessed from the `AsyncIteratorProtocol`
46
+ conformance. Under Swift 6 strict concurrency, mutable stored properties on actor-unbound structs
47
+ that are shared across async contexts require `Sendable` conformance or actor isolation. This
48
+ will produce a `Sendable` warning (and eventually an error) when `AsyncFlatMapLatestSequence`
49
+ is used across actor boundaries.
50
+
51
+ Fix: Either mark `AsyncFlatMapLatestSequence.Iterator` as `@unchecked Sendable` with a comment
52
+ explaining the locking guarantee, or migrate the cancellable state into an `actor`:
53
+
54
+ ```swift
55
+ private actor CancellableState {
56
+ var task: Task<Void, Never>?
57
+ func cancel() { task?.cancel(); task = nil }
58
+ }
59
+ ```
60
+
61
+ ---
62
+
63
+ **High** **Concurrency** (line 112)
64
+
65
+ Current:
66
+
67
+ ```swift
68
+ inner = Task {
69
+ do {
70
+ for try await element in transform(upstream) {
71
+ yield(element)
72
+ }
73
+ } catch { }
74
+ }
75
+ ```
76
+
77
+ Finding: The `catch { }` block silently swallows errors from the inner sequence. If
78
+ `transform(upstream)` throws, the outer sequence will simply stop producing elements with no
79
+ diagnostic. This violates the "never swallow errors silently" rule and makes it impossible for
80
+ callers to distinguish between normal completion and an error.
81
+
82
+ Fix:
83
+
84
+ ```swift
85
+ inner = Task {
86
+ do {
87
+ for try await element in transform(upstream) {
88
+ yield(element)
89
+ }
90
+ } catch is CancellationError {
91
+ // expected — outer task cancelled inner task
92
+ } catch {
93
+ yieldWithError(error) // propagate to caller
94
+ }
95
+ }
96
+ ```
97
+
98
+ ---
99
+
100
+ ## AsyncFlatMapLatestSequence+Testing.swift
101
+
102
+ **Medium** **Swift Quality** (line 23)
103
+
104
+ Current:
105
+
106
+ ```swift
107
+ extension AsyncFlatMapLatestSequence: @unchecked Sendable where Base: Sendable {}
108
+ ```
109
+
110
+ Finding: `@unchecked Sendable` suppresses the compiler check without documenting _why_ it is
111
+ safe. In a concurrent algorithm library this is particularly risky — readers have no way to
112
+ know whether the unchecked conformance is backed by a lock, actor isolation, or a known-safe
113
+ access pattern.
114
+
115
+ Fix: Add a comment:
116
+
117
+ ```swift
118
+ // SAFETY: all mutable state is accessed only from the iterator's single-consumer
119
+ // async context; no concurrent writes occur after initialization.
120
+ extension AsyncFlatMapLatestSequence: @unchecked Sendable where Base: Sendable {}
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Tests/AsyncAlgorithmsTests/TestFlatMapLatest.swift
126
+
127
+ **Medium** **Swift Quality** (line 67)
128
+
129
+ Current:
130
+
131
+ ```swift
132
+ func testCancellation() async {
133
+ var results: [Int] = []
134
+ ...
135
+ XCTAssertEqual(results, [1, 3])
136
+ }
137
+ ```
138
+
139
+ Finding: The test asserts on `[1, 3]` but does not cover the race where two upstream elements
140
+ arrive faster than the inner sequence can cancel. Under high scheduler pressure this test can
141
+ flake. The Swift Testing framework's `#expect` with `withKnownIssue` is preferred for
142
+ documenting known-flaky timing assertions.
143
+
144
+ Fix (Swift Testing migration):
145
+
146
+ ```swift
147
+ @Test func cancellationUnderLoad() async throws {
148
+ // drive rapid upstream emission to stress-test cancellation
149
+ let upstream = AsyncStream { c in
150
+ for i in 0..<100 { c.yield(i) }
151
+ c.finish()
152
+ }
153
+ var seen: [Int] = []
154
+ for await v in upstream.flatMapLatest { AsyncStream.just($0) } {
155
+ seen.append(v)
156
+ }
157
+ // only the last value is guaranteed to survive rapid cancellation
158
+ #expect(seen.last == 99)
159
+ }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Positive Observations
165
+
166
+ The `flatMapLatest` operator correctly stores only a single inner `Task` at a time and
167
+ cancels the previous one before launching the next — the core contract is correctly implemented.
168
+
169
+ The proposal markdown cleanup in `Proposals/` is clean and removes stale placeholder text
170
+ without touching any public API surface.
171
+
172
+ ---
173
+
174
+ ## Prioritized Action Items
175
+
176
+ - [Should fix] Migrate mutable task state to an actor or document `@unchecked Sendable` safety (AsyncFlatMapLatestSequence.swift:78)
177
+ - [Should fix] Propagate inner-sequence errors instead of swallowing with `catch { }` (AsyncFlatMapLatestSequence.swift:112)
178
+ - [Consider] Add `// SAFETY:` comment to `@unchecked Sendable` conformance
179
+ - [Consider] Add stress-test for rapid upstream emission to prevent cancellation race flakiness
180
+
181
+ ---
182
+
183
+ ## Agent Loop Feedback
184
+
185
+ ### Pattern: Silent error swallowing — `catch { }` (2 occurrences)
186
+
187
+ **Files**: AsyncFlatMapLatestSequence.swift:112, AsyncChain.swift:89
188
+
189
+ **Suggested rule for `AGENTS.md`**:
190
+
191
+ > Never use `catch { }` or `catch _ { }`. At minimum, rethrow `CancellationError` and
192
+ > propagate all other errors to callers. Silent catches hide bugs in async algorithm implementations.
193
+
194
+ ### Pattern: `@unchecked Sendable` without safety comment (2 occurrences)
195
+
196
+ **Files**: AsyncFlatMapLatestSequence+Testing.swift:23, AsyncThrottleSequence.swift:41
197
+
198
+ **Suggested rule for `AGENTS.md`**:
199
+
200
+ > Every `@unchecked Sendable` conformance must be preceded by a `// SAFETY:` comment
201
+ > explaining why concurrent access is safe (locking strategy, actor isolation, or access pattern).
202
+
203
+ ---
204
+
205
+ _Representative demonstration. Generated against commit
206
+ [`9d349bc`](https://github.com/apple/swift-async-algorithms/commit/9d349bcc328ac3c31ce40e746b5882742a0d1272)
207
+ of [apple/swift-async-algorithms](https://github.com/apple/swift-async-algorithms).
208
+ Line numbers and snippets are illustrative of the patterns the skill detects in this codebase._