@tekyzinc/gsd-t 2.46.11 → 2.50.11

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +22 -2
  3. package/bin/debug-ledger.js +193 -0
  4. package/bin/gsd-t.js +259 -1
  5. package/commands/gsd-t-debug.md +64 -1
  6. package/commands/gsd-t-execute.md +79 -3
  7. package/commands/gsd-t-help.md +18 -2
  8. package/commands/gsd-t-init.md +7 -0
  9. package/commands/gsd-t-integrate.md +16 -0
  10. package/commands/gsd-t-quick.md +56 -1
  11. package/commands/gsd-t-test-sync.md +5 -1
  12. package/commands/gsd-t-verify.md +6 -1
  13. package/commands/gsd-t-wave.md +26 -0
  14. package/docs/GSD-T-README.md +83 -1
  15. package/docs/architecture.md +9 -1
  16. package/docs/requirements.md +30 -0
  17. package/package.json +1 -1
  18. package/templates/CLAUDE-global.md +19 -2
  19. package/templates/stacks/_security.md +243 -0
  20. package/templates/stacks/desktop.ini +2 -0
  21. package/templates/stacks/docker.md +202 -0
  22. package/templates/stacks/firebase.md +166 -0
  23. package/templates/stacks/flutter.md +205 -0
  24. package/templates/stacks/github-actions.md +201 -0
  25. package/templates/stacks/graphql.md +216 -0
  26. package/templates/stacks/neo4j.md +218 -0
  27. package/templates/stacks/nextjs.md +184 -0
  28. package/templates/stacks/node-api.md +196 -0
  29. package/templates/stacks/playwright.md +528 -0
  30. package/templates/stacks/postgresql.md +225 -0
  31. package/templates/stacks/python.md +243 -0
  32. package/templates/stacks/react-native.md +216 -0
  33. package/templates/stacks/react.md +293 -0
  34. package/templates/stacks/redux.md +193 -0
  35. package/templates/stacks/rest-api.md +202 -0
  36. package/templates/stacks/supabase.md +188 -0
  37. package/templates/stacks/tailwind.md +169 -0
  38. package/templates/stacks/typescript.md +176 -0
  39. package/templates/stacks/vite.md +176 -0
  40. package/templates/stacks/vue.md +189 -0
  41. package/templates/stacks/zustand.md +203 -0
