Standard 5-phase workflow for most development tasks - bugs, small features, refactors (30-60 min)
Perfect for (80% of tasks):
Time estimate: 30-60 minutes
Success criteria:
Phase 1: Research → Understand current implementation
Phase 2: Plan → Design approach
Phase 3: Implement → Make changes + tests
Phase 4: Review → Edge cases + security
Phase 5: Deploy → Full test suite + deployment
Goal: Understand the current implementation and identify all affected files.
Find all related files
# Search for relevant code patterns
grep -r "featureName" src/
grep -r "ComponentName" src/
# Find component/function usage
grep -r "import.*ComponentName" src/
Understand current implementation
Check for existing patterns
Identify potential impacts
For data/state changes:
useAppStore, useUserStore, useSettingsStore, useLibraryStore)text/icon, Users use icon/name/src/utils/dataNormalizer.js for normalization logicFor UI changes:
.native.js, .web.js, .ios.js, .android.jsFor sync-related changes:
/src/services/sync/syncService.jsFiles to modify:
- /src/services/sync/syncService.js (main sync logic)
- /src/services/sync/syncStoreIntegration.js (store interaction)
- /src/utils/dataNormalizer.js (field normalization)
Current implementation:
- Conflict resolution uses Object.assign, overwrites nested fields
- Icons stored as `activity.icon` but also `activity.emoji` (legacy)
Risks:
- Must preserve all icon variations during conflict merge
- Need fallback: icon || emoji
Goal: Design the approach and create a file-by-file implementation plan.
Design the solution
List file changes
Identify dependencies
Plan testing approach
Field naming strategy:
text || name || title, icon || emojitext, icondataNormalizer.js if neededStore update strategy:
useAppStore.setState)Platform strategy:
.native.js, .web.js)Solution Design:
- Update conflict resolution to deep-merge nested objects
- Add explicit icon field preservation
- Add fallback logic for legacy emoji field
File Changes:
1. /src/services/sync/syncService.js
- Modify `resolveConflict()` function
- Add `preserveIconFields()` helper
- Use deep merge instead of Object.assign
2. /src/utils/dataNormalizer.js
- Add `normalizeActivityIcon()` function
- Handle emoji → icon migration
3. /tests/sync/syncService.test.js
- Add test: "preserves icon during conflict"
- Add test: "migrates emoji to icon"
Testing Approach:
- Unit tests for conflict resolution
- Integration test for full sync cycle
- Manual test: Create conflict, verify icon preserved
Goal: Make the changes and update tests.
Implement changes file-by-file
Update/add tests
Verify locally
npm testnpm run typecheckApply StackMap conventions
text/icon, not name/emojiBefore writing code:
During implementation:
useUserStore.getState().setUsers())text, icon)text || name || title)__DEV__ checkAfter implementation:
Store updates (CRITICAL):
// ❌ WRONG: Direct setState
useAppStore.setState({ users: newUsers })
// ✅ CORRECT: Store-specific method
useUserStore.getState().setUsers(newUsers)
// ✅ CORRECT: Store-specific method for settings
useSettingsStore.getState().updateSettings({ theme: 'dark' })
// ✅ CORRECT: Store-specific method for library
useLibraryStore.getState().setLibrary(newLibrary)
Field naming (CRITICAL):
// ❌ 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 (Android compatibility):
// ❌ WRONG: Direct fontWeight on Android
<Text style={{ fontWeight: 'bold' }}>Hello</Text>
// ✅ CORRECT: Use Typography component
<Typography fontWeight="bold">Hello</Typography>
// Typography handles Android font variants automatically
// File: /src/services/sync/syncService.js
// Helper function to preserve icon fields
const preserveIconFields = (local, remote) => {
// Use canonical field names
const localIcon = local.icon || local.emoji
const remoteIcon = remote.icon || remote.emoji
// Prefer newer, fallback to either
const preservedIcon = remote.icon || localIcon
return {
...remote,
icon: preservedIcon,
// Remove legacy field
emoji: undefined
}
}
// Update conflict resolution
const resolveConflict = (local, remote) => {
const resolved = preserveIconFields(local, remote)
// Use store-specific method
useUserStore.getState().setUsers(users =>
users.map(u => u.id === resolved.id ? resolved : u)
)
return resolved
}
Goal: Peer review for edge cases and security check.
Self-review first
Run validation commands
npm run typecheck
npm test
npm run lint
Invoke peer-reviewer agent (if available)
Security check (if applicable)
Code quality:
StackMap conventions:
useAppStore.setState)text/icon (not name/emoji)Platform compatibility:
Edge cases:
Testing:
npm test)npm run typecheck)Issue 1: Direct state update
// ❌ Found during review
useAppStore.setState({ users: updatedUsers })
// ✅ Fixed
useUserStore.getState().setUsers(updatedUsers)
Issue 2: Missing fallback
// ❌ Found during review
<Text>{activity.text}</Text> // Will break for legacy data
// ✅ Fixed
<Text>{activity.text || activity.name || activity.title}</Text>
Issue 3: Edge case not handled
// ❌ Found during review
const firstActivity = activities[0] // Crashes if empty
// ✅ Fixed
const firstActivity = activities.length > 0 ? activities[0] : null
if (!firstActivity) return null
Goal: Run full test suite and deploy via quality script.
Update PENDING_CHANGES.md
## Title: Fix sync icon preservation
### Changes Made:
- Updated conflict resolution to preserve icon fields
- Added deep merge for nested objects
- Migrated legacy emoji field to icon
- Added tests for icon preservation
Run full validation
npm run typecheck
npm test
npm run lint
Deploy using quality script
# For QUAL (local testing)
./scripts/deploy.sh qual --all
# For STAGE (internal validation)
./scripts/deploy.sh stage --all
# For BETA (closed testing)
./scripts/deploy.sh beta --all
# For PROD (production)
./scripts/deploy.sh prod --all
Verify deployment
Pre-deployment:
PENDING_CHANGES.md updated with clear descriptionnpm test)npm run typecheck)npm run lint)Deployment:
Post-deployment:
The deployment script automatically enforces:
PENDING_CHANGES.mdIf tests fail: Fix them. Don't skip tests. If type checking fails: Fix type errors. Don't bypass. If build fails: Debug build issues. Don't commit broken code.
# 1. Update PENDING_CHANGES.md
## Title: Fix activity icon preservation during sync conflicts
### Changes Made:
- Updated syncService conflict resolution to preserve icon fields
- Added deep merge utility for nested object conflicts
- Migrated legacy emoji field to canonical icon field
- Added test coverage for icon preservation scenarios
- Updated dataNormalizer with emoji→icon migration logic
# 2. Run validation
npm run typecheck # ✅ Pass
npm test # ✅ Pass
# 3. Deploy to QUAL for testing
./scripts/deploy.sh qual --all
# Output:
# ✅ Type checking: Pass
# ✅ Tests: Pass (15/15)
# ✅ Build: Success
# ✅ Version: 2025.01.18 → 2025.01.19
# ✅ Deployed: qual-api.stackmap.app
useAppStore.setState() directlyactivity.name, activity.emoji)__DEV__resources/research-patterns.md/CLAUDE.md/docs/platform//docs/STORE_ARCHITECTURE.md/docs/features/field-conventions.md# Find sync-related files
grep -r "resolveConflict" src/
grep -r "icon" src/services/sync/
# Files found:
# - /src/services/sync/syncService.js (conflict resolution)
# - /src/services/sync/syncStoreIntegration.js (store updates)
# - /src/utils/dataNormalizer.js (field normalization)
Understanding:
Object.assign, overwrites nested fieldsicon (new) and emoji (legacy)Solution:
resolveConflict() to deep-merge objectspreserveIconFields() helperemoji → icon in normalizerFiles to change:
syncService.js - add icon preservationdataNormalizer.js - add migrationsyncService.test.js - add tests// syncService.js
const preserveIconFields = (local, remote) => {
const icon = remote.icon || local.icon || local.emoji
return { ...remote, icon, emoji: undefined }
}
const resolveConflict = (local, remote) => {
const resolved = preserveIconFields(local, remote)
// Use store-specific method
useActivityStore.getState().updateActivity(resolved)
return resolved
}
// Add tests
test('preserves icon during conflict', () => {
const local = { id: 1, text: 'Run', icon: '🏃' }
const remote = { id: 1, text: 'Running' } // missing icon
const result = resolveConflict(local, remote)
expect(result.icon).toBe('🏃')
})
Self-review checklist:
Run validation:
npm run typecheck # ✅ Pass
npm test # ✅ Pass (16/16)
# Update PENDING_CHANGES.md
## Title: Fix activity icon preservation during sync conflicts
### Changes Made:
- Updated conflict resolution to preserve icon fields
- Added deep merge for nested objects
- Migrated legacy emoji to icon field
- Added test coverage
# Deploy
./scripts/deploy.sh qual --all
# ✅ Deployed successfully
Total time: ~50 minutes ✅
The Standard workflow is your daily driver for most development tasks. It provides the right balance of:
When in doubt, choose Standard workflow - it's correct for 80% of tasks.