@mind-fold/open-flow 0.1.17 → 0.2.2

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 (40) hide show
  1. package/dist/configurators/templates.d.ts.map +1 -1
  2. package/dist/configurators/templates.js +17 -6
  3. package/dist/configurators/templates.js.map +1 -1
  4. package/dist/configurators/workflow.d.ts.map +1 -1
  5. package/dist/configurators/workflow.js +82 -6
  6. package/dist/configurators/workflow.js.map +1 -1
  7. package/dist/templates/commands/break-loop.txt +107 -0
  8. package/dist/templates/commands/check-cross-layer.txt +153 -0
  9. package/dist/templates/commands/finish-work.txt +129 -0
  10. package/dist/templates/commands/index.d.ts +9 -5
  11. package/dist/templates/commands/index.d.ts.map +1 -1
  12. package/dist/templates/commands/index.js +16 -5
  13. package/dist/templates/commands/index.js.map +1 -1
  14. package/dist/templates/commands/init-agent.txt +100 -9
  15. package/dist/templates/commands/sync-from-runtime.txt +140 -0
  16. package/dist/templates/markdown/flow.md.txt +96 -84
  17. package/dist/templates/markdown/index.d.ts +21 -4
  18. package/dist/templates/markdown/index.d.ts.map +1 -1
  19. package/dist/templates/markdown/index.js +27 -4
  20. package/dist/templates/markdown/index.js.map +1 -1
  21. package/dist/templates/markdown/structure/backend/database-guidelines.md.txt +247 -0
  22. package/dist/templates/markdown/structure/backend/directory-structure.md.txt +153 -0
  23. package/dist/templates/markdown/structure/backend/error-handling.md.txt +257 -0
  24. package/dist/templates/markdown/structure/backend/index.md.txt +88 -0
  25. package/dist/templates/markdown/structure/backend/logging-guidelines.md.txt +212 -0
  26. package/dist/templates/markdown/structure/backend/quality-guidelines.md.txt +219 -0
  27. package/dist/templates/markdown/structure/backend/type-safety.md.txt +192 -0
  28. package/dist/templates/markdown/structure/flows/code-reuse-thinking-guide.md.txt +343 -0
  29. package/dist/templates/markdown/structure/flows/cross-layer-thinking-guide.md.txt +283 -0
  30. package/dist/templates/markdown/structure/flows/index.md.txt +133 -0
  31. package/dist/templates/markdown/structure/flows/pre-implementation-checklist.md.txt +182 -0
  32. package/dist/templates/markdown/structure/flows/spec-flow-template.md.txt +145 -0
  33. package/dist/templates/markdown/structure/frontend/component-guidelines.md.txt +335 -0
  34. package/dist/templates/markdown/structure/frontend/directory-structure.md.txt +172 -0
  35. package/dist/templates/markdown/structure/frontend/hook-guidelines.md.txt +287 -0
  36. package/dist/templates/markdown/structure/frontend/index.md.txt +91 -0
  37. package/dist/templates/markdown/structure/frontend/quality-guidelines.md.txt +274 -0
  38. package/dist/templates/markdown/structure/frontend/state-management.md.txt +293 -0
  39. package/dist/templates/markdown/structure/frontend/type-safety.md.txt +275 -0
  40. package/package.json +2 -2
