@relipa/ai-flow-kit 0.2.0-beta.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom/rules/java/spring-boot-rules.md +209 -0
- package/custom/rules/javascript/nestjs-examples.md +41 -0
- package/custom/rules/javascript/nestjs-rules.md +42 -0
- package/custom/rules/javascript/nodejs-express-examples.md +35 -0
- package/custom/rules/javascript/nodejs-express-rules.md +49 -0
- package/custom/rules/javascript/reactjs-examples.md +380 -0
- package/custom/rules/javascript/reactjs-rules.md +173 -0
- package/custom/rules/php/php-examples.md +161 -0
- package/custom/rules/php/php-rules.md +127 -0
- package/custom/rules/python/python-django-examples.md +34 -0
- package/custom/rules/python/python-django-rules.md +48 -0
- package/custom/rules/python/python-examples.md +32 -0
- package/custom/rules/python/python-fastapi-examples.md +30 -0
- package/custom/rules/python/python-fastapi-rules.md +35 -0
- package/custom/rules/python/python-ml-examples.md +187 -0
- package/custom/rules/python/python-ml-rules.md +121 -0
- package/custom/rules/python/python-rules.md +58 -0
- package/custom/skills/ba-skills/skill-ba-qna-template-v1.md +4 -4
- package/custom/skills/ba-skills/skill-ba-qna-v1.md +6 -0
- package/custom/skills/create-system-requirement/SKILL.md +52 -16
- package/custom/skills/create-system-requirement/system-requirement-template-v1.md +128 -0
- package/custom/skills/impact-analysis/SKILL.md +106 -106
- package/custom/skills/ingest-data/SKILL.md +53 -5
- package/custom/skills/report-customer/SKILL.md +99 -99
- package/custom/templates/nestjs.md +5 -72
- package/custom/templates/nodejs-express.md +5 -73
- package/custom/templates/php-plain.md +5 -261
- package/custom/templates/php.md +5 -261
- package/custom/templates/python-django.md +5 -71
- package/custom/templates/python-fastapi.md +5 -54
- package/custom/templates/python-ml.md +1 -269
- package/custom/templates/python.md +5 -79
- package/custom/templates/reactjs.md +5 -492
- package/custom/templates/shared/create-testcase-workflow.md +30 -2
- package/custom/templates/shared/gate-workflow.md +5 -3
- package/custom/templates/shared/ml-gate-workflow.md +1 -0
- package/custom/templates/spring-boot.md +5 -224
- package/docs/common/CHANGELOG.md +20 -10
- package/package.json +1 -1
- package/scripts/init.js +143 -40
- package/scripts/link-resolver.js +60 -24
- package/scripts/ticket-writer.js +72 -3
|
@@ -1,492 +1,5 @@
|
|
|
1
|
-
# React.js AI System Prompt
|
|
2
|
-
|
|
3
|
-
You are an expert React.js developer. Follow these specific rules when generating or modifying code in this project.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Project Stack
|
|
8
|
-
|
|
9
|
-
- **React:** 18+
|
|
10
|
-
- **Language:** TypeScript
|
|
11
|
-
- **Build Tool:** Vite (prefer) or Create React App
|
|
12
|
-
- **State Management:** Zustand (local/global) or TanStack Query (server state)
|
|
13
|
-
- **Routing:** React Router v6
|
|
14
|
-
- **Styling:** Tailwind CSS + shadcn/ui (or CSS Modules if no Tailwind)
|
|
15
|
-
- **Form:** React Hook Form + Zod validation
|
|
16
|
-
- **HTTP Client:** Axios with interceptors
|
|
17
|
-
- **Testing:** Vitest + React Testing Library
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Project Structure
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
src/
|
|
25
|
-
├── components/
|
|
26
|
-
│ ├── ui/ # Generic, reusable UI (Button, Input, Modal...)
|
|
27
|
-
│ └── [feature]/ # Feature-specific components
|
|
28
|
-
├── pages/ # Route-level components (thin, delegate to features)
|
|
29
|
-
├── features/ # Self-contained feature modules
|
|
30
|
-
│ └── [feature]/
|
|
31
|
-
│ ├── components/ # UI specific to this feature
|
|
32
|
-
│ ├── hooks/ # Custom hooks for this feature
|
|
33
|
-
│ ├── api.ts # API calls for this feature
|
|
34
|
-
│ ├── store.ts # Zustand slice (if needed)
|
|
35
|
-
│ ├── types.ts # TypeScript types/interfaces
|
|
36
|
-
│ └── index.ts # Public exports
|
|
37
|
-
├── hooks/ # Shared custom hooks
|
|
38
|
-
├── services/
|
|
39
|
-
│ └── api.ts # Axios instance + interceptors
|
|
40
|
-
├── store/ # Global Zustand store
|
|
41
|
-
├── types/ # Shared TypeScript types
|
|
42
|
-
├── utils/ # Pure utility functions
|
|
43
|
-
├── constants/ # App-wide constants
|
|
44
|
-
└── App.tsx
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## Component Rules
|
|
50
|
-
|
|
51
|
-
### Always use Functional Components
|
|
52
|
-
|
|
53
|
-
```tsx
|
|
54
|
-
// ✅ Good
|
|
55
|
-
const UserCard = ({ user }: UserCardProps) => {
|
|
56
|
-
return <div>{user.name}</div>;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
// ❌ Bad — class component
|
|
60
|
-
class UserCard extends React.Component {}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Define Props with TypeScript interface
|
|
64
|
-
|
|
65
|
-
```tsx
|
|
66
|
-
// ✅ Good
|
|
67
|
-
interface UserCardProps {
|
|
68
|
-
user: User;
|
|
69
|
-
onDelete?: (id: number) => void;
|
|
70
|
-
className?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const UserCard = ({ user, onDelete, className }: UserCardProps) => {
|
|
74
|
-
// ...
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// ❌ Bad — any, or no type
|
|
78
|
-
const UserCard = ({ user }: any) => {};
|
|
79
|
-
const UserCard = (props) => {};
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Keep components focused and small
|
|
83
|
-
|
|
84
|
-
- One component = one responsibility
|
|
85
|
-
- If a component exceeds ~150 lines, split it
|
|
86
|
-
- Extract logic to custom hooks, keep JSX clean
|
|
87
|
-
|
|
88
|
-
```tsx
|
|
89
|
-
// ✅ Good — logic extracted to hook
|
|
90
|
-
const UserList = () => {
|
|
91
|
-
const { users, isLoading, error, deleteUser } = useUserList();
|
|
92
|
-
|
|
93
|
-
if (isLoading) return <Spinner />;
|
|
94
|
-
if (error) return <ErrorMessage message={error.message} />;
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<ul>
|
|
98
|
-
{users.map(user => (
|
|
99
|
-
<UserCard key={user.id} user={user} onDelete={deleteUser} />
|
|
100
|
-
))}
|
|
101
|
-
</ul>
|
|
102
|
-
);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// ❌ Bad — logic mixed into component
|
|
106
|
-
const UserList = () => {
|
|
107
|
-
const [users, setUsers] = useState([]);
|
|
108
|
-
const [loading, setLoading] = useState(true);
|
|
109
|
-
|
|
110
|
-
useEffect(() => {
|
|
111
|
-
fetch('/api/users')
|
|
112
|
-
.then(r => r.json())
|
|
113
|
-
.then(data => { setUsers(data); setLoading(false); });
|
|
114
|
-
}, []);
|
|
115
|
-
|
|
116
|
-
const handleDelete = async (id) => {
|
|
117
|
-
await fetch(`/api/users/${id}`, { method: 'DELETE' });
|
|
118
|
-
setUsers(prev => prev.filter(u => u.id !== id));
|
|
119
|
-
};
|
|
120
|
-
// ... long JSX
|
|
121
|
-
};
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Export convention
|
|
125
|
-
|
|
126
|
-
```tsx
|
|
127
|
-
// Named export for regular components
|
|
128
|
-
export const UserCard = ({ user }: UserCardProps) => { ... };
|
|
129
|
-
|
|
130
|
-
// Default export only for page-level components
|
|
131
|
-
export default function UserPage() { ... }
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## Custom Hook Rules
|
|
137
|
-
|
|
138
|
-
- Prefix with `use`: `useUserList`, `useAuth`, `useModal`
|
|
139
|
-
- Extract all side effects, API calls, and complex state from components
|
|
140
|
-
- Return objects (not arrays) for multiple values — easier to destructure
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
// ✅ Good
|
|
144
|
-
const useUserList = () => {
|
|
145
|
-
const { data: users = [], isLoading, error } = useQuery({
|
|
146
|
-
queryKey: ['users'],
|
|
147
|
-
queryFn: userApi.getAll,
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
const { mutate: deleteUser } = useMutation({
|
|
151
|
-
mutationFn: userApi.delete,
|
|
152
|
-
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
return { users, isLoading, error, deleteUser };
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
// Usage
|
|
159
|
-
const { users, isLoading, deleteUser } = useUserList();
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## State Management Rules
|
|
165
|
-
|
|
166
|
-
### Server state → TanStack Query
|
|
167
|
-
|
|
168
|
-
Use for all API data (fetching, caching, mutations):
|
|
169
|
-
|
|
170
|
-
```tsx
|
|
171
|
-
// Fetching
|
|
172
|
-
const { data, isLoading, error } = useQuery({
|
|
173
|
-
queryKey: ['users', filters], // include deps in key
|
|
174
|
-
queryFn: () => userApi.getAll(filters),
|
|
175
|
-
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// Mutation
|
|
179
|
-
const { mutate, isPending } = useMutation({
|
|
180
|
-
mutationFn: userApi.create,
|
|
181
|
-
onSuccess: () => {
|
|
182
|
-
queryClient.invalidateQueries({ queryKey: ['users'] });
|
|
183
|
-
toast.success('User created');
|
|
184
|
-
},
|
|
185
|
-
onError: (error) => toast.error(error.message),
|
|
186
|
-
});
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Client/UI state → Zustand (or useState for local)
|
|
190
|
-
|
|
191
|
-
```tsx
|
|
192
|
-
// Local state — use useState
|
|
193
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
194
|
-
|
|
195
|
-
// Shared UI state — use Zustand
|
|
196
|
-
const useAuthStore = create<AuthStore>((set) => ({
|
|
197
|
-
user: null,
|
|
198
|
-
token: null,
|
|
199
|
-
login: (user, token) => set({ user, token }),
|
|
200
|
-
logout: () => set({ user: null, token: null }),
|
|
201
|
-
}));
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### Rules:
|
|
205
|
-
- **Never** use global state for server/API data — that's TanStack Query's job
|
|
206
|
-
- **Never** fetch in `useEffect` manually — use TanStack Query
|
|
207
|
-
- **Never** put loading/error state in Zustand — TanStack Query handles that
|
|
208
|
-
|
|
209
|
-
---
|
|
210
|
-
|
|
211
|
-
## Form Rules
|
|
212
|
-
|
|
213
|
-
Use **React Hook Form + Zod** for all forms:
|
|
214
|
-
|
|
215
|
-
```tsx
|
|
216
|
-
// 1. Define schema with Zod
|
|
217
|
-
const createUserSchema = z.object({
|
|
218
|
-
email: z.string().email('Invalid email'),
|
|
219
|
-
fullName: z.string().min(2, 'Min 2 characters').max(100),
|
|
220
|
-
password: z.string().min(8, 'Min 8 characters'),
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
type CreateUserForm = z.infer<typeof createUserSchema>;
|
|
224
|
-
|
|
225
|
-
// 2. Use in component
|
|
226
|
-
const CreateUserForm = () => {
|
|
227
|
-
const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<CreateUserForm>({
|
|
228
|
-
resolver: zodResolver(createUserSchema),
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
const onSubmit = async (data: CreateUserForm) => {
|
|
232
|
-
await createUser(data);
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
return (
|
|
236
|
-
<form onSubmit={handleSubmit(onSubmit)}>
|
|
237
|
-
<input {...register('email')} />
|
|
238
|
-
{errors.email && <span>{errors.email.message}</span>}
|
|
239
|
-
|
|
240
|
-
<button type="submit" disabled={isSubmitting}>
|
|
241
|
-
{isSubmitting ? 'Saving...' : 'Create'}
|
|
242
|
-
</button>
|
|
243
|
-
</form>
|
|
244
|
-
);
|
|
245
|
-
};
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
---
|
|
249
|
-
|
|
250
|
-
## API Layer Rules
|
|
251
|
-
|
|
252
|
-
One `axios` instance shared across the app with interceptors:
|
|
253
|
-
|
|
254
|
-
```tsx
|
|
255
|
-
// src/services/api.ts
|
|
256
|
-
const api = axios.create({
|
|
257
|
-
baseURL: import.meta.env.VITE_API_URL,
|
|
258
|
-
timeout: 10000,
|
|
259
|
-
headers: { 'Content-Type': 'application/json' },
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Attach token automatically
|
|
263
|
-
api.interceptors.request.use((config) => {
|
|
264
|
-
const token = useAuthStore.getState().token;
|
|
265
|
-
if (token) config.headers.Authorization = `Bearer ${token}`;
|
|
266
|
-
return config;
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
// Handle 401 globally
|
|
270
|
-
api.interceptors.response.use(
|
|
271
|
-
(response) => response,
|
|
272
|
-
(error) => {
|
|
273
|
-
if (error.response?.status === 401) {
|
|
274
|
-
useAuthStore.getState().logout();
|
|
275
|
-
window.location.href = '/login';
|
|
276
|
-
}
|
|
277
|
-
return Promise.reject(error);
|
|
278
|
-
}
|
|
279
|
-
);
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
Feature API module:
|
|
283
|
-
|
|
284
|
-
```tsx
|
|
285
|
-
// src/features/users/api.ts
|
|
286
|
-
export const userApi = {
|
|
287
|
-
getAll: (params?: UserListParams): Promise<User[]> =>
|
|
288
|
-
api.get('/users', { params }).then(r => r.data),
|
|
289
|
-
|
|
290
|
-
getById: (id: number): Promise<User> =>
|
|
291
|
-
api.get(`/users/${id}`).then(r => r.data),
|
|
292
|
-
|
|
293
|
-
create: (data: CreateUserRequest): Promise<User> =>
|
|
294
|
-
api.post('/users', data).then(r => r.data),
|
|
295
|
-
|
|
296
|
-
update: (id: number, data: UpdateUserRequest): Promise<User> =>
|
|
297
|
-
api.put(`/users/${id}`, data).then(r => r.data),
|
|
298
|
-
|
|
299
|
-
delete: (id: number): Promise<void> =>
|
|
300
|
-
api.delete(`/users/${id}`).then(r => r.data),
|
|
301
|
-
};
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
---
|
|
305
|
-
|
|
306
|
-
## TypeScript Rules
|
|
307
|
-
|
|
308
|
-
- **No `any`** — use `unknown`, proper types, or generics
|
|
309
|
-
- Define shared types in `types.ts` files
|
|
310
|
-
- Use `interface` for object shapes, `type` for unions/intersections
|
|
311
|
-
- Always type function return values for public hooks and API functions
|
|
312
|
-
|
|
313
|
-
```tsx
|
|
314
|
-
// ✅ Good
|
|
315
|
-
interface User {
|
|
316
|
-
id: number;
|
|
317
|
-
email: string;
|
|
318
|
-
fullName: string;
|
|
319
|
-
createdAt: string;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
type UserStatus = 'active' | 'inactive' | 'banned';
|
|
323
|
-
|
|
324
|
-
const getUser = async (id: number): Promise<User> => {
|
|
325
|
-
return api.get(`/users/${id}`).then(r => r.data);
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
// ❌ Bad
|
|
329
|
-
const getUser = async (id: any) => {
|
|
330
|
-
return api.get(`/users/${id}`).then((r: any) => r.data);
|
|
331
|
-
};
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
---
|
|
335
|
-
|
|
336
|
-
## Styling Rules (Tailwind CSS)
|
|
337
|
-
|
|
338
|
-
- Use utility classes directly — avoid custom CSS unless necessary
|
|
339
|
-
- Extract repeated class combinations into components or a `cn()` helper
|
|
340
|
-
- Use `className` prop for external style overrides
|
|
341
|
-
|
|
342
|
-
```tsx
|
|
343
|
-
// ✅ Good — cn() for conditional classes
|
|
344
|
-
import { cn } from '\@/utils/cn';
|
|
345
|
-
|
|
346
|
-
const Button = ({ variant = 'primary', disabled, className, children }: ButtonProps) => (
|
|
347
|
-
<button
|
|
348
|
-
className={cn(
|
|
349
|
-
'px-4 py-2 rounded font-medium transition-colors',
|
|
350
|
-
variant === 'primary' && 'bg-blue-600 text-white hover:bg-blue-700',
|
|
351
|
-
variant === 'outline' && 'border border-gray-300 hover:bg-gray-50',
|
|
352
|
-
disabled && 'opacity-50 cursor-not-allowed',
|
|
353
|
-
className
|
|
354
|
-
)}
|
|
355
|
-
disabled={disabled}
|
|
356
|
-
>
|
|
357
|
-
{children}
|
|
358
|
-
</button>
|
|
359
|
-
);
|
|
360
|
-
|
|
361
|
-
// ❌ Bad — inline style
|
|
362
|
-
<button style={{ backgroundColor: 'blue', padding: '8px 16px' }}>
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
---
|
|
366
|
-
|
|
367
|
-
## Performance Rules
|
|
368
|
-
|
|
369
|
-
- Use `React.memo` only when profiling shows a real problem — do not optimize prematurely
|
|
370
|
-
- Use `useMemo` / `useCallback` for expensive computations or stable references passed to children
|
|
371
|
-
- Lazy-load routes with `React.lazy` + `Suspense`
|
|
372
|
-
- Avoid anonymous functions in JSX props when passing to memoized children
|
|
373
|
-
|
|
374
|
-
```tsx
|
|
375
|
-
// Lazy routes
|
|
376
|
-
const UserPage = React.lazy(() => import('./pages/UserPage'));
|
|
377
|
-
|
|
378
|
-
<Suspense fallback={<PageSkeleton />}>
|
|
379
|
-
<UserPage />
|
|
380
|
-
</Suspense>
|
|
381
|
-
|
|
382
|
-
// useMemo for expensive computation
|
|
383
|
-
const sortedUsers = useMemo(
|
|
384
|
-
() => [...users].sort((a, b) => a.fullName.localeCompare(b.fullName)),
|
|
385
|
-
[users]
|
|
386
|
-
);
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
---
|
|
390
|
-
|
|
391
|
-
## Error Handling Rules
|
|
392
|
-
|
|
393
|
-
- Use React Error Boundary at the route level
|
|
394
|
-
- Handle API errors in TanStack Query `onError` callbacks
|
|
395
|
-
- Show user-friendly messages — never raw error objects
|
|
396
|
-
- Use toast notifications for async operation feedback
|
|
397
|
-
|
|
398
|
-
```tsx
|
|
399
|
-
// Error boundary at route level
|
|
400
|
-
<ErrorBoundary fallback={<ErrorPage />}>
|
|
401
|
-
<Routes>
|
|
402
|
-
<Route path="/users" element={<UserPage />} />
|
|
403
|
-
</Routes>
|
|
404
|
-
</ErrorBoundary>
|
|
405
|
-
|
|
406
|
-
// Async error handling
|
|
407
|
-
const { mutate } = useMutation({
|
|
408
|
-
mutationFn: userApi.create,
|
|
409
|
-
onSuccess: () => toast.success('User created successfully'),
|
|
410
|
-
onError: (error: AxiosError<ApiError>) =>
|
|
411
|
-
toast.error(error.response?.data?.message ?? 'Something went wrong'),
|
|
412
|
-
});
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
---
|
|
416
|
-
|
|
417
|
-
## Testing Rules
|
|
418
|
-
|
|
419
|
-
### Unit/Component tests with React Testing Library
|
|
420
|
-
|
|
421
|
-
```tsx
|
|
422
|
-
// Test behavior, not implementation
|
|
423
|
-
describe('UserCard', () => {
|
|
424
|
-
it('should display user name and email', () => {
|
|
425
|
-
const user: User = { id: 1, email: 'test\@example.com', fullName: 'Test User' };
|
|
426
|
-
render(<UserCard user={user} />);
|
|
427
|
-
|
|
428
|
-
expect(screen.getByText('Test User')).toBeInTheDocument();
|
|
429
|
-
expect(screen.getByText('test\@example.com')).toBeInTheDocument();
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
it('should call onDelete with user id when delete button clicked', async () => {
|
|
433
|
-
const onDelete = vi.fn();
|
|
434
|
-
const user: User = { id: 1, email: 'test\@example.com', fullName: 'Test User' };
|
|
435
|
-
|
|
436
|
-
render(<UserCard user={user} onDelete={onDelete} />);
|
|
437
|
-
await userEvent.click(screen.getByRole('button', { name: /delete/i }));
|
|
438
|
-
|
|
439
|
-
expect(onDelete).toHaveBeenCalledWith(1);
|
|
440
|
-
});
|
|
441
|
-
});
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
### Hook tests
|
|
445
|
-
|
|
446
|
-
```tsx
|
|
447
|
-
import { renderHook, waitFor } from '\@testing-library/react';
|
|
448
|
-
|
|
449
|
-
it('should fetch users', async () => {
|
|
450
|
-
const { result } = renderHook(() => useUserList(), { wrapper: QueryWrapper });
|
|
451
|
-
|
|
452
|
-
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
453
|
-
|
|
454
|
-
expect(result.current.users).toHaveLength(2);
|
|
455
|
-
});
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
## Naming Conventions
|
|
461
|
-
|
|
462
|
-
| Element | Convention | Example |
|
|
463
|
-
|---------|-----------|---------|
|
|
464
|
-
| Component file | PascalCase | `UserCard.tsx` |
|
|
465
|
-
| Hook file | camelCase | `useUserList.ts` |
|
|
466
|
-
| Utility file | camelCase | `formatDate.ts` |
|
|
467
|
-
| Type/Interface | PascalCase | `User`, `CreateUserRequest` |
|
|
468
|
-
| Component | PascalCase | `UserCard`, `OrderList` |
|
|
469
|
-
| Hook | `use` + PascalCase | `useUserList`, `useAuth` |
|
|
470
|
-
| Event handler | `handle` + Action | `handleDelete`, `handleSubmit` |
|
|
471
|
-
| Boolean variable | `is/has/can` prefix | `isLoading`, `hasError`, `canEdit` |
|
|
472
|
-
| Constant | UPPER_SNAKE_CASE | `MAX_RETRY`, `API_TIMEOUT` |
|
|
473
|
-
| CSS class (custom) | kebab-case | `user-card`, `nav-item` |
|
|
474
|
-
|
|
475
|
-
---
|
|
476
|
-
|
|
477
|
-
## Common Anti-Patterns to Avoid
|
|
478
|
-
|
|
479
|
-
- ❌ Fetching in `useEffect` → use TanStack Query
|
|
480
|
-
- ❌ Using `any` type → define proper TypeScript types
|
|
481
|
-
- ❌ Storing server data in Zustand → that's TanStack Query's responsibility
|
|
482
|
-
- ❌ Class components → use functional components
|
|
483
|
-
- ❌ `index.js` everywhere → use named files for traceability
|
|
484
|
-
- ❌ Direct DOM manipulation → use React state/refs
|
|
485
|
-
- ❌ Mutating state directly → always use setter functions
|
|
486
|
-
- ❌ Large components doing everything → split into smaller focused components
|
|
487
|
-
- ❌ Prop drilling more than 2 levels → use context or Zustand
|
|
488
|
-
- ❌ Hardcoding API URLs → use `import.meta.env.VITE_API_URL`
|
|
489
|
-
|
|
490
|
-
---
|
|
491
|
-
|
|
492
|
-
When explaining changes, refer to the [React Official Documentation](https://react.dev), [TanStack Query](https://tanstack.com/query), and [React Hook Form](https://react-hook-form.com) conventions.
|
|
1
|
+
# React.js AI System Prompt
|
|
2
|
+
|
|
3
|
+
You are an expert React.js developer. Follow these specific rules when generating or modifying code in this project.
|
|
4
|
+
|
|
5
|
+
> **Rules & code examples:** Read `.rules/javascript/reactjs-rules.md` (structure, per-area rules, naming, anti-patterns) and `.rules/javascript/reactjs-examples.md` (code samples per rule area) **in full** before writing or modifying any React code in this project.
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
Nếu `AK-Docs/` hoặc `Shared-Docs/` chưa tồn tại tại workspace root, hoặc không phải git repo → bỏ qua bước tương ứng, không cảnh báo.
|
|
20
20
|
|
|
21
|
+
> ❌ **KHÔNG** tự ý liệt kê (`git branch -a`), checkout, hoặc đọc/diff nhiều branch trong repo source để tự dò tìm "nhánh đang phát triển" của feature — rất tốn token và thời gian, và dễ đọc nhầm code chưa hoàn chỉnh/chưa merge. Bước 1 chỉ `git pull` đúng branch hiện tại đang checkout (thường là `main`/`develop`). Nếu cần biết chính xác code nào đã thay đổi cho ticket này → xem bước **Dev Artifacts Check** (Bước 1.5, Gate 1, bên dưới): hỏi TESTER cung cấp PR link hoặc commit SHA/branch name cụ thể, rồi fetch/diff **đúng** phạm vi đó qua skill `pr-impact-analysis`.
|
|
22
|
+
|
|
21
23
|
**Nếu bất kỳ lệnh `git pull` nào ở Bước 1–3 thất bại** → **KHÔNG dừng workflow** — hiển thị cảnh báo và tiếp tục gate với dữ liệu local hiện có:
|
|
22
24
|
|
|
23
25
|
```
|
|
@@ -33,6 +35,7 @@ Các skill sau đây được cài tự động vào `.claude/skills/test-skills
|
|
|
33
35
|
|
|
34
36
|
| Skill | File |
|
|
35
37
|
|---|---|
|
|
38
|
+
| `PR Impact Analysis` | `.claude/skills/pr-impact-analysis/SKILL.md` |
|
|
36
39
|
| `QA Writing Standards` | `.claude/skills/test-skills/rules/qa-writing-standards.md` |
|
|
37
40
|
| `Directory & Naming Convention` | `.claude/skills/test-skills/rules/directory-and-naming-convention.md` |
|
|
38
41
|
| `Template TestCase` | `.claude/skills/test-skills/template/testcase-template.md` |
|
|
@@ -204,6 +207,26 @@ Nếu tất cả điều kiện thỏa mãn → thông báo ngắn rồi tiếp
|
|
|
204
207
|
- Nếu có `supplementaryContext[]` → đọc từng item (SRS file, Figma link, API spec, spec MD file)
|
|
205
208
|
- Nếu có file yêu cầu thô được chỉ định → đọc file đó
|
|
206
209
|
|
|
210
|
+
#### Bước 1.5: Dev Artifacts Check (PR/Commit-based)
|
|
211
|
+
|
|
212
|
+
**Mục tiêu:** xác định **chính xác** phạm vi code đã thay đổi cho ticket này, để mở rộng coverage (regression scope) mà **không** phải tự dò/đọc toàn bộ branch đang phát triển của feature (tốn token, tốn thời gian, dễ đọc nhầm code chưa xong).
|
|
213
|
+
|
|
214
|
+
1. Kiểm tra ticket/context có PR link đính kèm không (`.aiflow/context/current.json`, mô tả ticket).
|
|
215
|
+
2. **Có PR link, hoặc TESTER đã khai báo `PR: <url>` trong chat** → **INVOKE** skill `pr-impact-analysis` ngay, dùng PR đó.
|
|
216
|
+
3. **Chưa có PR/commit nào được biết** → hỏi TESTER **một câu duy nhất**:
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
Để xác định đúng phạm vi ảnh hưởng code (tránh phải rà toàn bộ branch), bạn cung cấp giúp PR link hoặc commit SHA/branch name của thay đổi cho ticket này (có thể nhiều PR/commit nếu multi-repo). Nếu chưa có, gõ "chưa có" để bỏ qua bước này.
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
4. Xử lý câu trả lời của TESTER:
|
|
223
|
+
- Cung cấp PR/commit/branch → **INVOKE** skill `pr-impact-analysis` với thông tin đó (dùng fallback `git fetch` + `git diff main...<branch>` nếu không phải PR).
|
|
224
|
+
- Trả lời "chưa có" → ghi nhận vào `test-plan/impact-analysis.md` (hoặc tương đương) "chưa có dev artifacts — sẽ re-check ở Gate 3", **không block Gate 1**.
|
|
225
|
+
5. Kết quả `pr-impact-analysis` (màn hình ảnh hưởng trực tiếp/gián tiếp, đề xuất regression TCs) được dùng làm input bổ sung cho Bước 2 và Gate 2 (Scenario Building) — **không** dùng để xác định expected result (vẫn lấy từ ticket/UC Spec/System Requirement).
|
|
226
|
+
|
|
227
|
+
> ❌ **KHÔNG** tự ý `git branch -a`, checkout, hoặc đọc lần lượt nhiều branch để tìm "code đang phát triển" — luôn đi qua PR/commit cụ thể mà TESTER xác nhận, qua skill `pr-impact-analysis`.
|
|
228
|
+
> Ở Gate 3 (trước khi thiết kế TC chi tiết), re-run bước này nếu đã có `impact-analysis.md` từ Gate 1 — dùng Delta Detection của `pr-impact-analysis` (so SHA cũ/mới) để bắt commit mới, không đọc lại toàn bộ diff.
|
|
229
|
+
|
|
207
230
|
#### Bước 2: Phân tích yêu cầu và đánh giá rủi ro
|
|
208
231
|
- **READ skill:** `.claude/skills/test-skills/rules/qa-writing-standards.md` — đọc trước để nắm quy ước chung
|
|
209
232
|
- **READ skill:** `.claude/skills/test-skills/categories/00-core/00.01.requirement-analysis.md`
|
|
@@ -357,6 +380,10 @@ Nếu tất cả điều kiện thỏa mãn → thông báo ngắn rồi tiếp
|
|
|
357
380
|
|
|
358
381
|
**Pre-flight (bắt buộc, chạy trước Bước 1):** chạy [Pre-flight — Đồng bộ Source & Docs](#pre-flight-bắt-buộc--đồng-bộ-source--docs-đầu-mỗi-gate) ở đầu file. Lỗi → hiển thị ⚠️ cảnh báo, không dừng gate.
|
|
359
382
|
|
|
383
|
+
#### Bước 0.7: Dev Artifacts Check — Delta Detection
|
|
384
|
+
|
|
385
|
+
Nếu `test-plan/impact-analysis.md` đã có PR/commit từ Gate 1 (Bước 1.5) → re-run `pr-impact-analysis` (Delta Detection): so SHA đã ghi với SHA hiện tại, nếu có commit mới thì chỉ đọc diff phần thêm mới, bổ sung TC nếu cần. Không có gì mới hoặc chưa từng có PR → bỏ qua, không cần hỏi lại TESTER.
|
|
386
|
+
|
|
360
387
|
#### Bước 1: Đọc template và quy ước bắt buộc
|
|
361
388
|
- **READ template:** `.claude/skills/test-skills/template/testcase-template.md` — **BẮT BUỘC** tuân thủ 100%
|
|
362
389
|
- **READ skill:** `.claude/skills/test-skills/rules/qa-writing-standards.md`
|
|
@@ -545,15 +572,16 @@ Sau khi Gate 4 đã APPROVED (bộ Test Case hoàn thành):
|
|
|
545
572
|
|
|
546
573
|
| Gate | Skills đọc | Output |
|
|
547
574
|
|---|---|---|
|
|
548
|
-
| Gate 1 | `QA_Writing_Standards`, `00.01 Requirement Analysis`, `00.02 Risk Analysis` | `01_Requirement_Analysis_Result.md`, `01_QA.md` |
|
|
575
|
+
| Gate 1 | `pr-impact-analysis` (Bước 1.5), `QA_Writing_Standards`, `00.01 Requirement Analysis`, `00.02 Risk Analysis` | `01_Requirement_Analysis_Result.md`, `01_QA.md` |
|
|
549
576
|
| Gate 2 | `00.03 Scenario Builder`, `01.06 Error Guessing`, `03.02 Workflow Testing`, Domain skills | `02_Test_Scenarios_Result.md`, `02_QA.md` |
|
|
550
|
-
| Gate 3 | `testcase-template`, `01.01 BVA`, `01.02 EP`, `01.03 Decision Table`, `01.06 Error Guessing`, `02.01`–`02.04`, `03.01`, `03.03`, `04.01`, `04.04` | `03_Test_Cases_Draft_Result.md`, `03_QA.md` |
|
|
577
|
+
| Gate 3 | `pr-impact-analysis` (Delta Detection nếu có PR từ Gate 1), `testcase-template`, `01.01 BVA`, `01.02 EP`, `01.03 Decision Table`, `01.06 Error Guessing`, `02.01`–`02.04`, `03.01`, `03.03`, `04.01`, `04.04` | `03_Test_Cases_Draft_Result.md`, `03_QA.md` |
|
|
551
578
|
| Gate 4 | `00.04 TC Review`, `99.01 Coverage Review` | `04_Final_Result.md`, `04_QA.md`, `[functionId]_TestCase.md` |
|
|
552
579
|
|
|
553
580
|
---
|
|
554
581
|
|
|
555
582
|
### Quy tắc bắt buộc
|
|
556
583
|
|
|
584
|
+
- ❌ **KHÔNG** tự ý liệt kê/checkout/đọc nhiều branch trong repo source để dò tìm thay đổi code — xác định phạm vi ảnh hưởng code phải qua PR link hoặc commit SHA/branch cụ thể do TESTER cung cấp (Bước 1.5, Gate 1) + skill `pr-impact-analysis`
|
|
557
585
|
- ❌ **KHÔNG** bỏ qua thứ tự Gate — luôn đi từ Gate 1 → 2 → 3 → 4
|
|
558
586
|
- ❌ **KHÔNG** tự suy diễn nghiệp vụ — ghi rõ Assumption và TBD khi thiếu thông tin
|
|
559
587
|
- ❌ **KHÔNG** sinh `04_Final_Result.md` mà thiếu `[functionId]_TestCase.md` (hoặc ngược lại)
|
|
@@ -162,6 +162,7 @@ Only runs after Gate 2 has been APPROVED.
|
|
|
162
162
|
|
|
163
163
|
**INVOKE:** `superpowers:test-driven-development`
|
|
164
164
|
- **Pre-flight (bắt buộc):** chạy [Pre-flight — Đồng bộ Source & Docs](#pre-flight-bắt-buộc--đồng-bộ-source--docs-đầu-mỗi-gate) ở đầu file. Lỗi → hiển thị ⚠️ cảnh báo, không dừng gate.
|
|
165
|
+
- **Framework rules (bắt buộc, đọc trước dòng code đầu tiên):** nếu chưa đọc trong session này, đọc đầy đủ file(s) được trỏ ở dòng "> **Rules & code examples:**" đầu CLAUDE.md/AGENTS.md (`.rules/<lang>/<framework>-rules.md` + `-examples.md`). Áp dụng cho MỌI lần sửa code trong Gate này, không chỉ lần đầu.
|
|
165
166
|
- Complex feature (3+ files): `superpowers:subagent-driven-development`
|
|
166
167
|
- Write tests FIRST — run to confirm FAIL -> implement -> PASS.
|
|
167
168
|
- Bug fix EXTRA: `superpowers:systematic-debugging` + `investigate-bug` skill first.
|
|
@@ -725,12 +726,13 @@ Bugs logged: [N] | Skipped: [N]
|
|
|
725
726
|
> Implements "Vấn đề 5" trong `docs/internal/PM Workflow_v1.0.md`. **Không chờ APPROVED để bắt đầu** — chạy tự động ngay sau Gate 2 Bước 7, không cần lệnh riêng và không cần chờ PM merge MR (merge là việc độc lập của PM). `INVOKE`: `ingest-data` skill § 5 cho toàn bộ logic phân tích/đề xuất — mục này chỉ nêu gate mechanics.
|
|
726
727
|
|
|
727
728
|
1. Đọc lại entry vừa ghi + điều tra source/docs liên quan (skill § 5.1).
|
|
728
|
-
2. Quyết định content này có cần task không (skill § 5.2). Nếu KHÔNG cần task → hiển thị thông báo tương ứng, chạy `ak gate 3 skip --ticket [ticket-id] --reason "<1 câu lý do>"` (không chạy `ak gate 3 start`), và **kết thúc luôn, không có Gate 3 Display**. `skip` vẫn đóng gate đúng cách (advance `currentGate` giống `approved`) — task hiện đúng "done" trên dashboard, không treo ở trạng thái "sẵn sàng chạy Gate 3" mãi.
|
|
729
|
+
2. Quyết định content này có cần task không (skill § 5.2 — với entry từ `Confirmations-Log`, chạy qua checklist tối thiểu thay vì chỉ dựa Action items viết sẵn). Nếu KHÔNG cần task → hiển thị thông báo tương ứng, chạy `ak gate 3 skip --ticket [ticket-id] --reason "<1 câu lý do>"` (không chạy `ak gate 3 start`), và **kết thúc luôn, không có Gate 3 Display**. `skip` vẫn đóng gate đúng cách (advance `currentGate` giống `approved`) — task hiện đúng "done" trên dashboard, không treo ở trạng thái "sẵn sàng chạy Gate 3" mãi.
|
|
729
730
|
3. Nếu CẦN task → chạy `ak gate 3 start --ticket [ticket-id]`, rồi đề xuất danh sách task (skill § 5.3), cho PM sửa/thêm/xoá (skill § 5.4), lặp tới khi PM hài lòng.
|
|
730
731
|
4. Điểm dừng xác nhận trước khi tạo ticket (skill § 5.5) — ❌ không tự thêm `--yes`, phải có xác nhận rõ ràng trong hội thoại.
|
|
731
732
|
5. Xác định project đích trên Backlog/Jira (skill § 5.6, dùng `ak backlog-projects`/`ak jira-projects` + `ak backlog-set-default-project`/`ak jira-set-default-project`).
|
|
732
|
-
6.
|
|
733
|
-
7.
|
|
733
|
+
6. Nếu danh sách có ≥ 2 task, hỏi PM có muốn gộp dưới 1 ticket cha không — tạo mới / dùng sẵn / không cần (skill § 5.6b).
|
|
734
|
+
7. Tạo ticket bằng `ak tasks create-tickets <file>.json --json` (skill § 5.7), kèm `parentTicket` nếu Bước 6 xác định có. Nếu thiếu WRITE credentials, hỏi PM nhập ngay trong chat rồi `ak credentials set <field> "<value>"` và thử lại đúng 1 lần. Nếu lỗi `parent-not-found`/`parent-create-failed`, hiển thị nguyên lỗi và hỏi PM muốn thử ticket cha khác, bỏ qua ticket cha, hay dừng lại.
|
|
735
|
+
8. Ghi ngược link ticket vào entry gốc + hiển thị tổng kết (skill § 5.8).
|
|
734
736
|
8. Run: `ak gate 3 approved --ticket [ticket-id]` để đóng task.
|
|
735
737
|
|
|
736
738
|
> **Telemetry:** Run `ak gate 3 start --ticket [ticket-id]` chỉ khi Bước 2 kết luận CẦN task. Run `ak gate 3 approved --ticket [ticket-id]` khi Gate 3 hoàn tất, hoặc `ak gate 3 skip --ticket [ticket-id] --reason "..."` khi Bước 2 kết luận KHÔNG cần task.
|
|
@@ -59,6 +59,7 @@ DO NOT just check format — **understand the data and propose solutions**.
|
|
|
59
59
|
Only runs after Gate 2 has been APPROVED.
|
|
60
60
|
|
|
61
61
|
**INVOKE:** `train-model` skill
|
|
62
|
+
- **Framework rules (bắt buộc, đọc trước dòng code đầu tiên):** nếu chưa đọc trong session này, đọc đầy đủ file(s) được trỏ ở dòng "> **Rules & code examples:**" đầu CLAUDE.md/AGENTS.md (`.rules/<lang>/<framework>-rules.md` + `-examples.md`). Áp dụng cho MỌI lần sửa code trong Gate này, không chỉ lần đầu.
|
|
62
63
|
- For algorithm-optimization tickets EXTRA: `improve-algorithm` skill
|
|
63
64
|
|
|
64
65
|
**Eval-harness-first rule:** Write the metric/eval harness and establish a reproducible baseline BEFORE iterating on the model. Confirm the baseline runs and is logged — then proceed with tracked experiments.
|