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