codex-genesis-harness 0.1.5 → 0.1.7

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 (178) hide show
  1. package/.codebase/ARCHITECTURE_REVIEW_COMPLETE.md +216 -216
  2. package/.codebase/CURRENT_STATE.md +8 -2
  3. package/.codebase/FILE_NAMING_CLARIFICATION.md +161 -161
  4. package/.codebase/HARNESS_COMPLETENESS_AUDIT.md +613 -613
  5. package/.codebase/IMPLEMENTATION_COMPLETE.md +429 -429
  6. package/.codebase/IMPLEMENTATION_HANDOFF.md +351 -351
  7. package/.codebase/IMPROVEMENTS_SUMMARY.md +419 -419
  8. package/.codebase/PHASE3_SKILLS_NAMING_COMPLETE.md +292 -292
  9. package/.codebase/PHASE_DEPENDENCY_MAP.md +486 -486
  10. package/.codebase/QUICK_START_SPEC_IMPACT.md +456 -456
  11. package/.codebase/README.md +139 -139
  12. package/.codebase/RECOVERY_POINTS.md +83 -438
  13. package/.codebase/beads.json +16 -0
  14. package/.codex/skills/genesis-ai-provider/SKILL.md +1 -1
  15. package/.codex/skills/genesis-api-contract/SKILL.md +1 -1
  16. package/.codex/skills/genesis-api-sync/SKILL.md +354 -354
  17. package/.codex/skills/genesis-api-sync/checklists/api-sync-checklist.md +101 -101
  18. package/.codex/skills/genesis-api-sync/templates/api-change-template.md +257 -257
  19. package/.codex/skills/genesis-architecture/SKILL.md +1 -1
  20. package/.codex/skills/genesis-codebase-map/SKILL.md +1 -1
  21. package/.codex/skills/genesis-debug-guide/SKILL.md +479 -479
  22. package/.codex/skills/genesis-debug-guide/checklists/flaky-test-investigation.md +339 -339
  23. package/.codex/skills/genesis-debug-guide/checklists/production-bug-debug.md +210 -210
  24. package/.codex/skills/genesis-debug-guide/checklists/test-failure-debug.md +158 -158
  25. package/.codex/skills/genesis-debug-guide/observability/debug-commands.md +365 -365
  26. package/.codex/skills/genesis-debug-guide/playbooks/unit-test-failures.md +289 -289
  27. package/.codex/skills/genesis-debug-guide/templates/debug-investigation-log.md +288 -288
  28. package/.codex/skills/genesis-design-spec/SKILL.md +3 -3
  29. package/.codex/skills/genesis-docs-automation/SKILL.md +1003 -1003
  30. package/.codex/skills/genesis-docs-automation/checklists/docs-validation.md +359 -359
  31. package/.codex/skills/genesis-docs-automation/checklists/spec-alignment.md +312 -312
  32. package/.codex/skills/genesis-docs-automation/observability/docs-tracking.md +382 -382
  33. package/.codex/skills/genesis-docs-automation/playbooks/auto-update-flow.md +851 -851
  34. package/.codex/skills/genesis-docs-automation/playbooks/changelog-generation.md +491 -491
  35. package/.codex/skills/genesis-docs-automation/templates/changelog-entry-template.md +187 -187
  36. package/.codex/skills/genesis-docs-automation/templates/handoff-template.md +297 -297
  37. package/.codex/skills/genesis-harness/SKILL.md +1428 -1427
  38. package/.codex/skills/genesis-harness/agents/openai.yaml +7 -7
  39. package/.codex/skills/genesis-harness/checklists/bug-fix-qa.md +169 -169
  40. package/.codex/skills/genesis-harness/checklists/new-feature-qa.md +157 -157
  41. package/.codex/skills/genesis-harness/checklists/refactor-qa.md +216 -216
  42. package/.codex/skills/genesis-harness/checklists/requirements-validation.md +211 -211
  43. package/.codex/skills/genesis-harness/references/planning-schema.md +35 -35
  44. package/.codex/skills/genesis-harness/references/quality-rubric.md +21 -21
  45. package/.codex/skills/genesis-harness/references/research-rubric.md +41 -41
  46. package/.codex/skills/genesis-harness/references/workflows.md +33 -33
  47. package/.codex/skills/genesis-harness/resources/agents-template.md +27 -27
  48. package/.codex/skills/genesis-harness/resources/api-docs-template.md +32 -32
  49. package/.codex/skills/genesis-harness/resources/architecture-template.md +30 -30
  50. package/.codex/skills/genesis-harness/resources/audit-template.md +26 -26
  51. package/.codex/skills/genesis-harness/resources/bug-template.md +34 -34
  52. package/.codex/skills/genesis-harness/resources/change-impact-matrix-template.md +204 -204
  53. package/.codex/skills/genesis-harness/resources/check-template.md +21 -21
  54. package/.codex/skills/genesis-harness/resources/conventions-template.md +42 -42
  55. package/.codex/skills/genesis-harness/resources/decision-template.md +33 -33
  56. package/.codex/skills/genesis-harness/resources/design-template.md +26 -26
  57. package/.codex/skills/genesis-harness/resources/escalation-template.md +21 -21
  58. package/.codex/skills/genesis-harness/resources/feature-template.md +49 -49
  59. package/.codex/skills/genesis-harness/resources/foundation-phase-template.md +131 -131
  60. package/.codex/skills/genesis-harness/resources/integrations-template.md +32 -32
  61. package/.codex/skills/genesis-harness/resources/journeys-template.md +13 -13
  62. package/.codex/skills/genesis-harness/resources/lessons-learned-template.md +12 -12
  63. package/.codex/skills/genesis-harness/resources/observability-template.md +34 -34
  64. package/.codex/skills/genesis-harness/resources/phase-00-foundation-template.md +76 -76
  65. package/.codex/skills/genesis-harness/resources/phase-template.md +34 -34
  66. package/.codex/skills/genesis-harness/resources/pitfalls-template.md +22 -22
  67. package/.codex/skills/genesis-harness/resources/planning-tree-template.md +39 -39
  68. package/.codex/skills/genesis-harness/resources/post-implementation-guide.md +347 -347
  69. package/.codex/skills/genesis-harness/resources/project-template.md +38 -38
  70. package/.codex/skills/genesis-harness/resources/quality-score-template.md +11 -11
  71. package/.codex/skills/genesis-harness/resources/requirements-template.md +26 -26
  72. package/.codex/skills/genesis-harness/resources/research-template.md +26 -26
  73. package/.codex/skills/genesis-harness/resources/review-template.md +22 -22
  74. package/.codex/skills/genesis-harness/resources/spec-changelog-template.md +6 -6
  75. package/.codex/skills/genesis-harness/resources/stack-template.md +33 -33
  76. package/.codex/skills/genesis-harness/resources/verification-template.md +26 -26
  77. package/.codex/skills/genesis-harness/scripts/check-architecture-boundaries.sh +0 -0
  78. package/.codex/skills/genesis-harness/scripts/check-docs-sync.sh +0 -0
  79. package/.codex/skills/genesis-harness/scripts/check-no-debug-logs.sh +0 -0
  80. package/.codex/skills/genesis-harness/scripts/check-required-planning-files.sh +0 -0
  81. package/.codex/skills/genesis-harness/scripts/check-spec-changelog.sh +0 -0
  82. package/.codex/skills/genesis-harness/scripts/check-task-tracking.sh +0 -0
  83. package/.codex/skills/genesis-harness/scripts/compact-context.sh +0 -0
  84. package/.codex/skills/genesis-harness/scripts/create-adr.sh +0 -0
  85. package/.codex/skills/genesis-harness/scripts/create-bug.sh +0 -0
  86. package/.codex/skills/genesis-harness/scripts/create-feature.sh +0 -0
  87. package/.codex/skills/genesis-harness/scripts/detect-stack.sh +0 -0
  88. package/.codex/skills/genesis-harness/scripts/init-planning.sh +0 -0
  89. package/.codex/skills/genesis-harness/scripts/list-changed-files.sh +0 -0
  90. package/.codex/skills/genesis-harness/scripts/offload-log.sh +0 -0
  91. package/.codex/skills/genesis-harness/scripts/run-verification.sh +0 -0
  92. package/.codex/skills/genesis-harness/scripts/run-verify-loop.sh +0 -0
  93. package/.codex/skills/genesis-harness/scripts/update-state.sh +0 -0
  94. package/.codex/skills/genesis-harness-engineering/SKILL.md +1 -1
  95. package/.codex/skills/genesis-new-design/SKILL.md +2 -1
  96. package/.codex/skills/genesis-new-design/agents/openai.yaml +3 -3
  97. package/.codex/skills/genesis-observability-automation/checklists/.gitkeep +0 -0
  98. package/.codex/skills/genesis-observability-automation/observability/.gitkeep +0 -0
  99. package/.codex/skills/genesis-observability-automation/playbooks/.gitkeep +0 -0
  100. package/.codex/skills/genesis-observability-automation/templates/.gitkeep +0 -0
  101. package/.codex/skills/genesis-pipeline-orchestration/SKILL.md +1 -1
  102. package/.codex/skills/genesis-planning/SKILL.md +26 -1
  103. package/.codex/skills/genesis-planning/checklists/mvp-readiness.md +18 -0
  104. package/.codex/skills/genesis-planning/examples/5-phase-roadmap-example.md +43 -0
  105. package/.codex/skills/genesis-planning/templates/phase-1-core.md +17 -0
  106. package/.codex/skills/genesis-planning/templates/phase-2-auth.md +17 -0
  107. package/.codex/skills/genesis-planning/templates/phase-3-features.md +17 -0
  108. package/.codex/skills/genesis-planning/templates/phase-4-integrations.md +17 -0
  109. package/.codex/skills/genesis-planning/templates/phase-5-readiness.md +17 -0
  110. package/.codex/skills/genesis-release/SKILL.md +24 -1
  111. package/.codex/skills/{genesis-release-orchestration → genesis-release}/checklists/post-deployment-verification.md +274 -274
  112. package/.codex/skills/{genesis-release-orchestration → genesis-release}/checklists/pre-release-validation.md +220 -220
  113. package/.codex/skills/{genesis-release-orchestration → genesis-release}/observability/release-tracking.md +253 -253
  114. package/.codex/skills/{genesis-release-orchestration → genesis-release}/playbooks/canary-deployment-orchestration.md +472 -472
  115. package/.codex/skills/{genesis-release-orchestration → genesis-release}/playbooks/semantic-versioning-automation.md +494 -494
  116. package/.codex/skills/{genesis-release-orchestration → genesis-release}/templates/deployment-strategy-template.md +303 -303
  117. package/.codex/skills/{genesis-release-orchestration → genesis-release}/templates/release-runbook-template.md +420 -420
  118. package/.codex/skills/genesis-research-first/SKILL.md +237 -237
  119. package/.codex/skills/genesis-research-first/templates/.gitkeep +0 -0
  120. package/.codex/skills/genesis-spec-propagation/SKILL.md +534 -534
  121. package/.codex/skills/genesis-spec-propagation/checklists/phase-update-verification.md +384 -384
  122. package/.codex/skills/genesis-spec-propagation/checklists/spec-change-detection.md +257 -257
  123. package/.codex/skills/genesis-spec-propagation/observability/propagation-tracking.md +373 -373
  124. package/.codex/skills/genesis-spec-propagation/playbooks/breaking-change-propagation.md +692 -692
  125. package/.codex/skills/genesis-spec-propagation/playbooks/feature-change-propagation.md +434 -434
  126. package/.codex/skills/genesis-spec-propagation/templates/migration-guide-template.md +407 -407
  127. package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/SKILL.md +1 -1
  128. package/.codex/skills/genesis-upgrade-design/agents/openai.yaml +3 -3
  129. package/.codex/skills/spec-impact-engine/SKILL.md +504 -504
  130. package/.codex/skills/spec-impact-engine/detect-spec-changes.sh +0 -0
  131. package/.codex-plugin/plugin.json +19 -19
  132. package/CHANGELOG.md +56 -0
  133. package/LICENSE +22 -22
  134. package/README.EN.md +780 -730
  135. package/README.VI.md +772 -723
  136. package/README.md +102 -247
  137. package/VERSION +2 -2
  138. package/bin/genesis-harness.js +695 -92
  139. package/package.json +9 -3
  140. package/scripts/README.md +342 -342
  141. package/scripts/compact-context.sh +0 -0
  142. package/scripts/contract_integrity_gate.js +83 -0
  143. package/scripts/detect-changes.sh +0 -0
  144. package/scripts/healing_telemetry.js +118 -0
  145. package/scripts/install.sh +5 -6
  146. package/scripts/offload-log.sh +0 -0
  147. package/scripts/prompt_sentinel.js +84 -0
  148. package/scripts/run-evals.sh +20 -24
  149. package/scripts/run-verify-loop.sh +11 -0
  150. package/scripts/spec_visual_sync.js +157 -0
  151. package/scripts/test_generator.js +142 -0
  152. package/scripts/transition_state.sh +0 -0
  153. package/scripts/uninstall.sh +2 -5
  154. package/scripts/validation_gates.sh +40 -1
  155. package/scripts/verify.sh +6 -61
  156. package/tests/unit/contract_integrity_gate.test.js +74 -0
  157. package/tests/unit/healing_telemetry.test.js +58 -0
  158. package/tests/unit/prompt_sentinel.test.js +50 -0
  159. package/tests/unit/spec_visual_sync.test.js +77 -0
  160. package/tests/unit/test_generator.test.js +62 -0
  161. package/.codex/skills/genesis-docs/SKILL.md +0 -46
  162. package/.codex/skills/genesis-docs/agents/openai.yaml +0 -7
  163. package/.codex/skills/genesis-release-orchestration/SKILL.md +0 -653
  164. package/.codex/skills/genesis-release-orchestration/agents/openai.yaml +0 -7
  165. package/.codex/skills/genesis-research/SKILL.md +0 -46
  166. package/.codex/skills/genesis-research/agents/openai.yaml +0 -7
  167. /package/.codex/skills/{genesis-docs/checklists/checklist.md → genesis-docs-automation/checklists/manual-docs-checklist.md} +0 -0
  168. /package/.codex/skills/{genesis-docs/examples/example.md → genesis-docs-automation/examples/manual-docs-example.md} +0 -0
  169. /package/.codex/skills/{genesis-docs → genesis-docs-automation}/templates/docs-update-template.md +0 -0
  170. /package/.codex/skills/{genesis-state-machine/SKILL.md → genesis-harness/references/state-machine.md} +0 -0
  171. /package/.codex/skills/{genesis-release-orchestration/examples/example.md → genesis-release/examples/orchestration-example.md} +0 -0
  172. /package/.codex/skills/{genesis-research → genesis-research-first}/checklists/checklist.md +0 -0
  173. /package/.codex/skills/{genesis-research/examples/example.md → genesis-research-first/examples/manual-research-example.md} +0 -0
  174. /package/.codex/skills/{genesis-research → genesis-research-first}/templates/research-note-template.md +0 -0
  175. /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/agents/openai.yaml +0 -0
  176. /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/checklists/checklist.md +0 -0
  177. /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/examples/example.md +0 -0
  178. /package/.codex/skills/{ui-ux-test-skill → genesis-ui-ux-test}/templates/playwright-test-template.md +0 -0
