wiggum-cli 0.1.0

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 (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/bin/ralph.js +8 -0
  4. package/dist/ai/enhancer.d.ts +100 -0
  5. package/dist/ai/enhancer.d.ts.map +1 -0
  6. package/dist/ai/enhancer.js +233 -0
  7. package/dist/ai/enhancer.js.map +1 -0
  8. package/dist/ai/index.d.ts +8 -0
  9. package/dist/ai/index.d.ts.map +1 -0
  10. package/dist/ai/index.js +11 -0
  11. package/dist/ai/index.js.map +1 -0
  12. package/dist/ai/prompts.d.ts +26 -0
  13. package/dist/ai/prompts.d.ts.map +1 -0
  14. package/dist/ai/prompts.js +201 -0
  15. package/dist/ai/prompts.js.map +1 -0
  16. package/dist/ai/providers.d.ts +35 -0
  17. package/dist/ai/providers.d.ts.map +1 -0
  18. package/dist/ai/providers.js +104 -0
  19. package/dist/ai/providers.js.map +1 -0
  20. package/dist/cli.d.ts +6 -0
  21. package/dist/cli.d.ts.map +1 -0
  22. package/dist/cli.js +196 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/commands/init.d.ts +16 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +124 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/commands/monitor.d.ts +17 -0
  29. package/dist/commands/monitor.d.ts.map +1 -0
  30. package/dist/commands/monitor.js +342 -0
  31. package/dist/commands/monitor.js.map +1 -0
  32. package/dist/commands/new.d.ts +19 -0
  33. package/dist/commands/new.d.ts.map +1 -0
  34. package/dist/commands/new.js +272 -0
  35. package/dist/commands/new.js.map +1 -0
  36. package/dist/commands/run.d.ts +16 -0
  37. package/dist/commands/run.d.ts.map +1 -0
  38. package/dist/commands/run.js +175 -0
  39. package/dist/commands/run.js.map +1 -0
  40. package/dist/generator/config.d.ts +59 -0
  41. package/dist/generator/config.d.ts.map +1 -0
  42. package/dist/generator/config.js +68 -0
  43. package/dist/generator/config.js.map +1 -0
  44. package/dist/generator/index.d.ts +64 -0
  45. package/dist/generator/index.d.ts.map +1 -0
  46. package/dist/generator/index.js +147 -0
  47. package/dist/generator/index.js.map +1 -0
  48. package/dist/generator/templates.d.ts +70 -0
  49. package/dist/generator/templates.d.ts.map +1 -0
  50. package/dist/generator/templates.js +296 -0
  51. package/dist/generator/templates.js.map +1 -0
  52. package/dist/generator/writer.d.ts +93 -0
  53. package/dist/generator/writer.d.ts.map +1 -0
  54. package/dist/generator/writer.js +213 -0
  55. package/dist/generator/writer.js.map +1 -0
  56. package/dist/index.d.ts +12 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +17 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/scanner/detectors/core/framework.d.ts +11 -0
  61. package/dist/scanner/detectors/core/framework.d.ts.map +1 -0
  62. package/dist/scanner/detectors/core/framework.js +275 -0
  63. package/dist/scanner/detectors/core/framework.js.map +1 -0
  64. package/dist/scanner/detectors/core/packageManager.d.ts +11 -0
  65. package/dist/scanner/detectors/core/packageManager.d.ts.map +1 -0
  66. package/dist/scanner/detectors/core/packageManager.js +74 -0
  67. package/dist/scanner/detectors/core/packageManager.js.map +1 -0
  68. package/dist/scanner/detectors/core/styling.d.ts +12 -0
  69. package/dist/scanner/detectors/core/styling.d.ts.map +1 -0
  70. package/dist/scanner/detectors/core/styling.js +230 -0
  71. package/dist/scanner/detectors/core/styling.js.map +1 -0
  72. package/dist/scanner/detectors/core/testing.d.ts +12 -0
  73. package/dist/scanner/detectors/core/testing.d.ts.map +1 -0
  74. package/dist/scanner/detectors/core/testing.js +190 -0
  75. package/dist/scanner/detectors/core/testing.js.map +1 -0
  76. package/dist/scanner/detectors/data/api.d.ts +12 -0
  77. package/dist/scanner/detectors/data/api.d.ts.map +1 -0
  78. package/dist/scanner/detectors/data/api.js +261 -0
  79. package/dist/scanner/detectors/data/api.js.map +1 -0
  80. package/dist/scanner/detectors/data/database.d.ts +12 -0
  81. package/dist/scanner/detectors/data/database.d.ts.map +1 -0
  82. package/dist/scanner/detectors/data/database.js +213 -0
  83. package/dist/scanner/detectors/data/database.js.map +1 -0
  84. package/dist/scanner/detectors/data/orm.d.ts +12 -0
  85. package/dist/scanner/detectors/data/orm.d.ts.map +1 -0
  86. package/dist/scanner/detectors/data/orm.js +160 -0
  87. package/dist/scanner/detectors/data/orm.js.map +1 -0
  88. package/dist/scanner/detectors/frontend/formHandling.d.ts +12 -0
  89. package/dist/scanner/detectors/frontend/formHandling.d.ts.map +1 -0
  90. package/dist/scanner/detectors/frontend/formHandling.js +211 -0
  91. package/dist/scanner/detectors/frontend/formHandling.js.map +1 -0
  92. package/dist/scanner/detectors/frontend/stateManagement.d.ts +12 -0
  93. package/dist/scanner/detectors/frontend/stateManagement.d.ts.map +1 -0
  94. package/dist/scanner/detectors/frontend/stateManagement.js +221 -0
  95. package/dist/scanner/detectors/frontend/stateManagement.js.map +1 -0
  96. package/dist/scanner/detectors/frontend/uiComponents.d.ts +12 -0
  97. package/dist/scanner/detectors/frontend/uiComponents.d.ts.map +1 -0
  98. package/dist/scanner/detectors/frontend/uiComponents.js +285 -0
  99. package/dist/scanner/detectors/frontend/uiComponents.js.map +1 -0
  100. package/dist/scanner/detectors/infra/deployment.d.ts +12 -0
  101. package/dist/scanner/detectors/infra/deployment.d.ts.map +1 -0
  102. package/dist/scanner/detectors/infra/deployment.js +301 -0
  103. package/dist/scanner/detectors/infra/deployment.js.map +1 -0
  104. package/dist/scanner/detectors/infra/monorepo.d.ts +12 -0
  105. package/dist/scanner/detectors/infra/monorepo.d.ts.map +1 -0
  106. package/dist/scanner/detectors/infra/monorepo.js +219 -0
  107. package/dist/scanner/detectors/infra/monorepo.js.map +1 -0
  108. package/dist/scanner/detectors/mcp/mcpProject.d.ts +12 -0
  109. package/dist/scanner/detectors/mcp/mcpProject.d.ts.map +1 -0
  110. package/dist/scanner/detectors/mcp/mcpProject.js +154 -0
  111. package/dist/scanner/detectors/mcp/mcpProject.js.map +1 -0
  112. package/dist/scanner/detectors/mcp/mcpServers.d.ts +17 -0
  113. package/dist/scanner/detectors/mcp/mcpServers.d.ts.map +1 -0
  114. package/dist/scanner/detectors/mcp/mcpServers.js +193 -0
  115. package/dist/scanner/detectors/mcp/mcpServers.js.map +1 -0
  116. package/dist/scanner/detectors/services/analytics.d.ts +12 -0
  117. package/dist/scanner/detectors/services/analytics.d.ts.map +1 -0
  118. package/dist/scanner/detectors/services/analytics.js +236 -0
  119. package/dist/scanner/detectors/services/analytics.js.map +1 -0
  120. package/dist/scanner/detectors/services/auth.d.ts +12 -0
  121. package/dist/scanner/detectors/services/auth.d.ts.map +1 -0
  122. package/dist/scanner/detectors/services/auth.js +217 -0
  123. package/dist/scanner/detectors/services/auth.js.map +1 -0
  124. package/dist/scanner/detectors/services/email.d.ts +12 -0
  125. package/dist/scanner/detectors/services/email.d.ts.map +1 -0
  126. package/dist/scanner/detectors/services/email.js +211 -0
  127. package/dist/scanner/detectors/services/email.js.map +1 -0
  128. package/dist/scanner/detectors/services/payments.d.ts +12 -0
  129. package/dist/scanner/detectors/services/payments.d.ts.map +1 -0
  130. package/dist/scanner/detectors/services/payments.js +185 -0
  131. package/dist/scanner/detectors/services/payments.js.map +1 -0
  132. package/dist/scanner/detectors/utils.d.ts +160 -0
  133. package/dist/scanner/detectors/utils.d.ts.map +1 -0
  134. package/dist/scanner/detectors/utils.js +222 -0
  135. package/dist/scanner/detectors/utils.js.map +1 -0
  136. package/dist/scanner/index.d.ts +42 -0
  137. package/dist/scanner/index.d.ts.map +1 -0
  138. package/dist/scanner/index.js +282 -0
  139. package/dist/scanner/index.js.map +1 -0
  140. package/dist/scanner/registry.d.ts +43 -0
  141. package/dist/scanner/registry.d.ts.map +1 -0
  142. package/dist/scanner/registry.js +243 -0
  143. package/dist/scanner/registry.js.map +1 -0
  144. package/dist/scanner/types.d.ts +112 -0
  145. package/dist/scanner/types.d.ts.map +1 -0
  146. package/dist/scanner/types.js +6 -0
  147. package/dist/scanner/types.js.map +1 -0
  148. package/dist/templates/config/ralph.config.js.tmpl +38 -0
  149. package/dist/templates/guides/AGENTS.md.tmpl +100 -0
  150. package/dist/templates/guides/FRONTEND.md.tmpl +523 -0
  151. package/dist/templates/guides/PERFORMANCE.md.tmpl +264 -0
  152. package/dist/templates/guides/SECURITY.md.tmpl +100 -0
  153. package/dist/templates/prompts/PROMPT.md.tmpl +77 -0
  154. package/dist/templates/prompts/PROMPT_e2e.md.tmpl +234 -0
  155. package/dist/templates/prompts/PROMPT_feature.md.tmpl +83 -0
  156. package/dist/templates/prompts/PROMPT_review.md.tmpl +167 -0
  157. package/dist/templates/prompts/PROMPT_verify.md.tmpl +72 -0
  158. package/dist/templates/root/.gitignore.tmpl +5 -0
  159. package/dist/templates/root/LEARNINGS.md.tmpl +24 -0
  160. package/dist/templates/root/README.md.tmpl +61 -0
  161. package/dist/templates/scripts/feature-loop.sh.tmpl +267 -0
  162. package/dist/templates/scripts/loop.sh.tmpl +59 -0
  163. package/dist/templates/scripts/ralph-monitor.sh.tmpl +244 -0
  164. package/dist/templates/specs/README.md.tmpl +57 -0
  165. package/dist/templates/specs/_example.md.tmpl +71 -0
  166. package/dist/utils/config.d.ts +95 -0
  167. package/dist/utils/config.d.ts.map +1 -0
  168. package/dist/utils/config.js +148 -0
  169. package/dist/utils/config.js.map +1 -0
  170. package/dist/utils/header.d.ts +5 -0
  171. package/dist/utils/header.d.ts.map +1 -0
  172. package/dist/utils/header.js +15 -0
  173. package/dist/utils/header.js.map +1 -0
  174. package/dist/utils/logger.d.ts +11 -0
  175. package/dist/utils/logger.d.ts.map +1 -0
  176. package/dist/utils/logger.js +24 -0
  177. package/dist/utils/logger.js.map +1 -0
  178. package/package.json +44 -0
  179. package/src/ai/enhancer.ts +350 -0
  180. package/src/ai/index.ts +38 -0
  181. package/src/ai/prompts.ts +217 -0
  182. package/src/ai/providers.ts +136 -0
  183. package/src/cli.ts +255 -0
  184. package/src/commands/init.ts +149 -0
  185. package/src/commands/monitor.ts +412 -0
  186. package/src/commands/new.ts +312 -0
  187. package/src/commands/run.ts +214 -0
  188. package/src/generator/config.ts +116 -0
  189. package/src/generator/index.ts +227 -0
  190. package/src/generator/templates.ts +412 -0
  191. package/src/generator/writer.ts +293 -0
  192. package/src/index.ts +41 -0
  193. package/src/scanner/detectors/core/framework.ts +332 -0
  194. package/src/scanner/detectors/core/packageManager.ts +91 -0
  195. package/src/scanner/detectors/core/styling.ts +261 -0
  196. package/src/scanner/detectors/core/testing.ts +221 -0
  197. package/src/scanner/detectors/data/api.ts +303 -0
  198. package/src/scanner/detectors/data/database.ts +245 -0
  199. package/src/scanner/detectors/data/orm.ts +180 -0
  200. package/src/scanner/detectors/frontend/formHandling.ts +244 -0
  201. package/src/scanner/detectors/frontend/stateManagement.ts +261 -0
  202. package/src/scanner/detectors/frontend/uiComponents.ts +328 -0
  203. package/src/scanner/detectors/infra/deployment.ts +343 -0
  204. package/src/scanner/detectors/infra/monorepo.ts +251 -0
  205. package/src/scanner/detectors/mcp/mcpProject.ts +176 -0
  206. package/src/scanner/detectors/mcp/mcpServers.ts +237 -0
  207. package/src/scanner/detectors/services/analytics.ts +273 -0
  208. package/src/scanner/detectors/services/auth.ts +254 -0
  209. package/src/scanner/detectors/services/email.ts +244 -0
  210. package/src/scanner/detectors/services/payments.ts +213 -0
  211. package/src/scanner/detectors/utils.ts +251 -0
  212. package/src/scanner/index.ts +354 -0
  213. package/src/scanner/registry.ts +301 -0
  214. package/src/scanner/types.ts +152 -0
  215. package/src/templates/config/ralph.config.js.tmpl +38 -0
  216. package/src/templates/guides/AGENTS.md.tmpl +100 -0
  217. package/src/templates/guides/FRONTEND.md.tmpl +523 -0
  218. package/src/templates/guides/PERFORMANCE.md.tmpl +264 -0
  219. package/src/templates/guides/SECURITY.md.tmpl +100 -0
  220. package/src/templates/prompts/PROMPT.md.tmpl +77 -0
  221. package/src/templates/prompts/PROMPT_e2e.md.tmpl +234 -0
  222. package/src/templates/prompts/PROMPT_feature.md.tmpl +83 -0
  223. package/src/templates/prompts/PROMPT_review.md.tmpl +167 -0
  224. package/src/templates/prompts/PROMPT_verify.md.tmpl +72 -0
  225. package/src/templates/root/.gitignore.tmpl +5 -0
  226. package/src/templates/root/LEARNINGS.md.tmpl +24 -0
  227. package/src/templates/root/README.md.tmpl +61 -0
  228. package/src/templates/scripts/feature-loop.sh.tmpl +267 -0
  229. package/src/templates/scripts/loop.sh.tmpl +59 -0
  230. package/src/templates/scripts/ralph-monitor.sh.tmpl +244 -0
  231. package/src/templates/specs/README.md.tmpl +57 -0
  232. package/src/templates/specs/_example.md.tmpl +71 -0
  233. package/src/utils/config.ts +221 -0
  234. package/src/utils/header.ts +15 -0
  235. package/src/utils/logger.ts +28 -0
  236. package/tsconfig.json +19 -0
@@ -0,0 +1,264 @@
1
+ # Performance Patterns
2
+
3
+ {{framework}} performance best practices for implementation phases.
4
+ Reference when writing new components, data fetching, or optimizing existing code.
5
+
6
+ ## Critical: Eliminate Waterfalls
7
+
8
+ The #1 performance killer. Sequential awaits add full network latency per request.
9
+
10
+ ### Bad: Sequential Fetches
11
+ ```typescript
12
+ // 3 round trips = 3x latency
13
+ const user = await getUser(id);
14
+ const posts = await getPosts(user.id);
15
+ const comments = await getComments(posts[0].id);
16
+ ```
17
+
18
+ ### Good: Parallel Fetches
19
+ ```typescript
20
+ // 1 round trip for independent data
21
+ const [user, posts, settings] = await Promise.all([
22
+ getUser(id),
23
+ getPosts(id),
24
+ getSettings(id),
25
+ ]);
26
+ ```
27
+
28
+ ### Good: Defer Awaits
29
+ ```typescript
30
+ // Start fetch immediately, await when needed
31
+ const dataPromise = fetchData(); // no await
32
+ // ... do other work ...
33
+ const data = await dataPromise; // await at usage
34
+ ```
35
+
36
+ ### Good: Suspense Boundaries
37
+ ```tsx
38
+ // Show UI before data loads
39
+ <Suspense fallback={<Skeleton />}>
40
+ <DataComponent /> {/* fetches inside */}
41
+ </Suspense>
42
+ ```
43
+
44
+ ## Critical: Bundle Size
45
+
46
+ Reduces Time to Interactive and Largest Contentful Paint.
47
+
48
+ ### Bad: Barrel Imports
49
+ ```typescript
50
+ // Imports entire library, 200-800ms cold start penalty
51
+ import { Button } from '@/components/ui';
52
+ ```
53
+
54
+ ### Good: Direct Imports
55
+ ```typescript
56
+ // Import only what's needed
57
+ import { Button } from '@/components/ui/button';
58
+ ```
59
+
60
+ ### Good: Lazy Load Heavy Components
61
+ ```typescript
62
+ // Defer Monaco Editor (~300KB) until needed
63
+ const Editor = dynamic(() => import('@/components/editor'), {
64
+ loading: () => <Skeleton />,
65
+ ssr: false,
66
+ });
67
+ ```
68
+
69
+ ### Good: Defer Third-Party Scripts
70
+ ```typescript
71
+ // Load analytics after hydration
72
+ useEffect(() => {
73
+ import('posthog-js').then((posthog) => posthog.init(...));
74
+ }, []);
75
+ ```
76
+
77
+ ## High: Server-Side Performance
78
+
79
+ ### Use React.cache() for Request Deduplication
80
+ ```typescript
81
+ // Same data fetched by multiple components = 1 request
82
+ import { cache } from 'react';
83
+
84
+ export const getUser = cache(async (id: string) => {
85
+ return db.user.findUnique({ where: { id } });
86
+ });
87
+ ```
88
+
89
+ ### Minimize RSC Serialization
90
+ ```typescript
91
+ // Bad: Pass entire object
92
+ <ClientComponent user={user} /> // serializes all fields
93
+
94
+ // Good: Pass only needed fields
95
+ <ClientComponent name={user.name} avatar={user.avatar} />
96
+ ```
97
+
98
+ ### Use after() for Non-Blocking Work
99
+ ```typescript
100
+ import { after } from 'next/server';
101
+
102
+ export async function POST(request: Request) {
103
+ const data = await request.json();
104
+
105
+ // Respond immediately
106
+ after(async () => {
107
+ // Analytics, logging - doesn't block response
108
+ await trackEvent('form_submit', data);
109
+ });
110
+
111
+ return Response.json({ success: true });
112
+ }
113
+ ```
114
+
115
+ ## Medium: Re-render Optimization
116
+
117
+ ### Defer useSearchParams
118
+ ```typescript
119
+ // Bad: Subscribes entire component to URL changes
120
+ function Page() {
121
+ const searchParams = useSearchParams(); // triggers re-render on any URL change
122
+ return <Child params={searchParams} />;
123
+ }
124
+
125
+ // Good: Read in child that needs it
126
+ function Page() {
127
+ return <Child />; // no subscription here
128
+ }
129
+ function Child() {
130
+ const searchParams = useSearchParams(); // only this re-renders
131
+ }
132
+ ```
133
+
134
+ ### Use Functional setState
135
+ ```typescript
136
+ // Bad: Stale closure risk, recreates callback
137
+ const increment = useCallback(() => {
138
+ setCount(count + 1);
139
+ }, [count]);
140
+
141
+ // Good: Always fresh, stable callback
142
+ const increment = useCallback(() => {
143
+ setCount((c) => c + 1);
144
+ }, []);
145
+ ```
146
+
147
+ ### Lazy Initialize Expensive State
148
+ ```typescript
149
+ // Bad: Runs on every render
150
+ const [data, setData] = useState(expensiveComputation());
151
+
152
+ // Good: Runs only on mount
153
+ const [data, setData] = useState(() => expensiveComputation());
154
+ ```
155
+
156
+ ### Use Transitions for Non-Urgent Updates
157
+ ```typescript
158
+ const [isPending, startTransition] = useTransition();
159
+
160
+ function handleSearch(query: string) {
161
+ // Urgent: update input immediately
162
+ setQuery(query);
163
+
164
+ // Non-urgent: can be interrupted
165
+ startTransition(() => {
166
+ setFilteredResults(filterResults(query));
167
+ });
168
+ }
169
+ ```
170
+
171
+ ## Medium: Rendering Performance
172
+
173
+ ### Hoist Static JSX
174
+ ```typescript
175
+ // Bad: Recreated every render
176
+ function Component() {
177
+ const icon = <Icon size={24} />; // new object each time
178
+ return <Button icon={icon} />;
179
+ }
180
+
181
+ // Good: Created once
182
+ const icon = <Icon size={24} />;
183
+ function Component() {
184
+ return <Button icon={icon} />;
185
+ }
186
+ ```
187
+
188
+ ### Use content-visibility for Long Lists
189
+ ```css
190
+ .list-item {
191
+ content-visibility: auto;
192
+ contain-intrinsic-size: 0 80px; /* estimated height */
193
+ }
194
+ ```
195
+ Skips layout/paint for off-screen items. 1000-item list renders 10x faster.
196
+
197
+ ### Prevent Hydration Mismatches
198
+ ```tsx
199
+ // For theme/locale that differs server vs client
200
+ // Use inline script to set data attribute before React hydrates
201
+ <script>
202
+ {`document.documentElement.dataset.theme = localStorage.getItem('theme') || 'light'`}
203
+ </script>
204
+ ```
205
+
206
+ ## Low-Medium: JavaScript Optimizations
207
+
208
+ ### Build Index Maps for Repeated Lookups
209
+ ```typescript
210
+ // Bad: O(n) per lookup
211
+ users.find((u) => u.id === id);
212
+
213
+ // Good: O(1) per lookup
214
+ const userMap = new Map(users.map((u) => [u.id, u]));
215
+ userMap.get(id);
216
+ ```
217
+
218
+ ### Use Set for Membership Checks
219
+ ```typescript
220
+ // Bad: O(n) per check
221
+ const isSelected = selectedIds.includes(id);
222
+
223
+ // Good: O(1) per check
224
+ const selectedSet = new Set(selectedIds);
225
+ const isSelected = selectedSet.has(id);
226
+ ```
227
+
228
+ ### Single-Pass for Min/Max
229
+ ```typescript
230
+ // Bad: O(n log n)
231
+ const latest = items.sort((a, b) => b.date - a.date)[0];
232
+
233
+ // Good: O(n)
234
+ const latest = items.reduce((max, item) =>
235
+ item.date > max.date ? item : max
236
+ );
237
+ ```
238
+
239
+ ### Use .toSorted() to Avoid Mutation
240
+ ```typescript
241
+ // Bad: Mutates original array (breaks React)
242
+ items.sort((a, b) => a.name.localeCompare(b.name));
243
+
244
+ // Good: Returns new sorted array
245
+ items.toSorted((a, b) => a.name.localeCompare(b.name));
246
+ ```
247
+
248
+ ## Quick Reference
249
+
250
+ | Issue | Solution |
251
+ |-------|----------|
252
+ | Sequential fetches | `Promise.all()` or defer awaits |
253
+ | Large bundle | Direct imports, `next/dynamic` |
254
+ | Duplicate requests | `React.cache()`, SWR |
255
+ | Unnecessary re-renders | Functional setState, transitions |
256
+ | Slow lists | `content-visibility: auto` |
257
+ | Repeated lookups | Map/Set indexes |
258
+
259
+ ## When to Apply
260
+
261
+ - **New components**: Check waterfall and bundle patterns
262
+ - **Data fetching**: Use parallel fetches, React.cache()
263
+ - **Performance issues**: Profile first, then apply relevant patterns
264
+ - **Code review**: Flag sequential awaits and barrel imports
@@ -0,0 +1,100 @@
1
+ # Security Review Checklist
2
+
3
+ Red-team security review for each task. Check before committing.
4
+
5
+ ## Quick Scan (Every Task)
6
+
7
+ Run through these checks for any code you've written or modified:
8
+
9
+ ### Input Validation
10
+ - [ ] User inputs are validated and sanitized
11
+ - [ ] File uploads check type, size, and content
12
+ - [ ] URL parameters are validated before use
13
+ - [ ] JSON/form data is schema-validated
14
+
15
+ ### Injection Prevention
16
+ - [ ] SQL: Using parameterized queries (Supabase client handles this)
17
+ - [ ] XSS: User content is escaped before rendering
18
+ - [ ] Command injection: No shell commands with user input
19
+ - [ ] Path traversal: File paths are validated, no `../` allowed
20
+
21
+ ### Authentication & Authorization
22
+ - [ ] Protected routes check authentication
23
+ - [ ] API endpoints verify user permissions
24
+ - [ ] Sensitive actions require re-authentication
25
+ - [ ] No secrets in client-side code
26
+
27
+ ### Data Exposure
28
+ - [ ] API responses don't leak sensitive fields
29
+ - [ ] Error messages don't expose internals
30
+ - [ ] Logs don't contain PII or secrets
31
+ - [ ] Database queries filter by user ownership
32
+
33
+ ## Deep Scan (Sensitive Features)
34
+
35
+ For auth, payments, data export, admin features:
36
+
37
+ ### OWASP Top 10 Check
38
+ | Risk | Check |
39
+ |------|-------|
40
+ | Injection | Parameterized queries, no dynamic code execution |
41
+ | Broken Auth | Session handling, token expiry |
42
+ | Sensitive Data | Encryption at rest/transit |
43
+ | XXE | Disable external entities in XML parsers |
44
+ | Broken Access | Row-level security, ownership checks |
45
+ | Misconfig | No debug mode, secure headers |
46
+ | XSS | Content-Security-Policy, output encoding |
47
+ | Insecure Deserialization | Validate before deserialize |
48
+ | Vulnerable Components | Check {{packageManager}} audit |
49
+ | Logging | Audit trail, no sensitive data logged |
50
+
51
+ ### Supabase-Specific
52
+ - [ ] RLS policies enabled on tables with user data
53
+ - [ ] RLS policies test both SELECT and INSERT/UPDATE/DELETE
54
+ - [ ] Service role key only used server-side
55
+ - [ ] Anon key permissions are minimal
56
+
57
+ ### {{framework}}-Specific
58
+ - [ ] Server actions validate input
59
+ - [ ] API routes check authentication
60
+ - [ ] No sensitive data in client components
61
+ - [ ] Environment variables not exposed to client (no NEXT_PUBLIC_ for secrets)
62
+
63
+ ## Red Team Prompts
64
+
65
+ Ask yourself:
66
+ 1. **Can I bypass auth?** Try accessing protected routes/APIs without login
67
+ 2. **Can I access other users' data?** Change IDs in requests
68
+ 3. **Can I inject malicious content?** Try `<script>`, SQL fragments, `../`
69
+ 4. **Can I cause a DoS?** Large payloads, infinite loops, resource exhaustion
70
+ 5. **Can I exfiltrate data?** Check what the API returns, console logs
71
+
72
+ ## Commands
73
+
74
+ ```bash
75
+ # Check for vulnerable dependencies
76
+ cd {{appDir}} && {{packageManager}} audit
77
+
78
+ # Check for secrets in code (should return nothing)
79
+ cd {{appDir}} && grep -r "sk_live\|password=\|secret=" --include="*.ts" --include="*.tsx" .
80
+
81
+ # Check RLS policies
82
+ # Use Supabase MCP: mcp__supabase__get_advisors with type: "security"
83
+ ```
84
+
85
+ ## When to Flag
86
+
87
+ Stop and investigate if you find:
88
+ - Direct SQL string concatenation
89
+ - Dynamic code execution with user data
90
+ - Hardcoded credentials or API keys
91
+ - Missing authentication on sensitive endpoints
92
+ - User IDs accepted from client without verification
93
+ - File operations with user-controlled paths
94
+
95
+ ## Fixing Issues
96
+
97
+ 1. **Document** the vulnerability in the implementation plan
98
+ 2. **Fix** before committing (don't leave for later)
99
+ 3. **Test** the fix (try to exploit it)
100
+ 4. **Learn** - add to LEARNINGS.md if it's a new pattern
@@ -0,0 +1,77 @@
1
+ ## Context
2
+ Study @.ralph/AGENTS.md for commands and patterns.
3
+ Study @.ralph/specs/$FEATURE.md for feature specification.
4
+ Study @.ralph/specs/$FEATURE-implementation-plan.md for current tasks.
5
+ {{#if frameworkVariant}}For detailed architecture, see @{{appDir}}/.claude/CLAUDE.md{{/if}}
6
+
7
+ ## Learnings
8
+ Read @.ralph/LEARNINGS.md for patterns and anti-patterns from previous iterations.
9
+ Apply relevant learnings to avoid repeating past mistakes.
10
+
11
+ ## Performance
12
+ For data fetching, new components, or optimization tasks, reference @.ralph/guides/PERFORMANCE.md.
13
+ Key patterns: parallel fetches, direct imports, React.cache(), lazy loading.
14
+
15
+ ## Search
16
+ - Use `mgrep "query"` for codebase searches (patterns, implementations, usages)
17
+ - Use Context7 MCP for library/framework documentation
18
+ - Search codebase before assuming something doesn't exist
19
+
20
+ ## Task
21
+ Pick the next incomplete task from the implementation plan.
22
+ **Skip E2E tasks** (tasks starting with `E2E:`) - those are handled in a separate phase.
23
+ Implement it following the patterns in AGENTS.md.
24
+ Write tests for the implementation.
25
+
26
+ ## Validation
27
+ After changes, ALL must pass:
28
+ 1. Run: `cd {{appDir}} && {{lintCommand}} -- --fix`
29
+ 2. Run: `cd {{appDir}} && {{typecheckCommand}}` (typecheck)
30
+ 3. Run: `cd {{appDir}} && {{testCommand}}`
31
+ 4. Run: `cd {{appDir}} && {{buildCommand}}`
32
+
33
+ If any validation fails, fix the issue before proceeding.
34
+
35
+ ## Security Review
36
+ Before committing, review your changes against @.ralph/guides/SECURITY.md:
37
+ 1. **Quick scan**: Input validation, injection prevention, auth checks, data exposure
38
+ 2. **Run**: `cd {{appDir}} && {{packageManager}} audit` (check for vulnerable dependencies)
39
+ 3. **Check**: `mcp__supabase__get_advisors` with type "security" (RLS policies)
40
+ 4. **Red team**: Can auth be bypassed? Can other users' data be accessed?
41
+
42
+ Flag any security issues in the implementation plan and fix before committing.
43
+
44
+ ## Design Quality Check
45
+ Before marking a UI task complete, verify against @.ralph/guides/FRONTEND.md:
46
+ 1. Uses design tokens (no hard-coded colors like `#fff` or `rgb()`)
47
+ 2. Has hover/focus/active states on interactive elements
48
+ 3. Responsive on mobile (test at 375px width)
49
+ 4. Empty/loading/error states handled
50
+ 5. Charts have titles, tooltips, and legends (if applicable)
51
+ 6. Consistent spacing using Tailwind scale
52
+
53
+ If any check fails, fix before committing.
54
+
55
+ ## Completion
56
+ When ALL validations pass:
57
+ 1. Update @.ralph/specs/$FEATURE-implementation-plan.md - mark task done with commit hash
58
+ 2. `git -C {{appDir}} add -A`
59
+ 3. `git -C {{appDir}} commit -m "type(scope): description"`
60
+ 4. `git -C {{appDir}} push origin feat/$FEATURE`
61
+
62
+ ## Learning Capture
63
+ If this iteration revealed something useful, append to @.ralph/LEARNINGS.md:
64
+ - A useful pattern -> Add under "## Patterns (What Works)"
65
+ - A mistake/issue -> Add under "## Anti-Patterns (What to Avoid)"
66
+ - Tool usage tip -> Add under "## Tool Usage"
67
+ - Codebase convention -> Add under "## Codebase Conventions"
68
+
69
+ Format: `- [YYYY-MM-DD] [$FEATURE] Brief description`
70
+
71
+ ## Rules
72
+ - One task per iteration
73
+ - Tests are mandatory - no task is complete without tests
74
+ - Search codebase before assuming something doesn't exist
75
+ - If blocked, document in implementation plan and move to next task
76
+ - Use Supabase MCP for database operations
77
+ - Use PostHog MCP for analytics queries
@@ -0,0 +1,234 @@
1
+ ## Context
2
+ Study @.ralph/AGENTS.md for commands and patterns.
3
+ Study @.ralph/specs/$FEATURE.md for feature specification.
4
+ Study @.ralph/specs/$FEATURE-implementation-plan.md for E2E test scenarios.
5
+ {{#if frameworkVariant}}For detailed architecture, see @{{appDir}}/.claude/CLAUDE.md{{/if}}
6
+
7
+ ## Learnings
8
+ Read @.ralph/LEARNINGS.md for E2E patterns and anti-patterns.
9
+ Pay special attention to "E2E Pitfalls" section to avoid known issues.
10
+
11
+ ## Prerequisites
12
+ Before E2E testing, verify:
13
+ 1. Build passes: `cd {{appDir}} && {{buildCommand}}`
14
+ 2. All unit tests pass: `cd {{appDir}} && {{testCommand}}`
15
+ 3. Clear cache if issues: `rm -rf {{appDir}}/.next`
16
+
17
+ If either fails, fix issues before proceeding with E2E tests.
18
+
19
+ ## Task
20
+ Execute automated E2E tests for the completed feature using Playwright MCP tools.
21
+
22
+ ### Step 1: Check Dev Server
23
+ Verify dev server is running at http://localhost:3000. If not accessible, start it:
24
+ ```bash
25
+ cd {{appDir}} && {{devCommand}} &
26
+ ```
27
+ Wait ~10 seconds for server startup, then verify with a simple browser_navigate.
28
+
29
+ ### Step 1.5: Seed Test Data (if needed)
30
+
31
+ Check if test scenarios require specific data volumes (e.g., pagination needs >10 rows).
32
+
33
+ **Seeding with Supabase MCP:**
34
+ ```
35
+ mcp__supabase__execute_sql
36
+ query: "INSERT INTO table_name (survey_id, data, created_at)
37
+ SELECT '{survey_id}', '{"_test": true}'::jsonb, NOW() - (n || ' hours')::interval
38
+ FROM generate_series(1, 25) n;"
39
+ ```
40
+
41
+ **Mark test data for cleanup:**
42
+ - Add `"_test": true` to JSON data columns
43
+ - Use unique utm_source: `e2e_${FEATURE}_${timestamp}`
44
+
45
+ **Cleanup after tests:**
46
+ ```
47
+ mcp__supabase__execute_sql
48
+ query: "DELETE FROM table_name WHERE data->>'_test' = 'true';"
49
+ ```
50
+
51
+ **If seeding is impractical:** Document in implementation plan that E2E was skipped but unit tests provide coverage.
52
+
53
+ ### Step 2: Parse E2E Test Scenarios
54
+ Read E2E test scenarios from @.ralph/specs/$FEATURE-implementation-plan.md.
55
+ Each scenario is marked with `- [ ] E2E:` prefix and follows this format:
56
+
57
+ ```
58
+ - [ ] E2E: [Scenario name]
59
+ - **URL:** [starting URL]
60
+ - **Preconditions:** [setup needed]
61
+ - **Steps:**
62
+ 1. [Action] -> [expected result]
63
+ - **Verify:** [final assertion]
64
+ - **Database check:** [optional SQL]
65
+ ```
66
+
67
+ ### Step 3: Execute Each Scenario
68
+ For each E2E test scenario:
69
+
70
+ 1. **Navigate** to starting URL:
71
+ ```
72
+ mcp__plugin_playwright_playwright__browser_navigate
73
+ url: "http://localhost:3000/..."
74
+ ```
75
+
76
+ 2. **Capture page state** for element references:
77
+ ```
78
+ mcp__plugin_playwright_playwright__browser_snapshot
79
+ ```
80
+ This returns an accessibility tree with element refs (e.g., `button[3]`, `textbox[0]`).
81
+
82
+ 3. **Execute actions** using refs from snapshot:
83
+ - Click: `browser_click` with element description and ref
84
+ - Type: `browser_type` with ref, text, and optionally `submit: true`
85
+ - Fill form: `browser_fill_form` for multiple fields
86
+ - Select: `browser_select_option` for dropdowns
87
+ - Wait: `browser_wait_for` with text to appear/disappear
88
+
89
+ 4. **Verify results**:
90
+ - Call `browser_snapshot` to get current page state
91
+ - Check that expected text/elements are present in the snapshot
92
+ - Use `browser_wait_for` if async operations need time
93
+
94
+ 5. **On failure**:
95
+ - Take screenshot: `browser_take_screenshot`
96
+ - Check console: `browser_console_messages` for JS errors
97
+ - Document failure details
98
+
99
+ ### Step 4: Database Verification
100
+ For scenarios with database checks, use Supabase MCP:
101
+ ```
102
+ mcp__plugin_supabase_supabase__execute_sql
103
+ project_id: [project ID]
104
+ query: "SELECT * FROM survey_responses WHERE ..."
105
+ ```
106
+
107
+ Verify returned data matches expected state.
108
+
109
+ ### Unique Test Data (for Parallel Execution)
110
+ When creating test data, use unique identifiers to avoid conflicts with other loops:
111
+ - Add feature-specific UTM params: `?utm_source=e2e_${FEATURE}_${timestamp}`
112
+ - Use unique names/emails: `test_${FEATURE}_${timestamp}@example.com`
113
+ - This ensures database queries find only this test's data
114
+
115
+ ### Step 5: Report Results
116
+ Update @.ralph/specs/$FEATURE-implementation-plan.md for each scenario:
117
+
118
+ **Passed:**
119
+ ```markdown
120
+ - [x] E2E: scenario name - PASSED
121
+ ```
122
+
123
+ **Failed:**
124
+ ```markdown
125
+ - [ ] E2E: scenario name - FAILED: [brief reason]
126
+ - Error: [what went wrong]
127
+ - Screenshot: [if captured]
128
+ - Fix needed: [suggested action]
129
+ ```
130
+
131
+ ## Playwright MCP Tool Reference
132
+
133
+ | Tool | Purpose | Key Parameters |
134
+ |------|---------|----------------|
135
+ | `browser_navigate` | Go to URL | `url` |
136
+ | `browser_snapshot` | Get page state (use for assertions) | - |
137
+ | `browser_click` | Click element | `element`, `ref` |
138
+ | `browser_type` | Type into element | `element`, `ref`, `text`, `submit` |
139
+ | `browser_fill_form` | Fill multiple fields | `fields[]` with name, type, ref, value |
140
+ | `browser_select_option` | Select dropdown | `element`, `ref`, `values[]` |
141
+ | `browser_wait_for` | Wait for text/time | `text`, `textGone`, `time` |
142
+ | `browser_take_screenshot` | Capture visual state | `filename` (optional) |
143
+ | `browser_console_messages` | Get JS console output | `level` (error/warning/info) |
144
+ | `browser_press_key` | Press keyboard key | `key` (e.g., "Enter", "Tab") |
145
+ | `browser_close` | Close browser/reset state | - |
146
+
147
+ ## Assertion Patterns
148
+
149
+ ### Text Verification
150
+ ```
151
+ 1. browser_snapshot -> get page content
152
+ 2. Check snapshot output for expected text strings
153
+ 3. If text not found, scenario fails
154
+ ```
155
+
156
+ ### Element State
157
+ ```
158
+ 1. browser_snapshot -> accessibility tree shows element states
159
+ 2. Check for: enabled/disabled, checked/unchecked, visible
160
+ ```
161
+
162
+ ### URL Verification
163
+ ```
164
+ 1. After navigation/action, snapshot shows current URL
165
+ 2. Verify URL contains expected path/params
166
+ ```
167
+
168
+ ### Database State
169
+ ```
170
+ 1. mcp__plugin_supabase_supabase__execute_sql with SELECT query
171
+ 2. Verify row count, column values match expectations
172
+ ```
173
+
174
+ ## Browser State Management
175
+
176
+ - Use `browser_close` between unrelated scenarios to reset localStorage/cookies
177
+ - Keep browser open for scenarios that test state persistence (e.g., duplicate submission)
178
+ - Fresh browser state = clean localStorage, no prior submissions tracked
179
+
180
+ ## Error Recovery
181
+
182
+ If a scenario fails:
183
+ 1. Document the failure with specific error details
184
+ 2. Note what fix is likely needed (code bug vs test spec issue)
185
+ 3. Continue with remaining scenarios
186
+ 4. At end, summary shows total passed/failed
187
+
188
+ Failures will trigger a fix iteration in the loop.
189
+
190
+ ## Completion
191
+
192
+ When all scenarios are executed:
193
+ 1. Update implementation plan with results for each scenario
194
+ 2. Update the Implementation Summary status to `[PASSED]` if all passed
195
+ 3. **Commit the updated implementation plan:**
196
+ ```bash
197
+ git -C {{appDir}} add -A && git -C {{appDir}} commit -m "test($FEATURE): E2E tests passed via Playwright"
198
+ ```
199
+ 4. **Push to remote:**
200
+ ```bash
201
+ git -C {{appDir}} push origin feat/$FEATURE
202
+ ```
203
+ 5. If all passed: signal ready for PR phase
204
+ 6. If any failed: failures documented, loop will retry after fix iteration
205
+
206
+ ## Troubleshooting
207
+
208
+ ### UI Changes Not Visible
209
+ If code changes don't appear in the browser:
210
+ 1. Stop the dev server
211
+ 2. Clear cache: `rm -rf {{appDir}}/.next`
212
+ 3. Restart: `cd {{appDir}} && {{devCommand}}`
213
+ 4. Wait for full rebuild before testing
214
+
215
+ ### Stale Data
216
+ - Clear browser storage: Use `browser_close` between scenarios
217
+ - Check Supabase for stale test data from previous runs
218
+ - Delete test data: `DELETE FROM table WHERE data->>'_test' = 'true'`
219
+
220
+ ## Rules
221
+ - Always get a fresh `browser_snapshot` after actions before making assertions
222
+ - Use `browser_wait_for` when waiting for async operations (form submission, API calls)
223
+ - Take screenshots only on failures to avoid clutter
224
+ - Verify database state for data-mutation features
225
+ - Keep scenarios independent when possible
226
+ - Document failures clearly so fix iteration knows what to address
227
+
228
+ ## Learning Capture
229
+ If E2E testing revealed issues worth remembering, append to @.ralph/LEARNINGS.md:
230
+ - Flaky test patterns -> Add under "## Anti-Patterns" > "E2E Pitfalls"
231
+ - Useful Playwright techniques -> Add under "## Tool Usage"
232
+ - Timing issues or race conditions -> Add under "## Anti-Patterns"
233
+
234
+ Format: `- [YYYY-MM-DD] [$FEATURE] Brief description`