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:
378
.claude/skills/axiom-energy-diag/SKILL.md
Normal file
378
.claude/skills/axiom-energy-diag/SKILL.md
Normal file
@@ -0,0 +1,378 @@
|
||||
---
|
||||
name: axiom-energy-diag
|
||||
description: Symptom-based energy troubleshooting - decision trees for 'app at top of battery settings', 'phone gets hot', 'background drain', 'high cellular usage', with time-cost analysis for each diagnosis path
|
||||
license: MIT
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
---
|
||||
|
||||
# Energy Diagnostics
|
||||
|
||||
Symptom-based troubleshooting for energy issues. Start with your symptom, follow the decision tree, get the fix.
|
||||
|
||||
**Related skills**: `axiom-energy` (patterns, checklists), `axiom-energy-ref` (API reference)
|
||||
|
||||
---
|
||||
|
||||
## Symptom 1: App at Top of Battery Settings
|
||||
|
||||
Users or you notice your app consuming significant battery.
|
||||
|
||||
### Diagnosis Decision Tree
|
||||
|
||||
```
|
||||
App at top of Battery Settings?
|
||||
│
|
||||
├─ Step 1: Run Power Profiler (15 min)
|
||||
│ ├─ CPU Power Impact high?
|
||||
│ │ ├─ Continuous? → Timer leak or polling loop
|
||||
│ │ │ └─ Fix: Check timers, add tolerance, convert to push
|
||||
│ │ └─ Spikes during actions? → Eager loading or repeated parsing
|
||||
│ │ └─ Fix: Use LazyVStack, cache parsed data
|
||||
│ │
|
||||
│ ├─ Network Power Impact high?
|
||||
│ │ ├─ Many small requests? → Batching issue
|
||||
│ │ │ └─ Fix: Batch requests, use discretionary URLSession
|
||||
│ │ └─ Regular intervals? → Polling pattern
|
||||
│ │ └─ Fix: Convert to push notifications
|
||||
│ │
|
||||
│ ├─ GPU Power Impact high?
|
||||
│ │ ├─ Animations? → Running when not visible
|
||||
│ │ │ └─ Fix: Stop in viewWillDisappear
|
||||
│ │ └─ Blur effects? → Over dynamic content
|
||||
│ │ └─ Fix: Remove or use static backgrounds
|
||||
│ │
|
||||
│ └─ Display Power Impact high?
|
||||
│ └─ Light backgrounds on OLED?
|
||||
│ └─ Fix: Implement Dark Mode (up to 70% savings)
|
||||
│
|
||||
└─ Step 2: Check background section in Battery Settings
|
||||
├─ High background time?
|
||||
│ ├─ Location icon visible? → Continuous location
|
||||
│ │ └─ Fix: Switch to significant-change monitoring
|
||||
│ ├─ Audio active? → Session not deactivated
|
||||
│ │ └─ Fix: Deactivate audio session when not playing
|
||||
│ └─ BGTasks running long? → Not completing promptly
|
||||
│ └─ Fix: Call setTaskCompleted sooner
|
||||
│
|
||||
└─ Background time appropriate?
|
||||
└─ Issue is in foreground usage → Focus on CPU/GPU fixes above
|
||||
```
|
||||
|
||||
### Time-Cost Analysis
|
||||
|
||||
| Approach | Time | Accuracy |
|
||||
|----------|------|----------|
|
||||
| Run Power Profiler, identify subsystem | 15-20 min | High |
|
||||
| Guess and optimize random areas | 4+ hours | Low |
|
||||
| Read all code looking for issues | 2+ hours | Medium |
|
||||
|
||||
**Recommendation**: Always use Power Profiler first. It costs 15 minutes but guarantees you optimize the right subsystem.
|
||||
|
||||
---
|
||||
|
||||
## Symptom 2: Device Gets Hot
|
||||
|
||||
Device temperature increases noticeably during app use.
|
||||
|
||||
### Diagnosis Decision Tree
|
||||
|
||||
```
|
||||
Device gets hot during app use?
|
||||
│
|
||||
├─ Hot during specific action?
|
||||
│ │
|
||||
│ ├─ During video/camera use?
|
||||
│ │ ├─ Video encoding? → Expected, but check efficiency
|
||||
│ │ │ └─ Fix: Use hardware encoding, reduce resolution if possible
|
||||
│ │ └─ Camera active unnecessarily? → Not releasing session
|
||||
│ │ └─ Fix: Call stopRunning() when done
|
||||
│ │
|
||||
│ ├─ During scroll/animation?
|
||||
│ │ ├─ GPU-intensive effects? → Blur, shadows, many layers
|
||||
│ │ │ └─ Fix: Reduce effects, cache rendered content
|
||||
│ │ └─ High frame rate? → Unnecessary 120fps
|
||||
│ │ └─ Fix: Use CADisplayLink preferredFrameRateRange
|
||||
│ │
|
||||
│ └─ During data processing?
|
||||
│ ├─ JSON parsing? → Repeated or large payloads
|
||||
│ │ └─ Fix: Cache parsed results, paginate
|
||||
│ └─ Image processing? → Synchronous on main thread
|
||||
│ └─ Fix: Move to background, cache results
|
||||
│
|
||||
├─ Hot during normal use (no specific action)?
|
||||
│ │
|
||||
│ ├─ Run Power Profiler to identify:
|
||||
│ │ ├─ CPU high continuously → Timer, polling, tight loop
|
||||
│ │ ├─ GPU high continuously → Animation leak
|
||||
│ │ └─ Network high continuously → Polling pattern
|
||||
│ │
|
||||
│ └─ Check for infinite loops or runaway recursion
|
||||
│ └─ Use Time Profiler in Instruments
|
||||
│
|
||||
└─ Hot only in background?
|
||||
├─ Location updates continuous? → High accuracy or no stop
|
||||
│ └─ Fix: Reduce accuracy, stop when done
|
||||
├─ Audio session active? → Hardware kept powered
|
||||
│ └─ Fix: Deactivate when not playing
|
||||
└─ BGTask running too long? → System may throttle
|
||||
└─ Fix: Complete tasks faster, use requiresExternalPower
|
||||
```
|
||||
|
||||
### Time-Cost Analysis
|
||||
|
||||
| Approach | Time | Outcome |
|
||||
|----------|------|---------|
|
||||
| Power Profiler + Time Profiler | 20-30 min | Identifies exact cause |
|
||||
| Check code for obvious issues | 1-2 hours | May miss non-obvious causes |
|
||||
| Wait for user complaints | N/A | Reputation damage |
|
||||
|
||||
---
|
||||
|
||||
## Symptom 3: Background Battery Drain
|
||||
|
||||
App drains battery even when user isn't actively using it.
|
||||
|
||||
### Diagnosis Decision Tree
|
||||
|
||||
```
|
||||
High background battery usage?
|
||||
│
|
||||
├─ Step 1: Check Info.plist background modes
|
||||
│ │
|
||||
│ ├─ "location" enabled?
|
||||
│ │ ├─ Actually need background location?
|
||||
│ │ │ ├─ YES → Use significant-change, lowest accuracy
|
||||
│ │ │ └─ NO → Remove background mode, use when-in-use only
|
||||
│ │ └─ Check: Is stopUpdatingLocation called?
|
||||
│ │
|
||||
│ ├─ "audio" enabled?
|
||||
│ │ ├─ Audio playing? → Expected
|
||||
│ │ ├─ Audio NOT playing? → Session still active
|
||||
│ │ │ └─ Fix: Deactivate session, use autoShutdownEnabled
|
||||
│ │ └─ Playing silent audio? → Anti-pattern for keeping app alive
|
||||
│ │ └─ Fix: Use proper background API (BGTask)
|
||||
│ │
|
||||
│ ├─ "fetch" enabled?
|
||||
│ │ └─ Check: Is earliestBeginDate reasonable? (not too frequent)
|
||||
│ │
|
||||
│ └─ "remote-notification" enabled?
|
||||
│ └─ Expected for push updates, check didReceiveRemoteNotification efficiency
|
||||
│
|
||||
├─ Step 2: Check BGTaskScheduler usage
|
||||
│ │
|
||||
│ ├─ BGAppRefreshTask scheduled too frequently?
|
||||
│ │ └─ Fix: Increase earliestBeginDate interval
|
||||
│ │
|
||||
│ ├─ BGProcessingTask not using requiresExternalPower?
|
||||
│ │ └─ Fix: Add requiresExternalPower = true for non-urgent work
|
||||
│ │
|
||||
│ └─ Tasks not completing? (setTaskCompleted not called)
|
||||
│ └─ Fix: Always call setTaskCompleted, implement expirationHandler
|
||||
│
|
||||
└─ Step 3: Check beginBackgroundTask usage
|
||||
│
|
||||
├─ endBackgroundTask called promptly?
|
||||
│ └─ Fix: Call immediately after work completes, not at expiration
|
||||
│
|
||||
└─ Multiple overlapping background tasks?
|
||||
└─ Fix: Track task IDs, ensure each is ended
|
||||
```
|
||||
|
||||
### Common Background Drain Patterns
|
||||
|
||||
| Pattern | Power Profiler Signature | Fix |
|
||||
|---------|-------------------------|-----|
|
||||
| Continuous location | CPU lane + location icon | significant-change |
|
||||
| Audio session leak | CPU lane steady | setActive(false) |
|
||||
| Timer not invalidated | CPU spikes at intervals | invalidate in background |
|
||||
| Polling from background | Network lane at intervals | Push notifications |
|
||||
| BGTask too long | CPU sustained | Faster completion |
|
||||
|
||||
### Time-Cost Analysis
|
||||
|
||||
| Approach | Time | Outcome |
|
||||
|----------|------|---------|
|
||||
| Check Info.plist + BGTask code | 30 min | Finds common issues |
|
||||
| On-device Power Profiler trace | 1-2 hours (real usage) | Captures real behavior |
|
||||
| User-collected trace | Variable | Best for unreproducible issues |
|
||||
|
||||
---
|
||||
|
||||
## Symptom 4: High Energy Only on Cellular
|
||||
|
||||
Battery drains faster on cellular than WiFi.
|
||||
|
||||
### Diagnosis Decision Tree
|
||||
|
||||
```
|
||||
High battery drain on cellular only?
|
||||
│
|
||||
├─ Expected: Cellular radio uses more power than WiFi
|
||||
│ └─ But: Excessive drain indicates optimization opportunity
|
||||
│
|
||||
├─ Check URLSession configuration
|
||||
│ │
|
||||
│ ├─ allowsExpensiveNetworkAccess = true (default)?
|
||||
│ │ └─ Fix: Set to false for non-urgent requests
|
||||
│ │
|
||||
│ ├─ isDiscretionary = false (default)?
|
||||
│ │ └─ Fix: Set to true for background downloads
|
||||
│ │
|
||||
│ └─ waitsForConnectivity = false (default)?
|
||||
│ └─ Fix: Set to true to avoid failed connection retries
|
||||
│
|
||||
├─ Check request patterns
|
||||
│ │
|
||||
│ ├─ Many small requests? → High connection overhead
|
||||
│ │ └─ Fix: Batch into fewer larger requests
|
||||
│ │
|
||||
│ ├─ Polling? → Radio stays active
|
||||
│ │ └─ Fix: Push notifications
|
||||
│ │
|
||||
│ └─ Large downloads in foreground? → Could wait for WiFi
|
||||
│ └─ Fix: Use background URLSession with discretionary
|
||||
│
|
||||
└─ Check Low Data Mode handling
|
||||
├─ Respecting allowsConstrainedNetworkAccess?
|
||||
│ └─ Fix: Set to false for non-essential requests
|
||||
│
|
||||
└─ Checking ProcessInfo.processInfo.isLowDataModeEnabled?
|
||||
└─ Fix: Reduce payload sizes, defer non-essential transfers
|
||||
```
|
||||
|
||||
### Time-Cost Analysis
|
||||
|
||||
| Approach | Time | Outcome |
|
||||
|----------|------|---------|
|
||||
| Review URLSession configs | 15 min | Quick wins |
|
||||
| Add discretionary flags | 30 min | Significant savings |
|
||||
| Convert poll to push | 2-4 hours | Largest impact |
|
||||
|
||||
---
|
||||
|
||||
## Symptom 5: Energy Spike During Specific Action
|
||||
|
||||
Noticeable battery drain or heat when performing particular operation.
|
||||
|
||||
### Diagnosis Decision Tree
|
||||
|
||||
```
|
||||
Energy spike during specific action?
|
||||
│
|
||||
├─ Step 1: Record Power Profiler during action
|
||||
│ └─ Note which subsystem spikes (CPU/GPU/Network/Display)
|
||||
│
|
||||
├─ CPU spike?
|
||||
│ │
|
||||
│ ├─ Is it parsing data?
|
||||
│ │ ├─ Same data parsed repeatedly?
|
||||
│ │ │ └─ Fix: Cache parsed results (lazy var)
|
||||
│ │ └─ Large JSON/XML payload?
|
||||
│ │ └─ Fix: Paginate, stream parse, or use binary format
|
||||
│ │
|
||||
│ ├─ Is it creating views?
|
||||
│ │ ├─ Many views at once?
|
||||
│ │ │ └─ Fix: Use LazyVStack/LazyHStack
|
||||
│ │ └─ Complex view hierarchies?
|
||||
│ │ └─ Fix: Simplify, use drawingGroup()
|
||||
│ │
|
||||
│ └─ Is it image processing?
|
||||
│ ├─ On main thread?
|
||||
│ │ └─ Fix: Move to background queue
|
||||
│ └─ No caching?
|
||||
│ └─ Fix: Cache processed images
|
||||
│
|
||||
├─ GPU spike?
|
||||
│ │
|
||||
│ ├─ Starting animation?
|
||||
│ │ └─ Fix: Ensure frame rate appropriate
|
||||
│ │
|
||||
│ ├─ Showing blur effect?
|
||||
│ │ └─ Fix: Use solid color or pre-rendered blur
|
||||
│ │
|
||||
│ └─ Complex render? (shadows, masks, many layers)
|
||||
│ └─ Fix: Simplify, use shouldRasterize, cache
|
||||
│
|
||||
├─ Network spike?
|
||||
│ │
|
||||
│ ├─ Large download started?
|
||||
│ │ └─ Fix: Use background URLSession, show progress
|
||||
│ │
|
||||
│ ├─ Many parallel requests?
|
||||
│ │ └─ Fix: Limit concurrency, batch
|
||||
│ │
|
||||
│ └─ Retrying failed requests?
|
||||
│ └─ Fix: Exponential backoff, waitsForConnectivity
|
||||
│
|
||||
└─ Display spike?
|
||||
└─ Unusual unless changing brightness programmatically
|
||||
└─ Fix: Don't modify brightness, let system control
|
||||
```
|
||||
|
||||
### Time-Cost Analysis
|
||||
|
||||
| Approach | Time | Outcome |
|
||||
|----------|------|---------|
|
||||
| Power Profiler during action | 5-10 min | Identifies subsystem |
|
||||
| Time Profiler for CPU details | 10-15 min | Identifies function |
|
||||
| Code review without profiling | 1+ hours | May miss actual cause |
|
||||
|
||||
---
|
||||
|
||||
## Quick Diagnostic Checklist
|
||||
|
||||
Use this when you need fast answers:
|
||||
|
||||
### 30-Second Check
|
||||
- [ ] Device plugged in? (Power metrics show 0)
|
||||
- [ ] Debug build? (Less optimized than release)
|
||||
- [ ] Low Power Mode on? (May affect measurements)
|
||||
|
||||
### 5-Minute Check (Power Profiler)
|
||||
- [ ] Which subsystem is dominant? (CPU/GPU/Network/Display)
|
||||
- [ ] Sustained or spiky?
|
||||
- [ ] Foreground or background?
|
||||
|
||||
### 15-Minute Investigation
|
||||
- [ ] If CPU: Run Time Profiler to identify function
|
||||
- [ ] If Network: Check request frequency and size
|
||||
- [ ] If GPU: Check animation frame rates
|
||||
- [ ] If Background: Check Info.plist modes
|
||||
|
||||
### Common Quick Fixes
|
||||
|
||||
| Finding | Quick Fix | Time |
|
||||
|---------|-----------|------|
|
||||
| Timer without tolerance | Add `.tolerance = 0.1` | 1 min |
|
||||
| VStack with large ForEach | Change to LazyVStack | 1 min |
|
||||
| allowsExpensiveNetworkAccess = true | Set to false | 1 min |
|
||||
| Missing stopUpdatingLocation | Add stop call | 2 min |
|
||||
| No Dark Mode | Add asset variants | 30 min |
|
||||
| Audio session always active | Add setActive(false) | 5 min |
|
||||
|
||||
---
|
||||
|
||||
## When to Escalate
|
||||
|
||||
### Use `axiom-energy` skill when
|
||||
- Need full audit checklist
|
||||
- Want comprehensive patterns with code
|
||||
- Planning proactive optimization
|
||||
|
||||
### Use `axiom-energy-ref` skill when
|
||||
- Need specific API details
|
||||
- Want complete code examples
|
||||
- Implementing from scratch
|
||||
|
||||
### Use `energy-auditor` agent when
|
||||
- Want automated codebase scan
|
||||
- Looking for anti-patterns at scale
|
||||
- Pre-release energy audit
|
||||
|
||||
Run: `/axiom:audit energy`
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-12-26
|
||||
**Platforms**: iOS 26+, iPadOS 26+
|
||||
Reference in New Issue
Block a user