swift-code-reviewer-skill 1.0.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 +214 -0
- package/CONTRIBUTING.md +271 -0
- package/LICENSE +21 -0
- package/README.md +536 -0
- package/SKILL.md +690 -0
- package/bin/install.js +173 -0
- package/package.json +41 -0
- package/references/architecture-patterns.md +862 -0
- package/references/custom-guidelines.md +852 -0
- package/references/feedback-templates.md +666 -0
- package/references/performance-review.md +914 -0
- package/references/review-workflow.md +1131 -0
- package/references/security-checklist.md +781 -0
- package/references/swift-quality-checklist.md +928 -0
- package/references/swiftui-review-checklist.md +909 -0
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
# Custom Project Guidelines Integration
|
|
2
|
+
|
|
3
|
+
This guide explains how to read, parse, and validate code against project-specific standards defined in `.claude/CLAUDE.md` and related architecture documents.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Overview
|
|
8
|
+
|
|
9
|
+
### Purpose
|
|
10
|
+
|
|
11
|
+
Project-specific guidelines allow teams to:
|
|
12
|
+
- Define custom coding standards
|
|
13
|
+
- Document architecture decisions
|
|
14
|
+
- Establish testing requirements
|
|
15
|
+
- Define design system usage
|
|
16
|
+
- Set project-specific error handling patterns
|
|
17
|
+
- Document navigation patterns
|
|
18
|
+
|
|
19
|
+
### Common Locations
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
.claude/
|
|
23
|
+
├── CLAUDE.md # Main coding standards
|
|
24
|
+
├── DependencyInjection-Architecture.md # DI patterns
|
|
25
|
+
├── Design System Structure.md # Design system usage
|
|
26
|
+
├── Navigation-Architecture.md # Navigation patterns
|
|
27
|
+
├── Testing-Guidelines.md # Testing requirements
|
|
28
|
+
├── Error-Handling.md # Error handling patterns
|
|
29
|
+
└── API-Guidelines.md # API design standards
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 2. Reading .claude/CLAUDE.md
|
|
35
|
+
|
|
36
|
+
### 2.1 Locating the File
|
|
37
|
+
|
|
38
|
+
**Check for:**
|
|
39
|
+
- [ ] `.claude/CLAUDE.md` exists in repository root
|
|
40
|
+
- [ ] Related architecture docs in `.claude/` directory
|
|
41
|
+
- [ ] Project-specific subdirectories
|
|
42
|
+
|
|
43
|
+
**Example Commands:**
|
|
44
|
+
```bash
|
|
45
|
+
# Check if .claude/CLAUDE.md exists
|
|
46
|
+
if [ -f .claude/CLAUDE.md ]; then
|
|
47
|
+
echo "Project guidelines found"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# List all .claude files
|
|
51
|
+
ls -la .claude/
|
|
52
|
+
|
|
53
|
+
# Find all markdown files in .claude
|
|
54
|
+
find .claude -name "*.md"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 2.2 Common Sections in CLAUDE.md
|
|
58
|
+
|
|
59
|
+
**Typical Structure:**
|
|
60
|
+
|
|
61
|
+
```markdown
|
|
62
|
+
# Project Coding Standards
|
|
63
|
+
|
|
64
|
+
## Architecture
|
|
65
|
+
- Architecture pattern (MVVM, MVI, TCA, etc.)
|
|
66
|
+
- Layer organization
|
|
67
|
+
- Module structure
|
|
68
|
+
|
|
69
|
+
## Swift Style Guide
|
|
70
|
+
- Naming conventions
|
|
71
|
+
- Code formatting
|
|
72
|
+
- Documentation requirements
|
|
73
|
+
|
|
74
|
+
## SwiftUI Patterns
|
|
75
|
+
- State management approach
|
|
76
|
+
- Property wrapper usage
|
|
77
|
+
- View composition guidelines
|
|
78
|
+
|
|
79
|
+
## Dependency Injection
|
|
80
|
+
- DI approach (constructor, environment, etc.)
|
|
81
|
+
- Service location rules
|
|
82
|
+
|
|
83
|
+
## Error Handling
|
|
84
|
+
- Error type patterns
|
|
85
|
+
- Error reporting strategy
|
|
86
|
+
- User-facing error messages
|
|
87
|
+
|
|
88
|
+
## Testing
|
|
89
|
+
- Test coverage requirements
|
|
90
|
+
- Testing patterns
|
|
91
|
+
- Mock/stub conventions
|
|
92
|
+
|
|
93
|
+
## Design System
|
|
94
|
+
- Color palette usage
|
|
95
|
+
- Typography standards
|
|
96
|
+
- Spacing system
|
|
97
|
+
- Component library
|
|
98
|
+
|
|
99
|
+
## Navigation
|
|
100
|
+
- Navigation pattern
|
|
101
|
+
- Deep linking approach
|
|
102
|
+
- State restoration
|
|
103
|
+
|
|
104
|
+
## Performance
|
|
105
|
+
- Performance benchmarks
|
|
106
|
+
- Optimization priorities
|
|
107
|
+
|
|
108
|
+
## Security
|
|
109
|
+
- Authentication approach
|
|
110
|
+
- Data storage rules
|
|
111
|
+
- API security
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 2.3 Parsing Sections
|
|
115
|
+
|
|
116
|
+
**Strategy:**
|
|
117
|
+
|
|
118
|
+
1. **Read entire file**
|
|
119
|
+
2. **Identify sections** (markdown headers)
|
|
120
|
+
3. **Extract rules and patterns** from each section
|
|
121
|
+
4. **Create checklist** for validation
|
|
122
|
+
|
|
123
|
+
**Example Parsing Logic:**
|
|
124
|
+
|
|
125
|
+
```swift
|
|
126
|
+
struct ProjectGuidelines {
|
|
127
|
+
let architecture: ArchitectureGuidelines
|
|
128
|
+
let swiftStyle: SwiftStyleGuidelines
|
|
129
|
+
let swiftUIPatterns: SwiftUIGuidelines
|
|
130
|
+
let dependencyInjection: DIGuidelines
|
|
131
|
+
let errorHandling: ErrorHandlingGuidelines
|
|
132
|
+
let testing: TestingGuidelines
|
|
133
|
+
let designSystem: DesignSystemGuidelines
|
|
134
|
+
let navigation: NavigationGuidelines
|
|
135
|
+
|
|
136
|
+
static func parse(from markdown: String) -> ProjectGuidelines {
|
|
137
|
+
// Parse markdown sections into structured guidelines
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 3. Extracting Coding Standards
|
|
145
|
+
|
|
146
|
+
### 3.1 Architecture Patterns
|
|
147
|
+
|
|
148
|
+
**What to Extract:**
|
|
149
|
+
|
|
150
|
+
```markdown
|
|
151
|
+
## Architecture
|
|
152
|
+
|
|
153
|
+
We use **MVVM with Coordinators**:
|
|
154
|
+
|
|
155
|
+
- Views: SwiftUI views, presentation only
|
|
156
|
+
- ViewModels: @Observable classes, business logic
|
|
157
|
+
- Models: Data structures and domain logic
|
|
158
|
+
- Coordinators: Navigation flow management
|
|
159
|
+
- Repositories: Data access abstraction
|
|
160
|
+
- Use Cases: Single business operations
|
|
161
|
+
|
|
162
|
+
### Rules
|
|
163
|
+
1. ViewModels MUST use @Observable (iOS 17+)
|
|
164
|
+
2. All dependencies MUST be injected via constructor
|
|
165
|
+
3. Views MUST NOT contain business logic
|
|
166
|
+
4. Navigation MUST go through Coordinator
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Extracted Rules:**
|
|
170
|
+
- ✅ ViewModels use @Observable
|
|
171
|
+
- ✅ Constructor injection required
|
|
172
|
+
- ✅ No business logic in views
|
|
173
|
+
- ✅ Coordinator-based navigation
|
|
174
|
+
|
|
175
|
+
**Validation:**
|
|
176
|
+
```swift
|
|
177
|
+
// Check: ViewModel uses @Observable
|
|
178
|
+
// ❌ Violation
|
|
179
|
+
class UserViewModel: ObservableObject { }
|
|
180
|
+
|
|
181
|
+
// ✅ Compliant
|
|
182
|
+
@Observable
|
|
183
|
+
final class UserViewModel { }
|
|
184
|
+
|
|
185
|
+
// Check: Dependencies injected
|
|
186
|
+
// ❌ Violation
|
|
187
|
+
class ViewModel {
|
|
188
|
+
let service = NetworkService.shared
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ✅ Compliant
|
|
192
|
+
class ViewModel {
|
|
193
|
+
let service: NetworkService
|
|
194
|
+
init(service: NetworkService) {
|
|
195
|
+
self.service = service
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 3.2 Swift Style Guidelines
|
|
201
|
+
|
|
202
|
+
**What to Extract:**
|
|
203
|
+
|
|
204
|
+
```markdown
|
|
205
|
+
## Swift Style Guide
|
|
206
|
+
|
|
207
|
+
### Naming Conventions
|
|
208
|
+
- Types: `UpperCamelCase`
|
|
209
|
+
- Properties/Methods: `lowerCamelCase`
|
|
210
|
+
- Protocols describing capabilities: `-able` or `-ing` suffix
|
|
211
|
+
- Bool properties: Prefix with `is`, `has`, `should`
|
|
212
|
+
|
|
213
|
+
### Code Organization
|
|
214
|
+
- Maximum file length: 400 lines
|
|
215
|
+
- Maximum method length: 50 lines
|
|
216
|
+
- Use MARK comments for sections
|
|
217
|
+
|
|
218
|
+
### Access Control
|
|
219
|
+
- Default to `private`
|
|
220
|
+
- Mark `internal` explicitly
|
|
221
|
+
- Public API requires DocC comments
|
|
222
|
+
|
|
223
|
+
### Error Handling
|
|
224
|
+
- Custom error types conform to `AppError` protocol
|
|
225
|
+
- Use typed throws (Swift 6+)
|
|
226
|
+
- No force try except for bundled resources
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Extracted Rules:**
|
|
230
|
+
- ✅ Naming conventions enforced
|
|
231
|
+
- ✅ File length < 400 lines
|
|
232
|
+
- ✅ Method length < 50 lines
|
|
233
|
+
- ✅ MARK comments required
|
|
234
|
+
- ✅ Explicit access control
|
|
235
|
+
- ✅ Custom errors conform to AppError
|
|
236
|
+
- ✅ No force try
|
|
237
|
+
|
|
238
|
+
**Validation:**
|
|
239
|
+
```swift
|
|
240
|
+
// Check: Custom error conforms to AppError
|
|
241
|
+
// ❌ Violation
|
|
242
|
+
enum LoginError: Error {
|
|
243
|
+
case invalidCredentials
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ✅ Compliant
|
|
247
|
+
enum LoginError: AppError {
|
|
248
|
+
case invalidCredentials
|
|
249
|
+
|
|
250
|
+
var message: String {
|
|
251
|
+
switch self {
|
|
252
|
+
case .invalidCredentials: return "Invalid email or password"
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
var code: Int {
|
|
257
|
+
switch self {
|
|
258
|
+
case .invalidCredentials: return 1001
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 3.3 SwiftUI Patterns
|
|
265
|
+
|
|
266
|
+
**What to Extract:**
|
|
267
|
+
|
|
268
|
+
```markdown
|
|
269
|
+
## SwiftUI Patterns
|
|
270
|
+
|
|
271
|
+
### State Management
|
|
272
|
+
- Use @Observable for all ViewModels (iOS 17+)
|
|
273
|
+
- @State for view-local state only
|
|
274
|
+
- @Binding for parent-child communication
|
|
275
|
+
- @Environment for dependency injection
|
|
276
|
+
- NO @StateObject or @ObservedObject with @Observable
|
|
277
|
+
|
|
278
|
+
### View Composition
|
|
279
|
+
- Maximum view body: 50 lines
|
|
280
|
+
- Extract subviews for reusability
|
|
281
|
+
- Use private struct for local subviews
|
|
282
|
+
|
|
283
|
+
### Property Wrappers
|
|
284
|
+
| Use Case | Property Wrapper |
|
|
285
|
+
|----------|-----------------|
|
|
286
|
+
| ViewModel | @Observable class |
|
|
287
|
+
| View-local state | @State |
|
|
288
|
+
| Two-way binding | @Binding |
|
|
289
|
+
| Dependency | @Environment |
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**Extracted Rules:**
|
|
293
|
+
- ✅ @Observable for ViewModels
|
|
294
|
+
- ✅ No @StateObject with @Observable
|
|
295
|
+
- ✅ View body < 50 lines
|
|
296
|
+
- ✅ Proper property wrapper usage
|
|
297
|
+
|
|
298
|
+
### 3.4 Design System
|
|
299
|
+
|
|
300
|
+
**What to Extract:**
|
|
301
|
+
|
|
302
|
+
```markdown
|
|
303
|
+
## Design System
|
|
304
|
+
|
|
305
|
+
### Colors
|
|
306
|
+
Use AppColors enum only. No hardcoded colors.
|
|
307
|
+
|
|
308
|
+
```swift
|
|
309
|
+
// ✅ Correct
|
|
310
|
+
.foregroundColor(AppColors.primary)
|
|
311
|
+
|
|
312
|
+
// ❌ Wrong
|
|
313
|
+
.foregroundColor(.blue)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Typography
|
|
317
|
+
Use AppFonts enum only.
|
|
318
|
+
|
|
319
|
+
```swift
|
|
320
|
+
// ✅ Correct
|
|
321
|
+
.font(AppFonts.title)
|
|
322
|
+
|
|
323
|
+
// ❌ Wrong
|
|
324
|
+
.font(.system(size: 24))
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Spacing
|
|
328
|
+
Use AppSpacing for all padding and spacing.
|
|
329
|
+
|
|
330
|
+
```swift
|
|
331
|
+
// ✅ Correct
|
|
332
|
+
.padding(AppSpacing.medium)
|
|
333
|
+
|
|
334
|
+
// ❌ Wrong
|
|
335
|
+
.padding(16)
|
|
336
|
+
```
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Extracted Rules:**
|
|
340
|
+
- ✅ Use AppColors, no hardcoded colors
|
|
341
|
+
- ✅ Use AppFonts, no system fonts
|
|
342
|
+
- ✅ Use AppSpacing, no magic numbers
|
|
343
|
+
|
|
344
|
+
**Validation:**
|
|
345
|
+
```swift
|
|
346
|
+
// Check: No hardcoded colors
|
|
347
|
+
// Search for:
|
|
348
|
+
.foregroundColor(.red) // ❌ Violation
|
|
349
|
+
.background(.blue) // ❌ Violation
|
|
350
|
+
Color(red: 0.5, ...) // ❌ Violation
|
|
351
|
+
|
|
352
|
+
// Expected:
|
|
353
|
+
.foregroundColor(AppColors.primary) // ✅ Compliant
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 3.5 Testing Requirements
|
|
357
|
+
|
|
358
|
+
**What to Extract:**
|
|
359
|
+
|
|
360
|
+
```markdown
|
|
361
|
+
## Testing Guidelines
|
|
362
|
+
|
|
363
|
+
### Requirements
|
|
364
|
+
- Minimum test coverage: 80%
|
|
365
|
+
- All ViewModels MUST have unit tests
|
|
366
|
+
- All Use Cases MUST have unit tests
|
|
367
|
+
- Critical user flows MUST have UI tests
|
|
368
|
+
|
|
369
|
+
### Testing Patterns
|
|
370
|
+
- Arrange-Act-Assert pattern
|
|
371
|
+
- Mock all dependencies
|
|
372
|
+
- One assertion per test (when possible)
|
|
373
|
+
- Descriptive test names: `test[Method]_[Scenario]_[ExpectedOutcome]`
|
|
374
|
+
|
|
375
|
+
### Example
|
|
376
|
+
```swift
|
|
377
|
+
func testLogin_withValidCredentials_succeeds() async {
|
|
378
|
+
// Arrange
|
|
379
|
+
mockAuthService.loginResult = .success(user)
|
|
380
|
+
viewModel.email = "test@example.com"
|
|
381
|
+
viewModel.password = "password"
|
|
382
|
+
|
|
383
|
+
// Act
|
|
384
|
+
await viewModel.login()
|
|
385
|
+
|
|
386
|
+
// Assert
|
|
387
|
+
XCTAssertNil(viewModel.error)
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Extracted Rules:**
|
|
393
|
+
- ✅ 80% test coverage minimum
|
|
394
|
+
- ✅ ViewModels tested
|
|
395
|
+
- ✅ Use Cases tested
|
|
396
|
+
- ✅ Arrange-Act-Assert pattern
|
|
397
|
+
- ✅ Descriptive test names
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## 4. Validation Against Custom Guidelines
|
|
402
|
+
|
|
403
|
+
### 4.1 Architecture Validation
|
|
404
|
+
|
|
405
|
+
**Checklist:**
|
|
406
|
+
|
|
407
|
+
```markdown
|
|
408
|
+
Architecture Compliance:
|
|
409
|
+
- [ ] Follows defined pattern (MVVM, etc.)
|
|
410
|
+
- [ ] Layer separation enforced
|
|
411
|
+
- [ ] Dependencies injected properly
|
|
412
|
+
- [ ] No architecture violations
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
**Example Validation:**
|
|
416
|
+
|
|
417
|
+
```swift
|
|
418
|
+
// File: LoginViewModel.swift
|
|
419
|
+
|
|
420
|
+
// Check 1: Uses @Observable (project requirement)
|
|
421
|
+
@Observable // ✅ Compliant
|
|
422
|
+
final class LoginViewModel {
|
|
423
|
+
|
|
424
|
+
// Check 2: Dependencies injected via constructor
|
|
425
|
+
private let authService: AuthService // ✅ Protocol
|
|
426
|
+
private let loginUseCase: LoginUseCase
|
|
427
|
+
|
|
428
|
+
init(authService: AuthService, loginUseCase: LoginUseCase) { // ✅ Injected
|
|
429
|
+
self.authService = authService
|
|
430
|
+
self.loginUseCase = loginUseCase
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Check 3: Business logic in ViewModel, not View
|
|
434
|
+
func login() async { // ✅ Business logic here
|
|
435
|
+
// Implementation
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// File: LoginView.swift
|
|
440
|
+
struct LoginView: View {
|
|
441
|
+
let viewModel: LoginViewModel // ✅ ViewModel injected
|
|
442
|
+
|
|
443
|
+
var body: some View {
|
|
444
|
+
// ✅ Only presentation code, no business logic
|
|
445
|
+
VStack {
|
|
446
|
+
TextField("Email", text: $viewModel.email)
|
|
447
|
+
Button("Login") {
|
|
448
|
+
Task { await viewModel.login() } // ✅ Delegates to ViewModel
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### 4.2 Error Handling Validation
|
|
456
|
+
|
|
457
|
+
**Project Standard:**
|
|
458
|
+
```markdown
|
|
459
|
+
## Error Handling
|
|
460
|
+
|
|
461
|
+
All errors MUST conform to AppError protocol:
|
|
462
|
+
|
|
463
|
+
```swift
|
|
464
|
+
protocol AppError: Error {
|
|
465
|
+
var message: String { get }
|
|
466
|
+
var code: Int { get }
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Error codes:
|
|
471
|
+
- 1000-1999: Authentication errors
|
|
472
|
+
- 2000-2999: Network errors
|
|
473
|
+
- 3000-3999: Database errors
|
|
474
|
+
- 4000-4999: Validation errors
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
**Validation:**
|
|
478
|
+
|
|
479
|
+
```swift
|
|
480
|
+
// ❌ Violation: Doesn't conform to AppError
|
|
481
|
+
enum LoginError: Error {
|
|
482
|
+
case invalidCredentials
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// ✅ Compliant: Conforms to AppError with correct code range
|
|
486
|
+
enum LoginError: AppError {
|
|
487
|
+
case invalidCredentials
|
|
488
|
+
case accountLocked
|
|
489
|
+
|
|
490
|
+
var message: String {
|
|
491
|
+
switch self {
|
|
492
|
+
case .invalidCredentials: return "Invalid email or password"
|
|
493
|
+
case .accountLocked: return "Account locked"
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
var code: Int {
|
|
498
|
+
switch self {
|
|
499
|
+
case .invalidCredentials: return 1001 // ✅ In auth range (1000-1999)
|
|
500
|
+
case .accountLocked: return 1002
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### 4.3 Design System Validation
|
|
507
|
+
|
|
508
|
+
**Automated Checks:**
|
|
509
|
+
|
|
510
|
+
```bash
|
|
511
|
+
# Search for hardcoded colors
|
|
512
|
+
grep -r "\.foregroundColor(\." --include="*.swift" | grep -v "AppColors"
|
|
513
|
+
|
|
514
|
+
# Search for hardcoded font sizes
|
|
515
|
+
grep -r "\.font(\.system(size:" --include="*.swift"
|
|
516
|
+
|
|
517
|
+
# Search for magic numbers in padding
|
|
518
|
+
grep -r "\.padding([0-9]" --include="*.swift"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Example Violations:**
|
|
522
|
+
|
|
523
|
+
```swift
|
|
524
|
+
// ❌ Violation: Hardcoded color
|
|
525
|
+
Text("Hello")
|
|
526
|
+
.foregroundColor(.blue)
|
|
527
|
+
|
|
528
|
+
// ✅ Compliant: Uses design system
|
|
529
|
+
Text("Hello")
|
|
530
|
+
.foregroundColor(AppColors.primary)
|
|
531
|
+
|
|
532
|
+
// ❌ Violation: Hardcoded spacing
|
|
533
|
+
VStack(spacing: 16) { }
|
|
534
|
+
|
|
535
|
+
// ✅ Compliant: Uses design system
|
|
536
|
+
VStack(spacing: AppSpacing.medium) { }
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
## 5. Reporting Custom Guideline Violations
|
|
542
|
+
|
|
543
|
+
### 5.1 Violation Template
|
|
544
|
+
|
|
545
|
+
```markdown
|
|
546
|
+
🔴 **Violates Project Standard: [Standard Name]** ([file]:[line])
|
|
547
|
+
**Severity**: [Critical/High/Medium]
|
|
548
|
+
**Category**: Project Standards
|
|
549
|
+
|
|
550
|
+
**Project Guideline**: [Quote from .claude/CLAUDE.md]
|
|
551
|
+
|
|
552
|
+
**Violation**: [What doesn't comply]
|
|
553
|
+
|
|
554
|
+
**Current Code:**
|
|
555
|
+
```swift
|
|
556
|
+
[Code that violates]
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
**Expected Code:**
|
|
560
|
+
```swift
|
|
561
|
+
[Code that complies]
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
**Reference**: .claude/CLAUDE.md:[section]
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### 5.2 Example Violation Report
|
|
568
|
+
|
|
569
|
+
```markdown
|
|
570
|
+
🔴 **Violates Project Standard: Error Handling** (LoginViewModel.swift:45)
|
|
571
|
+
**Severity**: High
|
|
572
|
+
**Category**: Project Standards
|
|
573
|
+
|
|
574
|
+
**Project Guideline**: "All errors MUST conform to AppError protocol" (.claude/CLAUDE.md:Error Handling)
|
|
575
|
+
|
|
576
|
+
**Violation**: LoginError does not conform to AppError protocol
|
|
577
|
+
|
|
578
|
+
**Current Code:**
|
|
579
|
+
```swift
|
|
580
|
+
enum LoginError: Error {
|
|
581
|
+
case invalidCredentials
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
**Expected Code:**
|
|
586
|
+
```swift
|
|
587
|
+
enum LoginError: AppError {
|
|
588
|
+
case invalidCredentials
|
|
589
|
+
|
|
590
|
+
var message: String {
|
|
591
|
+
switch self {
|
|
592
|
+
case .invalidCredentials: return "Invalid email or password"
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
var code: Int {
|
|
597
|
+
switch self {
|
|
598
|
+
case .invalidCredentials: return 1001
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
**Reference**: .claude/CLAUDE.md:Error Handling
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
---
|
|
608
|
+
|
|
609
|
+
## 6. Integration with Review Process
|
|
610
|
+
|
|
611
|
+
### 6.1 Review Checklist
|
|
612
|
+
|
|
613
|
+
**Step-by-Step:**
|
|
614
|
+
|
|
615
|
+
1. **Load Project Guidelines**
|
|
616
|
+
```
|
|
617
|
+
- Read .claude/CLAUDE.md
|
|
618
|
+
- Read related architecture docs
|
|
619
|
+
- Extract all rules and patterns
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
2. **Create Validation Checklist**
|
|
623
|
+
```
|
|
624
|
+
- Architecture compliance
|
|
625
|
+
- Coding style adherence
|
|
626
|
+
- Error handling patterns
|
|
627
|
+
- Design system usage
|
|
628
|
+
- Testing requirements
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
3. **Validate Code**
|
|
632
|
+
```
|
|
633
|
+
- Compare code against each rule
|
|
634
|
+
- Flag violations
|
|
635
|
+
- Acknowledge compliance
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
4. **Generate Report**
|
|
639
|
+
```
|
|
640
|
+
- List all violations with references to .claude/CLAUDE.md
|
|
641
|
+
- Provide positive feedback for compliance
|
|
642
|
+
- Include specific line numbers and fixes
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### 6.2 Prioritization
|
|
646
|
+
|
|
647
|
+
**Severity Based on Impact:**
|
|
648
|
+
|
|
649
|
+
| Violation Type | Severity | Example |
|
|
650
|
+
|----------------|----------|---------|
|
|
651
|
+
| Architecture violation | High | Business logic in View |
|
|
652
|
+
| Security pattern violation | Critical | Credentials in UserDefaults |
|
|
653
|
+
| Error handling violation | High | No AppError conformance |
|
|
654
|
+
| Design system violation | Medium | Hardcoded colors |
|
|
655
|
+
| Style guide violation | Low | Naming convention |
|
|
656
|
+
| Testing requirement | Medium | Missing tests |
|
|
657
|
+
|
|
658
|
+
---
|
|
659
|
+
|
|
660
|
+
## 7. Example Project Guidelines
|
|
661
|
+
|
|
662
|
+
### 7.1 Complete .claude/CLAUDE.md Example
|
|
663
|
+
|
|
664
|
+
```markdown
|
|
665
|
+
# MyApp Coding Standards
|
|
666
|
+
|
|
667
|
+
## Architecture
|
|
668
|
+
|
|
669
|
+
We use **MVVM with Coordinators and Repositories**.
|
|
670
|
+
|
|
671
|
+
### Layers
|
|
672
|
+
- **View**: SwiftUI views, presentation only
|
|
673
|
+
- **ViewModel**: @Observable classes, business logic
|
|
674
|
+
- **Coordinator**: Navigation management
|
|
675
|
+
- **Repository**: Data access abstraction
|
|
676
|
+
- **Use Case**: Single business operations
|
|
677
|
+
|
|
678
|
+
### Rules
|
|
679
|
+
1. ViewModels MUST use @Observable (iOS 17+)
|
|
680
|
+
2. All dependencies MUST be injected via constructor
|
|
681
|
+
3. Views MUST NOT contain business logic
|
|
682
|
+
4. Navigation MUST go through Coordinator
|
|
683
|
+
|
|
684
|
+
## Error Handling
|
|
685
|
+
|
|
686
|
+
All errors MUST conform to AppError:
|
|
687
|
+
|
|
688
|
+
```swift
|
|
689
|
+
protocol AppError: Error {
|
|
690
|
+
var message: String { get }
|
|
691
|
+
var code: Int { get }
|
|
692
|
+
}
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
Error code ranges:
|
|
696
|
+
- 1000-1999: Authentication
|
|
697
|
+
- 2000-2999: Network
|
|
698
|
+
- 3000-3999: Database
|
|
699
|
+
|
|
700
|
+
## Design System
|
|
701
|
+
|
|
702
|
+
### Colors
|
|
703
|
+
Use `AppColors` enum ONLY. No hardcoded colors.
|
|
704
|
+
|
|
705
|
+
### Typography
|
|
706
|
+
Use `AppFonts` enum ONLY. No system fonts.
|
|
707
|
+
|
|
708
|
+
### Spacing
|
|
709
|
+
Use `AppSpacing` enum ONLY. No magic numbers.
|
|
710
|
+
|
|
711
|
+
## Testing
|
|
712
|
+
|
|
713
|
+
### Requirements
|
|
714
|
+
- Minimum coverage: 80%
|
|
715
|
+
- All ViewModels MUST have unit tests
|
|
716
|
+
- All Use Cases MUST have unit tests
|
|
717
|
+
- Critical flows MUST have UI tests
|
|
718
|
+
|
|
719
|
+
### Patterns
|
|
720
|
+
- Arrange-Act-Assert
|
|
721
|
+
- Mock all dependencies
|
|
722
|
+
- Descriptive names: `test[Method]_[Scenario]_[Expected]`
|
|
723
|
+
|
|
724
|
+
## SwiftUI Patterns
|
|
725
|
+
|
|
726
|
+
- @Observable for ViewModels
|
|
727
|
+
- @State for view-local state
|
|
728
|
+
- @Environment for dependencies
|
|
729
|
+
- View body < 50 lines
|
|
730
|
+
- Extract reusable subviews
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### 7.2 Validation Example
|
|
734
|
+
|
|
735
|
+
**Code to Review:**
|
|
736
|
+
|
|
737
|
+
```swift
|
|
738
|
+
// LoginViewModel.swift
|
|
739
|
+
@Observable
|
|
740
|
+
final class LoginViewModel {
|
|
741
|
+
private let loginUseCase: LoginUseCase
|
|
742
|
+
|
|
743
|
+
var email: String = ""
|
|
744
|
+
var password: String = ""
|
|
745
|
+
var isLoading: Bool = false
|
|
746
|
+
|
|
747
|
+
init(loginUseCase: LoginUseCase) {
|
|
748
|
+
self.loginUseCase = loginUseCase
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
func login() async {
|
|
752
|
+
// Implementation
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// LoginError.swift
|
|
757
|
+
enum LoginError: AppError {
|
|
758
|
+
case invalidCredentials
|
|
759
|
+
|
|
760
|
+
var message: String {
|
|
761
|
+
switch self {
|
|
762
|
+
case .invalidCredentials: return "Invalid email or password"
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
var code: Int {
|
|
767
|
+
switch self {
|
|
768
|
+
case .invalidCredentials: return 1001 // Auth range
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// LoginView.swift
|
|
774
|
+
struct LoginView: View {
|
|
775
|
+
let viewModel: LoginViewModel
|
|
776
|
+
|
|
777
|
+
var body: some View {
|
|
778
|
+
VStack(spacing: AppSpacing.medium) {
|
|
779
|
+
TextField("Email", text: $viewModel.email)
|
|
780
|
+
.textFieldStyle(.roundedBorder)
|
|
781
|
+
|
|
782
|
+
SecureField("Password", text: $viewModel.password)
|
|
783
|
+
.textFieldStyle(.roundedBorder)
|
|
784
|
+
|
|
785
|
+
Button("Login") {
|
|
786
|
+
Task { await viewModel.login() }
|
|
787
|
+
}
|
|
788
|
+
.buttonStyle(.borderedProminent)
|
|
789
|
+
}
|
|
790
|
+
.padding(AppSpacing.large)
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
**Review Report:**
|
|
796
|
+
|
|
797
|
+
```markdown
|
|
798
|
+
## Project Standards Compliance
|
|
799
|
+
|
|
800
|
+
✅ **Excellent Architecture Adherence**
|
|
801
|
+
- LoginViewModel uses @Observable (required for iOS 17+)
|
|
802
|
+
- Dependencies injected via constructor
|
|
803
|
+
- No business logic in LoginView
|
|
804
|
+
- Clear layer separation
|
|
805
|
+
|
|
806
|
+
✅ **Error Handling Compliance**
|
|
807
|
+
- LoginError conforms to AppError protocol
|
|
808
|
+
- Error code in correct range (1000-1999 for auth)
|
|
809
|
+
- Descriptive error messages
|
|
810
|
+
|
|
811
|
+
✅ **Design System Usage**
|
|
812
|
+
- Uses AppSpacing for all spacing
|
|
813
|
+
- No hardcoded values
|
|
814
|
+
- Consistent design token usage
|
|
815
|
+
|
|
816
|
+
✅ **SwiftUI Best Practices**
|
|
817
|
+
- Proper property wrapper usage (@Observable)
|
|
818
|
+
- View body is concise (< 50 lines)
|
|
819
|
+
- Clear separation of concerns
|
|
820
|
+
|
|
821
|
+
**Overall**: Fully compliant with project coding standards
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
## 8. Quick Reference
|
|
827
|
+
|
|
828
|
+
### Files to Check
|
|
829
|
+
1. `.claude/CLAUDE.md` - Main standards
|
|
830
|
+
2. `.claude/DependencyInjection-Architecture.md` - DI patterns
|
|
831
|
+
3. `.claude/Design System Structure.md` - Design system
|
|
832
|
+
4. `.claude/Testing-Guidelines.md` - Testing standards
|
|
833
|
+
|
|
834
|
+
### Key Validation Points
|
|
835
|
+
- [ ] Architecture pattern followed
|
|
836
|
+
- [ ] Error handling conforms to project standard
|
|
837
|
+
- [ ] Design system used (no hardcoded values)
|
|
838
|
+
- [ ] Testing requirements met
|
|
839
|
+
- [ ] Naming conventions followed
|
|
840
|
+
- [ ] Dependency injection pattern used
|
|
841
|
+
|
|
842
|
+
### Severity Guidelines
|
|
843
|
+
- **Critical**: Security, architecture violations
|
|
844
|
+
- **High**: Error handling, major patterns
|
|
845
|
+
- **Medium**: Design system, testing
|
|
846
|
+
- **Low**: Style, naming
|
|
847
|
+
|
|
848
|
+
---
|
|
849
|
+
|
|
850
|
+
## Version
|
|
851
|
+
**Last Updated**: 2026-02-10
|
|
852
|
+
**Version**: 1.0.0
|