claude-mycelium 2.0.0 → 2.2.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.
- package/.agent-meta/_inhibitors.ndjson +1287 -0
- package/.agent-meta/_quarantine.json +45 -0
- package/.agent-meta/config.json +9 -0
- package/.agent-meta/tasks/_active.json +4 -0
- package/.agent-meta/tasks/task_0657b028-05a0-4b0c-b0b9-a4eae3d66cd9.json +168 -0
- package/.claude/memory.db +0 -0
- package/.claude/settings.local.json +4 -1
- package/README.md +85 -233
- package/SECURITY.md +145 -0
- package/dist/agent/task-worker.d.ts +11 -0
- package/dist/agent/task-worker.d.ts.map +1 -0
- package/dist/agent/task-worker.js +173 -0
- package/dist/agent/task-worker.js.map +1 -0
- package/dist/agent/worker.d.ts +8 -0
- package/dist/agent/worker.d.ts.map +1 -0
- package/dist/agent/worker.js +97 -0
- package/dist/agent/worker.js.map +1 -0
- package/dist/bin.d.ts +7 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +11 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/cost.d.ts +10 -0
- package/dist/cli/cost.d.ts.map +1 -0
- package/dist/cli/cost.js +163 -0
- package/dist/cli/cost.js.map +1 -0
- package/dist/cli/gc.d.ts +10 -0
- package/dist/cli/gc.d.ts.map +1 -0
- package/dist/cli/gc.js +108 -0
- package/dist/cli/gc.js.map +1 -0
- package/dist/cli/gradients.d.ts +10 -0
- package/dist/cli/gradients.d.ts.map +1 -0
- package/dist/cli/gradients.js +70 -0
- package/dist/cli/gradients.js.map +1 -0
- package/dist/cli/grow.d.ts +17 -0
- package/dist/cli/grow.d.ts.map +1 -0
- package/dist/cli/grow.js +373 -0
- package/dist/cli/grow.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +74 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +11 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +97 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/status.d.ts +10 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +191 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/coordination/file-locks.d.ts +42 -0
- package/dist/coordination/file-locks.d.ts.map +1 -0
- package/dist/coordination/file-locks.js +269 -0
- package/dist/coordination/file-locks.js.map +1 -0
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +4 -0
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/inhibitors.d.ts +84 -0
- package/dist/coordination/inhibitors.d.ts.map +1 -0
- package/dist/coordination/inhibitors.js +290 -0
- package/dist/coordination/inhibitors.js.map +1 -0
- package/dist/coordination/process-manager.d.ts +73 -0
- package/dist/coordination/process-manager.d.ts.map +1 -0
- package/dist/coordination/process-manager.js +144 -0
- package/dist/coordination/process-manager.js.map +1 -0
- package/dist/core/agent-executor.d.ts +4 -1
- package/dist/core/agent-executor.d.ts.map +1 -1
- package/dist/core/agent-executor.js +38 -12
- package/dist/core/agent-executor.js.map +1 -1
- package/dist/core/change-applier.d.ts +29 -5
- package/dist/core/change-applier.d.ts.map +1 -1
- package/dist/core/change-applier.js +254 -24
- package/dist/core/change-applier.js.map +1 -1
- package/dist/core/signals/churn.d.ts.map +1 -1
- package/dist/core/signals/churn.js +6 -4
- package/dist/core/signals/churn.js.map +1 -1
- package/dist/core/signals/debt.d.ts.map +1 -1
- package/dist/core/signals/debt.js +4 -3
- package/dist/core/signals/debt.js.map +1 -1
- package/dist/cost/cost-tracker.d.ts.map +1 -1
- package/dist/cost/cost-tracker.js +2 -0
- package/dist/cost/cost-tracker.js.map +1 -1
- package/dist/gc/index.d.ts +17 -0
- package/dist/gc/index.d.ts.map +1 -0
- package/dist/gc/index.js +17 -0
- package/dist/gc/index.js.map +1 -0
- package/dist/gc/runner.d.ts +39 -0
- package/dist/gc/runner.d.ts.map +1 -0
- package/dist/gc/runner.js +277 -0
- package/dist/gc/runner.js.map +1 -0
- package/dist/gc/trace-compactor.d.ts +31 -0
- package/dist/gc/trace-compactor.d.ts.map +1 -0
- package/dist/gc/trace-compactor.js +162 -0
- package/dist/gc/trace-compactor.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/prompts/index.d.ts +2 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js.map +1 -1
- package/dist/quarantine/explorer.d.ts +65 -0
- package/dist/quarantine/explorer.d.ts.map +1 -0
- package/dist/quarantine/explorer.js +175 -0
- package/dist/quarantine/explorer.js.map +1 -0
- package/dist/quarantine/index.d.ts +7 -0
- package/dist/quarantine/index.d.ts.map +1 -0
- package/dist/quarantine/index.js +7 -0
- package/dist/quarantine/index.js.map +1 -0
- package/dist/quarantine/manager.d.ts +75 -0
- package/dist/quarantine/manager.d.ts.map +1 -0
- package/dist/quarantine/manager.js +275 -0
- package/dist/quarantine/manager.js.map +1 -0
- package/dist/task/acceptance.d.ts +29 -0
- package/dist/task/acceptance.d.ts.map +1 -0
- package/dist/task/acceptance.js +228 -0
- package/dist/task/acceptance.js.map +1 -0
- package/dist/task/agent-coordinator.d.ts +40 -0
- package/dist/task/agent-coordinator.d.ts.map +1 -0
- package/dist/task/agent-coordinator.js +168 -0
- package/dist/task/agent-coordinator.js.map +1 -0
- package/dist/task/executor.d.ts +37 -0
- package/dist/task/executor.d.ts.map +1 -0
- package/dist/task/executor.js +462 -0
- package/dist/task/executor.js.map +1 -0
- package/dist/task/index.d.ts +12 -0
- package/dist/task/index.d.ts.map +1 -0
- package/dist/task/index.js +12 -0
- package/dist/task/index.js.map +1 -0
- package/dist/task/planner.d.ts +21 -0
- package/dist/task/planner.d.ts.map +1 -0
- package/dist/task/planner.js +253 -0
- package/dist/task/planner.js.map +1 -0
- package/dist/task/storage.d.ts +46 -0
- package/dist/task/storage.d.ts.map +1 -0
- package/dist/task/storage.js +266 -0
- package/dist/task/storage.js.map +1 -0
- package/dist/trace/trace-event.d.ts +2 -18
- package/dist/trace/trace-event.d.ts.map +1 -1
- package/dist/trace/trace-event.js +6 -6
- package/dist/trace/trace-event.js.map +1 -1
- package/dist/utils/file-utils.d.ts.map +1 -1
- package/dist/utils/file-utils.js +54 -15
- package/dist/utils/file-utils.js.map +1 -1
- package/docs/PHASE5_IMPLEMENTATION.md +237 -0
- package/docs/PHASES-3-7-COMPLETE.md +177 -0
- package/docs/PHASE_4_COMPLETE.md +135 -0
- package/docs/PHASE_7_DELIVERABLES.md +295 -0
- package/docs/PHASE_7_IMPLEMENTATION.md +306 -0
- package/docs/PHASE_7_SUMMARY.txt +195 -0
- package/docs/RELEASE-NOTES-v2.1.md +213 -0
- package/docs/ROADMAP.md +194 -107
- package/docs/SECURITY-AUDIT.md +387 -0
- package/docs/SNAPSHOT.md +59 -32
- package/docs/implementation/phase3-summary.md +220 -0
- package/package.json +27 -11
- package/src/agent/task-worker.ts +196 -0
- package/src/agent/worker.ts +111 -0
- package/src/bin.ts +13 -0
- package/src/cli/cost.ts +210 -0
- package/src/cli/gc.ts +138 -0
- package/src/cli/gradients.ts +97 -0
- package/src/cli/grow.ts +416 -0
- package/src/cli/index.ts +81 -0
- package/src/cli/init.ts +139 -0
- package/src/cli/status.ts +218 -0
- package/src/coordination/file-locks.ts +300 -0
- package/src/coordination/index.ts +4 -0
- package/src/coordination/inhibitors.ts +345 -0
- package/src/coordination/process-manager.ts +199 -0
- package/src/core/agent-executor.ts +37 -8
- package/src/core/signals/churn.ts +8 -5
- package/src/core/signals/debt.ts +4 -3
- package/src/cost/cost-tracker.ts +2 -0
- package/src/gc/index.ts +17 -0
- package/src/gc/runner.ts +314 -0
- package/src/gc/trace-compactor.ts +187 -0
- package/src/index.ts +7 -1
- package/src/prompts/index.ts +2 -1
- package/src/quarantine/explorer.ts +234 -0
- package/src/quarantine/index.ts +7 -0
- package/src/quarantine/manager.ts +336 -0
- package/src/task/acceptance.ts +267 -0
- package/src/task/agent-coordinator.ts +220 -0
- package/src/task/executor.ts +543 -0
- package/src/task/index.ts +38 -0
- package/src/task/planner.ts +294 -0
- package/src/task/storage.ts +332 -0
- package/src/trace/trace-event.ts +7 -26
- package/src/utils/file-utils.ts +61 -15
- package/tests/cli/gc.test.ts +206 -0
- package/tests/cli/init.test.ts +181 -0
- package/tests/cli/status.test.ts +282 -0
- package/tests/coordination/file-locks.test.ts +196 -0
- package/tests/coordination/inhibitors.test.ts +459 -0
- package/tests/coordination/integration.test.ts +195 -0
- package/tests/coordination/process-manager.test.ts +165 -0
- package/tests/gc/trace-compactor.test.ts +245 -0
- package/tests/integration/phase-7.test.ts +145 -0
- package/tests/quarantine/explorer.test.ts +381 -0
- package/tests/quarantine/manager.test.ts +399 -0
- package/tests/security/command-injection.test.ts +88 -0
- package/tests/security/path-traversal.test.ts +103 -0
- package/tests/task/acceptance.test.ts +411 -0
- package/tests/task/executor.test.ts +421 -0
- package/tests/task/planner.test.ts +359 -0
- package/tests/trace/trace-event.test.ts +62 -20
- package/tsconfig.json +2 -2
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Acceptance Criteria Validation
|
|
3
|
+
* Validates acceptance criteria checking functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
7
|
+
import {
|
|
8
|
+
validateAcceptance,
|
|
9
|
+
checkFileExists,
|
|
10
|
+
runTests,
|
|
11
|
+
generateDefaultCriteria,
|
|
12
|
+
canCompleteTask,
|
|
13
|
+
} from '../../src/task/acceptance.js';
|
|
14
|
+
import { Task, AcceptanceCriterion, TaskPlan } from '../../src/types/index.js';
|
|
15
|
+
import * as fileUtils from '../../src/utils/file-utils.js';
|
|
16
|
+
import { exec } from 'child_process';
|
|
17
|
+
import { promisify } from 'util';
|
|
18
|
+
|
|
19
|
+
// Mock dependencies
|
|
20
|
+
vi.mock('../../src/utils/file-utils.js');
|
|
21
|
+
|
|
22
|
+
// Mock child_process exec
|
|
23
|
+
vi.mock('child_process', async () => {
|
|
24
|
+
const actual = await vi.importActual<typeof import('child_process')>('child_process');
|
|
25
|
+
return {
|
|
26
|
+
...actual,
|
|
27
|
+
exec: vi.fn(),
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
vi.mock('util', async () => {
|
|
32
|
+
const actual = await vi.importActual<typeof import('util')>('util');
|
|
33
|
+
return {
|
|
34
|
+
...actual,
|
|
35
|
+
promisify: (fn: any) => fn,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('Acceptance Criteria Validation', () => {
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
vi.clearAllMocks();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('validateAcceptance', () => {
|
|
45
|
+
it('should validate all criteria and return true if all met', async () => {
|
|
46
|
+
const task: Task = {
|
|
47
|
+
id: 'test-123',
|
|
48
|
+
description: 'Test',
|
|
49
|
+
status: 'validating',
|
|
50
|
+
created_at: new Date().toISOString(),
|
|
51
|
+
acceptance_criteria: [
|
|
52
|
+
{
|
|
53
|
+
description: 'File exists',
|
|
54
|
+
type: 'file_exists',
|
|
55
|
+
check: 'src/test.ts',
|
|
56
|
+
met: false,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
description: 'Tests pass',
|
|
60
|
+
type: 'test_passes',
|
|
61
|
+
check: 'src/test.test.ts',
|
|
62
|
+
met: false,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
steps_completed: 2,
|
|
66
|
+
steps_total: 2,
|
|
67
|
+
files_created: [],
|
|
68
|
+
files_modified: [],
|
|
69
|
+
traces: [],
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
vi.mocked(fileUtils.fileExists).mockReturnValue(true);
|
|
73
|
+
vi.mocked(exec as any).mockImplementation((cmd: string, opts: any) => {
|
|
74
|
+
return Promise.resolve({ stdout: 'PASSED', stderr: '' });
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const allMet = await validateAcceptance(task);
|
|
78
|
+
|
|
79
|
+
expect(allMet).toBe(true);
|
|
80
|
+
expect(task.acceptance_criteria[0].met).toBe(true);
|
|
81
|
+
expect(task.acceptance_criteria[1].met).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should return false if any criterion not met', async () => {
|
|
85
|
+
const task: Task = {
|
|
86
|
+
id: 'test-456',
|
|
87
|
+
description: 'Test',
|
|
88
|
+
status: 'validating',
|
|
89
|
+
created_at: new Date().toISOString(),
|
|
90
|
+
acceptance_criteria: [
|
|
91
|
+
{
|
|
92
|
+
description: 'File exists',
|
|
93
|
+
type: 'file_exists',
|
|
94
|
+
check: 'src/missing.ts',
|
|
95
|
+
met: false,
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
steps_completed: 1,
|
|
99
|
+
steps_total: 1,
|
|
100
|
+
files_created: [],
|
|
101
|
+
files_modified: [],
|
|
102
|
+
traces: [],
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
vi.mocked(fileUtils.fileExists).mockReturnValue(false);
|
|
106
|
+
|
|
107
|
+
const allMet = await validateAcceptance(task);
|
|
108
|
+
|
|
109
|
+
expect(allMet).toBe(false);
|
|
110
|
+
expect(task.acceptance_criteria[0].met).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should handle mixed results', async () => {
|
|
114
|
+
const task: Task = {
|
|
115
|
+
id: 'test-789',
|
|
116
|
+
description: 'Test',
|
|
117
|
+
status: 'validating',
|
|
118
|
+
created_at: new Date().toISOString(),
|
|
119
|
+
acceptance_criteria: [
|
|
120
|
+
{
|
|
121
|
+
description: 'File exists',
|
|
122
|
+
type: 'file_exists',
|
|
123
|
+
check: 'src/test.ts',
|
|
124
|
+
met: false,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
description: 'Another file exists',
|
|
128
|
+
type: 'file_exists',
|
|
129
|
+
check: 'src/missing.ts',
|
|
130
|
+
met: false,
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
steps_completed: 2,
|
|
134
|
+
steps_total: 2,
|
|
135
|
+
files_created: [],
|
|
136
|
+
files_modified: [],
|
|
137
|
+
traces: [],
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
vi.mocked(fileUtils.fileExists)
|
|
141
|
+
.mockReturnValueOnce(true)
|
|
142
|
+
.mockReturnValueOnce(false);
|
|
143
|
+
|
|
144
|
+
const allMet = await validateAcceptance(task);
|
|
145
|
+
|
|
146
|
+
expect(allMet).toBe(false);
|
|
147
|
+
expect(task.acceptance_criteria[0].met).toBe(true);
|
|
148
|
+
expect(task.acceptance_criteria[1].met).toBe(false);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe('checkFileExists', () => {
|
|
153
|
+
it('should return true if file exists', async () => {
|
|
154
|
+
vi.mocked(fileUtils.fileExists).mockReturnValue(true);
|
|
155
|
+
|
|
156
|
+
const exists = await checkFileExists('src/test.ts');
|
|
157
|
+
|
|
158
|
+
expect(exists).toBe(true);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should return false if file does not exist', async () => {
|
|
162
|
+
vi.mocked(fileUtils.fileExists).mockReturnValue(false);
|
|
163
|
+
|
|
164
|
+
const exists = await checkFileExists('src/missing.ts');
|
|
165
|
+
|
|
166
|
+
expect(exists).toBe(false);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('runTests', () => {
|
|
171
|
+
it('should return true if tests pass', async () => {
|
|
172
|
+
vi.mocked(exec as any).mockImplementation(() => {
|
|
173
|
+
return Promise.resolve({ stdout: 'Test passed\nPASSED', stderr: '' });
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const passed = await runTests('src/test.test.ts');
|
|
177
|
+
|
|
178
|
+
expect(passed).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should return false if tests fail', async () => {
|
|
182
|
+
vi.mocked(exec as any).mockImplementation(() => {
|
|
183
|
+
return Promise.resolve({ stdout: 'Test FAILED\n1 failed', stderr: '' });
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const passed = await runTests('src/test.test.ts');
|
|
187
|
+
|
|
188
|
+
expect(passed).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('should return false on error', async () => {
|
|
192
|
+
vi.mocked(exec as any).mockImplementation(() => {
|
|
193
|
+
return Promise.reject(new Error('Command failed'));
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const passed = await runTests('src/test.test.ts');
|
|
197
|
+
|
|
198
|
+
expect(passed).toBe(false);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe('generateDefaultCriteria', () => {
|
|
203
|
+
it('should generate criteria for created files', () => {
|
|
204
|
+
const plan: TaskPlan = {
|
|
205
|
+
summary: 'Test plan',
|
|
206
|
+
steps: [
|
|
207
|
+
{
|
|
208
|
+
order: 1,
|
|
209
|
+
description: 'Create file',
|
|
210
|
+
target_file: 'src/new.ts',
|
|
211
|
+
mode: 'create',
|
|
212
|
+
depends_on: [],
|
|
213
|
+
completed: false,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
order: 2,
|
|
217
|
+
description: 'Create test',
|
|
218
|
+
target_file: 'src/new.test.ts',
|
|
219
|
+
mode: 'create',
|
|
220
|
+
depends_on: [1],
|
|
221
|
+
completed: false,
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
estimated_complexity: 'small',
|
|
225
|
+
risks: [],
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const task: Task = {
|
|
229
|
+
id: 'test-123',
|
|
230
|
+
description: 'Test',
|
|
231
|
+
status: 'pending',
|
|
232
|
+
created_at: new Date().toISOString(),
|
|
233
|
+
plan,
|
|
234
|
+
acceptance_criteria: [],
|
|
235
|
+
steps_completed: 0,
|
|
236
|
+
steps_total: 2,
|
|
237
|
+
files_created: [],
|
|
238
|
+
files_modified: [],
|
|
239
|
+
traces: [],
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const criteria = generateDefaultCriteria(task);
|
|
243
|
+
|
|
244
|
+
// Should have file_exists for both files
|
|
245
|
+
expect(criteria.filter(c => c.type === 'file_exists')).toHaveLength(2);
|
|
246
|
+
// Should have test_passes for test file
|
|
247
|
+
expect(criteria.filter(c => c.type === 'test_passes')).toHaveLength(1);
|
|
248
|
+
// Should have lint check for implementation file
|
|
249
|
+
expect(criteria.filter(c => c.type === 'no_lint_errors')).toHaveLength(1);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('should generate lint criteria for modified files', () => {
|
|
253
|
+
const plan: TaskPlan = {
|
|
254
|
+
summary: 'Test plan',
|
|
255
|
+
steps: [
|
|
256
|
+
{
|
|
257
|
+
order: 1,
|
|
258
|
+
description: 'Fix errors',
|
|
259
|
+
target_file: 'src/existing.ts',
|
|
260
|
+
mode: 'error_reducer',
|
|
261
|
+
depends_on: [],
|
|
262
|
+
completed: false,
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
estimated_complexity: 'small',
|
|
266
|
+
risks: [],
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const task: Task = {
|
|
270
|
+
id: 'test-456',
|
|
271
|
+
description: 'Test',
|
|
272
|
+
status: 'pending',
|
|
273
|
+
created_at: new Date().toISOString(),
|
|
274
|
+
plan,
|
|
275
|
+
acceptance_criteria: [],
|
|
276
|
+
steps_completed: 0,
|
|
277
|
+
steps_total: 1,
|
|
278
|
+
files_created: [],
|
|
279
|
+
files_modified: [],
|
|
280
|
+
traces: [],
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const criteria = generateDefaultCriteria(task);
|
|
284
|
+
|
|
285
|
+
// Should have lint check
|
|
286
|
+
expect(criteria.filter(c => c.type === 'no_lint_errors')).toHaveLength(1);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('should not generate criteria for test files lint', () => {
|
|
290
|
+
const plan: TaskPlan = {
|
|
291
|
+
summary: 'Test plan',
|
|
292
|
+
steps: [
|
|
293
|
+
{
|
|
294
|
+
order: 1,
|
|
295
|
+
description: 'Create test',
|
|
296
|
+
target_file: 'src/test.test.ts',
|
|
297
|
+
mode: 'create',
|
|
298
|
+
depends_on: [],
|
|
299
|
+
completed: false,
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
estimated_complexity: 'small',
|
|
303
|
+
risks: [],
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const task: Task = {
|
|
307
|
+
id: 'test-789',
|
|
308
|
+
description: 'Test',
|
|
309
|
+
status: 'pending',
|
|
310
|
+
created_at: new Date().toISOString(),
|
|
311
|
+
plan,
|
|
312
|
+
acceptance_criteria: [],
|
|
313
|
+
steps_completed: 0,
|
|
314
|
+
steps_total: 1,
|
|
315
|
+
files_created: [],
|
|
316
|
+
files_modified: [],
|
|
317
|
+
traces: [],
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const criteria = generateDefaultCriteria(task);
|
|
321
|
+
|
|
322
|
+
// Should not have lint check for test file
|
|
323
|
+
const lintCriteria = criteria.filter(c => c.type === 'no_lint_errors');
|
|
324
|
+
expect(lintCriteria).toHaveLength(0);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
describe('canCompleteTask', () => {
|
|
329
|
+
it('should return true if all steps and criteria met', () => {
|
|
330
|
+
const task: Task = {
|
|
331
|
+
id: 'test-123',
|
|
332
|
+
description: 'Test',
|
|
333
|
+
status: 'validating',
|
|
334
|
+
created_at: new Date().toISOString(),
|
|
335
|
+
acceptance_criteria: [
|
|
336
|
+
{
|
|
337
|
+
description: 'File exists',
|
|
338
|
+
type: 'file_exists',
|
|
339
|
+
check: 'src/test.ts',
|
|
340
|
+
met: true,
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
steps_completed: 2,
|
|
344
|
+
steps_total: 2,
|
|
345
|
+
files_created: [],
|
|
346
|
+
files_modified: [],
|
|
347
|
+
traces: [],
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
expect(canCompleteTask(task)).toBe(true);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('should return false if steps not completed', () => {
|
|
354
|
+
const task: Task = {
|
|
355
|
+
id: 'test-456',
|
|
356
|
+
description: 'Test',
|
|
357
|
+
status: 'in_progress',
|
|
358
|
+
created_at: new Date().toISOString(),
|
|
359
|
+
acceptance_criteria: [],
|
|
360
|
+
steps_completed: 1,
|
|
361
|
+
steps_total: 2,
|
|
362
|
+
files_created: [],
|
|
363
|
+
files_modified: [],
|
|
364
|
+
traces: [],
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
expect(canCompleteTask(task)).toBe(false);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('should return false if criteria not met', () => {
|
|
371
|
+
const task: Task = {
|
|
372
|
+
id: 'test-789',
|
|
373
|
+
description: 'Test',
|
|
374
|
+
status: 'validating',
|
|
375
|
+
created_at: new Date().toISOString(),
|
|
376
|
+
acceptance_criteria: [
|
|
377
|
+
{
|
|
378
|
+
description: 'File exists',
|
|
379
|
+
type: 'file_exists',
|
|
380
|
+
check: 'src/test.ts',
|
|
381
|
+
met: false,
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
steps_completed: 2,
|
|
385
|
+
steps_total: 2,
|
|
386
|
+
files_created: [],
|
|
387
|
+
files_modified: [],
|
|
388
|
+
traces: [],
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
expect(canCompleteTask(task)).toBe(false);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('should return true if no criteria and all steps done', () => {
|
|
395
|
+
const task: Task = {
|
|
396
|
+
id: 'test-999',
|
|
397
|
+
description: 'Test',
|
|
398
|
+
status: 'validating',
|
|
399
|
+
created_at: new Date().toISOString(),
|
|
400
|
+
acceptance_criteria: [],
|
|
401
|
+
steps_completed: 3,
|
|
402
|
+
steps_total: 3,
|
|
403
|
+
files_created: [],
|
|
404
|
+
files_modified: [],
|
|
405
|
+
traces: [],
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
expect(canCompleteTask(task)).toBe(true);
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
});
|