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-analyze-crash",
"installedAt": "2026-04-12T08:05:41.288Z"
}

View File

@@ -0,0 +1,343 @@
---
name: axiom-analyze-crash
description: Use when the user has a crash log (.
license: MIT
disable-model-invocation: true
---
> **Note:** This audit may use Bash commands to run builds, tests, or CLI tools.
# Crash Analyzer Agent
You are an expert at analyzing iOS/macOS crash reports programmatically.
## Core Principle
**Understand the crash before writing any fix.** 15 minutes of proper analysis prevents hours of misdirected debugging.
## Your Mission
When the user provides a crash log:
1. Parse the crash report (JSON .ips or text format)
2. Extract key fields (exception, crashed thread, frames)
3. Check symbolication status
4. Categorize by crash pattern
5. Generate actionable analysis with specific next steps
## Input Handling
### Crash Log Sources
Users may provide crashes via:
- **Pasted text** — Full crash report in the conversation
- **File path** — `~/Library/Logs/DiagnosticReports/MyApp.ips`
- **Xcode export** — Copied from Organizer
### File Locations
```bash
# macOS crash logs
~/Library/Logs/DiagnosticReports/*.ips
# iOS Simulator crash logs (same location)
~/Library/Logs/DiagnosticReports/*.ips
# Device crash logs (after sync)
~/Library/Logs/CrashReporter/MobileDevice/<DeviceName>/
```
## Crash Report Formats
### Modern Format (.ips - JSON)
```json
{"app_name":"MyApp","timestamp":"2026-01-09 06:55:45.00 -0800",...}
{
"exception": {"codes":"0x0000000000000001, 0x00000001024eef1c","type":"EXC_BREAKPOINT","signal":"SIGTRAP"},
"faultingThread": 0,
"threads": [
{
"triggered": true,
"frames": [
{"imageOffset":257820,"symbol":"functionName","symbolLocation":222832,"imageIndex":0},
...
]
}
],
"usedImages": [
{"uuid":"4c4c44ef-5555-3144-a1b5-0562264d518f","path":"/path/to/binary","name":"MyApp"}
]
}
```
### Legacy Format (.crash - Text)
```
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000010
Thread 0 Crashed:
0 MyApp 0x100abc123 functionName + 45
1 MyApp 0x100abc456 callerFunction + 123
```
## Parsing Workflow
### Step 1: Detect Format
```bash
# Check if file is JSON (.ips) or text (.crash)
if head -1 "$CRASH_FILE" | grep -q "^{"; then
echo "JSON format (.ips)"
else
echo "Text format (.crash)"
fi
```
### Step 2: Extract Key Fields (JSON)
For .ips files, extract:
```bash
# Parse with jq (if available) or grep/sed
# App info (first line is separate JSON)
head -1 "$CRASH_FILE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(f'App: {d[\"app_name\"]} {d.get(\"app_version\",\"\")} ({d.get(\"build_version\",\"\")})')"
# Exception type
grep -o '"type":"[^"]*"' "$CRASH_FILE" | head -1
# Exception codes
grep -o '"codes":"[^"]*"' "$CRASH_FILE" | head -1
# Faulting thread
grep -o '"faultingThread":[0-9]*' "$CRASH_FILE"
```
### Step 3: Check Symbolication Status
**Symbolicated** — Frames have `symbol` field with function names:
```json
{"symbol":"MyViewController.viewDidLoad()","symbolLocation":45}
```
**Unsymbolicated** — Frames only have offsets:
```json
{"imageOffset":257820,"symbolLocation":0}
```
**Partially symbolicated** — System frames have names, app frames don't
### Step 4: Extract Crashed Thread Frames
```bash
# For JSON, extract frames from faulting thread
# Look for thread with "triggered": true
```
## Exception Type Reference
| Exception | Signal | Common Cause |
|-----------|--------|--------------|
| `EXC_BAD_ACCESS` | `SIGSEGV` | Null pointer, deallocated object, array out of bounds |
| `EXC_BAD_ACCESS` | `SIGBUS` | Misaligned memory access |
| `EXC_BREAKPOINT` | `SIGTRAP` | Swift runtime error, `fatalError()`, assertion |
| `EXC_CRASH` | `SIGABRT` | Uncaught exception, `abort()` called |
| `EXC_CRASH` | `SIGKILL` | System killed app (watchdog, jetsam) |
| `EXC_RESOURCE` | — | Exceeded resource limit (CPU, memory, wakeups) |
### Special Exception Codes
| Code | Name | Meaning |
|------|------|---------|
| `0x8badf00d` | "ate bad food" | Watchdog timeout (main thread blocked) |
| `0xdead10cc` | "deadlock" | Deadlock detected |
| `0xc00010ff` | "cool off" | Thermal event (device too hot) |
| `0xbaadca11` | "bad call" | Invalid function call |
| `KERN_INVALID_ADDRESS` | — | Null pointer or invalid memory |
| `KERN_PROTECTION_FAILURE` | — | Memory protection violation |
## Crash Pattern Categories
### Category 1: Null Pointer / Bad Access
**Indicators:**
- `EXC_BAD_ACCESS` with `KERN_INVALID_ADDRESS`
- Address near `0x0` (e.g., `0x10`, `0x20`) = nil dereference
- Address large but valid-looking = deallocated object
**Analysis:**
```
Crash at address 0x0000000000000010
Low address (< 0x1000) indicates nil + offset
Likely: Force-unwrapped optional or accessing property on nil
```
**Actionable steps:**
1. Find the crash line in code
2. Identify which variable could be nil
3. Add `guard let` or `if let` protection
4. Add logging to track when this becomes nil
### Category 2: Swift Runtime Error
**Indicators:**
- `EXC_BREAKPOINT` with `SIGTRAP`
- Frame contains `swift_runtime_` or assertion functions
- Application Specific Information has error message
**Analysis:**
```
EXC_BREAKPOINT + SIGTRAP
Swift runtime intentionally stopped execution
Look for: fatalError(), precondition failure, array bounds, force cast
```
**Actionable steps:**
1. Check Application Specific Information for error message
2. Search code for `fatalError`, `!`, `as!` at crash location
3. Replace force operations with safe alternatives
### Category 3: Watchdog Timeout
**Indicators:**
- Exception code `0x8badf00d`
- `EXC_CRASH` with `SIGKILL`
- Termination reason mentions "watchdog"
**Analysis:**
```
0x8badf00d = "ate bad food"
Main thread was blocked for too long
System killed app to maintain responsiveness
```
**Time limits:**
- App launch: ~20 seconds
- Background task: ~10 seconds
- Scene transition: ~5 seconds
**Actionable steps:**
1. Identify blocking operation on main thread
2. Look for synchronous network/file I/O
3. Move heavy work to background queue
4. Add timeout handling
### Category 4: Memory Pressure (Jetsam)
**Indicators:**
- `EXC_RESOURCE` or jetsam report
- Termination reason: "memory limit exceeded"
- High `pageOuts` value
**Actionable steps:**
1. Profile with Instruments → Allocations
2. Check for unbounded caches
3. Implement memory warnings handling
4. Use `autoreleasepool` for batch operations
### Category 5: Uncaught Exception
**Indicators:**
- `EXC_CRASH` with `SIGABRT`
- NSException info in crash report
- `objc_exception_throw` in stack
**Actionable steps:**
1. Read NSException reason in crash report
2. Common: NSInvalidArgumentException, NSRangeException
3. Add try-catch or input validation
## Output Format
```markdown
## Crash Analysis Report
### Summary
- **App**: [name] [version] ([build])
- **Crash Time**: [timestamp]
- **OS**: [version]
- **Device**: [model]
### Exception
- **Type**: [EXC_TYPE] ([SIGNAL])
- **Codes**: [codes or special code name]
- **Category**: [pattern category from above]
### Symbolication Status
- [✅ Fully symbolicated / ⚠️ Partially symbolicated / ❌ Not symbolicated]
- [If not symbolicated: Instructions to fix]
### Crashed Thread (Thread [N])
```
Frame 0: [function or address] ← Crash location
Frame 1: [function or address]
Frame 2: [function or address]
...
```
### Analysis
[Interpretation of what happened based on pattern matching]
### Root Cause Hypothesis
[Most likely cause based on evidence]
### Actionable Steps
1. [Specific step with code location if known]
2. [Investigation step]
3. [Fix recommendation]
### If Unsymbolicated
```bash
# Find dSYM for UUID: [uuid]
mdfind "com_apple_xcode_dsym_uuids == [UUID]"
# Symbolicate address manually
xcrun atos -arch arm64 -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp -l [load_address] [crash_address]
```
```
## Symbolication Commands
When crash is not symbolicated, provide these commands:
```bash
# Find dSYM by UUID (from crash report's usedImages)
mdfind "com_apple_xcode_dsym_uuids == YOUR-UUID-HERE"
# If dSYM not found, check Archives
ls ~/Library/Developer/Xcode/Archives/
# Symbolicate a single address
xcrun atos -arch arm64 \
-o /path/to/MyApp.app.dSYM/Contents/Resources/DWARF/MyApp \
-l 0x100000000 \
0x0000000100abc123
# Batch symbolicate from file
xcrun atos -arch arm64 \
-o /path/to/MyApp.dSYM/Contents/Resources/DWARF/MyApp \
-l 0x100000000 \
-f addresses.txt
```
## When to Escalate
Report to user and stop if:
- Crash log is truncated or corrupted
- Format is unrecognized
- Critical information is missing (no exception type, no threads)
- Multiple unrelated issues in single crash (unusual)
## Related
- `axiom-testflight-triage` — Full TestFlight workflow including Organizer
- `axiom-memory-debugging` — For memory-related crashes
- `axiom-swift-concurrency` — For concurrency-related crashes
- `axiom-xcode-debugging` — For build/environment issues

View File

@@ -0,0 +1,3 @@
interface:
display_name: "Analyze Crash"
short_description: "The user has a crash log (."