plan-flow-skill 1.0.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 (124) hide show
  1. package/.claude/commands/create-contract.md +468 -0
  2. package/.claude/commands/create-plan.md +512 -0
  3. package/.claude/commands/discovery-plan.md +561 -0
  4. package/.claude/commands/execute-plan.md +682 -0
  5. package/.claude/commands/review-code.md +459 -0
  6. package/.claude/commands/review-pr.md +651 -0
  7. package/.claude/commands/setup.md +1609 -0
  8. package/.claude/commands/write-tests.md +543 -0
  9. package/.claude/rules/core/allowed-patterns.md +175 -0
  10. package/.claude/rules/core/complexity-scoring.md +225 -0
  11. package/.claude/rules/core/forbidden-patterns.md +253 -0
  12. package/.claude/rules/languages/python-patterns.md +6 -0
  13. package/.claude/rules/languages/typescript-patterns.md +7 -0
  14. package/.claude/rules/patterns/contract-patterns.md +332 -0
  15. package/.claude/rules/patterns/discovery-patterns.md +342 -0
  16. package/.claude/rules/patterns/discovery-templates.md +319 -0
  17. package/.claude/rules/patterns/jest-patterns.md +482 -0
  18. package/.claude/rules/patterns/plans-patterns.md +225 -0
  19. package/.claude/rules/patterns/plans-templates.md +227 -0
  20. package/.claude/rules/patterns/pytest-patterns.md +457 -0
  21. package/.claude/rules/patterns/review-code-templates.md +305 -0
  22. package/.claude/rules/patterns/review-pr-patterns.md +360 -0
  23. package/.claude/rules/tools/auth-pr-tool.md +30 -0
  24. package/.claude/rules/tools/interactive-questions-tool.md +235 -0
  25. package/.claude/rules/tools/jest-testing-tool.md +73 -0
  26. package/.claude/rules/tools/plan-mode-tool.md +164 -0
  27. package/.claude/rules/tools/pytest-testing-tool.md +121 -0
  28. package/.claude/rules/tools/reference-expansion-tool.md +326 -0
  29. package/LICENSE +21 -0
  30. package/README.md +167 -0
  31. package/dist/cli/commands/init.d.ts +6 -0
  32. package/dist/cli/commands/init.d.ts.map +1 -0
  33. package/dist/cli/commands/init.js +139 -0
  34. package/dist/cli/commands/init.js.map +1 -0
  35. package/dist/cli/handlers/claude.d.ts +9 -0
  36. package/dist/cli/handlers/claude.d.ts.map +1 -0
  37. package/dist/cli/handlers/claude.js +119 -0
  38. package/dist/cli/handlers/claude.js.map +1 -0
  39. package/dist/cli/handlers/codex.d.ts +9 -0
  40. package/dist/cli/handlers/codex.d.ts.map +1 -0
  41. package/dist/cli/handlers/codex.js +100 -0
  42. package/dist/cli/handlers/codex.js.map +1 -0
  43. package/dist/cli/handlers/cursor.d.ts +8 -0
  44. package/dist/cli/handlers/cursor.d.ts.map +1 -0
  45. package/dist/cli/handlers/cursor.js +34 -0
  46. package/dist/cli/handlers/cursor.js.map +1 -0
  47. package/dist/cli/handlers/openclaw.d.ts +8 -0
  48. package/dist/cli/handlers/openclaw.d.ts.map +1 -0
  49. package/dist/cli/handlers/openclaw.js +34 -0
  50. package/dist/cli/handlers/openclaw.js.map +1 -0
  51. package/dist/cli/handlers/shared.d.ts +9 -0
  52. package/dist/cli/handlers/shared.d.ts.map +1 -0
  53. package/dist/cli/handlers/shared.js +44 -0
  54. package/dist/cli/handlers/shared.js.map +1 -0
  55. package/dist/cli/index.d.ts +8 -0
  56. package/dist/cli/index.d.ts.map +1 -0
  57. package/dist/cli/index.js +43 -0
  58. package/dist/cli/index.js.map +1 -0
  59. package/dist/cli/types.d.ts +26 -0
  60. package/dist/cli/types.d.ts.map +1 -0
  61. package/dist/cli/types.js +5 -0
  62. package/dist/cli/types.js.map +1 -0
  63. package/dist/cli/utils/files.d.ts +37 -0
  64. package/dist/cli/utils/files.d.ts.map +1 -0
  65. package/dist/cli/utils/files.js +122 -0
  66. package/dist/cli/utils/files.js.map +1 -0
  67. package/dist/cli/utils/logger.d.ts +11 -0
  68. package/dist/cli/utils/logger.d.ts.map +1 -0
  69. package/dist/cli/utils/logger.js +34 -0
  70. package/dist/cli/utils/logger.js.map +1 -0
  71. package/dist/cli/utils/prompts.d.ts +10 -0
  72. package/dist/cli/utils/prompts.d.ts.map +1 -0
  73. package/dist/cli/utils/prompts.js +65 -0
  74. package/dist/cli/utils/prompts.js.map +1 -0
  75. package/dist/test/setup.d.ts +5 -0
  76. package/dist/test/setup.d.ts.map +1 -0
  77. package/dist/test/setup.js +7 -0
  78. package/dist/test/setup.js.map +1 -0
  79. package/package.json +63 -0
  80. package/rules/core/_index.mdc +89 -0
  81. package/rules/core/allowed-patterns.mdc +185 -0
  82. package/rules/core/complexity-scoring.mdc +235 -0
  83. package/rules/core/forbidden-patterns.mdc +263 -0
  84. package/rules/languages/_index.mdc +80 -0
  85. package/rules/languages/python-patterns.mdc +188 -0
  86. package/rules/languages/typescript-patterns.mdc +128 -0
  87. package/rules/patterns/_index.mdc +185 -0
  88. package/rules/patterns/contract-patterns.mdc +344 -0
  89. package/rules/patterns/discovery-patterns.mdc +354 -0
  90. package/rules/patterns/discovery-templates.mdc +329 -0
  91. package/rules/patterns/jest-patterns.mdc +492 -0
  92. package/rules/patterns/plans-patterns.mdc +237 -0
  93. package/rules/patterns/plans-templates.mdc +237 -0
  94. package/rules/patterns/pytest-patterns.mdc +467 -0
  95. package/rules/patterns/review-code-templates.mdc +315 -0
  96. package/rules/patterns/review-pr-patterns.mdc +370 -0
  97. package/rules/skills/_index.mdc +174 -0
  98. package/rules/skills/create-contract-skill.mdc +239 -0
  99. package/rules/skills/create-plan-skill.mdc +271 -0
  100. package/rules/skills/discovery-skill.mdc +295 -0
  101. package/rules/skills/execute-plan-skill.mdc +388 -0
  102. package/rules/skills/review-code-skill.mdc +308 -0
  103. package/rules/skills/review-pr-skill.mdc +496 -0
  104. package/rules/skills/setup-skill.mdc +923 -0
  105. package/rules/skills/write-tests-skill.mdc +294 -0
  106. package/rules/templates/index-template.mdc +126 -0
  107. package/rules/tools/_index.mdc +114 -0
  108. package/rules/tools/auth-pr-tool.mdc +362 -0
  109. package/rules/tools/interactive-questions-tool.mdc +337 -0
  110. package/rules/tools/jest-testing-tool.mdc +96 -0
  111. package/rules/tools/plan-mode-tool.mdc +229 -0
  112. package/rules/tools/pytest-testing-tool.mdc +144 -0
  113. package/rules/tools/reference-expansion-tool.mdc +338 -0
  114. package/skills/plan-flow/SKILL.md +109 -0
  115. package/skills/plan-flow/create-contract/SKILL.md +139 -0
  116. package/skills/plan-flow/create-plan/SKILL.md +93 -0
  117. package/skills/plan-flow/discovery/SKILL.md +85 -0
  118. package/skills/plan-flow/execute-plan/SKILL.md +89 -0
  119. package/skills/plan-flow/review-code/SKILL.md +100 -0
  120. package/skills/plan-flow/review-pr/SKILL.md +122 -0
  121. package/skills/plan-flow/setup/SKILL.md +73 -0
  122. package/skills/plan-flow/write-tests/SKILL.md +115 -0
  123. package/templates/shared/AGENTS.md.template +60 -0
  124. package/templates/shared/CLAUDE.md.template +62 -0
