@shaykec/app-agent 1.0.8 → 1.0.10
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/.claude/agents/android-customizer.md +9 -1
- package/.claude/agents/catalog-analyzer.md +57 -0
- package/.claude/agents/ios-customizer.md +9 -1
- package/.claude/agents/react-native-customizer.md +71 -0
- package/.claude/skills/android-customizer/SKILL.md +108 -23
- package/.claude/skills/bug-fixer/SKILL.md +59 -0
- package/.claude/skills/catalog-analyzer/SKILL.md +96 -0
- package/.claude/skills/customization-planner/SKILL.md +44 -5
- package/.claude/skills/design-selector/SKILL.md +3 -1
- package/.claude/skills/design-system/SKILL.md +1 -1
- package/.claude/skills/exploratory-tester/SKILL.md +82 -0
- package/.claude/skills/ios-customizer/SKILL.md +123 -23
- package/.claude/skills/module-integrator/SKILL.md +1 -1
- package/.claude/skills/react-native-customizer/SKILL.md +97 -11
- package/.claude/skills/test-planner/SKILL.md +72 -0
- package/.cursor/agents/README.md +3 -1
- package/.cursor/agents/android-customizer.md +15 -11
- package/.cursor/agents/catalog-analyzer.md +83 -0
- package/.cursor/agents/ios-customizer.md +15 -10
- package/.cursor/agents/react-native-customizer.md +170 -0
- package/.cursor/mcp.json +2 -10
- package/.cursor/rules/safety-guardrails.mdc +1 -1
- package/.cursor/rules/workflow.mdc +52 -18
- package/.cursor/skills/android-customizer/SKILL.md +46 -22
- package/.cursor/skills/bug-fixer/SKILL.md +189 -0
- package/.cursor/skills/catalog-analyzer/SKILL.md +222 -0
- package/.cursor/skills/customization-planner/SKILL.md +55 -8
- package/.cursor/skills/design-selector/SKILL.md +6 -5
- package/.cursor/skills/design-system/SKILL.md +8 -7
- package/.cursor/skills/exploratory-tester/SKILL.md +223 -0
- package/.cursor/skills/ios-customizer/SKILL.md +50 -15
- package/.cursor/skills/module-integrator/SKILL.md +2 -2
- package/.cursor/skills/output-validator/SKILL.md +1 -1
- package/.cursor/skills/react-native-customizer/SKILL.md +115 -25
- package/.cursor/skills/test-planner/SKILL.md +199 -0
- package/AGENTS.md +32 -11
- package/CLAUDE.md +78 -33
- package/README.md +77 -11
- package/designs/DESIGN_CATALOG.md +17 -15
- package/designs/DESIGN_PRINCIPLES.md +53 -0
- package/designs/brands/accessible-high-contrast.md +14 -0
- package/designs/brands/corporate-professional.md +14 -0
- package/designs/brands/dark-luxe.md +14 -0
- package/designs/brands/kids-playful.md +14 -0
- package/designs/brands/medical-clinical.md +14 -0
- package/designs/brands/modern-minimal.md +14 -0
- package/designs/brands/nature-organic.md +14 -0
- package/designs/brands/neo-brutalist.md +14 -0
- package/designs/brands/retro-vintage.md +14 -0
- package/designs/brands/soft-gradient.md +14 -0
- package/designs/brands/sport-athletic.md +14 -0
- package/designs/brands/tech-dynamic.md +14 -0
- package/designs/brands/vibrant-playful.md +14 -0
- package/dist/cli.d.ts +4 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +91 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/engines/claude-engine.d.ts.map +1 -1
- package/dist/engines/claude-engine.js +16 -4
- package/dist/engines/claude-engine.js.map +1 -1
- package/dist/engines/types.d.ts +1 -1
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/engines/types.js +31 -2
- package/dist/engines/types.js.map +1 -1
- package/dist/github.d.ts +3 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +47 -4
- package/dist/github.js.map +1 -1
- package/dist/index.js +217 -9
- package/dist/index.js.map +1 -1
- package/dist/prompt-builder.d.ts +11 -1
- package/dist/prompt-builder.d.ts.map +1 -1
- package/dist/prompt-builder.js +216 -1
- package/dist/prompt-builder.js.map +1 -1
- package/dist/validator.d.ts +7 -2
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +61 -41
- package/dist/validator.js.map +1 -1
- package/dist/workspace.js +2 -2
- package/dist/workspace.js.map +1 -1
- package/package.json +2 -2
- package/prompts/agent-prompt.md +35 -18
- package/prompts/deep-test-agent-prompt.md +122 -0
- package/prompts/fix-agent-prompt.md +90 -0
- package/prompts/quick-agent-prompt.md +32 -2
- package/prompts/scratch-agent-prompt.md +5 -8
- package/templates/android/BookTemplate/app/src/main/kotlin/com/appship/book/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ChatTemplate/app/src/main/kotlin/com/appship/chat/features/conversations/ConversationsScreen.kt +1 -1
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/DashTemplate/app/src/main/kotlin/com/appship/dash/features/navigation/MainScreen.kt +1 -0
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/FamilyTemplate/app/src/main/java/com/appship/family/features/navigation/MainNavigation.kt +5 -1
- package/templates/android/FinanceTemplate/app/src/main/kotlin/com/appship/finance/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/core/animation/MotionPreferencesScreen.kt +3 -3
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/navigation/Navigation.kt +1 -1
- package/templates/android/GameTemplate/app/src/main/kotlin/com/appship/game/features/settings/SettingsScreen.kt +1 -1
- package/templates/android/HealthTemplate/app/src/main/kotlin/com/appship/health/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/LearnTemplate/app/src/main/kotlin/com/appship/learn/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/MapTemplate/app/src/main/kotlin/com/appship/map/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/MediaTemplate/app/src/main/kotlin/com/appship/media/features/settings/SettingsScreen.kt +3 -2
- package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ReferenceTemplate/app/src/main/kotlin/com/appship/reference/features/settings/SettingsScreen.kt +1 -1
- package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/ShopTemplate/app/src/main/kotlin/com/appship/shop/features/cart/CartScreen.kt +3 -2
- package/templates/android/Skeleton/TESTING_MANIFEST.md +2 -1
- package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/MainActivity.kt +23 -2
- package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/core/theme/AppearanceManager.kt +42 -0
- package/templates/android/Skeleton/app/src/main/kotlin/com/appship/skeleton/features/profile/ProfileScreen.kt +20 -8
- package/templates/android/Skeleton/tests/03_detail_screen.yaml +3 -2
- package/templates/android/Skeleton/tests/04_favorites.yaml +3 -2
- package/templates/android/Skeleton/tests/08_full_e2e.yaml +9 -2
- package/templates/android/Skeleton/tests/09_dark_mode.yaml +50 -0
- package/templates/android/SocialTemplate/app/src/main/kotlin/com/appship/social/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/android/TaskTemplate/app/src/main/kotlin/com/appship/task/features/settings/SettingsScreen.kt +3 -2
- package/templates/android/TrackTemplate/app/src/main/kotlin/com/appship/track/core/animation/AnimatedTransitionsModifiers.kt +188 -0
- package/templates/ios/BookTemplate/BookTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/ChatTemplate/ChatTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/DashTemplate/DashTemplate/App/AppConfig.swift +1 -0
- package/templates/ios/DashTemplate/DashTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/DashTemplate/DashTemplate/Core/Strings.swift +13 -0
- package/templates/ios/DashTemplate/DashTemplate.xcodeproj/project.pbxproj +32 -20
- package/templates/ios/FamilyTemplate/FamilyTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate/Core/Strings.swift +42 -0
- package/templates/ios/FinanceTemplate/FinanceTemplate.xcodeproj/project.pbxproj +36 -30
- package/templates/ios/GameTemplate/GameTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/HealthTemplate/HealthTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/LearnTemplate/LearnTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/MapTemplate/MapTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/MediaTemplate/MediaTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Core/Strings.swift +12 -0
- package/templates/ios/ReferenceTemplate/ReferenceTemplate/Features/SkeletonLoading/SkeletonLoadingView.swift +2 -37
- package/templates/ios/ShopTemplate/ShopTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/Skeleton/Skeleton/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/Skeleton/tests/08_full_e2e.yaml +4 -0
- package/templates/ios/Skeleton/tests/09_dark_mode.yaml +52 -0
- package/templates/ios/SocialTemplate/SocialTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/TaskTemplate/TaskTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/ios/TrackTemplate/TrackTemplate/Core/Animation/AnimatedTransitionsView.swift +201 -0
- package/templates/react-native/BookTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/BookTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/BookTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/ChatTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/ChatTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/ChatTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/DashTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/DashTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/DashTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/FamilyTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/FamilyTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/FamilyTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/FinanceTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/FinanceTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/FinanceTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/GameTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/GameTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/GameTemplate/src/screens/GameDetail/GameDetailScreen.tsx +2 -1
- package/templates/react-native/GameTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/HealthTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/HealthTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/HealthTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/HealthTemplate/src/screens/WorkoutDetail/WorkoutDetailScreen.tsx +1 -1
- package/templates/react-native/LearnTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/LearnTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/LearnTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/MapTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/MapTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/MapTemplate/src/screens/Map/MapScreen.tsx +14 -0
- package/templates/react-native/MapTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/MediaTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/MediaTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/MediaTemplate/src/screens/PlaylistDetail/PlaylistDetailScreen.tsx +1 -1
- package/templates/react-native/MediaTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/ReferenceTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/ReferenceTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/ReferenceTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
- package/templates/react-native/ShopTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/ShopTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/ShopTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/Skeleton/TESTING_MANIFEST.md +2 -1
- package/templates/react-native/Skeleton/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/Skeleton/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/Skeleton/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/Skeleton/tests/07_profile.yaml +3 -2
- package/templates/react-native/Skeleton/tests/08_full_e2e.yaml +12 -1
- package/templates/react-native/Skeleton/tests/09_dark_mode.yaml +46 -0
- package/templates/react-native/SocialTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/SocialTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/SocialTemplate/src/screens/Feed/FeedScreen.tsx +1 -0
- package/templates/react-native/SocialTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/TaskTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/TaskTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/TaskTemplate/src/screens/Profile/ProfileScreen.tsx +1 -1
- package/templates/react-native/TrackTemplate/src/animation/useAnimatedList.ts +219 -2
- package/templates/react-native/TrackTemplate/src/animation/useMotionPreferences.ts +23 -9
- package/templates/react-native/TrackTemplate/src/screens/Settings/SettingsScreen.tsx +1 -1
- package/templates/shared/ios/AnimatedTransitions/AnimatedTransitionsView.swift +233 -93
- package/.claude/agents/template-selector.md +0 -39
- package/.claude/skills/module-selector/SKILL.md +0 -81
- package/.claude/skills/template-selector/SKILL.md +0 -44
- package/.cursor/agents/template-selector.md +0 -52
- package/.cursor/skills/module-selector/SKILL.md +0 -135
- package/.cursor/skills/template-selector/SKILL.md +0 -123
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: exploratory-tester
|
|
3
|
+
description: Screenshot and accessibility-tree driven exploratory testing. Does NOT read source code — tests purely through what the AI sees on screen. Discovers visual bugs, accessibility issues, UX problems, and content issues.
|
|
4
|
+
allowed-tools: inspect, act, assert, wait, navigate, device, logs, Read, Write
|
|
5
|
+
context: fork
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Exploratory Tester Skill
|
|
9
|
+
|
|
10
|
+
Test the app by exploring it visually — screenshots and accessibility tree as your only inputs. Do NOT read source code.
|
|
11
|
+
|
|
12
|
+
## Context
|
|
13
|
+
|
|
14
|
+
- **Platform**, **Bundle ID**, **Simulator name** — for ai-tester MCP calls
|
|
15
|
+
- **App directory** — only for writing the bug report
|
|
16
|
+
|
|
17
|
+
## Instructions
|
|
18
|
+
|
|
19
|
+
### Phase A — Screen Discovery
|
|
20
|
+
|
|
21
|
+
1. Launch app: `inspect({ platform, app: bundleId, deviceName })`
|
|
22
|
+
2. Wait 3-5s, `inspect()` again
|
|
23
|
+
3. Map tab bar — identify all tabs from element tree
|
|
24
|
+
4. Visit each tab — `inspect()` on each
|
|
25
|
+
5. Discover sub-screens — tap list items, buttons, links
|
|
26
|
+
6. Build screen map (tab → screen → sub-screen)
|
|
27
|
+
|
|
28
|
+
### Phase B — Per-Screen Audit
|
|
29
|
+
|
|
30
|
+
For each screen, `inspect()` then:
|
|
31
|
+
|
|
32
|
+
**B1 — Visual Analysis (screenshot):**
|
|
33
|
+
- No overlapping/cut-off text, proper spacing, correct alignment
|
|
34
|
+
- Real domain text (not "Lorem ipsum", "Item 1", "Template")
|
|
35
|
+
- Images loaded, icons match context
|
|
36
|
+
- Consistent typography and colors
|
|
37
|
+
- Template leftover detection
|
|
38
|
+
|
|
39
|
+
**B2 — Accessibility Tree Audit:**
|
|
40
|
+
- Every button/link has non-empty label
|
|
41
|
+
- Images have a11y descriptions
|
|
42
|
+
- Form fields have labels
|
|
43
|
+
- No orphaned elements (in tree but not visible, or visible but not in tree)
|
|
44
|
+
- Touch targets >= 44x44pt (iOS) / 48x48dp (Android)
|
|
45
|
+
|
|
46
|
+
**B3 — Interactive Exploration:**
|
|
47
|
+
- Tap every button — verify something happens (flag dead buttons)
|
|
48
|
+
- Type into every text field — normal text + edge cases (empty, long, special chars)
|
|
49
|
+
- Toggle every switch — verify state change
|
|
50
|
+
- Scroll every list to bottom and back up
|
|
51
|
+
- Navigate 3+ levels deep, verify back nav works all the way
|
|
52
|
+
- Switch tabs rapidly — verify correct content
|
|
53
|
+
- Test state persistence (favorite, form text, scroll position)
|
|
54
|
+
|
|
55
|
+
**B4 — Before/After Comparison:**
|
|
56
|
+
- `inspect()` after interactions, compare element trees
|
|
57
|
+
- Flag unexpected changes (disappeared elements, count mismatches)
|
|
58
|
+
|
|
59
|
+
### Phase C — Bug Classification
|
|
60
|
+
|
|
61
|
+
| Tag | Category | Examples |
|
|
62
|
+
|-----|----------|----------|
|
|
63
|
+
| `[VISUAL]` | Layout | Overlap, truncation, wrong colors |
|
|
64
|
+
| `[A11Y]` | Accessibility | Missing labels, small targets |
|
|
65
|
+
| `[UX]` | Experience | Dead buttons, confusing nav |
|
|
66
|
+
| `[CONTENT]` | Content | Template leftovers, placeholders |
|
|
67
|
+
| `[STATE]` | State | Not persisting, stale views |
|
|
68
|
+
| `[CRASH]` | Crash | App crash on interaction |
|
|
69
|
+
|
|
70
|
+
Format: `BUG-{NNN}: [{SEVERITY}][EXPLORATORY][{TAG}] {description}` with screen, element, steps, expected, actual.
|
|
71
|
+
|
|
72
|
+
### Phase D — Write Bug Report
|
|
73
|
+
|
|
74
|
+
Write/append to `output/{app-name}/reports/11-bug-report.md` with: summary counts, accessibility summary, screen map, all bugs.
|
|
75
|
+
|
|
76
|
+
## Rules
|
|
77
|
+
|
|
78
|
+
- **DO NOT read source code** — only screenshots + element tree from `inspect()`
|
|
79
|
+
- **DO NOT follow a test plan** — explore freely
|
|
80
|
+
- Test EVERY interactive element in the element tree
|
|
81
|
+
- Use ai-tester MCP tools for ALL interaction
|
|
82
|
+
- Write findings to bug report — do NOT fix bugs
|
|
@@ -9,7 +9,7 @@ Use this skill to perform deep iOS/SwiftUI customization on a cloned template.
|
|
|
9
9
|
|
|
10
10
|
## When to Use
|
|
11
11
|
|
|
12
|
-
- At Step
|
|
12
|
+
- At Step 5 of the AppAgent workflow, when the platform is iOS
|
|
13
13
|
- After AppConfig, mock data, and design tokens are already in place
|
|
14
14
|
- When you need to modify SwiftUI views, navigation, and themes
|
|
15
15
|
|
|
@@ -100,6 +100,28 @@ iOS templates use a `Colors.swift` theme file:
|
|
|
100
100
|
- Use semantic colors where possible (`Color.primary`, `Color.secondary`)
|
|
101
101
|
- Apply corner radius and spacing tokens from the design brief
|
|
102
102
|
|
|
103
|
+
### Step 4.5 — Visual Polish Application
|
|
104
|
+
|
|
105
|
+
Apply the **Visual Polish Plan** from the manifest. MANDATORY for every build.
|
|
106
|
+
|
|
107
|
+
1. **Shadows**: Apply `.cardShadow()` or `shadow(color:radius:x:y:)` to every card/elevated surface using manifest shadow tokens.
|
|
108
|
+
2. **Gradients**: Apply `LinearGradient` to hero sections and primary CTAs (primary → secondary, 135deg).
|
|
109
|
+
3. **Press feedback**: All buttons use `.scaleOnPress()` (scale 0.95, spring return). Add `UIImpactFeedbackGenerator` to favorite toggles and submit buttons.
|
|
110
|
+
4. **Staggered animations**: All list views use `.staggeredAppear(index:)` on each item.
|
|
111
|
+
5. **Empty states**: Gradient circle behind icon + `.slideIn()` animation.
|
|
112
|
+
6. **Glass/blur**: `.ultraThinMaterial` on sheet backgrounds and overlays.
|
|
113
|
+
7. **Haptic**: Feedback on favorite toggles, pull-to-refresh, primary actions.
|
|
114
|
+
|
|
115
|
+
### Step 4.6 — Generate App Launcher Icon
|
|
116
|
+
|
|
117
|
+
Generate a domain-specific app icon using the manifest's **App Launcher Icon** section:
|
|
118
|
+
|
|
119
|
+
1. Read the icon spec: `iOS SF Symbol` (e.g., `bag.fill`) and `Background` hex color
|
|
120
|
+
2. Run: `swift scripts/generate-app-icon.swift "{symbol}" "{background}" "output/{app-name}/{AppName}/Resources/Assets.xcassets/AppIcon.appiconset/"`
|
|
121
|
+
3. Verify `AppIcon-1024.png` exists in the output directory
|
|
122
|
+
|
|
123
|
+
If `scripts/generate-app-icon.swift` does not exist or fails, skip — the template's default icon will be used.
|
|
124
|
+
|
|
103
125
|
### Step 5 — Data Layer & Offline Infrastructure
|
|
104
126
|
|
|
105
127
|
Templates now include an **offline-first data layer**. Understand these components:
|
|
@@ -118,18 +140,31 @@ Templates now include an **offline-first data layer**. Understand these componen
|
|
|
118
140
|
- `Data/SyncManager.swift` — if entity types were renamed, update domain methods
|
|
119
141
|
|
|
120
142
|
**ViewModel patterns** (how views consume data):
|
|
143
|
+
|
|
144
|
+
ViewModels use the `DataRepository` protocol abstraction, not `MockDataProvider` directly:
|
|
121
145
|
```swift
|
|
122
|
-
// ViewModels
|
|
123
|
-
|
|
146
|
+
// ViewModels depend on the DataRepository protocol
|
|
147
|
+
private let repository: any DataRepository
|
|
148
|
+
|
|
149
|
+
init(repository: any DataRepository = DataSourceResolver.repository) {
|
|
150
|
+
self.repository = repository
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Read data via the protocol
|
|
154
|
+
let items = repository.items
|
|
155
|
+
let categories = repository.categories
|
|
124
156
|
|
|
125
|
-
//
|
|
126
|
-
|
|
157
|
+
// CRUD via the protocol
|
|
158
|
+
repository.addItem(newItem)
|
|
159
|
+
repository.deleteItem(item)
|
|
160
|
+
repository.toggleFavorite(item)
|
|
127
161
|
|
|
128
|
-
//
|
|
162
|
+
// If SyncManager exists, it wraps the repository
|
|
129
163
|
SyncManager.shared.addProduct(newProduct)
|
|
130
|
-
SyncManager.shared.deleteProduct(id)
|
|
131
164
|
```
|
|
132
165
|
|
|
166
|
+
When customizing ViewModels, ALWAYS use `repository` (from `DataSourceResolver`), never `MockDataProvider.shared` directly. This ensures the app works with any data source.
|
|
167
|
+
|
|
133
168
|
**OfflineBanner integration** — add to main navigation views:
|
|
134
169
|
```swift
|
|
135
170
|
VStack(spacing: 0) {
|
|
@@ -138,27 +173,87 @@ VStack(spacing: 0) {
|
|
|
138
173
|
}
|
|
139
174
|
```
|
|
140
175
|
|
|
141
|
-
### Step 6 —
|
|
176
|
+
### Step 6 — Data Layer Verification
|
|
142
177
|
|
|
143
|
-
Verify the
|
|
178
|
+
Verify the data layer uses the correct patterns:
|
|
144
179
|
|
|
180
|
+
**DataRepository protocol:**
|
|
145
181
|
```swift
|
|
146
|
-
|
|
182
|
+
protocol DataRepository: AnyObject {
|
|
183
|
+
var items: [Item] { get }
|
|
184
|
+
var categories: [Category] { get }
|
|
185
|
+
var favoriteItems: [Item] { get }
|
|
186
|
+
func loadData()
|
|
187
|
+
func addItem(_ item: Item)
|
|
188
|
+
// ... all CRUD + query methods
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**MockDataProvider (conforms to DataRepository):**
|
|
193
|
+
```swift
|
|
194
|
+
class MockDataProvider: ObservableObject, DataRepository {
|
|
147
195
|
static let shared = MockDataProvider()
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
func addProduct(_ product: Product) { ... } // CRUD
|
|
154
|
-
func reset() { ... } // Reset to defaults
|
|
196
|
+
@Published var products: [Product]
|
|
197
|
+
static let defaultProducts: [Product] = [...]
|
|
198
|
+
func addProduct(_ product: Product) { ... }
|
|
199
|
+
func reset() { ... }
|
|
155
200
|
}
|
|
156
201
|
```
|
|
157
202
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
203
|
+
**DataSourceResolver:**
|
|
204
|
+
```swift
|
|
205
|
+
enum DataSourceResolver {
|
|
206
|
+
static var repository: any DataRepository {
|
|
207
|
+
switch AppConfig.DataSource.active {
|
|
208
|
+
case .mock: return MockDataProvider.shared
|
|
209
|
+
case .localStorage: return MockDataProvider.shared // TODO: LocalStorageProvider
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Verify:
|
|
216
|
+
- DataRepository protocol matches MockDataProvider's public interface
|
|
217
|
+
- MockDataProvider conforms to DataRepository
|
|
218
|
+
- DataSourceResolver returns the correct implementation
|
|
219
|
+
- ViewModels use `DataSourceResolver.repository`, not `MockDataProvider.shared` directly
|
|
220
|
+
- Seed data matches the new domain
|
|
221
|
+
- CRUD methods reference correct entity types
|
|
222
|
+
|
|
223
|
+
### Step 6.5 — Apply Animation Modifiers (if animation modules are integrated)
|
|
224
|
+
|
|
225
|
+
If the customization manifest includes an **"Animation & Sensory Plan"** section:
|
|
226
|
+
|
|
227
|
+
1. Read the "Per-Screen Animation Modifiers" table from the manifest
|
|
228
|
+
2. For each screen in your batch, apply the assigned modifiers:
|
|
229
|
+
|
|
230
|
+
```swift
|
|
231
|
+
// Built-in press feedback (always available)
|
|
232
|
+
Button("Add to Cart") { ... }
|
|
233
|
+
.scaleOnPress()
|
|
234
|
+
.hapticFeedback(.medium)
|
|
235
|
+
|
|
236
|
+
// Built-in staggered list items (always available)
|
|
237
|
+
ItemRow(item: items[index]).staggeredAppear(index: index)
|
|
238
|
+
|
|
239
|
+
// Built-in shadow and slide (always available)
|
|
240
|
+
CardView(item: item).cardShadow()
|
|
241
|
+
EmptyStateView().slideIn()
|
|
242
|
+
|
|
243
|
+
// Built-in shimmer, pulse, heartBounce (always available)
|
|
244
|
+
RoundedRectangle(cornerRadius: 8).fill(Color(.systemGray5)).shimmer()
|
|
245
|
+
Circle().fill(.red).frame(width: 8).pulse()
|
|
246
|
+
Image(systemName: "heart.fill").heartBounce(isActive: isFavorite)
|
|
247
|
+
|
|
248
|
+
// ScrollEffects module (if integrated)
|
|
249
|
+
ParallaxHeaderView(height: 280) { AsyncImage(url: item.imageURL) }
|
|
250
|
+
|
|
251
|
+
// CelebrationEffects module (if integrated)
|
|
252
|
+
.celebrationOverlay(isPresented: $showCelebration, style: .confetti)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
3. Wrap all applied animations with `.motionAware()` if MotionPreferences is integrated
|
|
256
|
+
4. Do NOT add animation modifiers to screens not listed in the manifest
|
|
162
257
|
|
|
163
258
|
## Report Output
|
|
164
259
|
|
|
@@ -167,7 +262,7 @@ Write the report to `output/{app-name}/reports/05-customization.md` (append iOS
|
|
|
167
262
|
```markdown
|
|
168
263
|
# Customization Report
|
|
169
264
|
|
|
170
|
-
**Step:**
|
|
265
|
+
**Step:** 5
|
|
171
266
|
**Skill:** ios-customizer
|
|
172
267
|
**Timestamp:** {ISO 8601}
|
|
173
268
|
**Result:** PASS
|
|
@@ -201,6 +296,11 @@ iOS (Swift / SwiftUI)
|
|
|
201
296
|
- SyncManager methods updated: {list or "no changes needed"}
|
|
202
297
|
- Data persistence verified: {yes/no}
|
|
203
298
|
|
|
299
|
+
## Animation Modifiers Applied
|
|
300
|
+
|
|
301
|
+
- {modifier}: applied to {screen} — {description}
|
|
302
|
+
- MotionPreferences respected: {yes/no/N/A}
|
|
303
|
+
|
|
204
304
|
## Potential Issues
|
|
205
305
|
|
|
206
306
|
- {any concerns or items needing manual review}
|
|
@@ -212,7 +312,7 @@ Update `output/{app-name}/reports/summary.json` — read the file, append this s
|
|
|
212
312
|
|
|
213
313
|
```json
|
|
214
314
|
{
|
|
215
|
-
"step":
|
|
315
|
+
"step": 5,
|
|
216
316
|
"name": "ios-customization",
|
|
217
317
|
"startedAt": "{ISO 8601 timestamp}",
|
|
218
318
|
"durationSeconds": 0,
|
|
@@ -9,7 +9,7 @@ Integrate selected shared modules by reading reference implementations from `tem
|
|
|
9
9
|
|
|
10
10
|
## Context You Need
|
|
11
11
|
|
|
12
|
-
-
|
|
12
|
+
- Catalog analysis report (`reports/02-catalog-analysis.md`) — template + module selection
|
|
13
13
|
- Customization manifest (`reports/customization-manifest.md`) — module integration plan
|
|
14
14
|
- Platform, app name, bundle ID
|
|
15
15
|
- AppConfig file path
|
|
@@ -91,27 +91,100 @@ React Native templates use a `ThemeContext.tsx`:
|
|
|
91
91
|
- Apply corner radius and spacing tokens
|
|
92
92
|
- Apply typography settings (font sizes, weights)
|
|
93
93
|
|
|
94
|
-
### Step 5 —
|
|
94
|
+
### Step 4.5 — Visual Polish Application
|
|
95
|
+
|
|
96
|
+
Apply the **Visual Polish Plan** from the manifest. MANDATORY for every build.
|
|
97
|
+
|
|
98
|
+
1. **Shadows**: Platform-aware shadow styles on all cards (`shadowColor`/`shadowOffset`/`shadowRadius` + `elevation`).
|
|
99
|
+
2. **Gradients**: `expo-linear-gradient` `LinearGradient` on hero sections and CTAs.
|
|
100
|
+
3. **Press feedback**: Scale animation (0.95, spring) on all TouchableOpacity. Wrap in `ScaleButton` component.
|
|
101
|
+
4. **Staggered animations**: `useStaggeredAppear(index)` on all FlatList items.
|
|
102
|
+
5. **Empty states**: Gradient circle behind icon + `useSlideIn()` animation.
|
|
103
|
+
6. **Blur/glass**: `expo-blur` BlurView on modal/sheet backgrounds.
|
|
104
|
+
7. **Haptic**: `expo-haptics` on favorite toggles and primary actions.
|
|
105
|
+
|
|
106
|
+
### Step 5 — Data Layer & Offline Infrastructure
|
|
107
|
+
|
|
108
|
+
Templates include an **offline-first data layer**:
|
|
95
109
|
|
|
96
110
|
**Files you should NOT modify** (generic infrastructure):
|
|
97
111
|
- `src/data/DataRepository.ts` — interface definition
|
|
112
|
+
- `src/data/NetworkMonitor.ts` — connectivity detection
|
|
113
|
+
- `src/data/LocalPersistence.ts` — JSON file persistence
|
|
114
|
+
- `src/components/OfflineBanner.tsx` — offline status banner
|
|
98
115
|
- `src/theme/ThemeContext.tsx` — theme provider
|
|
99
116
|
|
|
100
117
|
**Files you MAY need to update** (domain-specific):
|
|
101
|
-
- `src/mock/MockDataProvider.ts` — seed data already updated in Step 4. Verify
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
118
|
+
- `src/mock/MockDataProvider.ts` — seed data already updated in Step 4. Verify seed data, CRUD methods, subscription pattern, and reset defaults
|
|
119
|
+
- `src/data/SyncManager.ts` — if entity types were renamed, update domain methods
|
|
120
|
+
|
|
121
|
+
**ViewModel patterns** — use `DataSourceResolver`, not `MockDataProvider` directly:
|
|
122
|
+
```tsx
|
|
123
|
+
import { DataSourceResolver } from '../data/DataSourceResolver';
|
|
124
|
+
|
|
125
|
+
export function useHomeViewModel() {
|
|
126
|
+
const repository = DataSourceResolver.repository;
|
|
127
|
+
const [items, setItems] = useState<Item[]>([]);
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
setItems(repository.getItems());
|
|
130
|
+
const unsubscribe = repository.subscribe(() => setItems(repository.getItems()));
|
|
131
|
+
return unsubscribe;
|
|
132
|
+
}, []);
|
|
133
|
+
return { items };
|
|
134
|
+
}
|
|
135
|
+
```
|
|
106
136
|
|
|
107
|
-
|
|
137
|
+
**OfflineBanner integration** — add to main navigation screens:
|
|
138
|
+
```tsx
|
|
139
|
+
<View style={{ flex: 1 }}>
|
|
140
|
+
<OfflineBanner />
|
|
141
|
+
{/* ... rest of screen content */}
|
|
142
|
+
</View>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Step 6 — Data Layer Verification
|
|
108
146
|
|
|
109
|
-
Verify
|
|
110
|
-
-
|
|
111
|
-
-
|
|
147
|
+
Verify:
|
|
148
|
+
- `DataRepository` interface matches MockDataProvider's public methods
|
|
149
|
+
- MockDataProvider implements DataRepository
|
|
150
|
+
- `DataSourceResolver` returns the correct implementation
|
|
151
|
+
- ViewModel hooks use `DataSourceResolver.repository`, not `MockDataProvider` directly
|
|
112
152
|
- Seed data matches the new domain
|
|
113
153
|
- CRUD methods reference correct entity types
|
|
114
154
|
|
|
155
|
+
### Step 6.5 — Apply Animation Modifiers (if animation modules are integrated)
|
|
156
|
+
|
|
157
|
+
If the manifest includes an **"Animation & Sensory Plan"** section:
|
|
158
|
+
|
|
159
|
+
1. Read the "Per-Screen Animation Modifiers" table
|
|
160
|
+
2. Apply the assigned modifiers using imported module hooks/components:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
// Built-in (always available)
|
|
164
|
+
import { useScaleOnPress, useStaggeredAppear, useSlideIn, cardShadowStyle, useShimmer, usePulse, useHeartBounce } from '../animation/useAnimatedList';
|
|
165
|
+
const { style: pressStyle, onPressIn, onPressOut } = useScaleOnPress();
|
|
166
|
+
const listItemStyle = useStaggeredAppear(index);
|
|
167
|
+
<View style={[styles.card, cardShadowStyle()]}>{/* content */}</View>
|
|
168
|
+
<Animated.View style={[styles.placeholder, useShimmer()]} /> // loading
|
|
169
|
+
<Animated.View style={[styles.dot, usePulse()]} /> // live indicator
|
|
170
|
+
<Animated.View style={useHeartBounce(isFav)}><HeartIcon /></Animated.View> // favorite
|
|
171
|
+
|
|
172
|
+
// Modules (if integrated)
|
|
173
|
+
import { ParallaxHeader } from '../shared/ScrollEffects';
|
|
174
|
+
<ParallaxHeader height={280} imageSource={item.imageUrl} />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
3. Wrap with `useMotionPreferences` checks if MotionPreferences is integrated
|
|
178
|
+
4. Do NOT add animation modifiers to screens not listed in the manifest
|
|
179
|
+
|
|
180
|
+
### Step 6.7 — App Icon (if applicable)
|
|
181
|
+
|
|
182
|
+
React Native apps target both iOS and Android. App icon customization is handled per-platform:
|
|
183
|
+
- **iOS**: If `scripts/generate-app-icon.swift` exists, run it with SF Symbol + background color from manifest
|
|
184
|
+
- **Android**: If `templates/android/ICON_VECTORS.md` exists, update `ic_launcher_foreground.xml` and `ic_launcher_background` color
|
|
185
|
+
|
|
186
|
+
If scripts/resources are not available, skip — default icons will be used.
|
|
187
|
+
|
|
115
188
|
## Report Output
|
|
116
189
|
|
|
117
190
|
Write the report to `output/{app-name}/reports/05-customization.md`:
|
|
@@ -144,6 +217,17 @@ React Native (TypeScript)
|
|
|
144
217
|
- Empty states: {count}
|
|
145
218
|
- CTAs updated: {count}
|
|
146
219
|
|
|
220
|
+
## Offline Infrastructure
|
|
221
|
+
|
|
222
|
+
- OfflineBanner integrated: {yes/no}
|
|
223
|
+
- SyncManager methods updated: {list or "no changes needed"}
|
|
224
|
+
- Data persistence verified: {yes/no}
|
|
225
|
+
|
|
226
|
+
## Animation Modifiers Applied
|
|
227
|
+
|
|
228
|
+
- {modifier}: applied to {screen} — {description}
|
|
229
|
+
- MotionPreferences respected: {yes/no/N/A}
|
|
230
|
+
|
|
147
231
|
## Potential Issues
|
|
148
232
|
|
|
149
233
|
- {any concerns}
|
|
@@ -191,8 +275,10 @@ Templates include `testID` props on all interactive elements and a `TESTING_MANI
|
|
|
191
275
|
- ONLY edit files under `output/` — never touch `templates/`
|
|
192
276
|
- Ensure all imports resolve after your changes
|
|
193
277
|
- Preserve `MockDataProvider` CRUD methods and `reset()` function
|
|
278
|
+
- Do NOT modify NetworkMonitor, LocalPersistence, or OfflineBanner
|
|
279
|
+
- Ensure OfflineBanner is integrated into main navigation screens
|
|
194
280
|
- Use `testID` props on ALL interactive elements
|
|
195
|
-
- Follow `{screen}_{element}_{role}` convention for new test IDs
|
|
281
|
+
- Follow `{screen}_{element}_{role}` convention for new test IDs (see `templates/TEST_ID_CONVENTIONS.md`)
|
|
196
282
|
- Use `StyleSheet.create()` for styles, not inline objects
|
|
197
283
|
- Use functional components with TypeScript
|
|
198
284
|
- Keep React Navigation structure intact
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-planner
|
|
3
|
+
description: Analyzes app source code to generate a structured test plan before any simulator interaction. Reads Views, ViewModels, AppConfig, MockDataProvider, and TESTING_MANIFEST to produce a comprehensive test matrix.
|
|
4
|
+
allowed-tools: Read, Grep, Glob, LS
|
|
5
|
+
context: fork
|
|
6
|
+
agent: Explore
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Test Planner Skill
|
|
10
|
+
|
|
11
|
+
Analyze app source code and produce a structured test plan. Runs offline — no simulator needed.
|
|
12
|
+
|
|
13
|
+
## Instructions
|
|
14
|
+
|
|
15
|
+
### Step 1 — Gather App Inventory
|
|
16
|
+
|
|
17
|
+
Read from the app directory:
|
|
18
|
+
1. `TESTING_MANIFEST.md` — test IDs, screen inventory, element counts
|
|
19
|
+
2. `AppConfig` — feature flags, business rules (`.swift`/`.kt`/`.ts`)
|
|
20
|
+
3. `MockDataProvider` — data counts, categories, structure
|
|
21
|
+
4. `customization-manifest.md` (if exists) — screen descriptions, expected behavior
|
|
22
|
+
5. `summary.json` (if exists) — previous results, template, brand
|
|
23
|
+
6. `requirements.md` or `PRD.md` (if exists) — business-logic test cases
|
|
24
|
+
|
|
25
|
+
### Step 2 — Scan Screens + ViewModels
|
|
26
|
+
|
|
27
|
+
Read all View files (`*View.swift`, `*Screen.kt`, `*Screen.tsx`) and ViewModel files. Extract per screen:
|
|
28
|
+
- Interactive elements (buttons, toggles, fields, list items, FABs)
|
|
29
|
+
- Navigation targets
|
|
30
|
+
- Data dependencies from MockDataProvider
|
|
31
|
+
- Feature flags controlling visibility
|
|
32
|
+
- State transitions and CRUD operations
|
|
33
|
+
|
|
34
|
+
### Step 3 — Build Test Matrix
|
|
35
|
+
|
|
36
|
+
For each screen, create a checklist:
|
|
37
|
+
|
|
38
|
+
```markdown
|
|
39
|
+
### Screen: {Name}
|
|
40
|
+
**File:** {path} | **Elements:** {N}
|
|
41
|
+
|
|
42
|
+
#### Rendering
|
|
43
|
+
- [ ] Renders without crash
|
|
44
|
+
- [ ] Correct data shown ({N} items)
|
|
45
|
+
- [ ] No template leftover text
|
|
46
|
+
|
|
47
|
+
#### Navigation
|
|
48
|
+
- [ ] Navigate to screen, navigate back
|
|
49
|
+
|
|
50
|
+
#### Interactions
|
|
51
|
+
- [ ] {Button}: tap triggers {action}
|
|
52
|
+
- [ ] {Toggle}: state changes
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Add sections for: Edge Cases (empty states, long text, rapid taps, deep navigation), Regression Checks (leftovers, a11y IDs, images, back nav), Requirements-Based Tests (if PRD exists).
|
|
56
|
+
|
|
57
|
+
### Step 4 — Assign Priorities
|
|
58
|
+
|
|
59
|
+
- **P0** — crashes, data loss, broken navigation
|
|
60
|
+
- **P1** — features don't work, wrong data
|
|
61
|
+
- **P2** — visual, accessibility, minor UX
|
|
62
|
+
- **P3** — cosmetic
|
|
63
|
+
|
|
64
|
+
## Report Output
|
|
65
|
+
|
|
66
|
+
Write `output/{app-name}/reports/10-test-plan.md`. Update `summary.json` with step entry (step: 10, name: "test-plan").
|
|
67
|
+
|
|
68
|
+
## Rules
|
|
69
|
+
|
|
70
|
+
- READ-ONLY — do NOT modify source files or boot simulators
|
|
71
|
+
- Every interactive element must have at least one test case
|
|
72
|
+
- Test plan must be detailed enough for another agent to execute without reading source
|
package/.cursor/agents/README.md
CHANGED
|
@@ -12,8 +12,10 @@ These agent definition files (`.md`) are **preserved as a fallback** for when Cu
|
|
|
12
12
|
|---|---|
|
|
13
13
|
| `security-auditor.md` (Phase 1) | `.cursor/skills/prompt-validator/SKILL.md` |
|
|
14
14
|
| `security-auditor.md` (Phase 2) | `.cursor/skills/code-auditor/SKILL.md` |
|
|
15
|
-
| `template-selector.md` | `.cursor/skills/
|
|
15
|
+
| `template-selector.md` | `.cursor/skills/catalog-analyzer/SKILL.md` (merged with module-selector) |
|
|
16
16
|
| `design-selector.md` | `.cursor/skills/design-selector/SKILL.md` |
|
|
17
|
+
| `catalog-analyzer.md` | `.cursor/skills/catalog-analyzer/SKILL.md` (template + module selection) |
|
|
18
|
+
| `react-native-customizer.md` | `.cursor/skills/react-native-customizer/SKILL.md` |
|
|
17
19
|
| `ios-customizer.md` | `.cursor/skills/ios-customizer/SKILL.md` |
|
|
18
20
|
| `android-customizer.md` | `.cursor/skills/android-customizer/SKILL.md` |
|
|
19
21
|
| `build-tester.md` | `.cursor/skills/build-tester/SKILL.md` |
|
|
@@ -123,18 +123,19 @@ private val LightColorScheme = lightColorScheme(
|
|
|
123
123
|
- Use Material 3 color roles (primary, secondary, tertiary, surface, etc.)
|
|
124
124
|
- Keep `dynamicColor` support if present
|
|
125
125
|
|
|
126
|
-
###
|
|
127
|
-
|
|
126
|
+
### Data Layer
|
|
127
|
+
Templates use a `DataRepository` interface with `DataSourceResolver`:
|
|
128
128
|
```kotlin
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
// Screens get the repository from DataSourceResolver
|
|
130
|
+
val repository = remember { DataSourceResolver.repository }
|
|
131
|
+
val items by repository.items.collectAsState()
|
|
132
|
+
repository.addItem(newItem)
|
|
133
133
|
```
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
134
|
+
- ALWAYS use `DataSourceResolver.repository`, never `MockDataProvider` directly
|
|
135
|
+
- Preserve MockDataProvider CRUD functions and `reset()` method
|
|
136
|
+
- Do NOT modify NetworkMonitor, LocalPersistence, or OfflineBanner
|
|
137
|
+
- Verify NetworkMonitor is registered in the Application class
|
|
138
|
+
- Ensure OfflineBanner is integrated into main navigation composables
|
|
138
139
|
|
|
139
140
|
## Output
|
|
140
141
|
|
|
@@ -155,5 +156,8 @@ POTENTIAL ISSUES:
|
|
|
155
156
|
- Ensure all `import` statements resolve after renaming
|
|
156
157
|
- Keep `@HiltAndroidApp`, `@HiltViewModel`, `@AndroidEntryPoint` intact
|
|
157
158
|
- Keep `build.gradle.kts` syntactically valid Kotlin DSL
|
|
158
|
-
- Preserve `MockDataProvider`
|
|
159
|
+
- Preserve `MockDataProvider` CRUD functions and `reset()` method
|
|
160
|
+
- Do NOT modify NetworkMonitor, LocalPersistence, or OfflineBanner
|
|
159
161
|
- Use Material 3 components (not legacy Material 2)
|
|
162
|
+
- Preserve ALL `Modifier.testTag()` calls — do NOT remove test IDs
|
|
163
|
+
- Follow `{screen}_{element}_{role}` convention for new test tags (see `templates/TEST_ID_CONVENTIONS.md`)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: catalog-analyzer
|
|
3
|
+
description: Selects the best template from CATALOG.md and shared modules from MODULES_CATALOG.md in a single pass. Uses selected template context to boost module selection accuracy via "Relevant Templates" column.
|
|
4
|
+
tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Grep
|
|
7
|
+
- Glob
|
|
8
|
+
- LS
|
|
9
|
+
readonly: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Catalog Analyzer
|
|
13
|
+
|
|
14
|
+
You are a specialised subagent for selecting the best mobile app template AND the best shared modules. You have deep knowledge of both catalogs and their selection criteria.
|
|
15
|
+
|
|
16
|
+
## Logging Protocol
|
|
17
|
+
|
|
18
|
+
When you start, print:
|
|
19
|
+
`[SUBAGENT:catalog-analyzer] Starting — catalog analysis for "{app description}"`
|
|
20
|
+
|
|
21
|
+
When you finish, print:
|
|
22
|
+
`[SUBAGENT:catalog-analyzer] Completed — selected {TemplateName} (confidence: {high|medium|low}), {N} modules`
|
|
23
|
+
|
|
24
|
+
## Instructions
|
|
25
|
+
|
|
26
|
+
### Phase 1 — Template Selection
|
|
27
|
+
|
|
28
|
+
1. Read `templates/CATALOG.md` thoroughly
|
|
29
|
+
2. Given the user's app description and target platform, evaluate each template:
|
|
30
|
+
- Score against the "Best-For Keywords" in the decision matrix
|
|
31
|
+
- Check the "Best match when" criteria for each template
|
|
32
|
+
- Apply the "NOT a match when" rules to eliminate poor fits
|
|
33
|
+
- Consider the "Hybrid Apps" table if the app spans categories
|
|
34
|
+
3. If no template is a strong match, follow the "When No Template Fits" guidance — pick the template with the most similar navigation and screen patterns
|
|
35
|
+
4. Choose exactly ONE primary template
|
|
36
|
+
|
|
37
|
+
### Phase 2 — Module Selection
|
|
38
|
+
|
|
39
|
+
5. Read `templates/shared/MODULES_CATALOG.md` thoroughly
|
|
40
|
+
6. For every module, match by keywords AND check "Relevant Templates" against the selected template:
|
|
41
|
+
- Keyword match + template match → strong include
|
|
42
|
+
- Keyword match + no template match → include with lower confidence
|
|
43
|
+
- No keyword match + template match → consider if implied by domain
|
|
44
|
+
7. Apply BaaS heuristics (Firebase vs Supabase vs none)
|
|
45
|
+
8. Check module dependencies — add missing ones
|
|
46
|
+
9. Apply animation/sensory heuristics if description suggests premium feel
|
|
47
|
+
10. Aim for 5-15 modules
|
|
48
|
+
|
|
49
|
+
## Output Format
|
|
50
|
+
|
|
51
|
+
Return your answer in this exact format:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
SELECTED TEMPLATE: {TemplateName}
|
|
55
|
+
CONFIDENCE: high | medium | low
|
|
56
|
+
REASONING: {1-2 sentence explanation}
|
|
57
|
+
BORROW FROM: {other template name, if hybrid} or "none"
|
|
58
|
+
HYBRID NOTES: {what to borrow and why} or "n/a"
|
|
59
|
+
|
|
60
|
+
SELECTED MODULES ({N} total):
|
|
61
|
+
- {ModuleName}: {reason} [template boost: yes/no]
|
|
62
|
+
- ...
|
|
63
|
+
|
|
64
|
+
EXCLUDED MODULES:
|
|
65
|
+
- {ModuleName}: {reason for exclusion}
|
|
66
|
+
- ...
|
|
67
|
+
|
|
68
|
+
DEPENDENCIES ADDED:
|
|
69
|
+
- {ModuleName}: required by {other module}
|
|
70
|
+
- ...
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Rules
|
|
74
|
+
|
|
75
|
+
- Always recommend exactly ONE primary template
|
|
76
|
+
- If confidence is "low", explain what aspects of the user's request don't fit well
|
|
77
|
+
- For hybrid apps, identify which template to START with and what to borrow from the secondary template
|
|
78
|
+
- Do NOT recommend building from scratch — always pick the closest template
|
|
79
|
+
- Consider the platform (iOS vs Android vs React Native)
|
|
80
|
+
- Features covered by shared modules should NOT affect template scoring
|
|
81
|
+
- No modules are auto-included — every module must earn its place via keyword matching
|
|
82
|
+
- "Relevant Templates" is a boost signal, not a hard filter
|
|
83
|
+
- Aim for 5-15 modules — be selective, not exhaustive
|