@@ -1,339 +1,339 @@
1
- # Flaky Test Investigation Checklist
2
-
3
- **Purpose**: Systematic debugging for tests that fail intermittently. These are notoriously hard to fix but follow patterns.
4
-
5
- **Status**: MANDATORY - Complete before attempting flaky test fix.
6
-
7
- ## Characteristics: Is It Actually Flaky?
8
-
9
- - [ ] **Fails inconsistently**:
10
- - Run test 10 times: `for i in {1..10}; do npm test -- test.js; done`
11
- - Fails ~X times out of 10
12
- - Not always the same assertion fails
13
- - Not 0% or 100% (if always fails, see test-failure-debug.md)
14
-
15
- - [ ] **Failure pattern exists**:
16
- - Fails more often under load?
17
- - Fails in CI but not locally?
18
- - Fails after other tests?
19
- - Fails at specific time of day?
20
-
21
- - [ ] **Previous attempts failed**:
22
- - Simple retry didn't fix it
23
- - Disabling parallelization didn't fix it
24
- - Increasing timeout didn't fix it
25
-
26
- ---
27
-
28
- ## Root Cause Pattern Analysis
29
-
30
- ### Pattern 1: Race Condition (Most Common)
31
- ```javascript
32
- // ❌ WRONG: Race condition
33
- test('user updates profile', async () => {
34
- updateUser({ name: 'New Name' }); // Async, not awaited!
35
- expect(userName).toBe('New Name'); // Might run before update completes
36
- });
37
-
38
- // ✅ CORRECT: Wait for async operation
39
- test('user updates profile', async () => {
40
- await updateUser({ name: 'New Name' }); // Wait for it
41
- expect(userName).toBe('New Name');
42
- });
43
- ```
44
-
45
- **Signs**:
46
- - [ ] Test has async operations
47
- - [ ] Not all async operations awaited
48
- - [ ] Uses `setTimeout` or `setInterval`
49
- - [ ] Fails under high CPU load
50
- - [ ] Fails more in CI (slower machines)
51
-
52
- **Fix**:
53
- ```javascript
54
- // Add explicit waits
55
- await waitFor(() => expect(element).toBeVisible());
56
-
57
- // Use async/await properly
58
- const result = await asyncFunction();
59
-
60
- // Don't mix promises with callbacks
61
- // Use either async/await OR .then(), not both
62
- ```
63
-
64
- ### Pattern 2: Test Order Dependency
65
- ```javascript
66
- // ❌ WRONG: Tests affect each other
67
- let globalState = 0;
68
- test('first test', () => { globalState = 1; });
69
- test('second test', () => { expect(globalState).toBe(0); }); // Fails if first runs first!
70
-
71
- // ✅ CORRECT: Each test is isolated
72
- beforeEach(() => { state = 0; }); // Reset before each test
73
- test('first test', () => { state = 1; });
74
- test('second test', () => { expect(state).toBe(0); });
75
- ```
76
-
77
- **Signs**:
78
- - [ ] Test passes when run alone
79
- - [ ] Test fails when run with others
80
- - [ ] Test fails when run in random order
81
- - [ ] Global variables used
82
- - [ ] Database not cleaned between tests
83
-
84
- **Fix**:
85
- ```javascript
86
- beforeEach(() => {
87
- // Reset all state
88
- jest.clearAllMocks();
89
- db.clear();
90
- localStorage.clear();
91
- });
92
- ```
93
-
94
- ### Pattern 3: Timing Issues
95
- ```javascript
96
- // ❌ WRONG: Fixed timeout too short
97
- test('animation completes', async () => {
98
- await new Promise(r => setTimeout(r, 50)); // Sometimes not enough time
99
- expect(element.style.opacity).toBe(1);
100
- });
101
-
102
- // ✅ CORRECT: Wait for actual condition
103
- test('animation completes', async () => {
104
- await waitFor(() => expect(element).toHaveStyle('opacity: 1'), { timeout: 5000 });
105
- });
106
- ```
107
-
108
- **Signs**:
109
- - [ ] Uses `setTimeout` with fixed delays
110
- - [ ] Fails randomly
111
- - [ ] Fails when machine is busy
112
- - [ ] Fails in CI (which is slower)
113
- - [ ] Increasing timeout "fixes" it temporarily
114
-
115
- **Fix**:
116
- ```javascript
117
- // Instead of sleep:
118
- await new Promise(r => setTimeout(r, 100));
119
-
120
- // Use condition-based waiting:
121
- await waitFor(() => expect(element).toBeVisible());
122
- ```
123
-
124
- ### Pattern 4: External Service/Network
125
- ```javascript
126
- // ❌ WRONG: Calls actual API
127
- test('fetch user', async () => {
128
- const user = await fetchRealAPI('/users/1'); // Network unreliable!
129
- expect(user.name).toBe('John');
130
- });
131
-
132
- // ✅ CORRECT: Mock external service
133
- test('fetch user', async () => {
134
- jest.mock('api', () => ({
135
- fetch: jest.fn().mockResolvedValue({ name: 'John' })
136
- }));
137
- const user = await fetchUser(1);
138
- expect(user.name).toBe('John');
139
- });
140
- ```
141
-
142
- **Signs**:
143
- - [ ] Test makes network requests
144
- - [ ] Mock not configured properly
145
- - [ ] Network-dependent test
146
- - [ ] Fails in offline environment
147
- - [ ] Fails randomly (network issues)
148
-
149
- **Fix**:
150
- ```javascript
151
- // Mock all external APIs
152
- jest.mock('node-fetch');
153
- nodeFetch.mockResolvedValue({ json: () => ({ ... }) });
154
- ```
155
-
156
- ### Pattern 5: Randomness/Seeding
157
- ```javascript
158
- // ❌ WRONG: Random data without seed
159
- test('shuffle array', () => {
160
- const result = shuffle([1, 2, 3]);
161
- expect(result).toEqual([2, 1, 3]); // Different order each time!
162
- });
163
-
164
- // ✅ CORRECT: Seed random for reproducible tests
165
- test('shuffle array', () => {
166
- Math.seedrandom = () => 0.5; // Set seed
167
- const result = shuffle([1, 2, 3]);
168
- expect(result).toEqual([3, 1, 2]); // Same every time with same seed
169
- });
170
- ```
171
-
172
- **Signs**:
173
- - [ ] Test uses `Math.random()`
174
- - [ ] Test uses `Date.now()`
175
- - [ ] Test uses `UUID.generate()`
176
- - [ ] Different assertions fail each run
177
- - [ ] Works locally but fails in CI
178
-
179
- **Fix**:
180
- ```javascript
181
- // Seed random number generator
182
- beforeEach(() => {
183
- jest.spyOn(Math, 'random').mockReturnValue(0.5);
184
- });
185
-
186
- // Mock Date.now()
187
- jest.spyOn(Date, 'now').mockReturnValue(1234567890);
188
-
189
- // Generate UUIDs deterministically
190
- jest.mock('uuid', () => ({ v4: () => 'test-uuid-123' }));
191
- ```
192
-
193
- ---
194
-
195
- ## Investigation Checklist
196
-
197
- ### Documentation
198
- - [ ] When test was added
199
- - [ ] When it started failing
200
- - [ ] Failure frequency recorded
201
- - [ ] Specific assertion that fails (changes?)
202
-
203
- ### Reproduction
204
- - [ ] Test fails when run 10 times in sequence
205
- - [ ] Test fails when run in random order with others
206
- - [ ] Test fails in CI but not locally (or vice versa)
207
- - [ ] Test fails under high system load
208
-
209
- ### Code Analysis
210
- - [ ] All async operations have `await`
211
- - [ ] No global state modifications
212
- - [ ] All mocks are configured
213
- - [ ] No `setTimeout` with fixed delays
214
- - [ ] No external service calls
215
- - [ ] No random values without seeding
216
-
217
- ### Environment
218
- - [ ] Node version documented (local vs CI)
219
- - [ ] Operating system noted (different on CI?)
220
- - [ ] CI environment variables checked
221
- - [ ] Parallelization disabled for test
222
- - [ ] Test isolation verified
223
-
224
- ### Fix Validation
225
- - [ ] Test passes 20 times consecutively
226
- - [ ] Test passes in random order with other tests
227
- - [ ] Test passes in CI
228
- - [ ] Test passes under load
229
- - [ ] No other tests broken
230
-
231
- ---
232
-
233
- ## Debugging Strategy
234
-
235
- ### If Pattern 1: Race Condition
236
- ```bash
237
- # Add debug logging to see timing
238
- npm test -- --verbose path/to/test.js
239
-
240
- # Add explicit waits
241
- await new Promise(r => setTimeout(r, 100));
242
-
243
- # Use waitFor with debug
244
- await waitFor(() => {
245
- console.log('Checking condition...');
246
- expect(element).toBeVisible();
247
- });
248
- ```
249
-
250
- ### If Pattern 2: Test Order Dependency
251
- ```bash
252
- # Run tests in random order
253
- npm test -- --randomize path/to/test.js
254
-
255
- # Run test alone vs with others
256
- npm test -- test1.js test2.js test3.js # Together
257
- npm test -- test2.js # Alone
258
-
259
- # Check beforeEach/afterEach setup
260
- ```
261
-
262
- ### If Pattern 3: Timing Issues
263
- ```bash
264
- # Check system load
265
- # Monitor: CPU, Memory, Disk I/O during test run
266
-
267
- # Increase timeouts
268
- await waitFor(() => expect(...), { timeout: 10000 });
269
-
270
- # Replace sleep with condition
271
- // Instead of: await sleep(1000);
272
- await waitFor(() => expect(element).toBeVisible());
273
- ```
274
-
275
- ### If Pattern 4: External Service
276
- ```bash
277
- # Verify all external calls are mocked
278
- grep -r "fetch\|axios\|http" src/__tests__/
279
-
280
- # Check mock setup
281
- console.log(jest.mock(...));
282
- ```
283
-
284
- ### If Pattern 5: Randomness
285
- ```bash
286
- # Set seed for randomness
287
- jest.spyOn(Math, 'random').mockReturnValue(0.5);
288
-
289
- # Mock Date.now()
290
- jest.spyOn(Date, 'now').mockReturnValue(1234567890);
291
-
292
- # Use deterministic test data
293
- const testUser = { id: '123', name: 'Test' }; // Same each time
294
- ```
295
-
296
- ---
297
-
298
- ## Verification: Flaky Test Fixed
299
-
300
- - [ ] Test passes 20 times consecutively
301
- - [ ] Test passes 20 times in random order
302
- - [ ] Test passes in CI environment
303
- - [ ] Test passes under system load
304
- - [ ] No debug code left
305
- - [ ] Updated RECOVERY_POINTS.md with pattern
306
- - [ ] Similar tests checked for same issue
307
-
308
- ---
309
-
310
- ## Recovery: Still Flaky?
311
-
312
- If still failing after fixes:
313
-
314
- 1. **Add extensive logging**:
315
- ```javascript
316
- test('flaky test', async () => {
317
- console.log('Start:', Date.now());
318
- const value = getSomeValue();
319
- console.log('Value:', value);
320
- await waitForCondition();
321
- console.log('Condition met:', Date.now());
322
- expect(...).toBe(...);
323
- });
324
- ```
325
-
326
- 2. **Disable test temporarily**:
327
- ```javascript
328
- test.skip('flaky test', async () => { // Temporarily skip
329
- // ...
330
- });
331
- ```
332
-
333
- 3. **Escalate**: Mark test with TODO comment for team
334
- ```javascript
335
- // TODO: Fix flaky test - likely timing issue, investigate when time permits
336
- test.skip('should handle concurrent updates', async () => {
337
- ```
338
-
339
- 4. **Create issue**: Document flaky test pattern for future fix
1
+ # Flaky Test Investigation Checklist
2
+
3
+ **Purpose**: Systematic debugging for tests that fail intermittently. These are notoriously hard to fix but follow patterns.
4
+
5
+ **Status**: MANDATORY - Complete before attempting flaky test fix.
6
+
7
+ ## Characteristics: Is It Actually Flaky?
8
+
9
+ - [ ] **Fails inconsistently**:
10
+ - Run test 10 times: `for i in {1..10}; do npm test -- test.js; done`
11
+ - Fails ~X times out of 10
12
+ - Not always the same assertion fails
13
+ - Not 0% or 100% (if always fails, see test-failure-debug.md)
14
+
15
+ - [ ] **Failure pattern exists**:
16
+ - Fails more often under load?
17
+ - Fails in CI but not locally?
18
+ - Fails after other tests?
19
+ - Fails at specific time of day?
20
+
21
+ - [ ] **Previous attempts failed**:
22
+ - Simple retry didn't fix it
23
+ - Disabling parallelization didn't fix it
24
+ - Increasing timeout didn't fix it
25
+
26
+ ---
27
+
28
+ ## Root Cause Pattern Analysis
29
+
30
+ ### Pattern 1: Race Condition (Most Common)
31
+ ```javascript
32
+ // ❌ WRONG: Race condition
33
+ test('user updates profile', async () => {
34
+ updateUser({ name: 'New Name' }); // Async, not awaited!
35
+ expect(userName).toBe('New Name'); // Might run before update completes
36
+ });
37
+
38
+ // ✅ CORRECT: Wait for async operation
39
+ test('user updates profile', async () => {
40
+ await updateUser({ name: 'New Name' }); // Wait for it
41
+ expect(userName).toBe('New Name');
42
+ });
43
+ ```
44
+
45
+ **Signs**:
46
+ - [ ] Test has async operations
47
+ - [ ] Not all async operations awaited
48
+ - [ ] Uses `setTimeout` or `setInterval`
49
+ - [ ] Fails under high CPU load
50
+ - [ ] Fails more in CI (slower machines)
51
+
52
+ **Fix**:
53
+ ```javascript
54
+ // Add explicit waits
55
+ await waitFor(() => expect(element).toBeVisible());
56
+
57
+ // Use async/await properly
58
+ const result = await asyncFunction();
59
+
60
+ // Don't mix promises with callbacks
61
+ // Use either async/await OR .then(), not both
62
+ ```
63
+
64
+ ### Pattern 2: Test Order Dependency
65
+ ```javascript
66
+ // ❌ WRONG: Tests affect each other
67
+ let globalState = 0;
68
+ test('first test', () => { globalState = 1; });
69
+ test('second test', () => { expect(globalState).toBe(0); }); // Fails if first runs first!
70
+
71
+ // ✅ CORRECT: Each test is isolated
72
+ beforeEach(() => { state = 0; }); // Reset before each test
73
+ test('first test', () => { state = 1; });
74
+ test('second test', () => { expect(state).toBe(0); });
75
+ ```
76
+
77
+ **Signs**:
78
+ - [ ] Test passes when run alone
79
+ - [ ] Test fails when run with others
80
+ - [ ] Test fails when run in random order
81
+ - [ ] Global variables used
82
+ - [ ] Database not cleaned between tests
83
+
84
+ **Fix**:
85
+ ```javascript
86
+ beforeEach(() => {
87
+ // Reset all state
88
+ jest.clearAllMocks();
89
+ db.clear();
90
+ localStorage.clear();
91
+ });
92
+ ```
93
+
94
+ ### Pattern 3: Timing Issues
95
+ ```javascript
96
+ // ❌ WRONG: Fixed timeout too short
97
+ test('animation completes', async () => {
98
+ await new Promise(r => setTimeout(r, 50)); // Sometimes not enough time
99
+ expect(element.style.opacity).toBe(1);
100
+ });
101
+
102
+ // ✅ CORRECT: Wait for actual condition
103
+ test('animation completes', async () => {
104
+ await waitFor(() => expect(element).toHaveStyle('opacity: 1'), { timeout: 5000 });
105
+ });
106
+ ```
107
+
108
+ **Signs**:
109
+ - [ ] Uses `setTimeout` with fixed delays
110
+ - [ ] Fails randomly
111
+ - [ ] Fails when machine is busy
112
+ - [ ] Fails in CI (which is slower)
113
+ - [ ] Increasing timeout "fixes" it temporarily
114
+
115
+ **Fix**:
116
+ ```javascript
117
+ // Instead of sleep:
118
+ await new Promise(r => setTimeout(r, 100));
119
+
120
+ // Use condition-based waiting:
121
+ await waitFor(() => expect(element).toBeVisible());
122
+ ```
123
+
124
+ ### Pattern 4: External Service/Network
125
+ ```javascript
126
+ // ❌ WRONG: Calls actual API
127
+ test('fetch user', async () => {
128
+ const user = await fetchRealAPI('/users/1'); // Network unreliable!
129
+ expect(user.name).toBe('John');
130
+ });
131
+
132
+ // ✅ CORRECT: Mock external service
133
+ test('fetch user', async () => {
134
+ jest.mock('api', () => ({
135
+ fetch: jest.fn().mockResolvedValue({ name: 'John' })
136
+ }));
137
+ const user = await fetchUser(1);
138
+ expect(user.name).toBe('John');
139
+ });
140
+ ```
141
+
142
+ **Signs**:
143
+ - [ ] Test makes network requests
144
+ - [ ] Mock not configured properly
145
+ - [ ] Network-dependent test
146
+ - [ ] Fails in offline environment
147
+ - [ ] Fails randomly (network issues)
148
+
149
+ **Fix**:
150
+ ```javascript
151
+ // Mock all external APIs
152
+ jest.mock('node-fetch');
153
+ nodeFetch.mockResolvedValue({ json: () => ({ ... }) });
154
+ ```
155
+
156
+ ### Pattern 5: Randomness/Seeding
157
+ ```javascript
158
+ // ❌ WRONG: Random data without seed
159
+ test('shuffle array', () => {
160
+ const result = shuffle([1, 2, 3]);
161
+ expect(result).toEqual([2, 1, 3]); // Different order each time!
162
+ });
163
+
164
+ // ✅ CORRECT: Seed random for reproducible tests
165
+ test('shuffle array', () => {
166
+ Math.seedrandom = () => 0.5; // Set seed
167
+ const result = shuffle([1, 2, 3]);
168
+ expect(result).toEqual([3, 1, 2]); // Same every time with same seed
169
+ });
170
+ ```
171
+
172
+ **Signs**:
173
+ - [ ] Test uses `Math.random()`
174
+ - [ ] Test uses `Date.now()`
175
+ - [ ] Test uses `UUID.generate()`
176
+ - [ ] Different assertions fail each run
177
+ - [ ] Works locally but fails in CI
178
+
179
+ **Fix**:
180
+ ```javascript
181
+ // Seed random number generator
182
+ beforeEach(() => {
183
+ jest.spyOn(Math, 'random').mockReturnValue(0.5);
184
+ });
185
+
186
+ // Mock Date.now()
187
+ jest.spyOn(Date, 'now').mockReturnValue(1234567890);
188
+
189
+ // Generate UUIDs deterministically
190
+ jest.mock('uuid', () => ({ v4: () => 'test-uuid-123' }));
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Investigation Checklist
196
+
197
+ ### Documentation
198
+ - [ ] When test was added
199
+ - [ ] When it started failing
200
+ - [ ] Failure frequency recorded
201
+ - [ ] Specific assertion that fails (changes?)
202
+
203
+ ### Reproduction
204
+ - [ ] Test fails when run 10 times in sequence
205
+ - [ ] Test fails when run in random order with others
206
+ - [ ] Test fails in CI but not locally (or vice versa)
207
+ - [ ] Test fails under high system load
208
+
209
+ ### Code Analysis
210
+ - [ ] All async operations have `await`
211
+ - [ ] No global state modifications
212
+ - [ ] All mocks are configured
213
+ - [ ] No `setTimeout` with fixed delays
214
+ - [ ] No external service calls
215
+ - [ ] No random values without seeding
216
+
217
+ ### Environment
218
+ - [ ] Node version documented (local vs CI)
219
+ - [ ] Operating system noted (different on CI?)
220
+ - [ ] CI environment variables checked
221
+ - [ ] Parallelization disabled for test
222
+ - [ ] Test isolation verified
223
+
224
+ ### Fix Validation
225
+ - [ ] Test passes 20 times consecutively
226
+ - [ ] Test passes in random order with other tests
227
+ - [ ] Test passes in CI
228
+ - [ ] Test passes under load
229
+ - [ ] No other tests broken
230
+
231
+ ---
232
+
233
+ ## Debugging Strategy
234
+
235
+ ### If Pattern 1: Race Condition
236
+ ```bash
237
+ # Add debug logging to see timing
238
+ npm test -- --verbose path/to/test.js
239
+
240
+ # Add explicit waits
241
+ await new Promise(r => setTimeout(r, 100));
242
+
243
+ # Use waitFor with debug
244
+ await waitFor(() => {
245
+ console.log('Checking condition...');
246
+ expect(element).toBeVisible();
247
+ });
248
+ ```
249
+
250
+ ### If Pattern 2: Test Order Dependency
251
+ ```bash
252
+ # Run tests in random order
253
+ npm test -- --randomize path/to/test.js
254
+
255
+ # Run test alone vs with others
256
+ npm test -- test1.js test2.js test3.js # Together
257
+ npm test -- test2.js # Alone
258
+
259
+ # Check beforeEach/afterEach setup
260
+ ```
261
+
262
+ ### If Pattern 3: Timing Issues
263
+ ```bash
264
+ # Check system load
265
+ # Monitor: CPU, Memory, Disk I/O during test run
266
+
267
+ # Increase timeouts
268
+ await waitFor(() => expect(...), { timeout: 10000 });
269
+
270
+ # Replace sleep with condition
271
+ // Instead of: await sleep(1000);
272
+ await waitFor(() => expect(element).toBeVisible());
273
+ ```
274
+
275
+ ### If Pattern 4: External Service
276
+ ```bash
277
+ # Verify all external calls are mocked
278
+ grep -r "fetch\|axios\|http" src/__tests__/
279
+
280
+ # Check mock setup
281
+ console.log(jest.mock(...));
282
+ ```
283
+
284
+ ### If Pattern 5: Randomness
285
+ ```bash
286
+ # Set seed for randomness
287
+ jest.spyOn(Math, 'random').mockReturnValue(0.5);
288
+
289
+ # Mock Date.now()
290
+ jest.spyOn(Date, 'now').mockReturnValue(1234567890);
291
+
292
+ # Use deterministic test data
293
+ const testUser = { id: '123', name: 'Test' }; // Same each time
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Verification: Flaky Test Fixed
299
+
300
+ - [ ] Test passes 20 times consecutively
301
+ - [ ] Test passes 20 times in random order
302
+ - [ ] Test passes in CI environment
303
+ - [ ] Test passes under system load
304
+ - [ ] No debug code left
305
+ - [ ] Updated RECOVERY_POINTS.md with pattern
306
+ - [ ] Similar tests checked for same issue
307
+
308
+ ---
309
+
310
+ ## Recovery: Still Flaky?
311
+
312
+ If still failing after fixes:
313
+
314
+ 1. **Add extensive logging**:
315
+ ```javascript
316
+ test('flaky test', async () => {
317
+ console.log('Start:', Date.now());
318
+ const value = getSomeValue();
319
+ console.log('Value:', value);
320
+ await waitForCondition();
321
+ console.log('Condition met:', Date.now());
322
+ expect(...).toBe(...);
323
+ });
324
+ ```
325
+
326
+ 2. **Disable test temporarily**:
327
+ ```javascript
328
+ test.skip('flaky test', async () => { // Temporarily skip
329
+ // ...
330
+ });
331
+ ```
332
+
333
+ 3. **Escalate**: Mark test with TODO comment for team
334
+ ```javascript
335
+ // TODO: Fix flaky test - likely timing issue, investigate when time permits
336
+ test.skip('should handle concurrent updates', async () => {
337
+ ```
338
+
339
+ 4. **Create issue**: Document flaky test pattern for future fix