@@ -0,0 +1,482 @@
1
+
2
+ ## File Naming Conventions
3
+
4
+ Tests must follow specific naming conventions based on their execution environment:
5
+
6
+ | Suffix | Environment | Purpose |
7
+ | ------ | ----------- | ------- |
8
+ | `*.client.test.ts` | Client-side (jsdom) | React hooks, components, client utilities |
9
+ | `*.server.test.ts` | Server-side (node) | API routes, commands, server utilities |
10
+ | `*.test.ts` | Default (node) | General utilities without specific environment needs |
11
+ | `*.test.tsx` | JSX support | Components that need JSX in tests |
12
+
13
+ **Examples**:
14
+
15
+ ```
16
+ src/components/chat/MessageInput/useMessageInputLogic.client.test.ts
17
+ src/commands/streamChatCommand.server.test.ts
18
+ src/utils/linkRewriter.client.test.ts
19
+ src/app/api/chat/stream/route.server.test.ts
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Test File Location
25
+
26
+ Place test files next to the code they test (co-location pattern):
27
+
28
+ ```
29
+ src/
30
+ ├── components/
31
+ │ └── chat/
32
+ │ └── MessageInput/
33
+ │ ├── index.tsx
34
+ │ ├── useMessageInputLogic.internal.ts
35
+ │ └── useMessageInputLogic.client.test.ts # Co-located
36
+ ├── commands/
37
+ │ ├── streamChatCommand.ts
38
+ │ └── streamChatCommand.server.test.ts # Co-located
39
+ ├── utils/
40
+ │ ├── linkRewriter.ts
41
+ │ └── linkRewriter.client.test.ts # Co-located
42
+ ```
43
+
44
+ **Why**: Co-location makes tests easy to find, encourages testing, and ensures tests are updated when code changes.
45
+
46
+ ---
47
+
48
+ ## Test Structure
49
+
50
+ Use the **Arrange-Act-Assert** (AAA) pattern with descriptive `describe` and `it` blocks:
51
+
52
+ ```typescript
53
+ describe('streamChatCommand', () => {
54
+ beforeEach(() => {
55
+ jest.clearAllMocks()
56
+ })
57
+
58
+ describe('chat validation', () => {
59
+ it('should throw BadRequestError if chat does not exist', async () => {
60
+ // Arrange
61
+ mockDatabase.findChatWithUsers.mockResolvedValue(null)
62
+
63
+ // Act & Assert
64
+ await expect(streamChatCommand(createValidInput())).rejects.toThrow(
65
+ new BadRequestError(BadRequestReason.NOT_FOUND, { chatId: 'chat-1' }),
66
+ )
67
+
68
+ expect(mockDatabase.findChatWithUsers).toHaveBeenCalledWith('chat-1')
69
+ })
70
+ })
71
+ })
72
+ ```
73
+
74
+ **Guidelines**:
75
+
76
+ - Group related tests in `describe` blocks
77
+ - Use descriptive test names that explain the expected behavior
78
+ - Start test names with "should" for consistency
79
+ - One assertion per test when possible (or related assertions)
80
+
81
+ ---
82
+
83
+ ## Server Test Setup
84
+
85
+ For server-side tests, use the centralized mock setup:
86
+
87
+ ```typescript
88
+ import { mockDatabase } from '@/test-utils/setup-server-test' // MUST be first import
89
+ import { streamChatCommand } from './streamChatCommand'
90
+ import { JupiterEngineAPI } from '@/datasources/JupiterEngineAPI'
91
+ import { BadRequestError, BadRequestReason } from '@/types/errors'
92
+
93
+ // Mock external dependencies
94
+ jest.mock('@/datasources/JupiterEngineAPI')
95
+
96
+ const mockJupiterEngineAPI = JupiterEngineAPI as jest.MockedClass<
97
+ typeof JupiterEngineAPI
98
+ >
99
+
100
+ describe('streamChatCommand', () => {
101
+ beforeEach(() => {
102
+ jest.clearAllMocks()
103
+ })
104
+
105
+ // ... tests
106
+ })
107
+ ```
108
+
109
+ **Critical**: Import `@/test-utils/setup-server-test` **before** any other `@/` imports. This ensures the database mock is hoisted correctly.
110
+
111
+ ---
112
+
113
+ ## Client Test Setup
114
+
115
+ For client-side tests, mock stores and providers explicitly:
116
+
117
+ ```typescript
118
+ import { act, renderHook } from '@testing-library/react'
119
+ import { useMessageInputLogic } from './useMessageInputLogic.internal'
120
+
121
+ // Mock stores
122
+ jest.mock('@/stores/chatStore', () => ({
123
+ useChatStore: jest.fn(),
124
+ }))
125
+
126
+ jest.mock('@/stores/selectedAgentStore', () => ({
127
+ useSelectedAgentStore: jest.fn(),
128
+ }))
129
+
130
+ // Get typed mocks
131
+ const { useChatStore } = jest.requireMock('@/stores/chatStore')
132
+ const { useSelectedAgentStore } = jest.requireMock('@/stores/selectedAgentStore')
133
+
134
+ describe('useMessageInputLogic', () => {
135
+ beforeEach(() => {
136
+ jest.clearAllMocks()
137
+
138
+ // Setup default mock implementations
139
+ useChatStore.mockImplementation((selector) => {
140
+ if (typeof selector === 'function') {
141
+ return selector(mockStoreState)
142
+ }
143
+ return mockStoreState
144
+ })
145
+ })
146
+
147
+ // ... tests
148
+ })
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Mock Factories
154
+
155
+ Use type-safe mock factories from `@/types/mocks` for consistent test data:
156
+
157
+ ```typescript
158
+ import {
159
+ createMockUser,
160
+ createMockChatWithUsers,
161
+ createMockMessageWithUser,
162
+ createMockAgent,
163
+ } from '@/types/mocks'
164
+
165
+ describe('chat feature', () => {
166
+ it('should handle user message', async () => {
167
+ const mockUser = createMockUser({ id: 'user-1', name: 'Test User' })
168
+ const mockChat = createMockChatWithUsers({ tenantId: 'tenant-1' })
169
+ const mockMessage = createMockMessageWithUser({
170
+ id: 'msg-1',
171
+ message: 'Hello, world!',
172
+ })
173
+
174
+ // ... test logic
175
+ })
176
+ })
177
+ ```
178
+
179
+ **Creating Mock Factories**:
180
+
181
+ ```typescript
182
+ // In @/types/mocks.ts
183
+ export const createMockEntity = (overrides?: Partial<Entity>): Entity => ({
184
+ id: 'entity-1',
185
+ name: 'Default Name',
186
+ createdAt: new Date('2024-01-01'),
187
+ // ... all required fields with sensible defaults
188
+ ...overrides, // Allow overrides
189
+ })
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Testing Logic Hooks
195
+
196
+ Test logic hooks in isolation using `renderHook`:
197
+
198
+ ```typescript
199
+ import { renderHook, act } from '@testing-library/react'
200
+ import { useMessageInputLogic } from './useMessageInputLogic.internal'
201
+
202
+ describe('useMessageInputLogic', () => {
203
+ const createBaseProps = (overrides = {}) => ({
204
+ chatId: 'chat-1',
205
+ input: '',
206
+ handleChange: jest.fn(),
207
+ handleSubmit: jest.fn(),
208
+ ...overrides,
209
+ })
210
+
211
+ it('should update input value on change', () => {
212
+ const handleChange = jest.fn()
213
+ const { result } = renderHook(() =>
214
+ useMessageInputLogic(createBaseProps({ handleChange })),
215
+ )
216
+
217
+ act(() => {
218
+ result.current.handleChange({
219
+ target: { value: 'Hello' },
220
+ } as React.ChangeEvent<HTMLTextAreaElement>)
221
+ })
222
+
223
+ expect(handleChange).toHaveBeenCalled()
224
+ })
225
+ })
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Mocking Dependencies
231
+
232
+ ### Mocking Modules
233
+
234
+ ```typescript
235
+ // Full module mock
236
+ jest.mock('@/datasources/JupiterEngineAPI')
237
+
238
+ // Partial module mock
239
+ jest.mock('@/utils/streamProcessing', () => ({
240
+ processAssistantStream: jest.fn(),
241
+ toInputJson: jest.fn((data) => data), // Keep some real implementation
242
+ }))
243
+
244
+ // Typed mock access
245
+ const mockJupiterEngineAPI = JupiterEngineAPI as jest.MockedClass<
246
+ typeof JupiterEngineAPI
247
+ >
248
+ const mockProcessStream = processAssistantStream as jest.MockedFunction<
249
+ typeof processAssistantStream
250
+ >
251
+ ```
252
+
253
+ ### Mocking Class Instances
254
+
255
+ ```typescript
256
+ jest.mock('@/datasources/JupiterEngineAPI')
257
+
258
+ const mockJupiterEngineAPI = JupiterEngineAPI as jest.MockedClass<
259
+ typeof JupiterEngineAPI
260
+ >
261
+
262
+ beforeEach(() => {
263
+ mockJupiterEngineAPI.prototype.streamAgentResponse = jest
264
+ .fn()
265
+ .mockResolvedValue({
266
+ body: {
267
+ tee: () => [mockStream, mockStream],
268
+ },
269
+ })
270
+ })
271
+ ```
272
+
273
+ ### Mocking Zustand Stores
274
+
275
+ ```typescript
276
+ jest.mock('@/stores/chatStore', () => ({
277
+ useChatStore: jest.fn(),
278
+ }))
279
+
280
+ const { useChatStore } = jest.requireMock('@/stores/chatStore')
281
+
282
+ beforeEach(() => {
283
+ useChatStore.mockImplementation((selector) => {
284
+ if (typeof selector === 'function') {
285
+ return selector(mockStoreState)
286
+ }
287
+ return mockStoreState
288
+ })
289
+ })
290
+ ```
291
+
292
+ ---
293
+
294
+ ## Testing Async Code
295
+
296
+ ```typescript
297
+ describe('async operations', () => {
298
+ it('should handle successful async operation', async () => {
299
+ mockDatabase.findChatWithUsers.mockResolvedValue(mockChat)
300
+
301
+ const result = await streamChatCommand(createValidInput())
302
+
303
+ expect(result.stream).toBeDefined()
304
+ })
305
+
306
+ it('should handle async errors', async () => {
307
+ mockDatabase.findChatWithUsers.mockRejectedValue(new Error('DB Error'))
308
+
309
+ await expect(streamChatCommand(createValidInput())).rejects.toThrow('DB Error')
310
+ })
311
+ })
312
+ ```
313
+
314
+ ---
315
+
316
+ ## Testing Error Cases
317
+
318
+ ```typescript
319
+ import { BadRequestError, ForbiddenError, JupiterEngineError } from '@/types/errors'
320
+
321
+ describe('error handling', () => {
322
+ it('should throw BadRequestError for missing chat', async () => {
323
+ mockDatabase.findChatWithUsers.mockResolvedValue(null)
324
+
325
+ await expect(streamChatCommand(createValidInput())).rejects.toThrow(
326
+ new BadRequestError(BadRequestReason.NOT_FOUND, { chatId: 'chat-1' }),
327
+ )
328
+ })
329
+
330
+ it('should throw ForbiddenError for tenant mismatch', async () => {
331
+ mockDatabase.findChatWithUsers.mockResolvedValue(
332
+ createMockChatWithUsers({ tenantId: 'different-tenant' }),
333
+ )
334
+
335
+ await expect(streamChatCommand(createValidInput())).rejects.toThrow(
336
+ new ForbiddenError(ForbiddenReason.INVALID_TENANT_MEMBERSHIP),
337
+ )
338
+ })
339
+ })
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Testing with Input Factories
345
+
346
+ Create factory functions for valid inputs to reduce boilerplate:
347
+
348
+ ```typescript
349
+ const createValidInput = (overrides = {}) => ({
350
+ messages: [
351
+ {
352
+ id: 'msg-1',
353
+ role: 'user' as const,
354
+ parts: [{ type: 'text' as const, text: 'Hello' }],
355
+ },
356
+ ],
357
+ chatId: 'chat-1',
358
+ internalTenantId: 'tenant-1',
359
+ accessToken: 'token-123',
360
+ userId: 'user-1',
361
+ ...overrides,
362
+ })
363
+ ```
364
+
365
+ ---
366
+
367
+ ## Browser API Mocks
368
+
369
+ For client tests requiring browser APIs:
370
+
371
+ ```typescript
372
+ // ResizeObserver mock
373
+ const installResizeObserver = () => {
374
+ const callbacks: ResizeObserverCallback[] = []
375
+
376
+ class MockObserver implements ResizeObserver {
377
+ private callback: ResizeObserverCallback
378
+ constructor(callback: ResizeObserverCallback) {
379
+ this.callback = callback
380
+ callbacks.push(callback)
381
+ }
382
+ observe() {}
383
+ unobserve() {}
384
+ disconnect() {}
385
+ }
386
+
387
+ globalThis.ResizeObserver = MockObserver as unknown as typeof ResizeObserver
388
+ return callbacks
389
+ }
390
+
391
+ // Storage mock (in jest.setup.ts)
392
+ const createMockStorage = () => {
393
+ const storage: Record<string, string> = {}
394
+ return {
395
+ getItem: jest.fn((key) => storage[key] ?? null),
396
+ setItem: jest.fn((key, value) => { storage[key] = value }),
397
+ removeItem: jest.fn((key) => { delete storage[key] }),
398
+ clear: jest.fn(() => Object.keys(storage).forEach(k => delete storage[k])),
399
+ }
400
+ }
401
+ ```
402
+
403
+ ---
404
+
405
+ ## Forbidden Patterns
406
+
407
+ ### DON'T Skip Test Cleanup
408
+
409
+ ```typescript
410
+ // BAD - No cleanup
411
+ it('should handle error', () => {
412
+ jest.spyOn(console, 'error').mockImplementation()
413
+ // Test runs, but spy is never restored
414
+ })
415
+
416
+ // GOOD - Proper cleanup
417
+ it('should handle error', () => {
418
+ const spy = jest.spyOn(console, 'error').mockImplementation()
419
+ // ... test logic
420
+ spy.mockRestore()
421
+ })
422
+ ```
423
+
424
+ ### DON'T Use Implementation Details in Tests
425
+
426
+ ```typescript
427
+ // BAD - Testing implementation
428
+ it('should set internal state', () => {
429
+ const component = render(<MyComponent />)
430
+ expect(component.instance().state.isLoading).toBe(true)
431
+ })
432
+
433
+ // GOOD - Testing behavior
434
+ it('should show loading indicator', () => {
435
+ render(<MyComponent />)
436
+ expect(screen.getByRole('progressbar')).toBeInTheDocument()
437
+ })
438
+ ```
439
+
440
+ ### DON'T Write Tests That Always Pass
441
+
442
+ ```typescript
443
+ // BAD - No real assertion
444
+ it('should work', async () => {
445
+ await someFunction()
446
+ expect(true).toBe(true)
447
+ })
448
+
449
+ // GOOD - Meaningful assertion
450
+ it('should return processed data', async () => {
451
+ const result = await someFunction()
452
+ expect(result.data).toEqual(expectedData)
453
+ })
454
+ ```
455
+
456
+ ### DON'T Ignore Async Behavior
457
+
458
+ ```typescript
459
+ // BAD - Missing await
460
+ it('should fetch data', () => {
461
+ const result = fetchData() // Returns promise, not data!
462
+ expect(result).toBeDefined() // Always passes
463
+ })
464
+
465
+ // GOOD - Proper async handling
466
+ it('should fetch data', async () => {
467
+ const result = await fetchData()
468
+ expect(result.data).toBeDefined()
469
+ })
470
+ ```
471
+
472
+ ---
473
+
474
+ ## Summary
475
+
476
+ Following these testing patterns ensures:
477
+
478
+ - **Consistency**: Same patterns across the codebase
479
+ - **Maintainability**: Tests are easy to understand and update
480
+ - **Reliability**: Tests are isolated and deterministic
481
+ - **Coverage**: Edge cases and errors are tested
482
+ - **Speed**: Tests run efficiently with proper mocking
@@ -0,0 +1,225 @@
1
+
2
+ ## Workflow Folder Structure
3
+
4
+ ```
5
+ flow/
6
+ ├── archive/ # IGNORE - Completed/abandoned plans
7
+ ├── discovery/ # Research, spikes, and exploration
8
+ ├── plans/ # Active implementation plans
9
+ └── references/ # Reference materials (API contracts, specs, designs)
10
+ ```
11
+
12
+ | Folder | Purpose | When to Use |
13
+ | ------------------- | ------------------------------------------ | ---------------------------- |
14
+ | `flow/plans/` | Active implementation plans | Creating new feature plans |
15
+ | `flow/discovery/` | Research, spikes, exploration documents | Investigating before planning|
16
+ | `flow/references/` | Reference materials (API contracts, specs) | Storing documentation |
17
+ | `flow/archive/` | Completed or abandoned plans | After plan completion |
18
+
19
+ ---
20
+
21
+ ## Critical Rule: Ignore Archived Plans
22
+
23
+ **NEVER consider or reference files inside the `flow/archive/` folder.** These are outdated, superseded, or abandoned plans that should not influence current development.
24
+
25
+ ---
26
+
27
+ ## Allowed Patterns
28
+
29
+ ### 1. Store Plans with Snake Case Naming
30
+
31
+ All implementation plans must be created inside `flow/plans/` using snake_case naming with incremental versioning.
32
+
33
+ **Naming Convention**: `plan_<feature_name>_v<version>.md`
34
+
35
+ ---
36
+
37
+ ### 2. Use Discovery Folder for Research
38
+
39
+ Before creating a plan for complex features, create discovery documents in `flow/discovery/`. See `.claude/rules/patterns/discovery-patterns.md` for details.
40
+
41
+ ---
42
+
43
+ ### 3. Create Markdown Files with Required Sections
44
+
45
+ Every plan must include:
46
+
47
+ - **Overview**: Brief description
48
+ - **Goals**: Main objectives
49
+ - **Phases**: Implementation steps with complexity scores
50
+ - **Key Changes**: Summary of modifications
51
+
52
+ See `.claude/rules/patterns/plans-templates.md` for the full template.
53
+
54
+ ---
55
+
56
+ ### 4. Include Key Changes Summary
57
+
58
+ Every plan must end with a "Key Changes" section summarizing the most important modifications.
59
+
60
+ ---
61
+
62
+ ### 5. Follow All Cursor Rules During Execution
63
+
64
+ On every execution of each phase, ensure compliance with all cursor rules:
65
+
66
+ - `.claude/rules/core/allowed-patterns.md` - Follow allowed patterns
67
+ - `.claude/rules/core/forbidden-patterns.md` - Avoid forbidden patterns
68
+
69
+ ---
70
+
71
+ ### 6. Structure Plans with Scoped Phases
72
+
73
+ Every plan must be divided into implementation phases with clear scope boundaries:
74
+
75
+ - **Scope**: What this phase covers
76
+ - **Complexity**: Score from 0-10
77
+ - **Tasks**: Checkboxes for tracking
78
+ - **Build Verification**: Command to verify
79
+
80
+ ---
81
+
82
+ ### 7. Tests Must Be the Last Phase
83
+
84
+ Always schedule testing as the final phase of implementation. Tests validate complete implementation and avoid rewriting during development.
85
+
86
+ ---
87
+
88
+ ### 8. Verify Build Success After Each Phase
89
+
90
+ At the end of each phase, run `npm run build` to ensure no build errors.
91
+
92
+ ---
93
+
94
+ ### 9. Minimize Code in Plan Documents
95
+
96
+ Plans should describe what to implement, not how to code it. Only include code when it serves as an important reference example.
97
+
98
+ ---
99
+
100
+ ### 10. Move Completed Plans to Archive
101
+
102
+ When a plan is fully implemented or no longer relevant:
103
+
104
+ ```bash
105
+ mv flow/plans/plan_feature_name_v1.md flow/archive/
106
+ ```
107
+
108
+ ---
109
+
110
+ ### 11. Assign Complexity Scores to Each Phase
111
+
112
+ Every phase must include a **Complexity Score** from 0-10.
113
+
114
+ See `.claude/rules/core/complexity-scoring.md` for the complete scoring system.
115
+
116
+ ---
117
+
118
+ ### 12. Execute Phases Using Plan Mode
119
+
120
+ When executing a plan, each phase must trigger **Plan mode** before implementation:
121
+
122
+ 1. Use the [Plan Mode Tool](.claude/rules/tools/plan-mode-tool.md) to switch to Plan mode automatically
123
+ 2. Present phase details and approach
124
+ 3. Get user approval
125
+ 4. Implement
126
+ 5. Verify build
127
+ 6. Update progress in plan file
128
+
129
+ **Reference**: See `.claude/rules/tools/plan-mode-tool.md` for complete instructions on switching to Plan mode.
130
+
131
+ ---
132
+
133
+ ## Forbidden Patterns
134
+
135
+ ### 1. DON'T Read or Reference Archived Plans
136
+
137
+ Only reference active plans in the `flow/plans/` folder.
138
+
139
+ ---
140
+
141
+ ### 2. DON'T Create Plans Outside the Workflow Folder
142
+
143
+ Always create plans in the `flow/plans/` folder with proper naming.
144
+
145
+ ---
146
+
147
+ ### 3. DON'T Use Inconsistent Naming
148
+
149
+ Use the pattern `plan_<feature_name>_v<version>.md`.
150
+
151
+ ---
152
+
153
+ ### 4. DON'T Skip the Key Changes Section
154
+
155
+ Always include a "Key Changes" section at the end of the plan.
156
+
157
+ ---
158
+
159
+ ### 5. DON'T Ignore Cursor Rules During Implementation
160
+
161
+ Review and follow all cursor rules during each phase.
162
+
163
+ ---
164
+
165
+ ### 6. DON'T Create Monolithic Plans Without Phases
166
+
167
+ Break down plans into logical, scoped phases.
168
+
169
+ ---
170
+
171
+ ### 7. DON'T Write Tests Before Implementation
172
+
173
+ Tests should always be the last phase.
174
+
175
+ ---
176
+
177
+ ### 8. DON'T Skip Build Verification
178
+
179
+ Add `npm run build` verification at the end of each phase.
180
+
181
+ ---
182
+
183
+ ### 9. DON'T Include Full Implementation Code in Plans
184
+
185
+ Describe what to implement; let the actual code live in source files.
186
+
187
+ ---
188
+
189
+ ### 10. DON'T Skip Complexity Scores
190
+
191
+ Always include a complexity score for each phase.
192
+
193
+ ---
194
+
195
+ ### 11. DON'T Assign Arbitrary Complexity Scores
196
+
197
+ Use the scoring criteria consistently. When in doubt, score higher.
198
+
199
+ ---
200
+
201
+ ### 12. DON'T Execute Phases Without Plan Mode
202
+
203
+ Always switch to Plan mode before executing each phase group. Use the [Plan Mode Tool](.claude/rules/tools/plan-mode-tool.md) to ensure proper switching.
204
+
205
+ ---
206
+
207
+ ### 13. DON'T Mix Discovery and Plans
208
+
209
+ Keep discovery documents in `flow/discovery/` and plans in `flow/plans/`.
210
+
211
+ ---
212
+
213
+ ## Summary
214
+
215
+ Following these planning patterns ensures:
216
+
217
+ - **Discoverability**: All plans in `flow/plans/`, research in `flow/discovery/`
218
+ - **Traceability**: Version history and key changes documentation
219
+ - **Quality**: Cursor rules compliance verified at each phase
220
+ - **Reliability**: Build verification prevents accumulation of errors
221
+ - **Maintainability**: Scoped phases enable incremental, trackable progress
222
+ - **Testability**: Tests as the final phase ensure complete coverage
223
+ - **Clarity**: Archived plans are ignored, only active plans are referenced
224
+ - **Intelligent Pacing**: Complexity scores guide execution strategy
225
+ - **Collaborative Execution**: Plan mode ensures user approval before each phase