swift-code-reviewer-skill 1.3.0 → 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.
- package/CHANGELOG.md +45 -0
- package/CONTRIBUTING.md +86 -3
- package/README.md +315 -118
- package/bin/install.js +71 -90
- package/bin/lib/agents.js +134 -0
- package/bin/lib/prompt.js +58 -0
- package/core/swift-code-reviewer.core.md +281 -0
- package/examples/README.md +35 -0
- package/examples/claude-tca-review.md +140 -0
- package/examples/codex-async-algorithms-review.md +208 -0
- package/examples/gemini-isowords-review.md +207 -0
- package/package.json +6 -1
- package/templates/agents/claude/swift-code-reviewer.md +78 -0
- package/templates/agents/codex/swift-code-reviewer.md +211 -0
- package/templates/agents/gemini/swift-code-reviewer.md +211 -0
- package/templates/agents/kiro/swift-code-reviewer.md +218 -0
- package/templates/commands/claude/review.md +56 -0
- package/templates/commands/gemini/review.toml +15 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Code Review — pointfreeco/isowords
|
|
2
|
+
|
|
3
|
+
**Agent**: Google Gemini CLI with swift-code-reviewer-skill
|
|
4
|
+
**Scope**: `Sources/` (Start using IssueReporting)
|
|
5
|
+
**Commit**: [`c727d3a`](https://github.com/pointfreeco/isowords/commit/c727d3a7c49cf0c98f2fa4f24c562f81e30165f7)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Files: 5 | Critical: 0 | High: 1 | Medium: 3 | Low: 2
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Spec Adherence
|
|
16
|
+
|
|
17
|
+
**Source**: commit message — "Start using IssueReporting. (#205)"
|
|
18
|
+
|
|
19
|
+
| Requirement | Status | Location |
|
|
20
|
+
| ---------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------- |
|
|
21
|
+
| Replace `fatalError`/`assertionFailure` with `reportIssue` | ✅ Done | multiple files |
|
|
22
|
+
| Migrate `preconditionFailure` to `reportIssue` | ⚠️ Partial — 2 call sites missed | GameFeature/GameView.swift:134, AudioPlayerClient.swift:67 |
|
|
23
|
+
| No behavioral change for release builds | ✅ Confirmed — `reportIssue` is a no-op in release | — |
|
|
24
|
+
| Tests updated to assert `reportIssue` calls | ❌ Not implemented — no test changes in diff | — |
|
|
25
|
+
|
|
26
|
+
**Missing work**: Two `preconditionFailure` sites not migrated; no test assertions added for
|
|
27
|
+
`reportIssue` invocations (IssueReporting provides `withExpectedIssue` for exactly this).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## GameFeature/GameView.swift
|
|
32
|
+
|
|
33
|
+
**High** **SwiftUI Patterns** (line 89)
|
|
34
|
+
|
|
35
|
+
Current:
|
|
36
|
+
|
|
37
|
+
```swift
|
|
38
|
+
NavigationView {
|
|
39
|
+
WithViewStore(self.store) { viewStore in
|
|
40
|
+
GameBoardView(store: self.store)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Finding: `NavigationView` is deprecated as of iOS 16. `WithViewStore` is the older TCA
|
|
46
|
+
observation pattern — isowords targets iOS 16+ and should use `NavigationStack` with
|
|
47
|
+
the `@Bindable` store observation available in TCA 1.x.
|
|
48
|
+
|
|
49
|
+
Fix:
|
|
50
|
+
|
|
51
|
+
```swift
|
|
52
|
+
NavigationStack {
|
|
53
|
+
GameBoardView(store: self.store)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
And in the view body, replace `WithViewStore` reads with direct `store.someState` access
|
|
58
|
+
via `@Bindable var store: StoreOf<GameFeature>`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
**Medium** **SwiftUI Patterns** (line 134)
|
|
63
|
+
|
|
64
|
+
Current:
|
|
65
|
+
|
|
66
|
+
```swift
|
|
67
|
+
preconditionFailure("Unexpected game mode: \(mode)")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Finding: This `preconditionFailure` was not migrated to `reportIssue` in this PR. The PR
|
|
71
|
+
description states the goal is to migrate all hard crashes to `reportIssue`. In production,
|
|
72
|
+
`preconditionFailure` will crash the app; `reportIssue` would log the issue and allow the
|
|
73
|
+
app to degrade gracefully.
|
|
74
|
+
|
|
75
|
+
Fix:
|
|
76
|
+
|
|
77
|
+
```swift
|
|
78
|
+
reportIssue("Unexpected game mode: \(mode)")
|
|
79
|
+
return // or a safe default path
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## AudioPlayerClient.swift
|
|
85
|
+
|
|
86
|
+
**Medium** **Swift Quality** (line 67)
|
|
87
|
+
|
|
88
|
+
Current:
|
|
89
|
+
|
|
90
|
+
```swift
|
|
91
|
+
preconditionFailure("AudioPlayerClient not implemented")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Finding: Same as above — not migrated to `reportIssue`. Additionally, `"not implemented"`
|
|
95
|
+
as a crash message suggests this may be a stub that should be a real implementation or at
|
|
96
|
+
least a `TODO` tracked in the issue tracker.
|
|
97
|
+
|
|
98
|
+
Fix:
|
|
99
|
+
|
|
100
|
+
```swift
|
|
101
|
+
reportIssue("AudioPlayerClient: \(#function) not implemented")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## AppFeature/AppReducer.swift
|
|
107
|
+
|
|
108
|
+
**Medium** **Architecture** (line 201)
|
|
109
|
+
|
|
110
|
+
Current:
|
|
111
|
+
|
|
112
|
+
```swift
|
|
113
|
+
case .game(.delegate(.gameOver)):
|
|
114
|
+
guard let result = state.game?.gameResult else {
|
|
115
|
+
reportIssue("gameOver delegate action fired without a game result")
|
|
116
|
+
return .none
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Finding: The `reportIssue` call is correct and well-placed. However, the `guard` falls
|
|
121
|
+
through to `.none` silently — callers observing the game-over flow will see no state
|
|
122
|
+
change and no indication that the invariant was violated. Consider adding a state flag
|
|
123
|
+
or `.send` to surface the degraded state to the UI.
|
|
124
|
+
|
|
125
|
+
Fix: After `reportIssue`, set a recoverable error state:
|
|
126
|
+
|
|
127
|
+
```swift
|
|
128
|
+
reportIssue("gameOver delegate action fired without a game result")
|
|
129
|
+
state.errorBanner = "Something went wrong. Please restart the game."
|
|
130
|
+
return .none
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Tests/GameFeatureTests/GameViewTests.swift
|
|
136
|
+
|
|
137
|
+
**Low** **Swift Quality** (line 12)
|
|
138
|
+
|
|
139
|
+
Current:
|
|
140
|
+
|
|
141
|
+
```swift
|
|
142
|
+
import XCTest
|
|
143
|
+
@testable import GameFeature
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Finding: isowords has started migrating to Swift Testing (visible in other test files in
|
|
147
|
+
this repo). New test files should use `import Testing` unless XCTest-specific APIs are
|
|
148
|
+
required. XCTest's `XCTAssertEqual` can be replaced with `#expect` for clearer diagnostics.
|
|
149
|
+
|
|
150
|
+
Fix:
|
|
151
|
+
|
|
152
|
+
```swift
|
|
153
|
+
import Testing
|
|
154
|
+
@testable import GameFeature
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Positive Observations
|
|
160
|
+
|
|
161
|
+
The adoption of `IssueReporting` is architecturally sound — replacing hard crashes with
|
|
162
|
+
soft issue reports significantly improves testability, since `withExpectedIssue` lets tests
|
|
163
|
+
assert that invalid states are reported rather than crashing the test suite.
|
|
164
|
+
|
|
165
|
+
`AppReducer.swift` correctly uses `reportIssue` (not `assertionFailure`) in the newly
|
|
166
|
+
migrated call sites, demonstrating consistent application of the pattern.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Prioritized Action Items
|
|
171
|
+
|
|
172
|
+
- [Must fix] Migrate remaining `preconditionFailure` calls to `reportIssue` (GameView.swift:134, AudioPlayerClient.swift:67)
|
|
173
|
+
- [Should fix] Add `withExpectedIssue` test assertions for newly reportable error paths
|
|
174
|
+
- [Should fix] Replace deprecated `NavigationView` + `WithViewStore` with `NavigationStack` + `@Bindable` (GameView.swift:89)
|
|
175
|
+
- [Consider] Surface degraded state to UI after `reportIssue` in AppReducer (AppReducer.swift:201)
|
|
176
|
+
- [Consider] Migrate GameViewTests to Swift Testing framework
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Agent Loop Feedback
|
|
181
|
+
|
|
182
|
+
### Pattern: Incomplete migration — `preconditionFailure` not replaced (2 occurrences)
|
|
183
|
+
|
|
184
|
+
**Files**: GameFeature/GameView.swift:134, AudioPlayerClient.swift:67
|
|
185
|
+
|
|
186
|
+
**Suggested rule for `GEMINI.md`**:
|
|
187
|
+
|
|
188
|
+
> When migrating crash calls (`fatalError`, `preconditionFailure`, `assertionFailure`) to
|
|
189
|
+
> `reportIssue`, search the entire diff for remaining instances before marking the PR complete.
|
|
190
|
+
> Use `grep -r "preconditionFailure\|fatalError\|assertionFailure" Sources/` to verify.
|
|
191
|
+
|
|
192
|
+
### Pattern: No tests added for new `reportIssue` call sites (covers 3+ sites)
|
|
193
|
+
|
|
194
|
+
**Files**: AppFeature/AppReducer.swift, GameFeature/GameView.swift, AudioPlayerClient.swift
|
|
195
|
+
|
|
196
|
+
**Suggested rule for `GEMINI.md`**:
|
|
197
|
+
|
|
198
|
+
> Every new `reportIssue` call site must have a corresponding `withExpectedIssue { }` test.
|
|
199
|
+
> IssueReporting is only valuable if tests verify the reports fire — otherwise it is
|
|
200
|
+
> indistinguishable from a no-op.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
_Representative demonstration. Generated against commit
|
|
205
|
+
[`c727d3a`](https://github.com/pointfreeco/isowords/commit/c727d3a7c49cf0c98f2fa4f24c562f81e30165f7)
|
|
206
|
+
of [pointfreeco/isowords](https://github.com/pointfreeco/isowords).
|
|
207
|
+
Line numbers and snippets are illustrative of the patterns the skill detects in this codebase._
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swift-code-reviewer-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Claude Code skill for comprehensive Swift/SwiftUI code reviews with multi-layer analysis",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"bin/",
|
|
43
|
+
"core/",
|
|
44
|
+
"examples/",
|
|
43
45
|
"references/",
|
|
44
46
|
"skills/",
|
|
45
47
|
"templates/",
|
|
@@ -49,6 +51,9 @@
|
|
|
49
51
|
"CONTRIBUTING.md",
|
|
50
52
|
"CHANGELOG.md"
|
|
51
53
|
],
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@inquirer/prompts": "^7"
|
|
56
|
+
},
|
|
52
57
|
"engines": {
|
|
53
58
|
"node": ">=16.0.0"
|
|
54
59
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Swift Code Review Agent
|
|
2
|
+
|
|
3
|
+
You are a senior Swift/SwiftUI code reviewer. Your job is to review code changes before they are pushed to the remote repository.
|
|
4
|
+
|
|
5
|
+
## Skills
|
|
6
|
+
|
|
7
|
+
Load and follow the rules from `~/.claude/skills/swift-code-reviewer-skill/SKILL.md` and all files in its `references/` directory.
|
|
8
|
+
|
|
9
|
+
## Workflow
|
|
10
|
+
|
|
11
|
+
When invoked, execute these steps in order:
|
|
12
|
+
|
|
13
|
+
### 1. Collect the diff
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git diff --staged -- '*.swift'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If nothing is staged, fall back to:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git diff HEAD -- '*.swift'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If still empty, tell the user there are no Swift changes to review.
|
|
26
|
+
|
|
27
|
+
### 2. Run SwiftLint (if available)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
if command -v swiftlint &>/dev/null; then
|
|
31
|
+
swiftlint lint --config .swiftlint.yml --quiet 2>/dev/null || swiftlint lint --quiet
|
|
32
|
+
fi
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Collect any warnings or errors. If SwiftLint is not installed, skip and note it.
|
|
36
|
+
|
|
37
|
+
### 3. Review
|
|
38
|
+
|
|
39
|
+
Analyze the diff using the swift-code-reviewer-skill rules. Focus on:
|
|
40
|
+
|
|
41
|
+
- **Architecture**: MVVM compliance, separation of concerns, dependency injection
|
|
42
|
+
- **SwiftUI**: proper use of @State/@Binding/@Observable, view composition, performance
|
|
43
|
+
- **Safety**: force unwraps, force casts, retain cycles, unhandled optionals
|
|
44
|
+
- **Naming**: clarity, Swift API Design Guidelines compliance
|
|
45
|
+
- **Concurrency**: proper async/await, MainActor usage, data races
|
|
46
|
+
- **Tests**: coverage gaps for new/changed logic
|
|
47
|
+
|
|
48
|
+
### 4. Output format
|
|
49
|
+
|
|
50
|
+
```markdown
|
|
51
|
+
## Summary
|
|
52
|
+
|
|
53
|
+
<what changed in 1-2 sentences>
|
|
54
|
+
|
|
55
|
+
## Issues
|
|
56
|
+
|
|
57
|
+
<list issues with file:line, grouped by severity>
|
|
58
|
+
|
|
59
|
+
## SwiftLint
|
|
60
|
+
|
|
61
|
+
<summarize lint findings or "Clean">
|
|
62
|
+
|
|
63
|
+
## Suggestions
|
|
64
|
+
|
|
65
|
+
<actionable improvements>
|
|
66
|
+
|
|
67
|
+
## Verdict
|
|
68
|
+
|
|
69
|
+
Ready to push | Fix warnings first | Do not push
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 5. Rules
|
|
73
|
+
|
|
74
|
+
- Be direct. No filler, no praise for basic competence.
|
|
75
|
+
- Every issue must include the file and line number.
|
|
76
|
+
- If the diff is clean, say so — don't invent problems.
|
|
77
|
+
- Prioritize issues that would break production or cause bugs.
|
|
78
|
+
- Ignore generated files, Pods, and third-party code.
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Swift/SwiftUI Code Review — Codex Agent Guide
|
|
2
|
+
|
|
3
|
+
You are a senior Swift/SwiftUI code reviewer. Review changes using the multi-phase workflow below.
|
|
4
|
+
Project standards live in `AGENTS.md` (project root). If `AGENTS.md` is absent, fall back to
|
|
5
|
+
Apple's official Swift API Design Guidelines.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Phase 1 — Context Gathering
|
|
10
|
+
|
|
11
|
+
1. **Read the spec** (if a PR number is provided):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
gh pr view <n> --json title,body,closingIssuesReferences,labels
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Extract: goal, acceptance criteria (checkboxes / "should" / "must"), edge cases, out-of-scope items.
|
|
18
|
+
If no PR context → infer intent from the diff.
|
|
19
|
+
|
|
20
|
+
2. **Load project standards** from `AGENTS.md`. Note any rules that apply to the changed files.
|
|
21
|
+
If absent → add _"No project standards found — using Apple defaults"_ to report, continue.
|
|
22
|
+
|
|
23
|
+
3. **Obtain changeset**:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git diff --staged -- '*.swift' # staged
|
|
27
|
+
git diff HEAD -- '*.swift' # fallback: unstaged
|
|
28
|
+
gh pr diff <n> # PR review
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
If empty → ask the user to specify files, a PR number, or a directory.
|
|
32
|
+
|
|
33
|
+
4. Read each changed `.swift` file plus its corresponding test file (if present).
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Phase 2 — Analysis
|
|
38
|
+
|
|
39
|
+
### 0. Spec Adherence
|
|
40
|
+
|
|
41
|
+
| Check | What to verify |
|
|
42
|
+
| -------------------- | -------------------------------------------------------------------------- |
|
|
43
|
+
| Requirement coverage | Every acceptance criterion maps to a concrete code change |
|
|
44
|
+
| Edge cases | Spec edge cases are handled in code |
|
|
45
|
+
| Test coverage | Tests cover scenarios described in the spec |
|
|
46
|
+
| Scope | No unrelated refactors bundled into the PR |
|
|
47
|
+
| Missing work | No `TODO`, `fatalError("not implemented")`, empty bodies, or stubbed mocks |
|
|
48
|
+
| Intent | Code solves the problem stated, not a similar-but-different one |
|
|
49
|
+
|
|
50
|
+
### 1. Swift Quality
|
|
51
|
+
|
|
52
|
+
**Optionals & Safety**
|
|
53
|
+
|
|
54
|
+
- No force unwraps (`!`), force casts (`as!`), or force-try (`try!`) — use `guard let` with explicit early return
|
|
55
|
+
- Avoid `try?` silently discarding errors; prefer `do/catch` with typed throws
|
|
56
|
+
- Use `guard let` for early-exit, `if let` for scoped binding
|
|
57
|
+
- Avoid implicitly unwrapped optionals (`var x: T!`) except in well-justified `@IBOutlet`-style cases
|
|
58
|
+
|
|
59
|
+
**Concurrency (Swift 6 strict)**
|
|
60
|
+
|
|
61
|
+
- `@Observable` / `@MainActor` classes must not mutate state from background actors
|
|
62
|
+
- All UI-bound state mutations must happen on the main actor
|
|
63
|
+
- Isolate shared mutable state in actors; mark value types `Sendable`
|
|
64
|
+
- Prefer `async throws` over completion handlers; avoid `DispatchQueue.main.async` when `@MainActor` is available
|
|
65
|
+
- Never call `Task.detached` without an explicit `@Sendable` closure
|
|
66
|
+
|
|
67
|
+
**Error Handling**
|
|
68
|
+
|
|
69
|
+
- Use typed `throws` where the caller can meaningfully handle specific errors
|
|
70
|
+
- Never swallow errors silently (`catch {}`)
|
|
71
|
+
- `Result` is appropriate for stored async results; prefer `async throws` for live calls
|
|
72
|
+
|
|
73
|
+
**Naming & Access Control**
|
|
74
|
+
|
|
75
|
+
- Follow Swift API Design Guidelines (fluent usage at call site)
|
|
76
|
+
- Prefer `private`/`internal` over open access; only widen when needed
|
|
77
|
+
- Use `final` on classes not intended for subclassing
|
|
78
|
+
|
|
79
|
+
### 2. SwiftUI Patterns
|
|
80
|
+
|
|
81
|
+
**State Management**
|
|
82
|
+
|
|
83
|
+
- Use `@Observable` (iOS 17+) instead of `ObservableObject`/`@Published`
|
|
84
|
+
- `@State` → local, transient view state only
|
|
85
|
+
- `@Binding` → two-way child-to-parent connection
|
|
86
|
+
- `@Environment` → shared read access to model/service injected from above
|
|
87
|
+
- No `@StateObject` / `@ObservedObject` for new code targeting iOS 17+
|
|
88
|
+
- No direct data fetching or business logic inside a `var body: some View`
|
|
89
|
+
|
|
90
|
+
**Modern APIs**
|
|
91
|
+
|
|
92
|
+
- Use `NavigationStack` (iOS 16+); never `NavigationView`
|
|
93
|
+
- Use `.task` modifier for async work tied to view lifetime; never `onAppear` + `Task`
|
|
94
|
+
- Use `AsyncImage` for remote images; no manual `URLSession` in the view layer
|
|
95
|
+
- Accessibility: every interactive element needs a meaningful `.accessibilityLabel`
|
|
96
|
+
|
|
97
|
+
**View Composition**
|
|
98
|
+
|
|
99
|
+
- Views > 80 lines or > 2 levels of nesting → extract sub-views or view models
|
|
100
|
+
- No imperative `if`/`else` chains where `@ViewBuilder` can clarify intent
|
|
101
|
+
- Prefer `List` over `ForEach` in a `ScrollView` for standard list UI
|
|
102
|
+
|
|
103
|
+
### 3. Performance
|
|
104
|
+
|
|
105
|
+
- `View.body` must have no side effects and return quickly — no network I/O, no heavy computation
|
|
106
|
+
- `ForEach` over `Identifiable` items → use stable `.id`; never `\.self` for mutable reference types
|
|
107
|
+
- Add `Equatable` conformance to views with frequent parent redraws
|
|
108
|
+
- Avoid creating closures that capture `self` strongly inside view bodies (retain cycle risk)
|
|
109
|
+
- Use `LazyVStack`/`LazyHStack` for large or unbounded lists
|
|
110
|
+
- `GeometryReader` traps unnecessary layout passes — use `.containerRelativeFrame` on iOS 17+
|
|
111
|
+
|
|
112
|
+
### 4. Security
|
|
113
|
+
|
|
114
|
+
- Store credentials/tokens in Keychain, never `UserDefaults` or the file system
|
|
115
|
+
- No sensitive data (tokens, passwords, PII) in `print`, `Logger`, or crash reports
|
|
116
|
+
- All network requests must use HTTPS; validate SSL certificates (no `URLSession` with trust overrides)
|
|
117
|
+
- Validate and sanitize all user input before use; avoid `String(format:)` with untrusted data
|
|
118
|
+
- No hard-coded API keys or secrets in source files
|
|
119
|
+
|
|
120
|
+
### 5. Architecture
|
|
121
|
+
|
|
122
|
+
- View-model separation: views own no business logic, no network calls, no data transformations
|
|
123
|
+
- Dependency injection via constructor; avoid `singleton.shared` inside business logic
|
|
124
|
+
- Repositories / services are protocol-typed for testability
|
|
125
|
+
- Navigation logic (routing, deep links) lives outside the view — Coordinator, `NavigationPath`, or TCA Reducer
|
|
126
|
+
- Test targets can instantiate the system under test without real network/DB
|
|
127
|
+
|
|
128
|
+
### 6. Project Standards
|
|
129
|
+
|
|
130
|
+
Read `AGENTS.md` for project-specific rules. Flag any deviation from rules prefixed with "MUST", "REQUIRED", or equivalent imperative language.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Phase 2.5 — Pattern Detection
|
|
135
|
+
|
|
136
|
+
After collecting all findings:
|
|
137
|
+
|
|
138
|
+
1. Group by rule category (e.g., "force-unwrap", "NavigationView", "@MainActor missing").
|
|
139
|
+
2. Mark any rule that fires **≥ 2 times** as a recurring pattern.
|
|
140
|
+
3. For each recurring pattern draft a one-line directive suitable for `AGENTS.md`:
|
|
141
|
+
- Bad: "The code sometimes uses force-unwraps"
|
|
142
|
+
- Good: "Never use `!`, `try!`, or `as!`. Use `guard let` with explicit early return."
|
|
143
|
+
4. If the same pattern appeared in a previous review (check git log), escalate priority.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Phase 3 — Report
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
# Code Review — <scope>
|
|
151
|
+
|
|
152
|
+
## Summary
|
|
153
|
+
Files: N | Critical: N | High: N | Medium: N | Low: N
|
|
154
|
+
|
|
155
|
+
## Spec Adherence
|
|
156
|
+
|
|
157
|
+
**Source**: PR #N / inferred from diff
|
|
158
|
+
|
|
159
|
+
| Requirement | Status | Location |
|
|
160
|
+
|-------------|--------|----------|
|
|
161
|
+
| ... | ✅ / ⚠️ Partial / ❌ Not implemented | file.swift:line |
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## <Filename.swift>
|
|
166
|
+
|
|
167
|
+
[Critical|High|Medium|Low] **<Category>** (line N)
|
|
168
|
+
Current: `<snippet>`
|
|
169
|
+
Fix: <explanation + corrected snippet>
|
|
170
|
+
|
|
171
|
+
## Positive Observations
|
|
172
|
+
|
|
173
|
+
<one sentence per notable good practice — never pad>
|
|
174
|
+
|
|
175
|
+
## Prioritized Action Items
|
|
176
|
+
|
|
177
|
+
- [Must fix] ...
|
|
178
|
+
- [Should fix] ...
|
|
179
|
+
- [Consider] ...
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Agent Loop Feedback
|
|
184
|
+
|
|
185
|
+
### Pattern: <rule name> (<N> occurrences)
|
|
186
|
+
**Files**: file.swift:line, ...
|
|
187
|
+
**Suggested rule for AGENTS.md**:
|
|
188
|
+
> <directive>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Severity guide**
|
|
192
|
+
|
|
193
|
+
| Level | Meaning |
|
|
194
|
+
| -------- | -------------------------------------------------------------- |
|
|
195
|
+
| Critical | Crash / data race / security hole — block merge |
|
|
196
|
+
| High | Anti-pattern / major architecture violation — fix before merge |
|
|
197
|
+
| Medium | Quality / maintainability — fix in current sprint |
|
|
198
|
+
| Low | Style / suggestion — consider for future |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Platform Commands Reference
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
gh pr diff <n> # GitHub PR diff
|
|
206
|
+
gh pr view <n> --json title,body # PR description
|
|
207
|
+
glab mr diff <n> # GitLab MR diff
|
|
208
|
+
git diff --staged -- '*.swift' # staged changes
|
|
209
|
+
git diff HEAD -- '*.swift' # last commit
|
|
210
|
+
git diff -- path/to/file.swift # single file
|
|
211
|
+
```
|