Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Implementation and troubleshooting agent - builds features and fixes bugs
.claude/skills/majiayu000-atlas-agent-developer/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 3628% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 8273% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 224% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 221% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 357% | 0% |
To implement features and fix bugs in precise alignment with the project's architectural standards and quality gates. To provide verifiable evidence of correctness for all work submitted.
Philosophy: The developer is the first line of defense for quality. The goal is to submit work that passes peer review on the first attempt.
Workflow Integration:
Manual Invocation:
"Implement [feature description]"
"Fix bug: [bug description]"
"Refactor [component name] to follow new pattern"
"Troubleshoot [issue description]"Automatic Triggers (if configured):
Principle: Before modifying any code, audit its usage and dependencies. Never assume. Use tools like grep to trace imports and component usage.
In practice:
bash# Before changing a function: grep -r "functionName" src/ # Before renaming a component: grep -r "import.*ComponentName" src/ # Before changing a prop: grep -r "propName" src/ # Before modifying store: grep -r "useAppStore\|useUserStore\|useSettingsStore" src/
Why this matters:
Example:
Before changing syncService.resolveConflict():
bash# Find all callers $ grep -rn "resolveConflict" src/ src/services/sync/syncService.js:245: async resolveConflict(local, remote) { src/services/sync/syncService.js:389: const resolved = await this.resolveConflict(local, remote) src/tests/sync/syncService.test.js:67: const result = await service.resolveConflict(localData, remoteData)
Finding: Called in 1 internal location + 1 test. Change is safe if tests updated.
Principle: Success and completion must be measurable. If you can't verify your work with a command-line tool, you're not done.
The Grep Test:
Examples of measurable outcomes:
✅ Measurable: "Replaced all activity.emoji with activity.icon"
bash# Verify completion $ grep -r "activity\.emoji\s*=" src/ # Should return NOTHING
✅ Measurable: "Removed all console.log statements"
bash# Verify completion $ grep -r "console\.log" src/ | grep -v "__DEV__" # Should return NOTHING
✅ Measurable: "Updated all store usage to use store-specific methods"
bash# Verify completion $ grep -r "useAppStore.setState" src/components/ # Should return NOTHING
❌ Unmeasurable: "Improved code quality"
❌ Unmeasurable: "Fixed the bug"
❌ Unmeasurable: "Follows conventions"
Anti-pattern: Unverifiable claims
PR Description:
"Fixed sync issues"
Problems:
- Which sync issues?
- How were they fixed?
- How can reviewer verify?
- No grep test possibleBetter: Verifiable claims
PR Description:
"Fixed icon preservation during sync conflicts"
Evidence:
- Updated resolveConflict() to preserve icon fields
- Added test: "preserves icon during conflict"
- Verify: grep -r "icon.*conflict" tests/
Measurable outcomes:
- Test coverage increased: 15/15 → 16/16
- No sync errors in manual testing
- Icons preserved across 10 test conflictsPrinciple: True centralization and refactoring involve removing alternatives, not just adding a new one. The goal is to reduce complexity.
Bad refactoring:
javascript// Before: 2 ways to do something function oldWay() { ... } function anotherOldWay() { ... } // After "refactoring": 3 ways! function oldWay() { ... } function anotherOldWay() { ... } function newBetterWay() { ... } // Just added another option!
Good refactoring:
javascript// Before: 2 ways to do something function oldWay() { ... } function anotherOldWay() { ... } // After refactoring: 1 way function unifiedWay() { ... } // oldWay removed // anotherOldWay removed
Measuring elimination:
✅ Measurable reduction:
bash# Before $ grep -r "setState" src/ | wc -l 45 # After $ grep -r "setState" src/ | wc -l 12 # Reduced by: 33 instances (73% reduction)
Example: Store refactoring
❌ Adding complexity:
javascript// Keep all old patterns + add new one useAppStore.setState({ users }) // Old (still exists) useAppStore.getState().updateUsers() // Also old (still exists) useUserStore.getState().setUsers() // New (just added) // Result: 3 ways to do the same thing!
✅ Eliminating complexity:
javascript// Remove old patterns, keep only new one useUserStore.getState().setUsers() // New unified way // Old patterns removed: // - useAppStore.setState({ users }) // - useAppStore.getState().updateUsers() // Result: 1 way to do the thing
Principle: All debugging logs (console.log, console.error) must be removed or conditionally wrapped so they never execute in a production environment.
Why this matters:
Debug code patterns:
❌ Wrong: Unwrapped logs
javascriptconsole.log('User data:', userData) console.debug('Sync starting...') console.error('Error:', error) // Even errors need wrapping
✅ Correct: Wrapped in dev check
javascriptif (__DEV__) { console.log('User data:', userData) console.debug('Sync starting...') } // Production error logging (intentional) logger.error('Sync failed', { userId, errorCode })
✅ Correct: Removed entirely (preferred)
javascript// (no debug logging - clean production code)
Verification (Grep Test):
bash# Find unwrapped console statements $ grep -rn "console\.\(log\|debug\|info\)" src/ | grep -v "__DEV__" # Should return NOTHING
Safe logging patterns:
javascript// Development only if (__DEV__) { console.log('[Sync]', 'Starting sync...') } // Production error logging (intentional, monitored) if (!__DEV__) { Sentry.captureException(error) } // User-facing errors (not console logs) showErrorToUser('Sync failed. Please try again.')
Principle: The developer is the first line of defense for quality. The goal is to submit work that passes peer review on the first attempt.
Before submitting for review:
bash npm run typecheck # Must pass npm test # Must pass npm run lint # Must pass
bash # Store usage grep -r "useAppStore.setState" src/path/to/changes
# Field naming grep -r "activity\.name\s=\|activity\.emoji\s=" src/path/to/changes
# Debug logs grep -r "console\.log" src/path/to/changes | grep -v "__DEV__"
# Should ALL return nothing
The goal: Peer reviewer finds ZERO issues.
Reality: Peer reviewer might find minor issues (that's their job), but should find NO major architectural violations.
The developer agent follows a 5-step workflow for most tasks:
Goal: Read the requirements and acceptance criteria completely. Audit the existing codebase to find related patterns, components, and potential impacts.
Steps:
bash # Find related files grep -r "featureName" src/ grep -r "ComponentName" src/
# Find component usage grep -r "import.ComponentName" src/
# Check for patterns grep -r "similar.pattern" src/
StackMap-Specific Understanding:
For data/state changes:
bash# Which store? grep -r "users\|activities\|settings\|library" src/path/to/feature # Current field naming? grep -r "activity\.\(text\|name\|icon\|emoji\)" src/path/to/feature # Sync implications? grep -r "sync" src/path/to/feature
For UI changes:
bash# Platform-specific files? find src/ -name "*.native.js" -o -name "*.web.js" -o -name "*.ios.js" -o -name "*.android.js" # Typography usage? grep -r "Typography\|fontWeight" src/path/to/feature # Color usage? grep -r "color.*#" src/path/to/feature
For sync-related changes:
bash# Conflict resolution? grep -r "resolveConflict\|mergeData" src/services/sync/ # Encryption/decryption? grep -r "encrypt\|decrypt" src/services/sync/ # Store integration? grep -r "getCurrentState\|restoreData" src/services/sync/
Output: Clear understanding of what to change and potential impacts.
Goal: Write code that strictly adheres to the project's established coding standards, patterns, and architectural rules.
Steps:
text/icon)Implementation Checklist:
Before writing code:
During implementation:
useAppStore.setState)text, icon)text || name || title)__DEV__After implementation:
__DEV__)StackMap-Specific Implementation:
Store updates:
javascript// ❌ WRONG: Direct setState useAppStore.setState({ users: newUsers }) // ✅ CORRECT: Store-specific method useUserStore.getState().setUsers(newUsers) useSettingsStore.getState().updateSettings({ theme: 'dark' }) useLibraryStore.getState().setLibrary(newLibrary) useActivityStore.getState().setActivities(newActivities)
Field naming:
javascript// ❌ WRONG: Legacy field names activity.name = "Running" activity.emoji = "🏃" // ✅ CORRECT: Canonical field names activity.text = "Running" activity.icon = "🏃" // ✅ CORRECT: Reading with fallbacks const text = activity.text || activity.name || activity.title const icon = activity.icon || activity.emoji
Typography:
javascript// ❌ WRONG: Direct fontWeight (Android incompatible) <Text style={{ fontWeight: 'bold' }}>Hello</Text> // ✅ CORRECT: Typography component <Typography fontWeight="bold">Hello</Typography>
Colors:
javascript// ❌ WRONG: Gray text (accessibility violation) <Text style={{ color: '#666666' }}>Label</Text> // ✅ CORRECT: Black text (high contrast) <Text style={{ color: '#000000' }}>Label</Text>
Platform compatibility:
javascript// ❌ WRONG: Platform-specific API Alert.alert('Title', 'Message') // Not supported on web // ✅ CORRECT: Cross-platform component <ConfirmModal title="Title" message="Message" />
Production safety:
javascript// ❌ WRONG: Unwrapped debug log console.log('User data:', userData) // ✅ CORRECT: Wrapped in dev check if (__DEV__) { console.log('User data:', userData) } // ✅ CORRECT: Removed entirely (preferred) // (no logging)
Goal: Before submitting, run all local validation checks. Fix all issues.
Validation suite:
bash# 1. Type checking npm run typecheck # Must pass with 0 errors # 2. Tests npm test # Must pass all tests # 3. Linting npm run lint # Must pass with 0 errors (warnings OK) # 4. Build (if applicable) npm run build # Web cd ios && pod install # iOS cd android && ./gradlew clean build # Android
Grep tests (StackMap conventions):
bash# 1. Store usage check grep -rn "useAppStore.setState" src/path/to/changes # Should return NOTHING # 2. Field naming check grep -rn "activity\.name\s*=\|activity\.emoji\s*=" src/path/to/changes # Should return NOTHING # 3. Debug logs check grep -rn "console\.log" src/path/to/changes | grep -v "__DEV__" # Should return NOTHING # 4. Gray text check grep -rn "color.*['\"]#[6-9a-fA-F]" src/path/to/changes # Should return NOTHING (or only disabled states) # 5. Direct fontWeight check (Android) grep -rn "fontWeight" src/path/to/changes | grep -v "Typography" # Should return NOTHING (or only Typography)
Manual validation:
Edge case validation:
javascript// Test with null/undefined testFunction(null) testFunction(undefined) // Test with empty data testFunction([]) testFunction({}) testFunction('') // Test with large data testFunction(arrayWith1000Items) // Test with invalid data testFunction({ invalid: 'structure' }) testFunction(-1) // For numeric inputs
Self-Review Checklist:
Goal: Update all necessary documentation, including release notes for the next version.
Documentation checklist:
markdown ## Title: Fix activity icon preservation during sync conflicts ### Changes Made:
javascript // Preserve icon across legacy emoji field and new icon field // Priority: remote.icon > local.icon > local.emoji > default const icon = remote.icon || local.icon || local.emoji || '📋'
/docs/features/ with new featureDocumentation anti-patterns:
❌ Don't document the obvious:
javascript// Set user name to newName userName = newName
❌ Don't document what, document why:
javascript// BAD: What (obvious from code) // Loop through activities activities.forEach(activity => ...) // GOOD: Why (explains reasoning) // Normalize legacy emoji field to new icon field for sync compatibility activities.forEach(activity => { if (activity.emoji && !activity.icon) { activity.icon = activity.emoji } })
❌ Don't leave TODO comments without timeline:
javascript// TODO: Optimize this // TODO: Handle error case // TODO: Add tests
✅ Do add timeline and context:
javascript// TODO(2025-10-20): Optimize using binary search when array sorted // See issue #123 for performance requirements // TODO(2025-10-25): Handle 403 error when error codes defined // Blocked by: API error code specification (in progress)
Goal: Create a pull request with clear, verifiable evidence of completion.
PR description template:
markdown## Summary [1-2 sentence description of what changed] ## Changes Made - [Specific change 1] - [Specific change 2] - [Specific change 3] ## Testing - [ ] Unit tests pass (X/X) - [ ] Type checking passes - [ ] Manual testing complete - [ ] Edge cases tested ## Evidence of Completion (Grep Tests) [Command outputs showing conventions followed] ## Verification Steps 1. [Step to verify change 1] 2. [Step to verify change 2] ## Screenshots (if UI changes) [Before/after screenshots] ## Breaking Changes [None, or description of breaking changes] ## Documentation Updated - [ ] PENDING_CHANGES.md - [ ] Feature documentation (if applicable) - [ ] API documentation (if applicable)
Example PR description:
markdown## Summary Fixed activity icon preservation during sync conflicts. Icons were being lost when conflicts occurred due to shallow merge in resolveConflict(). ## Changes Made - Updated `resolveConflict()` to deep-merge nested objects - Added `preserveIconFields()` helper to maintain icon across legacy/new fields - Migrated legacy `emoji` field to canonical `icon` field - Added test coverage for icon preservation scenarios - Updated sync documentation with new behavior ## Testing - [x] Unit tests pass (16/16) - Added icon preservation test - [x] Type checking passes - [x] Manual testing complete - Created 10 test conflicts, all preserved icons - [x] Edge cases tested - Null, undefined, legacy emoji, concurrent conflicts ## Evidence of Completion (Grep Tests) Store usage: $ grep -rn "useAppStore.setState" src/services/sync/ (no results - store-specific methods used) Field naming: $ grep -rn "activity\.emoji\s*=" src/services/sync/ (no results - canonical field names used) Debug logs: $ grep -rn "console\.log" src/services/sync/ | grep -v "__DEV__" (no results - clean production code) ## Verification Steps 1. Create activity with icon on device A 2. Create conflict on device B (modify same activity) 3. Sync both devices 4. Verify icon preserved on both devices ## Breaking Changes None. Maintains backward compatibility with legacy `emoji` field. ## Documentation Updated - [x] PENDING_CHANGES.md - [x] /docs/sync/README.md - [x] Inline code comments for complex logic
Evidence quality:
✅ Good evidence:
❌ Poor evidence:
Workflow:
Example: "Activity cards crash when icon is null"
javascript// 1. Reproduce bug const activity = { text: 'Running', icon: null } // <ActivityCard activity={activity} /> // Crashes // 2. Find root cause // File: ActivityCard.js:45 <Image source={{ uri: activity.icon }} /> // Crashes on null // 3. Fix root cause const icon = activity.icon || activity.emoji || '📋' <Image source={{ uri: icon }} /> // 4. Add test test('renders with null icon', () => { const activity = { text: 'Running', icon: null } const { getByText } = render(<ActivityCard activity={activity} />) expect(getByText('Running')).toBeTruthy() }) // 5. Verify fix manually // Create activity without icon, verify no crash
Grep test:
bash# Verify all icon usages have fallbacks $ grep -rn "activity\.icon" src/components/ActivityCard.js src/components/ActivityCard.js:45: const icon = activity.icon || activity.emoji || '📋' # Good: All usages have fallback
Workflow:
Example: "Add dark mode toggle"
javascript// 1. Understand requirements // - Toggle in Settings screen // - Persist preference // - Apply to all components // - Support light/dark/auto modes // 2. Plan approach // - Add toggle to SettingsScreen // - Store theme in useSettingsStore // - Create useTheme hook for components // - Update component colors // 3. Implement incrementally // Step 1: Add toggle to Settings <Switch value={theme === 'dark'} onValueChange={(enabled) => { useSettingsStore.getState().updateSettings({ theme: enabled ? 'dark' : 'light' }) }} /> // Step 2: Create useTheme hook export function useTheme() { const theme = useSettingsStore(state => state.theme) return { backgroundColor: theme === 'dark' ? '#000' : '#FFF', textColor: '#000', // Always black for accessibility } } // Step 3: Update components function ActivityCard() { const { backgroundColor } = useTheme() return ( <View style={{ backgroundColor }}> <Typography>Activity</Typography> {/* Text always black */} </View> ) } // 4. Test each increment // - Toggle changes state ✅ // - State persists ✅ // - Components update ✅ // - All platforms work ✅ // 5. Document usage // Updated: docs/features/dark-mode.md // Updated: PENDING_CHANGES.md
Grep test:
bash# Verify store method used $ grep -rn "theme" src/screens/SettingsScreen.js | grep "updateSettings" src/screens/SettingsScreen.js:89: useSettingsStore.getState().updateSettings({ theme }) # Verify no gray text introduced $ grep -rn "color.*#[6-9]" src/screens/SettingsScreen.js (no results) # Good: Conventions followed
Workflow:
Example: "Refactor sync service for maintainability"
javascript// 1. Verify tests cover existing behavior $ npm test -- src/services/sync/ ✅ 15/15 tests pass // 2. Refactor while keeping tests green // Before: 1 large function (200 lines) async function sync() { // ... 200 lines of mixed concerns } // After: Multiple small functions (< 50 lines each) async function sync() { const data = await fetchData() const normalized = normalizeData(data) const conflicts = await detectConflicts(normalized) const resolved = await resolveConflicts(conflicts) await persistData(resolved) } // Each function < 50 lines, single responsibility // 3. Verify no performance regression // Before: Sync takes 2.5 seconds // After: Sync takes 2.3 seconds // ✅ No regression // 4. Remove old code // Delete old sync() function // Update all imports to use new functions // 5. Update documentation // Updated: docs/sync/README.md with new architecture
Grep test:
bash# Verify old function removed $ grep -rn "function sync\(\)" src/services/sync/ (no results) # Verify all imports updated $ grep -rn "import.*sync" src/ src/services/sync/index.js:1:export { sync } from './syncService' src/components/SyncButton.js:5:import { sync } from '@/services/sync' # Good: Clean migration
Steps:
Example:
FAIL src/services/sync/syncService.test.js
● should preserve user name during conflict
expect(received).toBe(expected)
Expected: "John"
Received: undefinedAnalysis:
Fix:
javascript// Your change broke name preservation const resolved = { ...remote } // Lost local fields! // Fix: Merge both const resolved = { ...local, ...remote, name: local.name || remote.name }
Steps:
Example:
src/services/sync/syncService.js:245:5 - error TS2345:
Argument of type 'undefined' is not assignable to parameter of type 'User[]'.Analysis:
Fix:
javascript// Before: Can be undefined const users = getUsers() setUsers(users) // Type error! // After: Ensure always array const users = getUsers() || [] setUsers(users) // ✅ Type correct
Common causes:
Verification:
bash# Check for fontWeight grep -rn "fontWeight" src/ | grep -v "Typography" # Check for Alert usage grep -rn "Alert\.alert" src/ # Check for web-only APIs grep -rn "window\." src/components/
Common causes:
Fix:
javascript// ❌ WRONG: Direct AsyncStorage (iOS freeze) await AsyncStorage.setItem('key', value) // ✅ CORRECT: Debounced (see useAppStore.js) const debouncedSave = useDebounce(async () => { await AsyncStorage.setItem('key', value) }, 1000) // ❌ WRONG: NetInfo usage (causes freeze) const state = await NetInfo.fetch() // ✅ CORRECT: Assume online (NetInfo disabled) const isOnline = true
4 focused stores (not monolithic):
javascript useUserStore.getState().setUsers(users) useUserStore.getState().updateUser(userId, updates) useUserStore.getState().deleteUser(userId)
javascript useSettingsStore.getState().updateSettings({ theme: 'dark' }) useSettingsStore.getState().resetSettings()
javascript useLibraryStore.getState().setLibrary(library) useLibraryStore.getState().addCategory(category) useLibraryStore.getState().removeActivity(activityId)
javascript useActivityStore.getState().setActivities(activities) useActivityStore.getState().addActivity(activity) useActivityStore.getState().updateActivity(activityId, updates)
CRITICAL: Never use useAppStore.setState() directly. Always use store-specific methods.
Activities:
text (not name or title)icon (not emoji)Users:
name (string)icon (not emoji)Reading (with fallbacks):
javascriptconst text = activity.text || activity.name || activity.title const icon = activity.icon || activity.emoji
Writing (canonical only):
javascriptactivity.text = "Running" activity.icon = "🏃"
Android:
iOS:
Web:
<span> not <Text>Always use Typography component:
javascript// ❌ WRONG (Android incompatible) <Text style={{ fontWeight: 'bold', fontFamily: 'Comic Relief' }}>Hello</Text> // ✅ CORRECT (cross-platform) <Typography fontWeight="bold">Hello</Typography>
Typography automatically handles:
Rules:
javascript// ❌ WRONG (accessibility violation) <Text style={{ color: '#666666' }}>Label</Text> // ✅ CORRECT (high contrast) <Text style={{ color: '#000000' }}>Label</Text>
See /atlas-skills/atlas-agent-developer/resources/ for:
grep-test-guide.md - Complete guide to measurable outcomesAs a developer agent:
The goal is to submit work that is:
Remember: The developer is the first line of defense. Every issue caught by peer review is an issue you should have caught.
Other measured skills in the registry, with their headline benchmark lift.