edsger 0.51.0 → 0.53.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 (188) hide show
  1. package/.claude/settings.local.json +23 -3
  2. package/.env.local +12 -0
  3. package/dist/commands/find-smells/index.d.ts +21 -0
  4. package/dist/commands/find-smells/index.js +65 -0
  5. package/dist/index.js +29 -0
  6. package/dist/phases/find-bugs/index.js +7 -92
  7. package/dist/phases/find-bugs/state.d.ts +10 -35
  8. package/dist/phases/find-bugs/state.js +12 -120
  9. package/dist/phases/find-features/index.js +16 -83
  10. package/dist/phases/find-features/prompts.d.ts +7 -1
  11. package/dist/phases/find-features/prompts.js +31 -11
  12. package/dist/phases/find-features/state.d.ts +15 -19
  13. package/dist/phases/find-features/state.js +17 -89
  14. package/dist/phases/find-features/types.d.ts +1 -1
  15. package/dist/phases/find-shared/git.d.ts +24 -0
  16. package/dist/phases/find-shared/git.js +60 -0
  17. package/dist/phases/find-shared/mcp.d.ts +33 -0
  18. package/dist/phases/find-shared/mcp.js +69 -0
  19. package/dist/phases/find-shared/scan-state.d.ts +33 -0
  20. package/dist/phases/find-shared/scan-state.js +112 -0
  21. package/dist/phases/find-smells/index.d.ts +47 -0
  22. package/dist/phases/find-smells/index.js +278 -0
  23. package/dist/phases/find-smells/prompts.d.ts +30 -0
  24. package/dist/phases/find-smells/prompts.js +129 -0
  25. package/dist/phases/find-smells/state.d.ts +21 -0
  26. package/dist/phases/find-smells/state.js +17 -0
  27. package/dist/phases/find-smells/types.d.ts +51 -0
  28. package/dist/phases/find-smells/types.js +64 -0
  29. package/dist/phases/pr-execution/context.js +40 -32
  30. package/dist/phases/pr-splitting/context.js +18 -13
  31. package/dist/utils/github-repo-info.d.ts +13 -1
  32. package/dist/utils/github-repo-info.js +32 -6
  33. package/package.json +1 -1
  34. package/vitest.config.ts +2 -0
  35. package/dist/api/__tests__/app-store.test.d.ts +0 -7
  36. package/dist/api/__tests__/app-store.test.js +0 -60
  37. package/dist/api/__tests__/intelligence.test.d.ts +0 -11
  38. package/dist/api/__tests__/intelligence.test.js +0 -315
  39. package/dist/api/features/__tests__/feature-utils.test.d.ts +0 -4
  40. package/dist/api/features/__tests__/feature-utils.test.js +0 -370
  41. package/dist/api/features/__tests__/status-updater.test.d.ts +0 -4
  42. package/dist/api/features/__tests__/status-updater.test.js +0 -88
  43. package/dist/api/features/approval-checker.d.ts +0 -20
  44. package/dist/api/features/approval-checker.js +0 -152
  45. package/dist/api/features/batch-operations.d.ts +0 -17
  46. package/dist/api/features/batch-operations.js +0 -100
  47. package/dist/api/features/feature-utils.d.ts +0 -23
  48. package/dist/api/features/feature-utils.js +0 -80
  49. package/dist/api/features/get-feature.d.ts +0 -5
  50. package/dist/api/features/get-feature.js +0 -21
  51. package/dist/api/features/index.d.ts +0 -8
  52. package/dist/api/features/index.js +0 -10
  53. package/dist/api/features/status-updater.d.ts +0 -41
  54. package/dist/api/features/status-updater.js +0 -122
  55. package/dist/api/features/test-cases.d.ts +0 -29
  56. package/dist/api/features/test-cases.js +0 -110
  57. package/dist/api/features/update-feature.d.ts +0 -20
  58. package/dist/api/features/update-feature.js +0 -83
  59. package/dist/api/features/user-stories.d.ts +0 -21
  60. package/dist/api/features/user-stories.js +0 -88
  61. package/dist/commands/agent-workflow/feature-worker.d.ts +0 -14
  62. package/dist/commands/agent-workflow/feature-worker.js +0 -65
  63. package/dist/commands/build/__tests__/build.test.d.ts +0 -5
  64. package/dist/commands/build/__tests__/build.test.js +0 -206
  65. package/dist/commands/build/__tests__/detect-project.test.d.ts +0 -6
  66. package/dist/commands/build/__tests__/detect-project.test.js +0 -160
  67. package/dist/commands/build/__tests__/run-build.test.d.ts +0 -6
  68. package/dist/commands/build/__tests__/run-build.test.js +0 -433
  69. package/dist/commands/intelligence/__tests__/command.test.d.ts +0 -4
  70. package/dist/commands/intelligence/__tests__/command.test.js +0 -48
  71. package/dist/commands/workflow/core/__tests__/feature-filter.test.d.ts +0 -5
  72. package/dist/commands/workflow/core/__tests__/feature-filter.test.js +0 -316
  73. package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.d.ts +0 -4
  74. package/dist/commands/workflow/core/__tests__/pipeline-evaluator.test.js +0 -397
  75. package/dist/commands/workflow/core/__tests__/state-manager.test.d.ts +0 -4
  76. package/dist/commands/workflow/core/__tests__/state-manager.test.js +0 -384
  77. package/dist/commands/workflow/core/feature-filter.d.ts +0 -16
  78. package/dist/commands/workflow/core/feature-filter.js +0 -47
  79. package/dist/commands/workflow/feature-coordinator.d.ts +0 -18
  80. package/dist/commands/workflow/feature-coordinator.js +0 -161
  81. package/dist/config/__tests__/config.test.d.ts +0 -4
  82. package/dist/config/__tests__/config.test.js +0 -286
  83. package/dist/config/__tests__/feature-status.test.d.ts +0 -4
  84. package/dist/config/__tests__/feature-status.test.js +0 -111
  85. package/dist/config/feature-status.d.ts +0 -56
  86. package/dist/config/feature-status.js +0 -130
  87. package/dist/errors/__tests__/index.test.d.ts +0 -4
  88. package/dist/errors/__tests__/index.test.js +0 -349
  89. package/dist/phases/app-store-generation/__tests__/agent.test.d.ts +0 -5
  90. package/dist/phases/app-store-generation/__tests__/agent.test.js +0 -142
  91. package/dist/phases/app-store-generation/__tests__/context.test.d.ts +0 -4
  92. package/dist/phases/app-store-generation/__tests__/context.test.js +0 -284
  93. package/dist/phases/app-store-generation/__tests__/prompts.test.d.ts +0 -4
  94. package/dist/phases/app-store-generation/__tests__/prompts.test.js +0 -122
  95. package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.d.ts +0 -5
  96. package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +0 -826
  97. package/dist/phases/code-review/__tests__/diff-utils.test.d.ts +0 -1
  98. package/dist/phases/code-review/__tests__/diff-utils.test.js +0 -101
  99. package/dist/phases/feature-analysis/agent.d.ts +0 -13
  100. package/dist/phases/feature-analysis/agent.js +0 -112
  101. package/dist/phases/feature-analysis/context.d.ts +0 -24
  102. package/dist/phases/feature-analysis/context.js +0 -138
  103. package/dist/phases/feature-analysis/index.d.ts +0 -8
  104. package/dist/phases/feature-analysis/index.js +0 -199
  105. package/dist/phases/feature-analysis/outcome.d.ts +0 -40
  106. package/dist/phases/feature-analysis/outcome.js +0 -280
  107. package/dist/phases/feature-analysis/prompts.d.ts +0 -10
  108. package/dist/phases/feature-analysis/prompts.js +0 -212
  109. package/dist/phases/feature-analysis-verification/agent.d.ts +0 -33
  110. package/dist/phases/feature-analysis-verification/agent.js +0 -124
  111. package/dist/phases/feature-analysis-verification/index.d.ts +0 -25
  112. package/dist/phases/feature-analysis-verification/index.js +0 -92
  113. package/dist/phases/feature-analysis-verification/prompts.d.ts +0 -10
  114. package/dist/phases/feature-analysis-verification/prompts.js +0 -100
  115. package/dist/phases/intelligence-analysis/__tests__/context.test.d.ts +0 -4
  116. package/dist/phases/intelligence-analysis/__tests__/context.test.js +0 -192
  117. package/dist/phases/intelligence-analysis/__tests__/matching.test.d.ts +0 -13
  118. package/dist/phases/intelligence-analysis/__tests__/matching.test.js +0 -154
  119. package/dist/phases/intelligence-analysis/__tests__/orchestration.test.d.ts +0 -5
  120. package/dist/phases/intelligence-analysis/__tests__/orchestration.test.js +0 -378
  121. package/dist/phases/intelligence-analysis/__tests__/prompts.test.d.ts +0 -4
  122. package/dist/phases/intelligence-analysis/__tests__/prompts.test.js +0 -33
  123. package/dist/phases/pr-execution/__tests__/file-assigner.test.d.ts +0 -1
  124. package/dist/phases/pr-execution/__tests__/file-assigner.test.js +0 -303
  125. package/dist/phases/pr-resolve/__tests__/checklist-learner.test.d.ts +0 -1
  126. package/dist/phases/pr-resolve/__tests__/checklist-learner.test.js +0 -157
  127. package/dist/phases/pr-resolve/__tests__/prompts.test.d.ts +0 -1
  128. package/dist/phases/pr-resolve/__tests__/prompts.test.js +0 -116
  129. package/dist/phases/pr-resolve/__tests__/resolve-mapping.test.d.ts +0 -1
  130. package/dist/phases/pr-resolve/__tests__/resolve-mapping.test.js +0 -138
  131. package/dist/phases/pr-resolve/__tests__/types.test.d.ts +0 -1
  132. package/dist/phases/pr-resolve/__tests__/types.test.js +0 -43
  133. package/dist/phases/pr-resolve/__tests__/workspace.test.d.ts +0 -1
  134. package/dist/phases/pr-resolve/__tests__/workspace.test.js +0 -111
  135. package/dist/phases/pr-review/__tests__/prompts.test.d.ts +0 -1
  136. package/dist/phases/pr-review/__tests__/prompts.test.js +0 -49
  137. package/dist/phases/pr-review/__tests__/review-comments.test.d.ts +0 -1
  138. package/dist/phases/pr-review/__tests__/review-comments.test.js +0 -110
  139. package/dist/phases/pr-shared/__tests__/agent-utils.test.d.ts +0 -1
  140. package/dist/phases/pr-shared/__tests__/agent-utils.test.js +0 -91
  141. package/dist/phases/pr-shared/__tests__/context.test.d.ts +0 -1
  142. package/dist/phases/pr-shared/__tests__/context.test.js +0 -94
  143. package/dist/phases/pr-splitting/__tests__/import-dep-validator.test.d.ts +0 -1
  144. package/dist/phases/pr-splitting/__tests__/import-dep-validator.test.js +0 -331
  145. package/dist/phases/run-sheet/render.d.ts +0 -60
  146. package/dist/phases/run-sheet/render.js +0 -297
  147. package/dist/phases/smoke-test/__tests__/agent.test.d.ts +0 -4
  148. package/dist/phases/smoke-test/__tests__/agent.test.js +0 -84
  149. package/dist/phases/smoke-test/__tests__/github.test.d.ts +0 -9
  150. package/dist/phases/smoke-test/__tests__/github.test.js +0 -120
  151. package/dist/phases/smoke-test/__tests__/snapshot.test.d.ts +0 -8
  152. package/dist/phases/smoke-test/__tests__/snapshot.test.js +0 -93
  153. package/dist/phases/smoke-test/github.d.ts +0 -54
  154. package/dist/phases/smoke-test/github.js +0 -101
  155. package/dist/phases/smoke-test/snapshot.d.ts +0 -27
  156. package/dist/phases/smoke-test/snapshot.js +0 -157
  157. package/dist/services/coaching/__tests__/coaching-agent.test.d.ts +0 -1
  158. package/dist/services/coaching/__tests__/coaching-agent.test.js +0 -74
  159. package/dist/services/coaching/__tests__/coaching-loop.test.d.ts +0 -1
  160. package/dist/services/coaching/__tests__/coaching-loop.test.js +0 -59
  161. package/dist/services/coaching/__tests__/self-rating.test.d.ts +0 -1
  162. package/dist/services/coaching/__tests__/self-rating.test.js +0 -188
  163. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.d.ts +0 -4
  164. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.js +0 -133
  165. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.d.ts +0 -4
  166. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.js +0 -336
  167. package/dist/services/lifecycle-agent/index.d.ts +0 -24
  168. package/dist/services/lifecycle-agent/index.js +0 -25
  169. package/dist/services/lifecycle-agent/phase-criteria.d.ts +0 -57
  170. package/dist/services/lifecycle-agent/phase-criteria.js +0 -335
  171. package/dist/services/lifecycle-agent/transition-rules.d.ts +0 -60
  172. package/dist/services/lifecycle-agent/transition-rules.js +0 -184
  173. package/dist/services/lifecycle-agent/types.d.ts +0 -190
  174. package/dist/services/lifecycle-agent/types.js +0 -12
  175. package/dist/services/phase-hooks/__tests__/bindings-fetcher.test.d.ts +0 -1
  176. package/dist/services/phase-hooks/__tests__/bindings-fetcher.test.js +0 -122
  177. package/dist/services/phase-hooks/__tests__/hook-executor.test.d.ts +0 -1
  178. package/dist/services/phase-hooks/__tests__/hook-executor.test.js +0 -321
  179. package/dist/services/phase-hooks/__tests__/hook-runner.test.d.ts +0 -1
  180. package/dist/services/phase-hooks/__tests__/hook-runner.test.js +0 -261
  181. package/dist/services/phase-hooks/__tests__/plugin-loader.test.d.ts +0 -1
  182. package/dist/services/phase-hooks/__tests__/plugin-loader.test.js +0 -158
  183. package/dist/services/video/__tests__/video-pipeline.test.d.ts +0 -6
  184. package/dist/services/video/__tests__/video-pipeline.test.js +0 -249
  185. package/dist/types/features.d.ts +0 -35
  186. package/dist/types/features.js +0 -1
  187. package/dist/workspace/__tests__/workspace-manager.test.d.ts +0 -7
  188. package/dist/workspace/__tests__/workspace-manager.test.js +0 -52
