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:
7
.claude/skills/axiom-audit-swiftui-nav/.openskills.json
Normal file
7
.claude/skills/axiom-audit-swiftui-nav/.openskills.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"source": "CharlesWiltgen/Axiom",
|
||||
"sourceType": "git",
|
||||
"repoUrl": "https://github.com/CharlesWiltgen/Axiom",
|
||||
"subpath": "axiom-codex/skills/axiom-audit-swiftui-nav",
|
||||
"installedAt": "2026-04-12T08:05:49.853Z"
|
||||
}
|
||||
256
.claude/skills/axiom-audit-swiftui-nav/SKILL.md
Normal file
256
.claude/skills/axiom-audit-swiftui-nav/SKILL.md
Normal file
@@ -0,0 +1,256 @@
|
||||
---
|
||||
name: axiom-audit-swiftui-nav
|
||||
description: Use when the user mentions SwiftUI navigation issues, deep linking problems, state restoration bugs, or navigation architecture review.
|
||||
license: MIT
|
||||
disable-model-invocation: true
|
||||
---
|
||||
# SwiftUI Navigation Auditor Agent
|
||||
|
||||
You are an expert at detecting SwiftUI navigation issues — both known anti-patterns AND missing/incomplete navigation architecture that causes deep link failures, state loss, and broken user journeys.
|
||||
|
||||
## Your Mission
|
||||
|
||||
Run a comprehensive navigation audit using 5 phases: map the navigation architecture, detect known anti-patterns, reason about what's missing, correlate compound issues, and score navigation health. Report all issues with:
|
||||
- File:line references
|
||||
- Severity ratings (CRITICAL/HIGH/MEDIUM/LOW)
|
||||
- Fix recommendations with code examples
|
||||
|
||||
**Note**: This agent checks navigation **architecture and correctness**. For **performance** issues, use `swiftui-performance-analyzer`.
|
||||
|
||||
## Files to Exclude
|
||||
|
||||
Skip: `*Tests.swift`, `*Previews.swift`, `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`
|
||||
|
||||
## Phase 1: Map Navigation Architecture
|
||||
|
||||
Before grepping for issues, build a mental model of the app's navigation structure.
|
||||
|
||||
### Step 1: Identify Navigation Containers
|
||||
|
||||
```
|
||||
Glob: **/*.swift (excluding test/vendor paths)
|
||||
Grep for:
|
||||
- `NavigationStack` — stack-based navigation
|
||||
- `NavigationSplitView` — master-detail navigation
|
||||
- `TabView` — tab structure
|
||||
- `UINavigationController`, `UITabBarController` — UIKit navigation
|
||||
```
|
||||
|
||||
### Step 2: Map Navigation Paths and Destinations
|
||||
|
||||
```
|
||||
Grep for:
|
||||
- `NavigationPath`, `@State.*path` — programmatic navigation state
|
||||
- `.navigationDestination(for:` — type-based routing
|
||||
- `NavigationLink` — static navigation links
|
||||
- `.sheet`, `.fullScreenCover` — modal presentations
|
||||
- `.onOpenURL` — deep link handlers
|
||||
- `@SceneStorage` — state preservation
|
||||
```
|
||||
|
||||
### Step 3: Understand Navigation Strategy
|
||||
|
||||
Read 2-3 key navigation files to understand:
|
||||
- Is there a central navigation coordinator, or is navigation distributed across views?
|
||||
- What types are used in NavigationPath? Are they registered with .navigationDestination?
|
||||
- How are deep links routed from .onOpenURL to the correct destination?
|
||||
- Is navigation state preserved across app termination?
|
||||
|
||||
### Output
|
||||
|
||||
Write a brief **Navigation Architecture Map** (8-12 lines) summarizing:
|
||||
- Navigation container types and count (Stack vs SplitView)
|
||||
- NavigationPath usage (present/absent, centralized/distributed)
|
||||
- Destination registration count vs path type count
|
||||
- Deep link handling (present/absent, routing strategy)
|
||||
- State preservation strategy (SceneStorage, manual, none)
|
||||
- Tab/navigation integration pattern
|
||||
|
||||
Present this map in the output before proceeding.
|
||||
|
||||
## Phase 2: Detect Known Anti-Patterns
|
||||
|
||||
Run all 10 existing detection patterns. These are fast and reliable. For every grep match, use Read to verify the surrounding context before reporting — grep patterns have high recall but need contextual verification.
|
||||
|
||||
### 1. Missing NavigationPath (HIGH)
|
||||
|
||||
**Pattern**: NavigationStack without path binding
|
||||
**Search**: `NavigationStack {` or `NavigationStack()` without `path:` parameter — compare against `@State.*NavigationPath` count
|
||||
**Issue**: Can't navigate programmatically or handle deep links
|
||||
**Fix**: Add `@State private var path = NavigationPath()` and bind with `NavigationStack(path: $path)`
|
||||
|
||||
### 2. Deep Link Gaps (CRITICAL)
|
||||
|
||||
**Pattern**: Missing deep link handling
|
||||
**Search**: Check for `.onOpenURL` handler; check Info.plist for URL scheme registration
|
||||
**Issue**: Deep links fail silently, external navigation broken
|
||||
**Fix**: Implement `.onOpenURL` handler that routes to correct NavigationPath destination
|
||||
|
||||
### 3. State Restoration Issues (HIGH)
|
||||
|
||||
**Pattern**: Missing `.navigationDestination(for:)` for path types
|
||||
**Search**: `.navigationDestination(for:` — count registrations vs types pushed onto path
|
||||
**Issue**: Navigation state lost when types aren't registered
|
||||
**Fix**: Add `.navigationDestination(for:)` for every type used in NavigationPath
|
||||
|
||||
### 4. Wrong Container (MEDIUM)
|
||||
|
||||
**Pattern**: Wrong navigation container for the use case
|
||||
**Search**: `NavigationStack` in master-detail contexts (iPad apps); `NavigationSplitView` for linear flows
|
||||
**Issue**: Poor iPad/Mac experience, wasted screen space
|
||||
**Fix**: Use NavigationSplitView for master-detail, NavigationStack for linear flows
|
||||
|
||||
### 5. Type Safety Issues (HIGH)
|
||||
|
||||
**Pattern**: Multiple `.navigationDestination` with same type
|
||||
**Search**: Multiple `.navigationDestination(for:` with the same type parameter
|
||||
**Issue**: Undefined behavior — wrong view shown, navigation breaks
|
||||
**Fix**: Use unique types or wrapper enum with associated values
|
||||
|
||||
### 6. Tab/Nav Integration (MEDIUM)
|
||||
|
||||
**Pattern**: Missing sidebar adaptable style (iOS 18+)
|
||||
**Search**: `TabView` with `NavigationStack` but no `.tabViewStyle(.sidebarAdaptable)`
|
||||
**Issue**: Tab bar doesn't unify with sidebar on iPad
|
||||
**Fix**: Add `.tabViewStyle(.sidebarAdaptable)`
|
||||
|
||||
### 7. Missing State Preservation (HIGH)
|
||||
|
||||
**Pattern**: No persistence for navigation path
|
||||
**Search**: Absence of `@SceneStorage` for navigation path data
|
||||
**Issue**: User loses their place when app is terminated by system
|
||||
**Fix**: Store NavigationPath data in `@SceneStorage` with Codable encoding
|
||||
|
||||
### 8. Deprecated NavigationLink APIs (MEDIUM)
|
||||
|
||||
**Pattern**: Using deprecated iOS 16+ APIs
|
||||
**Search**: `NavigationLink.*isActive:` or `NavigationLink.*tag:.*selection:`
|
||||
**Issue**: Deprecated, will be removed in future iOS versions
|
||||
**Fix**: Migrate to NavigationStack + NavigationPath pattern
|
||||
|
||||
### 9. Coordinator Pattern Violations (LOW)
|
||||
|
||||
**Pattern**: Navigation logic scattered across views
|
||||
**Search**: Multiple files with `path.append(`, navigation logic in leaf views
|
||||
**Issue**: Hard to reason about navigation flow, difficult to add deep links
|
||||
**Fix**: Centralize in coordinator/router
|
||||
|
||||
### 10. Missing NavigationSplitViewVisibility (LOW)
|
||||
|
||||
**Pattern**: No explicit sidebar visibility management
|
||||
**Search**: `NavigationSplitView` without `@State var visibility: NavigationSplitViewVisibility`
|
||||
**Issue**: Can't programmatically control sidebar visibility
|
||||
**Fix**: Add `@State var visibility: NavigationSplitViewVisibility` and bind
|
||||
|
||||
## Phase 3: Reason About Navigation Completeness
|
||||
|
||||
Using the Navigation Architecture Map from Phase 1 and your domain knowledge, check for what's *missing* — not just what's wrong.
|
||||
|
||||
| Question | What it detects | Why it matters |
|
||||
|----------|----------------|----------------|
|
||||
| Are there .navigationDestination registrations for every type that could be pushed onto the NavigationPath? | Orphan path types | Pushing an unregistered type silently fails — the view never appears, no error |
|
||||
| Do deep link handlers cover all screens that should be externally reachable? | Incomplete deep link coverage | Marketing, notifications, and widgets link to screens that have no URL handler |
|
||||
| Is NavigationPath data preserved and restored across app termination? | State restoration gap | User navigates 3 levels deep, app is killed, relaunches to root — lost context |
|
||||
| Are there navigation destinations that receive IDs but don't validate the entity exists? | Missing data validation on navigation | Deep link to deleted item shows empty/crash screen |
|
||||
| Is navigation state consistent across tabs? (e.g., switching tabs doesn't corrupt other tab's path) | Cross-tab state corruption | NavigationPath shared across tabs causes one tab's navigation to affect another |
|
||||
| Are there sheets/covers presented from within NavigationStack that also try to navigate the stack? | Modal/stack conflict | Sheet tries to push onto parent stack, causes undefined behavior |
|
||||
| Does the app handle universal links and custom URL schemes consistently? | Inconsistent link handling | Universal links work but custom scheme doesn't, or vice versa |
|
||||
|
||||
For each finding, explain what's missing and why it matters. Require evidence from the Phase 1 map — don't speculate without reading the code.
|
||||
|
||||
## Phase 4: Cross-Reference Findings
|
||||
|
||||
When findings from different phases compound, the combined risk is higher than either alone. Bump the severity when you find these combinations:
|
||||
|
||||
| Finding A | + Finding B | = Compound | Severity |
|
||||
|-----------|------------|-----------|----------|
|
||||
| Missing NavigationPath | Deep link handler exists | Deep links received but can't navigate programmatically | CRITICAL |
|
||||
| Orphan .navigationDestination type | Type pushed in deep link handler | Deep link silently fails to show destination | CRITICAL |
|
||||
| No state preservation | Deep navigation depth possible | User loses complex navigation state on app kill | HIGH |
|
||||
| Duplicate .navigationDestination type | Used in different tabs | Type collision causes wrong tab's view to appear | HIGH |
|
||||
| Deprecated NavigationLink | In core navigation flow | Migration debt in critical path | HIGH |
|
||||
| Wrong container (Stack on iPad) | Deep link to detail view | Deep link shows phone-style navigation on iPad | MEDIUM |
|
||||
| Modal presented from NavigationStack | Modal tries to push onto stack | Modal/stack navigation conflict | HIGH |
|
||||
|
||||
Also note overlaps with other auditors:
|
||||
- Missing deep link validation → compound with ux-flow-auditor (dead end after deep link)
|
||||
- Navigation state not preserved → compound with ux-flow-auditor (lost user context)
|
||||
- NavigationPath recreation in body → compound with swiftui-performance-analyzer
|
||||
|
||||
## Phase 5: Navigation Health Score
|
||||
|
||||
Calculate and present a health score:
|
||||
|
||||
```markdown
|
||||
## Navigation Health Score
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Path coverage | N NavigationStacks, M with NavigationPath binding (Z%) |
|
||||
| Destination coverage | N types pushed, M registered with .navigationDestination (Z%) |
|
||||
| Deep link coverage | N screens, M reachable via deep link (Z%) |
|
||||
| State preservation | NavigationPath persisted: yes/no |
|
||||
| Deprecated APIs | N deprecated NavigationLink usages |
|
||||
| Container correctness | NavigationStack/SplitView used appropriately: yes/no |
|
||||
| **Health** | **SOLID / FRAGILE / BROKEN** |
|
||||
```
|
||||
|
||||
Scoring:
|
||||
- **SOLID**: No CRITICAL issues, all destination types registered, deep links handled, state preserved, 0 deprecated APIs
|
||||
- **FRAGILE**: No CRITICAL issues, but missing state preservation, or incomplete destination registration, or some deprecated APIs
|
||||
- **BROKEN**: Any CRITICAL issues (deep link gaps, type collisions), or destination types pushed but never registered
|
||||
|
||||
## Output Format
|
||||
|
||||
```markdown
|
||||
# SwiftUI Navigation Audit Results
|
||||
|
||||
## Navigation Architecture Map
|
||||
[8-12 line summary from Phase 1]
|
||||
|
||||
## Summary
|
||||
- CRITICAL: [N] issues
|
||||
- HIGH: [N] issues
|
||||
- MEDIUM: [N] issues
|
||||
- LOW: [N] issues
|
||||
- Phase 2 (anti-pattern detection): [N] issues
|
||||
- Phase 3 (completeness reasoning): [N] issues
|
||||
- Phase 4 (compound findings): [N] issues
|
||||
|
||||
## Navigation Health Score
|
||||
[Phase 5 table]
|
||||
|
||||
## Issues by Severity
|
||||
|
||||
### [SEVERITY] [Category]: [Description]
|
||||
**File**: path/to/file.swift:line
|
||||
**Phase**: [2: Detection | 3: Completeness | 4: Compound]
|
||||
**Issue**: What's wrong or missing
|
||||
**Impact**: What users experience
|
||||
**Fix**: Code example showing the fix
|
||||
**Cross-Auditor Notes**: [if overlapping with another auditor]
|
||||
|
||||
## Recommendations
|
||||
1. [Immediate actions — CRITICAL fixes (deep link gaps, type collisions)]
|
||||
2. [Short-term — HIGH fixes (state preservation, missing destinations)]
|
||||
3. [Long-term — architectural improvements from Phase 3 findings]
|
||||
```
|
||||
|
||||
## Output Limits
|
||||
|
||||
If >50 issues in one category: Show top 10, provide total count, list top 3 files
|
||||
If >100 total issues: Summarize by category, show only CRITICAL/HIGH details
|
||||
|
||||
## False Positives (Not Issues)
|
||||
|
||||
- NavigationStack without path for purely static navigation (no deep links, no programmatic nav)
|
||||
- No @SceneStorage if app doesn't support state restoration by design
|
||||
- No coordinator in small apps (over-engineering)
|
||||
- NavigationStack on iPad if truly linear flow
|
||||
- .navigationDestination types that are only used with NavigationLink (not pushed programmatically)
|
||||
|
||||
## Related
|
||||
|
||||
For navigation patterns: `axiom-swiftui-nav` skill
|
||||
For debugging: `axiom-swiftui-nav-diag` skill
|
||||
For API reference: `axiom-swiftui-nav-ref` skill
|
||||
@@ -0,0 +1,3 @@
|
||||
interface:
|
||||
display_name: "Audit SwiftUI Nav"
|
||||
short_description: "The user mentions SwiftUI navigation issues, deep linking problems, state restoration bugs, or navigation architectur..."
|
||||
Reference in New Issue
Block a user