@@ -0,0 +1,225 @@
1
+ # PostgreSQL Standards
2
+
3
+ These rules are MANDATORY. Violations fail the task. No exceptions.
4
+
5
+ ---
6
+
7
+ ## 1. Naming Conventions
8
+
9
+ ```
10
+ MANDATORY:
11
+ ├── Tables: snake_case, plural (users, order_items)
12
+ ├── Columns: snake_case, singular (first_name, created_at)
13
+ ├── Primary keys: id (UUID preferred over serial for distributed systems)
14
+ ├── Foreign keys: {referenced_table_singular}_id (user_id, order_id)
15
+ ├── Indexes: idx_{table}_{columns} (idx_users_email)
16
+ ├── Constraints: {type}_{table}_{columns} (uq_users_email, fk_orders_user_id)
17
+ ├── Enums: snake_case singular (user_role, order_status)
18
+ └── Boolean columns: is_ or has_ prefix (is_active, has_verified_email)
19
+ ```
20
+
21
+ ---
22
+
23
+ ## 2. Schema Design
24
+
25
+ ```
26
+ MANDATORY:
27
+ ├── Every table has: id (PK), created_at (timestamptz DEFAULT now()), updated_at
28
+ ├── Use timestamptz — NEVER timestamp without time zone
29
+ ├── Use UUID for primary keys in distributed or API-exposed systems
30
+ ├── Use appropriate types: text (not varchar), numeric (not float for money)
31
+ ├── Add NOT NULL constraints by default — allow NULL only with explicit reason
32
+ ├── Foreign keys with ON DELETE policy (CASCADE, SET NULL, or RESTRICT — choose deliberately)
33
+ └── NEVER store JSON when a proper relational schema exists — use jsonb only for truly unstructured data
34
+ ```
35
+
36
+ **GOOD**
37
+ ```sql
38
+ CREATE TABLE users (
39
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
40
+ email TEXT NOT NULL,
41
+ display_name TEXT NOT NULL,
42
+ role user_role NOT NULL DEFAULT 'viewer',
43
+ is_active BOOLEAN NOT NULL DEFAULT true,
44
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
45
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
46
+ CONSTRAINT uq_users_email UNIQUE (email)
47
+ );
48
+ ```
49
+
50
+ ---
51
+
52
+ ## 3. Migrations
53
+
54
+ ```
55
+ MANDATORY:
56
+ ├── One migration per change — never combine unrelated schema changes
57
+ ├── Migrations are forward-only in production — NEVER edit a deployed migration
58
+ ├── Name format: {timestamp}_{description}.sql (20260325_add_users_table.sql)
59
+ ├── Every migration must be reversible — include a down/rollback section
60
+ ├── Test migrations on a copy of production data before deploying
61
+ └── NEVER use DROP COLUMN or DROP TABLE without user approval (Destructive Action Guard)
62
+ ```
63
+
64
+ ---
65
+
66
+ ## 4. Indexing
67
+
68
+ ```
69
+ MANDATORY:
70
+ ├── Index every foreign key column
71
+ ├── Index columns used in WHERE, JOIN, and ORDER BY
72
+ ├── Use partial indexes for common filter patterns: WHERE is_active = true
73
+ ├── Use composite indexes in query column order (leftmost prefix rule)
74
+ ├── GIN indexes for jsonb, array, and full-text search columns
75
+ ├── NEVER create indexes speculatively — profile queries first (EXPLAIN ANALYZE)
76
+ └── Monitor unused indexes and remove them
77
+ ```
78
+
79
+ **GOOD**
80
+ ```sql
81
+ -- Foreign key index
82
+ CREATE INDEX idx_orders_user_id ON orders (user_id);
83
+
84
+ -- Composite for common query pattern
85
+ CREATE INDEX idx_orders_user_status ON orders (user_id, status);
86
+
87
+ -- Partial index — only active users
88
+ CREATE INDEX idx_users_active_email ON users (email) WHERE is_active = true;
89
+
90
+ -- GIN for jsonb queries
91
+ CREATE INDEX idx_products_metadata ON products USING GIN (metadata);
92
+ ```
93
+
94
+ ---
95
+
96
+ ## 5. Query Patterns
97
+
98
+ ```
99
+ MANDATORY:
100
+ ├── Use parameterized queries — NEVER string concatenation for SQL
101
+ ├── SELECT only the columns you need — NEVER SELECT *
102
+ ├── Use LIMIT on all user-facing queries — prevent unbounded result sets
103
+ ├── Use EXISTS instead of COUNT(*) > 0 for existence checks
104
+ ├── Use CTEs (WITH) for readability — but not for performance (CTEs can be optimization fences)
105
+ ├── Prefer JOIN over subquery where equivalent
106
+ └── Always include ORDER BY when results must be deterministic
107
+ ```
108
+
109
+ **BAD**
110
+ ```sql
111
+ SELECT * FROM users WHERE name LIKE '%' || $1 || '%';
112
+ SELECT COUNT(*) FROM orders WHERE user_id = $1; -- just to check existence
113
+ ```
114
+
115
+ **GOOD**
116
+ ```sql
117
+ SELECT id, email, display_name FROM users WHERE name ILIKE '%' || $1 || '%' LIMIT 50;
118
+ SELECT EXISTS(SELECT 1 FROM orders WHERE user_id = $1);
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 6. Connection Management
124
+
125
+ ```
126
+ MANDATORY:
127
+ ├── Use connection pooling (PgBouncer, or built-in pool in your ORM/driver)
128
+ ├── Set pool size based on workload — not unlimited
129
+ ├── Close/release connections after use — never leak
130
+ ├── Set statement_timeout on application connections (e.g., 30s)
131
+ ├── Use read replicas for heavy read workloads
132
+ └── Serverless: use Supabase connection pooler or PgBouncer — not direct connections
133
+ ```
134
+
135
+ ---
136
+
137
+ ## 7. Transactions
138
+
139
+ ```
140
+ MANDATORY:
141
+ ├── Wrap multi-statement operations in transactions
142
+ ├── Keep transactions short — don't hold locks while doing I/O
143
+ ├── Use appropriate isolation level (READ COMMITTED is default — sufficient for most cases)
144
+ ├── Handle deadlocks with retry logic (up to 3 retries)
145
+ └── NEVER leave transactions open — always COMMIT or ROLLBACK
146
+ ```
147
+
148
+ ---
149
+
150
+ ## 8. Graph-in-SQL Patterns
151
+
152
+ When implementing graph structures in PostgreSQL (adjacency lists, knowledge graphs, hierarchies):
153
+
154
+ ```
155
+ PATTERNS:
156
+ ├── Node tables: one table per entity type with UUID primary keys
157
+ ├── Edge tables (junction): {source}_id + {target}_id + metadata columns
158
+ │ Add relevance_score, weight, or edge_count for weighted graphs
159
+ ├── Hierarchies: parent_id self-referencing FK + recursive CTE for traversal
160
+ ├── Index both sides of every edge table FK
161
+ ├── Stable seed UUIDs for reproducible deploys (deterministic UUID format)
162
+ └── In-memory cache (LRU, 5-min TTL) for frequently traversed paths
163
+ ```
164
+
165
+ **Hierarchy traversal — recursive CTE:**
166
+ ```sql
167
+ WITH RECURSIVE ancestors AS (
168
+ SELECT id, name, parent_id, 0 AS depth
169
+ FROM graph_business_types
170
+ WHERE id = $1
171
+ UNION ALL
172
+ SELECT t.id, t.name, t.parent_id, a.depth + 1
173
+ FROM graph_business_types t
174
+ JOIN ancestors a ON t.id = a.parent_id
175
+ )
176
+ SELECT * FROM ancestors ORDER BY depth;
177
+ ```
178
+
179
+ **Weighted edge query:**
180
+ ```sql
181
+ SELECT w.id, w.name, e.relevance_score
182
+ FROM graph_edges_bt_workflow e
183
+ JOIN graph_workflows w ON w.id = e.workflow_id
184
+ WHERE e.business_type_id = $1
185
+ ORDER BY e.relevance_score DESC
186
+ LIMIT 8;
187
+ ```
188
+
189
+ **Rules:**
190
+ - Index edge tables on both FK columns
191
+ - Use ON DELETE CASCADE for edges when the node is deleted
192
+ - Consider materialized views for expensive multi-hop traversals
193
+ - For deep graphs (5+ hops), evaluate whether Neo4j is more appropriate
194
+
195
+ ---
196
+
197
+ ## 9. Anti-Patterns
198
+
199
+ ```
200
+ NEVER:
201
+ ├── SELECT * in application queries
202
+ ├── String concatenation for SQL — parameterized queries only
203
+ ├── Unbounded queries without LIMIT
204
+ ├── timestamp without time zone — always timestamptz
205
+ ├── float/double for money — use numeric or integer (cents)
206
+ ├── Storing structured relational data in jsonb
207
+ ├── Missing indexes on foreign keys
208
+ ├── Long-running transactions holding locks
209
+ └── Direct connections from serverless without pooling
210
+ ```
211
+
212
+ ---
213
+
214
+ ## PostgreSQL Verification Checklist
215
+
216
+ - [ ] Naming follows conventions (snake_case, plural tables, singular columns)
217
+ - [ ] Every table has id, created_at, updated_at
218
+ - [ ] timestamptz used — not timestamp
219
+ - [ ] All foreign keys indexed
220
+ - [ ] Parameterized queries only — no string concatenation
221
+ - [ ] All user-facing queries have LIMIT
222
+ - [ ] Connection pooling configured
223
+ - [ ] Migrations are forward-only and reversible
224
+ - [ ] No SELECT * in application code
225
+ - [ ] Graph edges indexed on both FK columns (if applicable)
@@ -0,0 +1,243 @@
1
+ # Python Standards
2
+
3
+ These rules are MANDATORY. Violations fail the task. No exceptions.
4
+
5
+ ---
6
+
7
+ ## 1. Type Hints
8
+
9
+ ```
10
+ MANDATORY:
11
+ ├── Type hints on ALL function signatures (params + return)
12
+ ├── Use built-in generics (list, dict, tuple) — not typing.List etc. (Python 3.9+)
13
+ ├── Use | for unions — not typing.Union (Python 3.10+)
14
+ ├── Use dataclasses or Pydantic models for structured data — NEVER raw dicts
15
+ └── Run mypy or pyright in CI — no untyped public functions
16
+ ```
17
+
18
+ **BAD**
19
+ ```python
20
+ def get_users(filters):
21
+ result = {"users": [], "total": 0}
22
+ return result
23
+ ```
24
+
25
+ **GOOD**
26
+ ```python
27
+ @dataclass
28
+ class UserList:
29
+ users: list[User]
30
+ total: int
31
+
32
+ def get_users(filters: UserFilters) -> UserList:
33
+ ...
34
+ ```
35
+
36
+ ---
37
+
38
+ ## 2. Project Structure
39
+
40
+ ```
41
+ MANDATORY:
42
+ ├── Use src/ layout for packages — src/{package_name}/
43
+ ├── Tests mirror source: tests/{module}/test_{file}.py
44
+ ├── One class per file for major classes — small helpers can share
45
+ ├── __init__.py exports only the public API
46
+ └── Config in environment variables or .env — NEVER hardcoded
47
+ ```
48
+
49
+ ---
50
+
51
+ ## 3. Data Models
52
+
53
+ ```
54
+ MANDATORY:
55
+ ├── Use dataclasses for internal data structures
56
+ ├── Use Pydantic BaseModel for API input/output and validation
57
+ ├── Use Enums for fixed option sets — NEVER magic strings
58
+ ├── Frozen dataclasses for immutable value objects
59
+ └── NEVER pass raw dicts between functions — define a model
60
+ ```
61
+
62
+ **BAD** — `def create_user(data: dict) -> dict:`
63
+
64
+ **GOOD**
65
+ ```python
66
+ class CreateUserRequest(BaseModel):
67
+ name: str = Field(min_length=2)
68
+ email: EmailStr
69
+ role: UserRole # Enum
70
+
71
+ class UserResponse(BaseModel):
72
+ id: str
73
+ name: str
74
+ email: str
75
+ role: UserRole
76
+ created_at: datetime
77
+
78
+ def create_user(request: CreateUserRequest) -> UserResponse:
79
+ ...
80
+ ```
81
+
82
+ ---
83
+
84
+ ## 4. Error Handling
85
+
86
+ ```
87
+ MANDATORY:
88
+ ├── Define custom exception hierarchy per domain — NEVER raise bare Exception
89
+ ├── Catch specific exceptions — NEVER bare except: or except Exception:
90
+ ├── Use try/except at boundaries (API handlers, CLI entry) — not deep in logic
91
+ ├── Log exceptions with context (structlog or logging) before re-raising
92
+ └── Return error types or raise — NEVER return None to signal failure
93
+ ```
94
+
95
+ **BAD**
96
+ ```python
97
+ try:
98
+ result = do_something()
99
+ except:
100
+ return None
101
+ ```
102
+
103
+ **GOOD**
104
+ ```python
105
+ class UserNotFoundError(DomainError):
106
+ def __init__(self, user_id: str):
107
+ super().__init__(f"User {user_id} not found")
108
+ self.user_id = user_id
109
+
110
+ try:
111
+ user = user_repo.get(user_id)
112
+ except UserNotFoundError:
113
+ logger.warning("user_not_found", user_id=user_id)
114
+ raise
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 5. Functions and Methods
120
+
121
+ ```
122
+ MANDATORY:
123
+ ├── Max 30 lines per function — split if longer
124
+ ├── Max 200 lines per file — create new modules if needed
125
+ ├── Single responsibility — one function does one thing
126
+ ├── Use keyword arguments for functions with 3+ parameters
127
+ ├── Default mutable arguments are FORBIDDEN — use None + factory
128
+ └── Docstrings on public functions only — skip for obvious private methods
129
+ ```
130
+
131
+ **BAD** — `def register(name, email, role, send_email=True, template=[], notify=[]):`
132
+
133
+ **GOOD**
134
+ ```python
135
+ def register(
136
+ *,
137
+ name: str,
138
+ email: str,
139
+ role: UserRole,
140
+ send_email: bool = True,
141
+ template: list[str] | None = None,
142
+ notify: list[str] | None = None,
143
+ ) -> User:
144
+ template = template or []
145
+ notify = notify or []
146
+ ...
147
+ ```
148
+
149
+ ---
150
+
151
+ ## 6. Async Patterns
152
+
153
+ ```
154
+ WHEN USING ASYNC:
155
+ ├── async def for I/O-bound operations (HTTP, DB, file) — not CPU-bound
156
+ ├── Use asyncio.gather for concurrent I/O — not sequential awaits
157
+ ├── NEVER mix sync and async — use run_in_executor for sync libraries
158
+ ├── Always set timeouts on external calls (httpx, aiohttp)
159
+ └── Use async context managers for connections and sessions
160
+ ```
161
+
162
+ **BAD** — sequential awaits for independent calls:
163
+ ```python
164
+ users = await get_users()
165
+ orders = await get_orders() # waits for users to finish first
166
+ ```
167
+
168
+ **GOOD**
169
+ ```python
170
+ users, orders = await asyncio.gather(get_users(), get_orders())
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 7. Testing
176
+
177
+ ```
178
+ MANDATORY:
179
+ ├── pytest as the test runner — not unittest
180
+ ├── Use fixtures for setup/teardown — not setUp/tearDown methods
181
+ ├── Use parametrize for testing multiple inputs
182
+ ├── Test file naming: test_{module}.py
183
+ ├── Test function naming: test_{behavior}_when_{condition}
184
+ └── Assert with plain assert — not self.assertEqual
185
+ ```
186
+
187
+ **GOOD**
188
+ ```python
189
+ @pytest.fixture
190
+ def user_service(db_session: Session) -> UserService:
191
+ return UserService(db_session)
192
+
193
+ @pytest.mark.parametrize("role,expected", [
194
+ (UserRole.ADMIN, True),
195
+ (UserRole.VIEWER, False),
196
+ ])
197
+ def test_can_delete_when_role(user_service: UserService, role: UserRole, expected: bool):
198
+ assert user_service.can_delete(role) == expected
199
+ ```
200
+
201
+ ---
202
+
203
+ ## 8. Dependencies and Imports
204
+
205
+ ```
206
+ MANDATORY:
207
+ ├── Use virtual environments (venv, poetry, uv) — NEVER install globally
208
+ ├── Pin dependencies in requirements.txt or pyproject.toml
209
+ ├── Import order: stdlib → third-party → local (enforced by isort/ruff)
210
+ ├── Use absolute imports for cross-module — relative for same-package
211
+ └── NEVER import * — explicit imports only
212
+ ```
213
+
214
+ ---
215
+
216
+ ## 9. Anti-Patterns
217
+
218
+ ```
219
+ NEVER:
220
+ ├── Bare except: or except Exception: without re-raise
221
+ ├── Mutable default arguments (def f(items=[]))
222
+ ├── Global mutable state — use dependency injection
223
+ ├── String concatenation for SQL — use parameterized queries
224
+ ├── print() for logging — use logging/structlog
225
+ ├── Raw dicts as function params or return types
226
+ ├── Nested functions deeper than 2 levels
227
+ └── Type: ignore without explanation comment
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Python Verification Checklist
233
+
234
+ - [ ] Type hints on all function signatures
235
+ - [ ] Pydantic or dataclass for all structured data — no raw dicts
236
+ - [ ] Custom exceptions — no bare Exception raises
237
+ - [ ] Functions under 30 lines, files under 200 lines
238
+ - [ ] No mutable default arguments
239
+ - [ ] pytest with fixtures — no unittest patterns
240
+ - [ ] Import order enforced (stdlib → third-party → local)
241
+ - [ ] No print() in committed code — use logging
242
+ - [ ] Virtual environment with pinned dependencies
243
+ - [ ] No string-formatted SQL — parameterized queries only
@@ -0,0 +1,216 @@
1
+ # React Native Standards
2
+
3
+ These rules are MANDATORY. Violations fail the task. No exceptions.
4
+
5
+ ---
6
+
7
+ ## 1. State Management — React Query + Zustand
8
+
9
+ ```
10
+ MANDATORY:
11
+ ├── React Query (TanStack Query) for ALL server data — NEVER useEffect + fetch
12
+ ├── Zustand for client-side global state (auth, theme, navigation state)
13
+ ├── useState for local UI state only (toggles, form inputs)
14
+ ├── NEVER store server data in useState or Zustand — it belongs in the query cache
15
+ └── Set staleTime explicitly on all queries
16
+ ```
17
+
18
+ **GOOD**
19
+ ```tsx
20
+ // Server data → React Query
21
+ const { data: users } = useQuery({
22
+ queryKey: ['users'],
23
+ queryFn: api.getUsers,
24
+ staleTime: 5 * 60 * 1000,
25
+ });
26
+
27
+ // Client state → Zustand
28
+ const useAuthStore = create<AuthState>((set) => ({
29
+ token: null,
30
+ setToken: (token) => set({ token }),
31
+ logout: () => set({ token: null }),
32
+ }));
33
+ ```
34
+
35
+ ---
36
+
37
+ ## 2. Component Design
38
+
39
+ ```
40
+ MANDATORY:
41
+ ├── Max 150 lines per component — extract sub-components
42
+ ├── Use FlatList for all dynamic lists — NEVER ScrollView with .map()
43
+ ├── Separate screen components (screens/) from reusable components (components/)
44
+ ├── One component per file
45
+ ├── No business logic in JSX — compute above the return
46
+ └── Use custom hooks for complex logic (useXxx)
47
+ ```
48
+
49
+ **BAD**
50
+ ```tsx
51
+ <ScrollView>
52
+ {items.map(item => <ItemRow key={item.id} item={item} />)}
53
+ </ScrollView>
54
+ ```
55
+
56
+ **GOOD**
57
+ ```tsx
58
+ <FlatList
59
+ data={items}
60
+ keyExtractor={(item) => item.id}
61
+ renderItem={({ item }) => <ItemRow item={item} />}
62
+ ListEmptyComponent={<EmptyState />}
63
+ />
64
+ ```
65
+
66
+ ---
67
+
68
+ ## 3. Navigation — React Navigation
69
+
70
+ ```
71
+ MANDATORY:
72
+ ├── Use React Navigation (not react-native-router-flux, not expo-router for bare RN)
73
+ ├── Type all navigation params with RootStackParamList
74
+ ├── Define all routes in a central navigation config
75
+ ├── Deep linking config in the navigator — not hardcoded in components
76
+ └── Handle auth flow with conditional navigator (logged in → app, else → auth)
77
+ ```
78
+
79
+ **GOOD**
80
+ ```tsx
81
+ type RootStackParamList = {
82
+ Home: undefined;
83
+ UserDetail: { userId: string };
84
+ Settings: undefined;
85
+ };
86
+
87
+ const Stack = createNativeStackNavigator<RootStackParamList>();
88
+
89
+ function AppNavigator() {
90
+ const { isLoggedIn } = useAuth();
91
+ return (
92
+ <Stack.Navigator>
93
+ {isLoggedIn ? (
94
+ <>
95
+ <Stack.Screen name="Home" component={HomeScreen} />
96
+ <Stack.Screen name="UserDetail" component={UserDetailScreen} />
97
+ </>
98
+ ) : (
99
+ <Stack.Screen name="Login" component={LoginScreen} />
100
+ )}
101
+ </Stack.Navigator>
102
+ );
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## 4. Styling
109
+
110
+ ```
111
+ MANDATORY:
112
+ ├── Use StyleSheet.create for all styles — NEVER inline style objects
113
+ ├── Co-locate styles at the bottom of the component file
114
+ ├── Use a theme object for colors, spacing, typography — NEVER hardcode
115
+ ├── Responsive: use useWindowDimensions or percentage-based layouts
116
+ └── Platform-specific styles via Platform.select or .ios.tsx/.android.tsx files
117
+ ```
118
+
119
+ **BAD** — `<View style={{ padding: 16, backgroundColor: '#f5f5f5' }}>`
120
+
121
+ **GOOD**
122
+ ```tsx
123
+ const styles = StyleSheet.create({
124
+ container: {
125
+ padding: theme.spacing.md,
126
+ backgroundColor: theme.colors.surface,
127
+ },
128
+ });
129
+ ```
130
+
131
+ ---
132
+
133
+ ## 5. Performance
134
+
135
+ ```
136
+ MANDATORY:
137
+ ├── FlatList with keyExtractor — NEVER ScrollView for lists
138
+ ├── Use React.memo on list item components
139
+ ├── useCallback for renderItem and event handlers passed to FlatList
140
+ ├── Avoid anonymous functions in props of list items
141
+ ├── Use react-native-fast-image for image caching
142
+ ├── Minimize bridge calls — batch state updates
143
+ └── Profile with Flipper or React DevTools before optimizing
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 6. Platform Differences
149
+
150
+ ```
151
+ MANDATORY:
152
+ ├── Test on BOTH iOS and Android before marking complete
153
+ ├── Use Platform.OS checks sparingly — prefer cross-platform components
154
+ ├── Handle safe areas with SafeAreaView or useSafeAreaInsets
155
+ ├── Handle keyboard: KeyboardAvoidingView (behavior differs per platform)
156
+ ├── Permissions: request at point of use, explain why, handle denial gracefully
157
+ └── Status bar: manage with StatusBar component — don't assume default
158
+ ```
159
+
160
+ ---
161
+
162
+ ## 7. Offline and Networking
163
+
164
+ ```
165
+ WHEN APPLICABLE:
166
+ ├── React Query's built-in cache for offline reads
167
+ ├── Use @react-native-community/netinfo for connectivity detection
168
+ ├── Show offline indicator — don't silently fail
169
+ ├── Queue mutations when offline, replay when online
170
+ └── Set reasonable timeouts on all network requests
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 8. Error Handling
176
+
177
+ ```
178
+ MANDATORY:
179
+ ├── Global error boundary at the app root — never a blank crash screen
180
+ ├── Per-screen error boundaries for isolated failures
181
+ ├── Handle loading, error, and empty states for every data fetch
182
+ ├── Crash reporting (Sentry, Bugsnag) in production builds
183
+ └── User-friendly error messages — not raw error strings
184
+ ```
185
+
186
+ ---
187
+
188
+ ## 9. Anti-Patterns
189
+
190
+ ```
191
+ NEVER:
192
+ ├── ScrollView with .map() for dynamic lists (use FlatList)
193
+ ├── Inline style objects (use StyleSheet.create)
194
+ ├── useEffect for data fetching (use React Query)
195
+ ├── Hardcoded colors/spacing — use theme
196
+ ├── console.log in committed code
197
+ ├── Ignoring platform differences — test on both
198
+ ├── Ignoring keyboard avoidance — forms become unusable
199
+ └── Large images without caching — use FastImage
200
+ ```
201
+
202
+ ---
203
+
204
+ ## React Native Verification Checklist
205
+
206
+ - [ ] React Query for server data — no useEffect + fetch
207
+ - [ ] FlatList for all dynamic lists — no ScrollView + map
208
+ - [ ] Components under 150 lines
209
+ - [ ] StyleSheet.create for all styles — no inline objects
210
+ - [ ] Theme object for colors/spacing — no hardcoded values
211
+ - [ ] React Navigation with typed params
212
+ - [ ] Loading, error, and empty states handled
213
+ - [ ] Tested on both iOS and Android
214
+ - [ ] Safe areas and keyboard avoidance handled
215
+ - [ ] No console.log in committed code
216
+ - [ ] Error boundaries at root and per-screen