@@ -1,286 +0,0 @@
1
- /**
2
- * Unit tests for the config module (loadConfig and validateConfig)
3
- */
4
- import assert from 'node:assert';
5
- import { mkdtempSync } from 'node:fs';
6
- import { tmpdir } from 'node:os';
7
- import { join } from 'node:path';
8
- import { describe, it } from 'node:test';
9
- import { loadConfig, validateConfig } from '../../config.js';
10
- /**
11
- * Helper to create a valid default-shaped config for validateConfig tests.
12
- * Individual tests override specific fields to trigger validation errors.
13
- */
14
- function makeValidConfig(overrides = {}) {
15
- return {
16
- patterns: ['**/*.ts'],
17
- exclude: ['**/node_modules/**'],
18
- severity: 'error',
19
- maxFiles: 50,
20
- claude: { timeout: 120000 },
21
- workflow: {
22
- maxConcurrency: 3,
23
- pollInterval: 30000,
24
- maxRetries: 3,
25
- retryCooldown: 300000,
26
- workerTimeout: 1800000,
27
- maxVerificationIterations: 10,
28
- },
29
- ...overrides,
30
- };
31
- }
32
- void describe('Config Module', () => {
33
- // ── loadConfig ──────────────────────────────────────────────────────
34
- void describe('loadConfig', () => {
35
- void it('should return defaults when no config file exists', () => {
36
- // Use a fresh temp directory that has no config files
37
- const tempDir = mkdtempSync(join(tmpdir(), 'edsger-test-'));
38
- const originalCwd = process.cwd();
39
- try {
40
- process.chdir(tempDir);
41
- const config = loadConfig();
42
- assert.ok(Array.isArray(config.patterns), 'patterns should be an array');
43
- assert.ok(config.patterns.length > 0, 'patterns should not be empty');
44
- assert.ok(Array.isArray(config.exclude), 'exclude should be an array');
45
- assert.ok(config.exclude.length > 0, 'exclude should not be empty');
46
- assert.strictEqual(config.severity, 'error');
47
- assert.strictEqual(config.maxFiles, 50);
48
- assert.strictEqual(config.claude.timeout, 120000);
49
- }
50
- finally {
51
- process.chdir(originalCwd);
52
- }
53
- });
54
- void it('should include all default patterns for common languages', () => {
55
- const tempDir = mkdtempSync(join(tmpdir(), 'edsger-test-'));
56
- const originalCwd = process.cwd();
57
- try {
58
- process.chdir(tempDir);
59
- const config = loadConfig();
60
- const expectedPatterns = [
61
- '**/*.js',
62
- '**/*.ts',
63
- '**/*.tsx',
64
- '**/*.py',
65
- '**/*.go',
66
- '**/*.rs',
67
- '**/*.java',
68
- ];
69
- for (const pattern of expectedPatterns) {
70
- assert.ok(config.patterns.includes(pattern), `Default patterns should include ${pattern}`);
71
- }
72
- }
73
- finally {
74
- process.chdir(originalCwd);
75
- }
76
- });
77
- void it('should include sensible default excludes', () => {
78
- const tempDir = mkdtempSync(join(tmpdir(), 'edsger-test-'));
79
- const originalCwd = process.cwd();
80
- try {
81
- process.chdir(tempDir);
82
- const config = loadConfig();
83
- assert.ok(config.exclude.includes('**/node_modules/**'), 'Should exclude node_modules');
84
- assert.ok(config.exclude.includes('**/dist/**'), 'Should exclude dist');
85
- assert.ok(config.exclude.includes('**/__tests__/**'), 'Should exclude __tests__');
86
- }
87
- finally {
88
- process.chdir(originalCwd);
89
- }
90
- });
91
- void it('should return correct default workflow values', () => {
92
- const tempDir = mkdtempSync(join(tmpdir(), 'edsger-test-'));
93
- const originalCwd = process.cwd();
94
- try {
95
- process.chdir(tempDir);
96
- const config = loadConfig();
97
- assert.strictEqual(config.workflow.maxConcurrency, 3);
98
- assert.strictEqual(config.workflow.pollInterval, 30000);
99
- assert.strictEqual(config.workflow.maxRetries, 3);
100
- assert.strictEqual(config.workflow.retryCooldown, 300000);
101
- assert.strictEqual(config.workflow.workerTimeout, 1800000);
102
- assert.strictEqual(config.workflow.maxVerificationIterations, 10);
103
- }
104
- finally {
105
- process.chdir(originalCwd);
106
- }
107
- });
108
- void it('should return a claude object with default timeout', () => {
109
- const tempDir = mkdtempSync(join(tmpdir(), 'edsger-test-'));
110
- const originalCwd = process.cwd();
111
- try {
112
- process.chdir(tempDir);
113
- const config = loadConfig();
114
- assert.ok(typeof config.claude === 'object' && config.claude !== null, 'claude should be an object');
115
- assert.strictEqual(config.claude.timeout, 120000);
116
- }
117
- finally {
118
- process.chdir(originalCwd);
119
- }
120
- });
121
- });
122
- // ── validateConfig: valid configs ───────────────────────────────────
123
- void describe('validateConfig - valid configs', () => {
124
- void it('should return empty errors for a valid config', () => {
125
- const config = makeValidConfig();
126
- const errors = validateConfig(config);
127
- assert.deepStrictEqual(errors, []);
128
- });
129
- void it('should accept severity "warning"', () => {
130
- const config = makeValidConfig({ severity: 'warning' });
131
- const errors = validateConfig(config);
132
- assert.deepStrictEqual(errors, []);
133
- });
134
- void it('should accept config without claude.timeout (undefined)', () => {
135
- const config = makeValidConfig({ claude: {} });
136
- const errors = validateConfig(config);
137
- assert.deepStrictEqual(errors, []);
138
- });
139
- void it('should accept maxFiles of 1', () => {
140
- const config = makeValidConfig({ maxFiles: 1 });
141
- const errors = validateConfig(config);
142
- assert.deepStrictEqual(errors, []);
143
- });
144
- void it('should accept a large maxFiles value', () => {
145
- const config = makeValidConfig({ maxFiles: 10000 });
146
- const errors = validateConfig(config);
147
- assert.deepStrictEqual(errors, []);
148
- });
149
- });
150
- // ── validateConfig: patterns ────────────────────────────────────────
151
- void describe('validateConfig - patterns validation', () => {
152
- void it('should return error for empty patterns array', () => {
153
- const config = makeValidConfig({ patterns: [] });
154
- const errors = validateConfig(config);
155
- assert.ok(errors.length > 0, 'Should have at least one error');
156
- assert.ok(errors.some((e) => e.includes('patterns')), 'Error should mention patterns');
157
- });
158
- void it('should return error for non-array patterns', () => {
159
- const config = makeValidConfig({
160
- patterns: 'not-an-array',
161
- });
162
- const errors = validateConfig(config);
163
- assert.ok(errors.length > 0, 'Should have at least one error');
164
- assert.ok(errors.some((e) => e.includes('patterns')), 'Error should mention patterns');
165
- });
166
- });
167
- // ── validateConfig: exclude ─────────────────────────────────────────
168
- void describe('validateConfig - exclude validation', () => {
169
- void it('should return error for non-array exclude', () => {
170
- const config = makeValidConfig({
171
- exclude: 'not-an-array',
172
- });
173
- const errors = validateConfig(config);
174
- assert.ok(errors.length > 0, 'Should have at least one error');
175
- assert.ok(errors.some((e) => e.includes('exclude')), 'Error should mention exclude');
176
- });
177
- void it('should accept empty exclude array', () => {
178
- const config = makeValidConfig({ exclude: [] });
179
- const errors = validateConfig(config);
180
- assert.deepStrictEqual(errors, []);
181
- });
182
- });
183
- // ── validateConfig: severity ────────────────────────────────────────
184
- void describe('validateConfig - severity validation', () => {
185
- void it('should return error for invalid severity', () => {
186
- const config = makeValidConfig({
187
- severity: 'info',
188
- });
189
- const errors = validateConfig(config);
190
- assert.ok(errors.length > 0, 'Should have at least one error');
191
- assert.ok(errors.some((e) => e.includes('severity')), 'Error should mention severity');
192
- });
193
- });
194
- // ── validateConfig: maxFiles ────────────────────────────────────────
195
- void describe('validateConfig - maxFiles validation', () => {
196
- void it('should return error for zero maxFiles', () => {
197
- const config = makeValidConfig({ maxFiles: 0 });
198
- const errors = validateConfig(config);
199
- assert.ok(errors.length > 0, 'Should have at least one error');
200
- assert.ok(errors.some((e) => e.includes('maxFiles')), 'Error should mention maxFiles');
201
- });
202
- void it('should return error for negative maxFiles', () => {
203
- const config = makeValidConfig({ maxFiles: -5 });
204
- const errors = validateConfig(config);
205
- assert.ok(errors.length > 0, 'Should have at least one error');
206
- assert.ok(errors.some((e) => e.includes('maxFiles')), 'Error should mention maxFiles');
207
- });
208
- void it('should return error for non-number maxFiles', () => {
209
- const config = makeValidConfig({
210
- maxFiles: 'fifty',
211
- });
212
- const errors = validateConfig(config);
213
- assert.ok(errors.length > 0, 'Should have at least one error');
214
- assert.ok(errors.some((e) => e.includes('maxFiles')), 'Error should mention maxFiles');
215
- });
216
- });
217
- // ── validateConfig: claude.timeout ──────────────────────────────────
218
- void describe('validateConfig - claude.timeout validation', () => {
219
- void it('should return error for negative timeout', () => {
220
- const config = makeValidConfig({ claude: { timeout: -1000 } });
221
- const errors = validateConfig(config);
222
- assert.ok(errors.length > 0, 'Should have at least one error');
223
- assert.ok(errors.some((e) => e.includes('timeout')), 'Error should mention timeout');
224
- });
225
- void it('should return error for zero timeout', () => {
226
- // timeout of 0 is falsy, so the validation guard skips it
227
- // This documents the current behavior
228
- const config = makeValidConfig({ claude: { timeout: 0 } });
229
- const errors = validateConfig(config);
230
- // 0 is falsy, so the `config.claude.timeout &&` guard means
231
- // zero timeout does NOT trigger the validation error
232
- assert.deepStrictEqual(errors, []);
233
- });
234
- void it('should return error for non-number timeout', () => {
235
- const config = makeValidConfig({
236
- claude: { timeout: 'slow' },
237
- });
238
- const errors = validateConfig(config);
239
- assert.ok(errors.length > 0, 'Should have at least one error');
240
- assert.ok(errors.some((e) => e.includes('timeout')), 'Error should mention timeout');
241
- });
242
- });
243
- // ── validateConfig: multiple errors ─────────────────────────────────
244
- void describe('validateConfig - multiple errors', () => {
245
- void it('should collect all validation errors at once', () => {
246
- const config = {
247
- patterns: [],
248
- exclude: 'not-array',
249
- severity: 'info',
250
- maxFiles: -1,
251
- claude: { timeout: -500 },
252
- workflow: {
253
- maxConcurrency: 3,
254
- pollInterval: 30000,
255
- maxRetries: 3,
256
- retryCooldown: 300000,
257
- workerTimeout: 1800000,
258
- maxVerificationIterations: 10,
259
- },
260
- };
261
- const errors = validateConfig(config);
262
- assert.strictEqual(errors.length, 5, 'Should report all five errors');
263
- assert.ok(errors.some((e) => e.includes('patterns')));
264
- assert.ok(errors.some((e) => e.includes('exclude')));
265
- assert.ok(errors.some((e) => e.includes('severity')));
266
- assert.ok(errors.some((e) => e.includes('maxFiles')));
267
- assert.ok(errors.some((e) => e.includes('timeout')));
268
- });
269
- });
270
- // ── Default config passes validation ────────────────────────────────
271
- void describe('loadConfig + validateConfig integration', () => {
272
- void it('should produce a config from loadConfig that passes validation', () => {
273
- const tempDir = mkdtempSync(join(tmpdir(), 'edsger-test-'));
274
- const originalCwd = process.cwd();
275
- try {
276
- process.chdir(tempDir);
277
- const config = loadConfig();
278
- const errors = validateConfig(config);
279
- assert.deepStrictEqual(errors, [], 'Default config from loadConfig should pass validation');
280
- }
281
- finally {
282
- process.chdir(originalCwd);
283
- }
284
- });
285
- });
286
- });
@@ -1,4 +0,0 @@
1
- /**
2
- * Unit tests for feature status configuration
3
- */
4
- export {};
@@ -1,111 +0,0 @@
1
- /**
2
- * Unit tests for feature status configuration
3
- */
4
- import assert from 'node:assert';
5
- import { describe, it } from 'node:test';
6
- import { PHASE_STATUS_MAP, STATUS_PROGRESSION_ORDER, } from '../feature-status.js';
7
- void describe('Feature Status Configuration', () => {
8
- void describe('STATUS_PROGRESSION_ORDER', () => {
9
- void it('should start with backlog and end with archived', () => {
10
- assert.strictEqual(STATUS_PROGRESSION_ORDER[0], 'backlog', 'First status should be backlog');
11
- assert.strictEqual(STATUS_PROGRESSION_ORDER[STATUS_PROGRESSION_ORDER.length - 1], 'archived', 'Last status should be archived');
12
- });
13
- void it('should be readonly', () => {
14
- // This test ensures the configuration is properly typed as readonly
15
- // TypeScript will catch attempts to modify the array at compile time
16
- assert.ok(Array.isArray(STATUS_PROGRESSION_ORDER));
17
- assert.ok(STATUS_PROGRESSION_ORDER.length > 0);
18
- });
19
- void it('should maintain logical workflow order', () => {
20
- const criticalOrder = [
21
- 'backlog',
22
- 'ready_for_ai',
23
- 'feature_analysis',
24
- 'technical_design',
25
- 'code_implementation',
26
- 'shipped',
27
- ];
28
- let lastIndex = -1;
29
- for (const status of criticalOrder) {
30
- const currentIndex = STATUS_PROGRESSION_ORDER.indexOf(status);
31
- assert.ok(currentIndex > lastIndex, `${status} should come after the previous critical status`);
32
- lastIndex = currentIndex;
33
- }
34
- });
35
- });
36
- void describe('PHASE_STATUS_MAP', () => {
37
- void it('should map all expected phases', () => {
38
- const expectedPhases = [
39
- 'feature-analysis',
40
- 'feature-analysis-verification',
41
- 'technical-design',
42
- 'technical-design-verification',
43
- 'code-implementation',
44
- 'code-implementation-verification',
45
- 'code-refine',
46
- 'code-refine-verification',
47
- 'bug-fixing',
48
- 'code-review',
49
- 'pull-request',
50
- 'functional-testing',
51
- 'testing-in-progress',
52
- 'testing-passed',
53
- 'testing-failed',
54
- ];
55
- for (const phase of expectedPhases) {
56
- assert.ok(phase in PHASE_STATUS_MAP, `Should have mapping for phase: ${phase}`);
57
- }
58
- });
59
- void it('should map phases to valid statuses', () => {
60
- for (const [phase, status] of Object.entries(PHASE_STATUS_MAP)) {
61
- assert.ok(STATUS_PROGRESSION_ORDER.includes(status), `Phase ${phase} maps to valid status ${status}`);
62
- }
63
- });
64
- void it('should use kebab-case for multi-word phase names and snake_case for multi-word status names', () => {
65
- for (const [phase, status] of Object.entries(PHASE_STATUS_MAP)) {
66
- // Phase names should not contain underscores
67
- assert.ok(!phase.includes('_'), `Phase name ${phase} should not contain underscores`);
68
- // Status names should not contain hyphens
69
- assert.ok(!status.includes('-'), `Status name ${status} should not contain hyphens`);
70
- // Multi-word phase names should use hyphens
71
- if (phase.split('-').length > 1) {
72
- assert.ok(phase.includes('-'), `Multi-word phase name ${phase} should use kebab-case`);
73
- }
74
- // Multi-word status names should use underscores
75
- if (status.split('_').length > 1) {
76
- assert.ok(status.includes('_'), `Multi-word status name ${status} should use snake_case`);
77
- }
78
- }
79
- });
80
- void it('should maintain consistency with phase naming conventions', () => {
81
- // Test some specific mappings to ensure they follow expected patterns
82
- assert.strictEqual(PHASE_STATUS_MAP['feature-analysis'], 'feature_analysis', 'feature-analysis should map to feature_analysis');
83
- assert.strictEqual(PHASE_STATUS_MAP['technical-design-verification'], 'technical_design_verification', 'technical-design-verification should map to technical_design_verification');
84
- assert.strictEqual(PHASE_STATUS_MAP['code-implementation'], 'code_implementation', 'code-implementation should map to code_implementation');
85
- });
86
- void it('should be readonly', () => {
87
- // Ensure the mapping is properly configured as readonly
88
- assert.ok(typeof PHASE_STATUS_MAP === 'object');
89
- assert.ok(Object.keys(PHASE_STATUS_MAP).length > 0);
90
- });
91
- });
92
- void describe('Integration Tests', () => {
93
- void it('should have all mapped statuses in progression order', () => {
94
- const mappedStatuses = Object.values(PHASE_STATUS_MAP);
95
- for (const status of mappedStatuses) {
96
- assert.ok(STATUS_PROGRESSION_ORDER.includes(status), `Mapped status ${status} should be in progression order`);
97
- }
98
- });
99
- void it('should not have gaps in critical workflow phases', () => {
100
- const workflowPhases = [
101
- 'feature-analysis',
102
- 'technical-design',
103
- 'code-implementation',
104
- 'functional-testing',
105
- ];
106
- for (const phase of workflowPhases) {
107
- assert.ok(phase in PHASE_STATUS_MAP, `Critical workflow phase ${phase} should be mapped`);
108
- }
109
- });
110
- });
111
- });
@@ -1,56 +0,0 @@
1
- /**
2
- * Feature status configuration
3
- * Defines the progression order and mappings for feature statuses
4
- */
5
- import type { FeatureStatus } from '../types/index.js';
6
- /**
7
- * Status progression order - higher index means more advanced status
8
- * This defines the allowed forward progression through the feature workflow
9
- *
10
- * Business Logic Rules:
11
- * - Features can only move forward or stay at the same status level
12
- * - No regression to earlier stages is allowed (e.g., cannot go back to 'backlog' from 'code_implementation')
13
- * - Status updates preserve development momentum and prevent accidental rollbacks
14
- *
15
- * Special Cases:
16
- * - testing_failed → testing_in_progress: Allowed for retry attempts after fixing issues
17
- * - Same status → same status: Allowed for retries, reprocessing, or status confirmation
18
- * - code_refine_verification → code_refine: Handled by specific retry logic, not this progression
19
- *
20
- * Note: The order reflects the typical development workflow from initial planning
21
- * through to final shipping. All status values must match the database constraint
22
- * in migration 20251019000000_update_feature_status_constraint.sql
23
- */
24
- export declare const STATUS_PROGRESSION_ORDER: readonly FeatureStatus[];
25
- /**
26
- * Phase to status mapping
27
- * Maps pipeline phase names to their corresponding feature statuses
28
- *
29
- * This mapping ensures that each pipeline phase updates the feature to the appropriate
30
- * status. Phase names use kebab-case (e.g., 'feature-analysis') while status values
31
- * use snake_case (e.g., 'feature_analysis') to match database schema.
32
- *
33
- * All status values must match the database constraint in migration 20251019000000_update_feature_status_constraint.sql
34
- *
35
- * If a phase is not found in this mapping, updateFeatureStatusForPhase will return null
36
- * and skip the status update to prevent unintended regression to 'backlog'.
37
- */
38
- export declare const PHASE_STATUS_MAP: Record<string, FeatureStatus>;
39
- /**
40
- * Human-selectable statuses
41
- * These are the statuses that a human user can manually set.
42
- *
43
- * Excluded statuses (system-managed):
44
- * - *_verification statuses: Automatically entered after completing the corresponding phase
45
- * - testing_in_progress: Automatically set when functional testing begins
46
- * - testing_passed: Automatically set when all tests pass
47
- * - testing_failed: Automatically set when tests fail
48
- *
49
- * These excluded statuses should not be shown in UI dropdowns for manual status changes
50
- * because they represent intermediate states that are managed by the workflow system.
51
- */
52
- export declare const HUMAN_SELECTABLE_STATUSES: readonly FeatureStatus[];
53
- /**
54
- * Check if a status can be manually selected by a human user
55
- */
56
- export declare function isHumanSelectableStatus(status: FeatureStatus): boolean;
@@ -1,130 +0,0 @@
1
- /**
2
- * Feature status configuration
3
- * Defines the progression order and mappings for feature statuses
4
- */
5
- /**
6
- * Status progression order - higher index means more advanced status
7
- * This defines the allowed forward progression through the feature workflow
8
- *
9
- * Business Logic Rules:
10
- * - Features can only move forward or stay at the same status level
11
- * - No regression to earlier stages is allowed (e.g., cannot go back to 'backlog' from 'code_implementation')
12
- * - Status updates preserve development momentum and prevent accidental rollbacks
13
- *
14
- * Special Cases:
15
- * - testing_failed → testing_in_progress: Allowed for retry attempts after fixing issues
16
- * - Same status → same status: Allowed for retries, reprocessing, or status confirmation
17
- * - code_refine_verification → code_refine: Handled by specific retry logic, not this progression
18
- *
19
- * Note: The order reflects the typical development workflow from initial planning
20
- * through to final shipping. All status values must match the database constraint
21
- * in migration 20251019000000_update_feature_status_constraint.sql
22
- */
23
- export const STATUS_PROGRESSION_ORDER = [
24
- 'backlog',
25
- 'ready_for_ai',
26
- 'assigned_to_ai',
27
- 'feature_analysis',
28
- 'feature_analysis_verification',
29
- 'user_stories_analysis',
30
- 'user_stories_analysis_verification',
31
- 'test_cases_analysis',
32
- 'test_cases_analysis_verification',
33
- 'technical_design',
34
- 'technical_design_verification',
35
- 'branch_planning',
36
- 'branch_planning_verification',
37
- 'code_implementation',
38
- 'code_implementation_verification',
39
- 'pr_splitting',
40
- 'pr_splitting_verification',
41
- 'pr_execution',
42
- 'code_refine',
43
- 'code_refine_verification',
44
- 'bug_fixing',
45
- 'code_review',
46
- 'functional_testing',
47
- 'testing_in_progress',
48
- 'testing_passed',
49
- 'testing_failed',
50
- 'ready_for_review',
51
- 'shipped',
52
- 'archived',
53
- ];
54
- /**
55
- * Phase to status mapping
56
- * Maps pipeline phase names to their corresponding feature statuses
57
- *
58
- * This mapping ensures that each pipeline phase updates the feature to the appropriate
59
- * status. Phase names use kebab-case (e.g., 'feature-analysis') while status values
60
- * use snake_case (e.g., 'feature_analysis') to match database schema.
61
- *
62
- * All status values must match the database constraint in migration 20251019000000_update_feature_status_constraint.sql
63
- *
64
- * If a phase is not found in this mapping, updateFeatureStatusForPhase will return null
65
- * and skip the status update to prevent unintended regression to 'backlog'.
66
- */
67
- export const PHASE_STATUS_MAP = {
68
- 'feature-analysis': 'feature_analysis',
69
- 'feature-analysis-verification': 'feature_analysis_verification',
70
- 'user-stories-analysis': 'user_stories_analysis',
71
- 'user-stories-analysis-verification': 'user_stories_analysis_verification',
72
- 'test-cases-analysis': 'test_cases_analysis',
73
- 'test-cases-analysis-verification': 'test_cases_analysis_verification',
74
- 'technical-design': 'technical_design',
75
- 'technical-design-verification': 'technical_design_verification',
76
- 'branch-planning': 'branch_planning',
77
- 'branch-planning-verification': 'branch_planning_verification',
78
- 'code-implementation': 'code_implementation',
79
- 'code-implementation-verification': 'code_implementation_verification',
80
- 'pr-splitting': 'pr_splitting',
81
- 'pr-splitting-verification': 'pr_splitting_verification',
82
- 'pr-execution': 'pr_execution',
83
- 'code-refine': 'code_refine',
84
- 'code-refine-verification': 'code_refine_verification',
85
- 'bug-fixing': 'bug_fixing',
86
- 'code-review': 'code_review',
87
- 'functional-testing': 'functional_testing',
88
- 'testing-in-progress': 'testing_in_progress',
89
- 'testing-passed': 'testing_passed',
90
- 'testing-failed': 'testing_failed',
91
- 'ready-for-review': 'ready_for_review',
92
- };
93
- /**
94
- * Human-selectable statuses
95
- * These are the statuses that a human user can manually set.
96
- *
97
- * Excluded statuses (system-managed):
98
- * - *_verification statuses: Automatically entered after completing the corresponding phase
99
- * - testing_in_progress: Automatically set when functional testing begins
100
- * - testing_passed: Automatically set when all tests pass
101
- * - testing_failed: Automatically set when tests fail
102
- *
103
- * These excluded statuses should not be shown in UI dropdowns for manual status changes
104
- * because they represent intermediate states that are managed by the workflow system.
105
- */
106
- export const HUMAN_SELECTABLE_STATUSES = [
107
- 'backlog',
108
- 'ready_for_ai',
109
- 'feature_analysis',
110
- 'user_stories_analysis',
111
- 'test_cases_analysis',
112
- 'technical_design',
113
- 'branch_planning',
114
- 'code_implementation',
115
- 'pr_splitting',
116
- 'pr_execution',
117
- 'code_refine',
118
- 'bug_fixing',
119
- 'code_review',
120
- 'functional_testing',
121
- 'ready_for_review',
122
- 'shipped',
123
- 'archived',
124
- ];
125
- /**
126
- * Check if a status can be manually selected by a human user
127
- */
128
- export function isHumanSelectableStatus(status) {
129
- return HUMAN_SELECTABLE_STATUSES.includes(status);
130
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * Unit tests for Edsger error classification system
3
- */
4
- export {};