@@ -0,0 +1,287 @@
1
+ # Hook Guidelines
2
+
3
+ > Query hooks, mutation hooks, and custom hooks patterns
4
+
5
+ ---
6
+
7
+ ## Query Hooks
8
+
9
+ Use React Query for data fetching.
10
+
11
+ ### Basic Query Hook
12
+
13
+ ```typescript
14
+ import { useQuery } from '@tanstack/react-query';
15
+ import { api } from '@/lib/api-client';
16
+ import type { User } from '@/types';
17
+
18
+ export function useUser(userId: string) {
19
+ return useQuery({
20
+ queryKey: ['user', userId],
21
+ queryFn: () => api.users.get(userId),
22
+ enabled: !!userId, // Don't fetch if no userId
23
+ });
24
+ }
25
+
26
+ // Usage
27
+ function UserProfile({ userId }: { userId: string }) {
28
+ const { data: user, isLoading, error } = useUser(userId);
29
+
30
+ if (isLoading) return <Spinner />;
31
+ if (error) return <Error message={error.message} />;
32
+ if (!user) return <NotFound />;
33
+
34
+ return <div>{user.name}</div>;
35
+ }
36
+ ```
37
+
38
+ ### List Query with Pagination
39
+
40
+ ```typescript
41
+ export function useUsers(page: number, pageSize: number = 20) {
42
+ return useQuery({
43
+ queryKey: ['users', { page, pageSize }],
44
+ queryFn: () => api.users.list({ page, pageSize }),
45
+ placeholderData: keepPreviousData, // Keep old data while fetching new
46
+ });
47
+ }
48
+ ```
49
+
50
+ ### Query Key Rules
51
+
52
+ ```typescript
53
+ // ✅ GOOD: Include all dependencies in query key
54
+ queryKey: ['user', userId]
55
+ queryKey: ['users', { page, pageSize, filter }]
56
+ queryKey: ['posts', userId, 'comments']
57
+
58
+ // ❌ BAD: Missing dependencies
59
+ queryKey: ['user'] // Same key for different users!
60
+ queryKey: ['users'] // Same key for different pages!
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Mutation Hooks
66
+
67
+ For create, update, delete operations.
68
+
69
+ ### Basic Mutation
70
+
71
+ ```typescript
72
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
73
+
74
+ export function useUpdateUser() {
75
+ const queryClient = useQueryClient();
76
+
77
+ return useMutation({
78
+ mutationFn: (data: { id: string; name: string }) =>
79
+ api.users.update(data.id, { name: data.name }),
80
+
81
+ onSuccess: (updatedUser) => {
82
+ // Invalidate and refetch
83
+ queryClient.invalidateQueries({ queryKey: ['users'] });
84
+ queryClient.invalidateQueries({ queryKey: ['user', updatedUser.id] });
85
+ },
86
+ });
87
+ }
88
+
89
+ // Usage
90
+ function EditUserForm({ user }: { user: User }) {
91
+ const updateUser = useUpdateUser();
92
+
93
+ const handleSubmit = (data: FormData) => {
94
+ updateUser.mutate(
95
+ { id: user.id, name: data.name },
96
+ {
97
+ onSuccess: () => toast.success('User updated'),
98
+ onError: (error) => toast.error(error.message),
99
+ }
100
+ );
101
+ };
102
+
103
+ return (
104
+ <form onSubmit={handleSubmit}>
105
+ {/* ... */}
106
+ <button disabled={updateUser.isPending}>
107
+ {updateUser.isPending ? 'Saving...' : 'Save'}
108
+ </button>
109
+ </form>
110
+ );
111
+ }
112
+ ```
113
+
114
+ ### Optimistic Updates
115
+
116
+ ```typescript
117
+ export function useToggleFavorite() {
118
+ const queryClient = useQueryClient();
119
+
120
+ return useMutation({
121
+ mutationFn: (postId: string) => api.posts.toggleFavorite(postId),
122
+
123
+ // Optimistically update before server responds
124
+ onMutate: async (postId) => {
125
+ await queryClient.cancelQueries({ queryKey: ['posts'] });
126
+
127
+ const previousPosts = queryClient.getQueryData(['posts']);
128
+
129
+ queryClient.setQueryData(['posts'], (old: Post[]) =>
130
+ old.map(post =>
131
+ post.id === postId
132
+ ? { ...post, isFavorite: !post.isFavorite }
133
+ : post
134
+ )
135
+ );
136
+
137
+ return { previousPosts };
138
+ },
139
+
140
+ // Rollback on error
141
+ onError: (err, postId, context) => {
142
+ queryClient.setQueryData(['posts'], context?.previousPosts);
143
+ },
144
+
145
+ // Always refetch after error or success
146
+ onSettled: () => {
147
+ queryClient.invalidateQueries({ queryKey: ['posts'] });
148
+ },
149
+ });
150
+ }
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Custom Hooks
156
+
157
+ ### State + Logic Encapsulation
158
+
159
+ ```typescript
160
+ export function useToggle(initialValue = false) {
161
+ const [value, setValue] = useState(initialValue);
162
+
163
+ const toggle = useCallback(() => setValue(v => !v), []);
164
+ const setTrue = useCallback(() => setValue(true), []);
165
+ const setFalse = useCallback(() => setValue(false), []);
166
+
167
+ return { value, toggle, setTrue, setFalse };
168
+ }
169
+
170
+ // Usage
171
+ function Dialog() {
172
+ const { value: isOpen, setTrue: open, setFalse: close } = useToggle();
173
+
174
+ return (
175
+ <>
176
+ <button onClick={open}>Open</button>
177
+ {isOpen && <Modal onClose={close} />}
178
+ </>
179
+ );
180
+ }
181
+ ```
182
+
183
+ ### Debounced Value
184
+
185
+ ```typescript
186
+ export function useDebounce<T>(value: T, delay: number): T {
187
+ const [debouncedValue, setDebouncedValue] = useState(value);
188
+
189
+ useEffect(() => {
190
+ const timer = setTimeout(() => setDebouncedValue(value), delay);
191
+ return () => clearTimeout(timer);
192
+ }, [value, delay]);
193
+
194
+ return debouncedValue;
195
+ }
196
+
197
+ // Usage
198
+ function SearchInput() {
199
+ const [query, setQuery] = useState('');
200
+ const debouncedQuery = useDebounce(query, 300);
201
+
202
+ const { data } = useSearch(debouncedQuery);
203
+
204
+ return <input value={query} onChange={e => setQuery(e.target.value)} />;
205
+ }
206
+ ```
207
+
208
+ ### Local Storage
209
+
210
+ ```typescript
211
+ export function useLocalStorage<T>(key: string, initialValue: T) {
212
+ const [storedValue, setStoredValue] = useState<T>(() => {
213
+ if (typeof window === 'undefined') return initialValue;
214
+
215
+ try {
216
+ const item = window.localStorage.getItem(key);
217
+ return item ? JSON.parse(item) : initialValue;
218
+ } catch {
219
+ return initialValue;
220
+ }
221
+ });
222
+
223
+ const setValue = useCallback((value: T | ((val: T) => T)) => {
224
+ setStoredValue(prev => {
225
+ const valueToStore = value instanceof Function ? value(prev) : value;
226
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
227
+ return valueToStore;
228
+ });
229
+ }, [key]);
230
+
231
+ return [storedValue, setValue] as const;
232
+ }
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Best Practices
238
+
239
+ ### DO
240
+
241
+ ```typescript
242
+ // Include all dependencies in query keys
243
+ queryKey: ['user', userId, { includeDetails }]
244
+
245
+ // Handle loading and error states
246
+ if (isLoading) return <Spinner />;
247
+ if (error) return <ErrorDisplay error={error} />;
248
+
249
+ // Use enabled option for conditional fetching
250
+ enabled: !!userId && isAuthenticated
251
+
252
+ // Memoize callbacks in custom hooks
253
+ const toggle = useCallback(() => setValue(v => !v), []);
254
+ ```
255
+
256
+ ### DON'T
257
+
258
+ ```typescript
259
+ // Don't fetch in useEffect
260
+ useEffect(() => {
261
+ fetch('/api/user').then(...) // ❌ Use useQuery instead
262
+ }, []);
263
+
264
+ // Don't ignore error states
265
+ const { data } = useUser(id);
266
+ return <div>{data.name}</div>; // ❌ data might be undefined
267
+
268
+ // Don't mutate query data directly
269
+ data.name = 'New Name'; // ❌ Use mutation
270
+ ```
271
+
272
+ ---
273
+
274
+ ## Hook Naming
275
+
276
+ | Pattern | Name | Example |
277
+ |---------|------|---------|
278
+ | Query single | `use{Entity}` | `useUser` |
279
+ | Query list | `use{Entity}s` | `useUsers` |
280
+ | Mutation create | `useCreate{Entity}` | `useCreateUser` |
281
+ | Mutation update | `useUpdate{Entity}` | `useUpdateUser` |
282
+ | Mutation delete | `useDelete{Entity}` | `useDeleteUser` |
283
+ | Custom utility | `use{Action}` | `useDebounce`, `useToggle` |
284
+
285
+ ---
286
+
287
+ **Language**: All documentation must be written in **English**.
@@ -0,0 +1,91 @@
1
+ # Frontend Development Guidelines
2
+
3
+ > Best practices for frontend development with React
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ This collection of guidelines covers essential patterns and best practices for building robust frontend applications.
10
+
11
+ ---
12
+
13
+ ## Guidelines Index
14
+
15
+ ### Core Patterns
16
+
17
+ | Guide | Description |
18
+ |-------|-------------|
19
+ | [Directory Structure](./directory-structure.md) | Module organization and file layout |
20
+ | [Type Safety](./type-safety.md) | TypeScript patterns, type inference |
21
+ | [Quality Guidelines](./quality-guidelines.md) | Forbidden patterns, code standards |
22
+
23
+ ### React Patterns
24
+
25
+ | Guide | Description |
26
+ |-------|-------------|
27
+ | [Hook Guidelines](./hook-guidelines.md) | Query hooks, mutation hooks, custom hooks |
28
+ | [Component Guidelines](./component-guidelines.md) | Component patterns, semantic HTML, accessibility |
29
+ | [State Management](./state-management.md) | Local state, global state, server state |
30
+
31
+ ---
32
+
33
+ ## Quick Reference
34
+
35
+ ### Directory Structure
36
+
37
+ ```
38
+ src/
39
+ ├── components/ # Shared components
40
+ │ ├── ui/ # Base UI components
41
+ │ └── common/ # Common composite components
42
+
43
+ ├── modules/ # Feature modules
44
+ │ └── {feature}/
45
+ │ ├── components/ # Feature-specific components
46
+ │ ├── hooks/ # Feature-specific hooks
47
+ │ └── types.ts # Feature types
48
+
49
+ ├── hooks/ # Shared hooks
50
+ ├── lib/ # Utilities
51
+ └── types/ # Shared types
52
+ ```
53
+
54
+ ### Key Rules
55
+
56
+ | Rule | Description |
57
+ |------|-------------|
58
+ | Import types from API | Don't redefine backend types |
59
+ | Use semantic HTML | `<button>` not `<div role="button">` |
60
+ | No `any` type | Use `unknown` + type guards |
61
+ | No `!` assertions | Use null checks |
62
+
63
+ ---
64
+
65
+ ## Getting Started
66
+
67
+ 1. **New to this codebase?** Start with [Directory Structure](./directory-structure.md)
68
+ 2. **Writing hooks?** Read [Hook Guidelines](./hook-guidelines.md)
69
+ 3. **Building components?** Read [Component Guidelines](./component-guidelines.md)
70
+ 4. **Before commit?** Check [Quality Guidelines](./quality-guidelines.md)
71
+
72
+ ---
73
+
74
+ ## Common Tasks
75
+
76
+ ### Create a New Feature Module
77
+
78
+ ```bash
79
+ mkdir -p src/modules/{feature}/{components,hooks}
80
+ touch src/modules/{feature}/types.ts
81
+ ```
82
+
83
+ See: [Directory Structure](./directory-structure.md)
84
+
85
+ ### Add a Data Fetching Hook
86
+
87
+ See: [Hook Guidelines](./hook-guidelines.md) - Query Hooks section
88
+
89
+ ---
90
+
91
+ **Language**: All documentation must be written in **English**.
@@ -0,0 +1,274 @@
1
+ # Quality Guidelines
2
+
3
+ > Code standards and forbidden patterns for frontend
4
+
5
+ ---
6
+
7
+ ## Before Every Commit
8
+
9
+ Run these checks before committing:
10
+
11
+ ```bash
12
+ # Must pass with 0 errors
13
+ pnpm lint
14
+
15
+ # Must pass with no type errors
16
+ pnpm type-check
17
+
18
+ # Run tests
19
+ pnpm test
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Forbidden Patterns
25
+
26
+ ### Any Type
27
+
28
+ ```typescript
29
+ // ❌ FORBIDDEN
30
+ function process(data: any) { ... }
31
+ const result: any = await fetch(...);
32
+
33
+ // ✅ REQUIRED
34
+ function process(data: unknown) {
35
+ if (isValidData(data)) {
36
+ // Now data is typed
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### Non-Null Assertions
42
+
43
+ ```typescript
44
+ // ❌ FORBIDDEN
45
+ const name = user!.name;
46
+ const element = document.querySelector('.item')!;
47
+
48
+ // ✅ REQUIRED
49
+ if (!user) return null;
50
+ const name = user.name;
51
+
52
+ const element = document.querySelector('.item');
53
+ if (!element) return;
54
+ ```
55
+
56
+ ### Type Assertions Without Validation
57
+
58
+ ```typescript
59
+ // ❌ FORBIDDEN
60
+ const data = response as UserData;
61
+ const config = JSON.parse(str) as Config;
62
+
63
+ // ✅ REQUIRED
64
+ const data = userDataSchema.parse(response);
65
+ if (!isUserData(response)) throw new Error('Invalid data');
66
+ ```
67
+
68
+ ### Div Instead of Semantic HTML
69
+
70
+ ```typescript
71
+ // ❌ FORBIDDEN
72
+ <div role="button" onClick={handleClick}>Click</div>
73
+ <div onClick={handleNavigate}>Go to page</div>
74
+
75
+ // ✅ REQUIRED
76
+ <button onClick={handleClick}>Click</button>
77
+ <Link href="/page">Go to page</Link>
78
+ ```
79
+
80
+ ### Native img in Next.js
81
+
82
+ ```typescript
83
+ // ❌ FORBIDDEN
84
+ <img src="/photo.jpg" alt="Photo" />
85
+
86
+ // ✅ REQUIRED
87
+ import Image from 'next/image';
88
+ <Image src="/photo.jpg" alt="Photo" width={200} height={200} />
89
+ ```
90
+
91
+ ### useEffect for Data Fetching
92
+
93
+ ```typescript
94
+ // ❌ FORBIDDEN
95
+ useEffect(() => {
96
+ fetch('/api/users')
97
+ .then(res => res.json())
98
+ .then(setUsers);
99
+ }, []);
100
+
101
+ // ✅ REQUIRED
102
+ const { data: users } = useQuery({
103
+ queryKey: ['users'],
104
+ queryFn: () => api.users.list(),
105
+ });
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Required Patterns
111
+
112
+ ### Handle Loading States
113
+
114
+ ```typescript
115
+ // ✅ REQUIRED: Handle all states
116
+ function UserList() {
117
+ const { data, isLoading, error } = useUsers();
118
+
119
+ if (isLoading) return <Skeleton />;
120
+ if (error) return <Error message={error.message} />;
121
+ if (!data?.length) return <Empty />;
122
+
123
+ return <List items={data} />;
124
+ }
125
+ ```
126
+
127
+ ### Accessible Forms
128
+
129
+ ```typescript
130
+ // ✅ REQUIRED: Labels for all inputs
131
+ <label htmlFor="email">Email</label>
132
+ <input id="email" type="email" aria-describedby="email-error" />
133
+ {error && <span id="email-error" role="alert">{error}</span>}
134
+ ```
135
+
136
+ ### Error Boundaries
137
+
138
+ ```typescript
139
+ // ✅ REQUIRED: Wrap feature modules
140
+ <ErrorBoundary fallback={<ErrorFallback />}>
141
+ <FeatureModule />
142
+ </ErrorBoundary>
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Code Style
148
+
149
+ ### Naming Conventions
150
+
151
+ | Type | Convention | Example |
152
+ |------|------------|---------|
153
+ | Components | PascalCase | `UserCard`, `SubmitButton` |
154
+ | Hooks | camelCase with `use` | `useUser`, `useToggle` |
155
+ | Files | kebab-case | `user-card.tsx`, `use-user.ts` |
156
+ | Types | PascalCase | `UserData`, `FormState` |
157
+ | Constants | SCREAMING_SNAKE | `MAX_FILE_SIZE` |
158
+
159
+ ### Component File Structure
160
+
161
+ ```typescript
162
+ // 1. Imports
163
+ import { useState } from 'react';
164
+ import { Button } from '@/components/ui';
165
+
166
+ // 2. Types
167
+ interface Props {
168
+ user: User;
169
+ }
170
+
171
+ // 3. Component
172
+ export function UserCard({ user }: Props) {
173
+ // Hooks first
174
+ const [isOpen, setIsOpen] = useState(false);
175
+
176
+ // Derived state
177
+ const displayName = user.nickname ?? user.name;
178
+
179
+ // Event handlers
180
+ const handleClick = () => setIsOpen(true);
181
+
182
+ // Render
183
+ return (
184
+ <article>
185
+ <h3>{displayName}</h3>
186
+ <Button onClick={handleClick}>View</Button>
187
+ </article>
188
+ );
189
+ }
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Performance
195
+
196
+ ### Memoization
197
+
198
+ ```typescript
199
+ // ✅ Memoize expensive calculations
200
+ const sortedItems = useMemo(
201
+ () => items.sort((a, b) => a.name.localeCompare(b.name)),
202
+ [items]
203
+ );
204
+
205
+ // ✅ Memoize callbacks passed to children
206
+ const handleClick = useCallback(() => {
207
+ doSomething(id);
208
+ }, [id]);
209
+
210
+ // ❌ Don't memoize everything - only when needed
211
+ const name = useMemo(() => user.name, [user.name]); // Unnecessary
212
+ ```
213
+
214
+ ### Avoid Unnecessary Rerenders
215
+
216
+ ```typescript
217
+ // ❌ BAD: Creates new object every render
218
+ <Component style={{ color: 'red' }} />
219
+
220
+ // ✅ GOOD: Stable reference
221
+ const style = { color: 'red' }; // Outside component
222
+ <Component style={style} />
223
+
224
+ // ✅ GOOD: Or use className
225
+ <Component className="text-red" />
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Accessibility Checklist
231
+
232
+ - [ ] All images have alt text
233
+ - [ ] All inputs have labels
234
+ - [ ] Interactive elements are focusable
235
+ - [ ] Color is not the only indicator
236
+ - [ ] Proper heading hierarchy
237
+ - [ ] Keyboard navigation works
238
+
239
+ ---
240
+
241
+ ## Testing Requirements
242
+
243
+ ### What to Test
244
+
245
+ - User interactions (click, type, submit)
246
+ - Error states
247
+ - Loading states
248
+ - Edge cases (empty data, long text)
249
+
250
+ ### What NOT to Test
251
+
252
+ - Implementation details
253
+ - CSS styling
254
+ - Third-party library internals
255
+
256
+ ---
257
+
258
+ ## Checklist
259
+
260
+ Before submitting for review:
261
+
262
+ - [ ] No TypeScript errors (`pnpm type-check`)
263
+ - [ ] No lint errors (`pnpm lint`)
264
+ - [ ] No `any` types
265
+ - [ ] No `!` assertions
266
+ - [ ] Semantic HTML used
267
+ - [ ] Loading/error states handled
268
+ - [ ] Images use Next.js Image
269
+ - [ ] Tests pass
270
+ - [ ] Accessibility basics covered
271
+
272
+ ---
273
+
274
+ **Language**: All documentation must be written in **English**.