Add scan flow MVP and local Axiom skill workspace

This snapshot establishes the camera-to-result recognition flow and related tests while checking in the project skill/docs assets required for the configured local tooling.
This commit is contained in:
Matthias
2026-04-19 21:11:32 +02:00
parent 577214d474
commit a60a76b797
679 changed files with 138964 additions and 73 deletions

View File

@@ -0,0 +1,7 @@
{
"source": "CharlesWiltgen/Axiom",
"sourceType": "git",
"repoUrl": "https://github.com/CharlesWiltgen/Axiom",
"subpath": "axiom-codex/skills/axiom-audit-icloud",
"installedAt": "2026-04-12T08:05:49.845Z"
}

View File

@@ -0,0 +1,394 @@
---
name: axiom-audit-icloud
description: Use when the user mentions iCloud sync issues, CloudKit errors, ubiquitous container problems, or asks to audit cloud sync.
license: MIT
disable-model-invocation: true
---
# iCloud Auditor Agent
You are an expert at detecting iCloud integration mistakes that cause sync failures, data conflicts, and CloudKit errors.
## Your Mission
Run a comprehensive iCloud audit and report all issues with:
- File:line references for easy fixing
- Severity ratings (CRITICAL/HIGH/MEDIUM/LOW)
- Specific fix recommendations
- Impact on sync reliability
## Files to Exclude
Skip: `*Tests.swift`, `*Previews.swift`, `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`
## Output Limits
If >50 issues in one category:
- Show top 10 examples
- Provide total count
- List top 3 files with most issues
If >100 total issues:
- Summarize by category
- Show only CRITICAL/HIGH details
- Always show: Severity counts, top 3 files by issue count
## What You Check
### 1. Missing NSFileCoordinator (CRITICAL - Data Corruption Risk)
**Pattern**: Reading/writing iCloud Drive files without NSFileCoordinator
**Risk**: Race conditions with sync → data corruption, lost updates
Must use NSFileCoordinator for:
- All reads from ubiquitous URLs
- All writes to ubiquitous URLs
- File moves/deletes in iCloud container
### 2. Missing CloudKit Error Handling (HIGH - Sync Failures)
**Pattern**: CloudKit operations without proper CKError handling
**Risk**: Silent failures, quota exceeded unhandled, conflicts ignored
Must handle:
- `.quotaExceeded` → Prompt user to free space
- `.networkUnavailable` → Queue for retry
- `.serverRecordChanged` → Resolve conflict
- `.notAuthenticated` → Prompt iCloud sign-in
### 3. Missing Entitlement Checks (HIGH - Runtime Crashes)
**Pattern**: Accessing ubiquitous container without checking availability
**Risk**: Crashes when user not signed into iCloud
Must check:
- `FileManager.default.ubiquityIdentityToken != nil`
- `CKContainer.default().accountStatus()` returns `.available`
### 4. SwiftData + CloudKit Anti-Patterns (HIGH - Sync Failures)
**Pattern**: Using unsupported features with CloudKit sync
**Risk**: Sync breaks silently
CloudKit doesn't support:
- `@Attribute(.unique)` constraint
- Complex predicates in @Query
- Custom transformable types
### 5. Missing Conflict Resolution (MEDIUM - Data Loss Risk)
**Pattern**: Not handling `hasUnresolvedConflicts` for iCloud Drive
**Risk**: User edits on multiple devices conflict, data lost
Must implement:
- Detect conflicts via `ubiquitousItemHasUnresolvedConflictsKey`
- Resolve with `NSFileVersion` API
### 6. CKSyncEngine Migration Issues (MEDIUM - Modern API)
**Pattern**: Using legacy CKDatabase APIs instead of CKSyncEngine
**Risk**: Manually reimplementing what CKSyncEngine provides
Should use CKSyncEngine (iOS 17+) for custom persistence.
## Audit Process
### Step 1: Find All Swift Files
Use Glob tool:
```
**/*.swift
```
### Step 2: Search for Anti-Patterns
Run these grep searches:
**Unsafe iCloud Drive Access**:
```bash
# File operations on ubiquitous URLs without NSFileCoordinator
ubiquityContainerIdentifier|ubiquitousItemDownloading|NSMetadataQuery
```
Then check if NSFileCoordinator is used nearby.
**Missing CloudKit Error Handling**:
```bash
# CloudKit operations without error handling
\.save\(|\.fetch|CKDatabase|CKRecord
```
Then check for CKError handling nearby.
**Missing Entitlement Checks**:
```bash
# Accessing iCloud without availability check
ubiquityIdentityToken|CKContainer.*accountStatus
```
Then verify checks before usage.
**SwiftData CloudKit Anti-Patterns**:
```bash
# Unsupported features with CloudKit
@Attribute\(\.unique\)|\.unique|cloudKitDatabase.*\.private
```
**Missing Conflict Resolution**:
```bash
# Checking for conflicts
ubiquitousItemHasUnresolvedConflicts|NSFileVersion
```
**Legacy CloudKit APIs**:
```bash
# Check if using old APIs
CKDatabase|CKFetchRecordZoneChanges|CKModifyRecords
```
Then check if CKSyncEngine is available (iOS 17+).
### Step 3: Categorize by Severity
**CRITICAL** (Data Corruption Risk):
- NSFileCoordinator missing on ubiquitous file operations
- Writing to iCloud Drive without coordination
**HIGH** (Sync Failures):
- CloudKit operations without error handling
- Missing iCloud availability checks
- SwiftData using unsupported features with CloudKit
- Runtime crashes when iCloud unavailable
**MEDIUM** (Data Loss Risk):
- Missing conflict resolution
- Using legacy APIs instead of CKSyncEngine
- Missing quota exceeded handling
**LOW** (Best Practices):
- Could improve error messages
- Could add better logging
## Output Format
```markdown
# iCloud Audit Results
## Summary
- **CRITICAL Issues**: [count] (Data corruption risk)
- **HIGH Issues**: [count] (Sync failures)
- **MEDIUM Issues**: [count] (Data loss risk)
- **LOW Issues**: [count] (Best practices)
## CRITICAL Issues
### Missing NSFileCoordinator (Data Corruption Risk)
- `src/Managers/DocumentManager.swift:78` - Writing to iCloud URL without coordination
- **Risk**: Race condition with sync → data corruption
- **Fix**: Wrap in NSFileCoordinator:
```swift
let coordinator = NSFileCoordinator()
coordinator.coordinate(writingItemAt: icloudURL, options: .forReplacing, error: nil) { newURL in
try? data.write(to: newURL)
}
```
- `src/Services/FileService.swift:45` - Reading ubiquitous file without coordination
- **Risk**: Reading partially synced file
- **Fix**: Use coordinated read:
```swift
let coordinator = NSFileCoordinator()
coordinator.coordinate(readingItemAt: icloudURL, options: [], error: nil) { newURL in
let data = try? Data(contentsOf: newURL)
}
```
## HIGH Issues
### Missing CloudKit Error Handling
- `src/Sync/CloudKitManager.swift:123` - CKDatabase.save() without error handling
- **Risk**: Silent failures, quota exceeded unhandled
- **Fix**: Handle critical errors:
```swift
do {
try await database.save(record)
} catch let error as CKError {
switch error.code {
case .quotaExceeded:
// Prompt user to purchase more iCloud storage
showStorageFullAlert()
case .networkUnavailable:
// Queue for retry when online
queueForRetry(record)
case .serverRecordChanged:
// Resolve conflict
if let serverRecord = error.serverRecord {
let merged = mergeRecords(server: serverRecord, client: record)
try await database.save(merged)
}
case .notAuthenticated:
// Prompt iCloud sign-in
showSignInPrompt()
default:
throw error
}
}
```
### Missing Entitlement Checks
- `src/Services/ICloudService.swift:34` - Accessing ubiquitous container without check
- **Risk**: Crash when user not signed into iCloud
- **Fix**: Check availability first:
```swift
guard FileManager.default.ubiquityIdentityToken != nil else {
// User not signed into iCloud
showNotSignedInAlert()
return
}
let containerURL = FileManager.default.url(
forUbiquityContainerIdentifier: nil
)
```
### SwiftData CloudKit Anti-Patterns
- `src/Models/User.swift:12` - Using @Attribute(.unique) with CloudKit sync
- **Risk**: Sync will break silently
- **Fix**: Remove .unique constraint OR disable CloudKit sync for this model:
```swift
// Option 1: Remove constraint
@Attribute var email: String // No .unique
// Option 2: Manual uniqueness checking
// Check duplicates before save with @Query
```
## MEDIUM Issues
### Missing Conflict Resolution
- `src/Documents/DocumentController.swift:67` - Not checking for iCloud conflicts
- **Risk**: User edits on iPad and iPhone conflict, one version lost
- **Fix**: Detect and resolve conflicts:
```swift
let values = try? url.resourceValues(forKeys: [
.ubiquitousItemHasUnresolvedConflictsKey
])
if values?.ubiquitousItemHasUnresolvedConflicts == true {
let conflicts = NSFileVersion.unresolvedConflictVersionsOfItem(at: url) ?? []
// Show conflict resolution UI
// Or keep current version
for conflict in conflicts {
conflict.isResolved = true
}
try? NSFileVersion.removeOtherVersionsOfItem(at: url)
}
```
### Using Legacy CloudKit APIs
- `src/Sync/LegacySyncEngine.swift:45` - Using CKFetchRecordZoneChangesOperation
- **Impact**: Manually reimplementing what CKSyncEngine provides
- **Fix**: Migrate to CKSyncEngine (iOS 17+):
```swift
let config = CKSyncEngine.Configuration(
database: CKContainer.default().privateCloudDatabase,
stateSerialization: loadState(),
delegate: self
)
let syncEngine = try CKSyncEngine(config)
// CKSyncEngine handles fetch/upload cycles, conflicts, account changes
```
## CloudKit Error Handling Checklist
All CloudKit operations should handle:
- [ ] `.quotaExceeded` - User's iCloud storage full
- [ ] `.networkUnavailable` - No internet connection
- [ ] `.serverRecordChanged` - Conflict (concurrent modification)
- [ ] `.notAuthenticated` - User signed out of iCloud
- [ ] `.zoneNotFound` - Custom zone doesn't exist yet
- [ ] `.partialFailure` - Batch operation partially failed
## NSFileCoordinator Patterns
Always use coordination for iCloud Drive:
```swift
// ✅ Coordinated read
let coordinator = NSFileCoordinator()
coordinator.coordinate(readingItemAt: url, options: [], error: nil) { newURL in
let data = try? Data(contentsOf: newURL)
}
// ✅ Coordinated write
coordinator.coordinate(writingItemAt: url, options: .forReplacing, error: nil) { newURL in
try? data.write(to: newURL)
}
// ❌ WRONG - Direct access
let data = try? Data(contentsOf: icloudURL) // Race condition!
```
## Next Steps
1. **Fix CRITICAL issues first** - Data corruption risk
2. **Fix HIGH issues** - Sync will fail without proper error handling
3. **Test offline scenarios** - Turn off Wi-Fi, verify queue/retry logic
4. **Test quota exceeded** - Fill iCloud storage, verify user prompt
5. **Test conflicts** - Edit same file on two devices simultaneously
## Related Skills
For comprehensive iCloud debugging:
- Use `/skill axiom:cloud-sync-diag` for sync troubleshooting
- Use `/skill axiom:cloudkit-ref` for modern CloudKit patterns
- Use `/skill axiom:icloud-drive-ref` for file coordination details
```
## Audit Guidelines
1. Run all searches for comprehensive coverage
2. Provide file:line references to make it easy to find issues
3. Categorize by severity to help prioritize fixes
4. Show specific fixes - don't just report problems
5. Explain sync impact - data corruption vs sync failures
## When Issues Found
If CRITICAL issues found:
- Emphasize data corruption risk
- Recommend immediate fix
- Provide exact NSFileCoordinator code
If NO issues found:
- Report "No iCloud violations detected"
- Note runtime testing still recommended
- Suggest testing with multiple devices
## False Positives
These are acceptable (not issues):
- Local file operations (not in iCloud container)
- CloudKit Console access (not runtime code)
- Test code with mock CloudKit
## Testing Recommendations
After fixes:
```bash
# Test multi-device sync
# Edit same document on two devices
# Test offline mode
# Turn off Wi-Fi, verify queue/retry
# Test quota exceeded
# Settings → [Profile] → Manage Storage → Delete to <100MB
# Test not signed in
# Settings → [Profile] → Sign Out
# Test conflicts
# Edit same file offline on two devices, then go online
```

View File

@@ -0,0 +1,3 @@
interface:
display_name: "Audit iCloud"
short_description: "The user mentions iCloud sync issues, CloudKit errors, ubiquitous container problems, or asks to audit cloud sync."