@codemcp/workflows 5.0.1 → 5.1.1
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/package.json +6 -2
- package/skill/SKILL.md +23 -0
- package/.prettierignore +0 -2
- package/.turbo/turbo-build.log +0 -4
- package/.vibe/conversation-state.sqlite +0 -0
- package/src/components/beads/beads-instruction-generator.ts +0 -230
- package/src/components/beads/beads-plan-manager.ts +0 -333
- package/src/components/beads/beads-task-backend-client.ts +0 -229
- package/src/index.ts +0 -93
- package/src/notification-service.ts +0 -23
- package/src/plugin-system/beads-plugin.ts +0 -649
- package/src/plugin-system/commit-plugin.ts +0 -252
- package/src/plugin-system/index.ts +0 -20
- package/src/plugin-system/plugin-interfaces.ts +0 -153
- package/src/plugin-system/plugin-registry.ts +0 -190
- package/src/resource-handlers/conversation-state.ts +0 -55
- package/src/resource-handlers/development-plan.ts +0 -48
- package/src/resource-handlers/index.ts +0 -73
- package/src/resource-handlers/system-prompt.ts +0 -55
- package/src/resource-handlers/workflow-resource.ts +0 -132
- package/src/response-renderer.ts +0 -116
- package/src/server-config.ts +0 -760
- package/src/server-helpers.ts +0 -245
- package/src/server-implementation.ts +0 -277
- package/src/server.ts +0 -9
- package/src/tool-handlers/base-tool-handler.ts +0 -151
- package/src/tool-handlers/conduct-review.ts +0 -190
- package/src/tool-handlers/get-tool-info.ts +0 -273
- package/src/tool-handlers/index.ts +0 -115
- package/src/tool-handlers/list-workflows.ts +0 -78
- package/src/tool-handlers/no-idea.ts +0 -47
- package/src/tool-handlers/proceed-to-phase.ts +0 -296
- package/src/tool-handlers/reset-development.ts +0 -90
- package/src/tool-handlers/resume-workflow.ts +0 -378
- package/src/tool-handlers/setup-project-docs.ts +0 -232
- package/src/tool-handlers/start-development.ts +0 -746
- package/src/tool-handlers/whats-next.ts +0 -246
- package/src/types.ts +0 -135
- package/src/version-info.ts +0 -213
- package/test/e2e/beads-plugin-integration.test.ts +0 -1623
- package/test/e2e/commit-plugin-integration.test.ts +0 -222
- package/test/e2e/core-functionality.test.ts +0 -167
- package/test/e2e/git-branch-detection.test.ts +0 -351
- package/test/e2e/mcp-contract.test.ts +0 -509
- package/test/e2e/plan-management.test.ts +0 -334
- package/test/e2e/plugin-system-integration.test.ts +0 -1410
- package/test/e2e/state-management.test.ts +0 -387
- package/test/e2e/workflow-integration.test.ts +0 -498
- package/test/unit/beads-instruction-generator.test.ts +0 -979
- package/test/unit/beads-phase-task-id-integration.test.ts +0 -535
- package/test/unit/beads-plugin-behavioral.test.ts +0 -545
- package/test/unit/beads-plugin.test.ts +0 -117
- package/test/unit/commit-plugin.test.ts +0 -196
- package/test/unit/conduct-review.test.ts +0 -151
- package/test/unit/conversation-not-found-error.test.ts +0 -120
- package/test/unit/plugin-error-handling.test.ts +0 -240
- package/test/unit/proceed-to-phase-plugin-integration.test.ts +0 -150
- package/test/unit/reset-functionality.test.ts +0 -72
- package/test/unit/resume-workflow.test.ts +0 -193
- package/test/unit/server-config-plugin-registry.test.ts +0 -99
- package/test/unit/server-tools.test.ts +0 -310
- package/test/unit/setup-project-docs-handler.test.ts +0 -268
- package/test/unit/start-development-artifact-detection.test.ts +0 -387
- package/test/unit/start-development-gitignore.test.ts +0 -178
- package/test/unit/start-development-goal-extraction.test.ts +0 -226
- package/test/unit/system-prompt-resource.test.ts +0 -102
- package/test/unit/tool-handlers/no-idea.test.ts +0 -40
- package/test/utils/e2e-test-setup.ts +0 -451
- package/test/utils/run-server-in-dir.sh +0 -27
- package/test/utils/temp-files.ts +0 -320
- package/test/utils/test-access.ts +0 -79
- package/test/utils/test-helpers.ts +0 -288
- package/test/utils/test-setup.ts +0 -77
- package/tsconfig.build.json +0 -10
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -12
- package/vitest.config.ts +0 -19
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Git Branch Detection Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests that verify the system correctly detects and uses git branch names
|
|
5
|
-
* for plan file naming, especially on first conversation.
|
|
6
|
-
*
|
|
7
|
-
* Related to issue #161: First conversation ignores git repo
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
11
|
-
import {
|
|
12
|
-
TempProject,
|
|
13
|
-
createTempProjectWithDefaultStateMachine,
|
|
14
|
-
} from '../utils/temp-files';
|
|
15
|
-
import {
|
|
16
|
-
DirectServerInterface,
|
|
17
|
-
createSuiteIsolatedE2EScenario,
|
|
18
|
-
assertToolSuccess,
|
|
19
|
-
} from '../utils/e2e-test-setup';
|
|
20
|
-
import { execSync } from 'node:child_process';
|
|
21
|
-
import path from 'node:path';
|
|
22
|
-
|
|
23
|
-
describe('Git Branch Detection', () => {
|
|
24
|
-
let client: DirectServerInterface;
|
|
25
|
-
let cleanup: () => Promise<void>;
|
|
26
|
-
|
|
27
|
-
afterEach(async () => {
|
|
28
|
-
if (cleanup) {
|
|
29
|
-
await cleanup();
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe('Plan File Naming Based on Branch', () => {
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
// Explicitly disable beads auto-detection to test markdown format
|
|
36
|
-
vi.stubEnv('TASK_BACKEND', 'markdown');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should use branch name in plan file when on feature branch (not default)', async () => {
|
|
40
|
-
// Create a temp project on a feature branch
|
|
41
|
-
const scenario = await createSuiteIsolatedE2EScenario({
|
|
42
|
-
suiteName: 'git-branch-feature',
|
|
43
|
-
tempProjectFactory: baseDir => {
|
|
44
|
-
// Create project with a feature branch
|
|
45
|
-
const project = new TempProject({
|
|
46
|
-
projectName: `feature-branch-test-${Date.now()}`,
|
|
47
|
-
gitBranch: 'feature/awesome-feature',
|
|
48
|
-
baseDirectory: baseDir,
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Remove the fake .git directory created by TempProject
|
|
52
|
-
// so we can create a real git repository
|
|
53
|
-
const { rmSync } = require('node:fs');
|
|
54
|
-
const gitPath = path.join(project.projectPath, '.git');
|
|
55
|
-
rmSync(gitPath, { recursive: true, force: true });
|
|
56
|
-
|
|
57
|
-
// Initialize it as a real git repository so git commands work
|
|
58
|
-
try {
|
|
59
|
-
execSync('git init', {
|
|
60
|
-
cwd: project.projectPath,
|
|
61
|
-
stdio: 'pipe',
|
|
62
|
-
});
|
|
63
|
-
execSync('git config user.email "test@example.com"', {
|
|
64
|
-
cwd: project.projectPath,
|
|
65
|
-
stdio: 'pipe',
|
|
66
|
-
});
|
|
67
|
-
execSync('git config user.name "Test User"', {
|
|
68
|
-
cwd: project.projectPath,
|
|
69
|
-
stdio: 'pipe',
|
|
70
|
-
});
|
|
71
|
-
execSync('git checkout -b feature/awesome-feature', {
|
|
72
|
-
cwd: project.projectPath,
|
|
73
|
-
stdio: 'pipe',
|
|
74
|
-
});
|
|
75
|
-
// Make an initial commit so HEAD exists
|
|
76
|
-
execSync(
|
|
77
|
-
'git commit --allow-empty --no-gpg-sign -m "Initial commit"',
|
|
78
|
-
{
|
|
79
|
-
cwd: project.projectPath,
|
|
80
|
-
stdio: 'pipe',
|
|
81
|
-
}
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
// Verify the branch was created successfully
|
|
85
|
-
const currentBranch = execSync('git rev-parse --abbrev-ref HEAD', {
|
|
86
|
-
cwd: project.projectPath,
|
|
87
|
-
encoding: 'utf-8',
|
|
88
|
-
stdio: 'pipe',
|
|
89
|
-
}).trim();
|
|
90
|
-
console.log('Git repo initialized. Current branch:', currentBranch);
|
|
91
|
-
} catch (error) {
|
|
92
|
-
console.error('Failed to initialize git repo for test:', error);
|
|
93
|
-
throw error;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Add mock project documents
|
|
97
|
-
project.addMockProjectDocs();
|
|
98
|
-
return project;
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
client = scenario.client;
|
|
103
|
-
cleanup = scenario.cleanup;
|
|
104
|
-
|
|
105
|
-
// Start development on the feature branch
|
|
106
|
-
const result = await client.callTool('start_development', {
|
|
107
|
-
workflow: 'waterfall',
|
|
108
|
-
commit_behaviour: 'none',
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
const response = assertToolSuccess(result);
|
|
112
|
-
|
|
113
|
-
// The plan file should include the branch name, NOT "default"
|
|
114
|
-
expect(response.plan_file_path).toBeTruthy();
|
|
115
|
-
expect(response.plan_file_path).toContain('feature-awesome-feature');
|
|
116
|
-
expect(response.plan_file_path).not.toContain(
|
|
117
|
-
'development-plan-default.md'
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
console.log('Plan file path:', response.plan_file_path);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('should detect branch name even without commits', async () => {
|
|
124
|
-
// Create a temp project on a feature branch WITHOUT any commits
|
|
125
|
-
const scenario = await createSuiteIsolatedE2EScenario({
|
|
126
|
-
suiteName: 'git-branch-no-commits',
|
|
127
|
-
tempProjectFactory: baseDir => {
|
|
128
|
-
const project = new TempProject({
|
|
129
|
-
projectName: `no-commits-test-${Date.now()}`,
|
|
130
|
-
gitBranch: 'feature/no-commits',
|
|
131
|
-
baseDirectory: baseDir,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// Remove fake .git directory and initialize real git repo
|
|
135
|
-
const { rmSync } = require('node:fs');
|
|
136
|
-
const gitPath = path.join(project.projectPath, '.git');
|
|
137
|
-
rmSync(gitPath, { recursive: true, force: true });
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
execSync('git init', { cwd: project.projectPath, stdio: 'pipe' });
|
|
141
|
-
execSync('git config user.email "test@example.com"', {
|
|
142
|
-
cwd: project.projectPath,
|
|
143
|
-
stdio: 'pipe',
|
|
144
|
-
});
|
|
145
|
-
execSync('git config user.name "Test User"', {
|
|
146
|
-
cwd: project.projectPath,
|
|
147
|
-
stdio: 'pipe',
|
|
148
|
-
});
|
|
149
|
-
// Create branch but DO NOT make any commits
|
|
150
|
-
execSync('git checkout -b feature/no-commits', {
|
|
151
|
-
cwd: project.projectPath,
|
|
152
|
-
stdio: 'pipe',
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// Verify the branch was created
|
|
156
|
-
const currentBranch = execSync('git symbolic-ref --short HEAD', {
|
|
157
|
-
cwd: project.projectPath,
|
|
158
|
-
encoding: 'utf-8',
|
|
159
|
-
stdio: 'pipe',
|
|
160
|
-
}).trim();
|
|
161
|
-
console.log(
|
|
162
|
-
'Git repo initialized without commits. Current branch:',
|
|
163
|
-
currentBranch
|
|
164
|
-
);
|
|
165
|
-
} catch (error) {
|
|
166
|
-
console.error('Failed to initialize git repo for test:', error);
|
|
167
|
-
throw error;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
project.addMockProjectDocs();
|
|
171
|
-
return project;
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
client = scenario.client;
|
|
176
|
-
cleanup = scenario.cleanup;
|
|
177
|
-
|
|
178
|
-
const result = await client.callTool('start_development', {
|
|
179
|
-
workflow: 'waterfall',
|
|
180
|
-
commit_behaviour: 'none',
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
const response = assertToolSuccess(result);
|
|
184
|
-
|
|
185
|
-
// Should detect the branch name even without commits
|
|
186
|
-
expect(response.plan_file_path).toBeTruthy();
|
|
187
|
-
expect(response.plan_file_path).toContain('feature-no-commits');
|
|
188
|
-
expect(response.plan_file_path).not.toContain(
|
|
189
|
-
'development-plan-default.md'
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
console.log('Plan file path (no commits):', response.plan_file_path);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('should use "default" in plan file name when not in a git repository', async () => {
|
|
196
|
-
// Create a temp project WITHOUT git initialization
|
|
197
|
-
const scenario = await createSuiteIsolatedE2EScenario({
|
|
198
|
-
suiteName: 'no-git-repo',
|
|
199
|
-
tempProjectFactory: baseDir => {
|
|
200
|
-
const project = createTempProjectWithDefaultStateMachine(baseDir);
|
|
201
|
-
// Don't create .git directory at all
|
|
202
|
-
const gitPath = path.join(project.projectPath, '.git');
|
|
203
|
-
const { rmSync, existsSync } = require('node:fs');
|
|
204
|
-
if (existsSync(gitPath)) {
|
|
205
|
-
rmSync(gitPath, { recursive: true, force: true });
|
|
206
|
-
}
|
|
207
|
-
return project;
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
client = scenario.client;
|
|
212
|
-
cleanup = scenario.cleanup;
|
|
213
|
-
|
|
214
|
-
const result = await client.callTool('start_development', {
|
|
215
|
-
workflow: 'waterfall',
|
|
216
|
-
commit_behaviour: 'none',
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const response = assertToolSuccess(result);
|
|
220
|
-
|
|
221
|
-
// When not a git repo, should use "default"
|
|
222
|
-
expect(response.plan_file_path).toContain('development-plan-default.md');
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('should use different plan files for different branches', async () => {
|
|
226
|
-
// Create a temp project on branch1
|
|
227
|
-
const scenario1 = await createSuiteIsolatedE2EScenario({
|
|
228
|
-
suiteName: 'git-branch-1',
|
|
229
|
-
tempProjectFactory: baseDir => {
|
|
230
|
-
const project = new TempProject({
|
|
231
|
-
projectName: `multi-branch-test-${Date.now()}`,
|
|
232
|
-
gitBranch: 'feature/branch-1',
|
|
233
|
-
baseDirectory: baseDir,
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Remove fake .git directory and initialize real git repo
|
|
237
|
-
const { rmSync } = require('node:fs');
|
|
238
|
-
const gitPath = path.join(project.projectPath, '.git');
|
|
239
|
-
rmSync(gitPath, { recursive: true, force: true });
|
|
240
|
-
|
|
241
|
-
try {
|
|
242
|
-
execSync('git init', { cwd: project.projectPath, stdio: 'pipe' });
|
|
243
|
-
execSync('git config user.email "test@example.com"', {
|
|
244
|
-
cwd: project.projectPath,
|
|
245
|
-
stdio: 'pipe',
|
|
246
|
-
});
|
|
247
|
-
execSync('git config user.name "Test User"', {
|
|
248
|
-
cwd: project.projectPath,
|
|
249
|
-
stdio: 'pipe',
|
|
250
|
-
});
|
|
251
|
-
execSync('git checkout -b feature/branch-1', {
|
|
252
|
-
cwd: project.projectPath,
|
|
253
|
-
stdio: 'pipe',
|
|
254
|
-
});
|
|
255
|
-
execSync(
|
|
256
|
-
'git commit --allow-empty --no-gpg-sign -m "Initial commit"',
|
|
257
|
-
{
|
|
258
|
-
cwd: project.projectPath,
|
|
259
|
-
stdio: 'pipe',
|
|
260
|
-
}
|
|
261
|
-
);
|
|
262
|
-
} catch (error) {
|
|
263
|
-
console.error('Failed to initialize git repo:', error);
|
|
264
|
-
throw error;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
project.addMockProjectDocs();
|
|
268
|
-
return project;
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
const client1 = scenario1.client;
|
|
273
|
-
const cleanup1 = scenario1.cleanup;
|
|
274
|
-
|
|
275
|
-
const result1 = await client1.callTool('start_development', {
|
|
276
|
-
workflow: 'waterfall',
|
|
277
|
-
commit_behaviour: 'none',
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
const response1 = assertToolSuccess(result1);
|
|
281
|
-
|
|
282
|
-
// Should contain branch-1
|
|
283
|
-
expect(response1.plan_file_path).toContain('branch-1');
|
|
284
|
-
expect(response1.plan_file_path).not.toContain('branch-2');
|
|
285
|
-
|
|
286
|
-
await cleanup1();
|
|
287
|
-
|
|
288
|
-
// Create a temp project on branch2 with same project name
|
|
289
|
-
const scenario2 = await createSuiteIsolatedE2EScenario({
|
|
290
|
-
suiteName: 'git-branch-2',
|
|
291
|
-
tempProjectFactory: baseDir => {
|
|
292
|
-
const project = new TempProject({
|
|
293
|
-
projectName: `multi-branch-test-${Date.now()}`,
|
|
294
|
-
gitBranch: 'feature/branch-2',
|
|
295
|
-
baseDirectory: baseDir,
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
// Remove fake .git directory and initialize real git repo
|
|
299
|
-
const { rmSync } = require('node:fs');
|
|
300
|
-
const gitPath2 = path.join(project.projectPath, '.git');
|
|
301
|
-
rmSync(gitPath2, { recursive: true, force: true });
|
|
302
|
-
|
|
303
|
-
try {
|
|
304
|
-
execSync('git init', { cwd: project.projectPath, stdio: 'pipe' });
|
|
305
|
-
execSync('git config user.email "test@example.com"', {
|
|
306
|
-
cwd: project.projectPath,
|
|
307
|
-
stdio: 'pipe',
|
|
308
|
-
});
|
|
309
|
-
execSync('git config user.name "Test User"', {
|
|
310
|
-
cwd: project.projectPath,
|
|
311
|
-
stdio: 'pipe',
|
|
312
|
-
});
|
|
313
|
-
execSync('git checkout -b feature/branch-2', {
|
|
314
|
-
cwd: project.projectPath,
|
|
315
|
-
stdio: 'pipe',
|
|
316
|
-
});
|
|
317
|
-
execSync(
|
|
318
|
-
'git commit --allow-empty --no-gpg-sign -m "Initial commit"',
|
|
319
|
-
{
|
|
320
|
-
cwd: project.projectPath,
|
|
321
|
-
stdio: 'pipe',
|
|
322
|
-
}
|
|
323
|
-
);
|
|
324
|
-
} catch (error) {
|
|
325
|
-
console.error('Failed to initialize git repo:', error);
|
|
326
|
-
throw error;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
project.addMockProjectDocs();
|
|
330
|
-
return project;
|
|
331
|
-
},
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
const client2 = scenario2.client;
|
|
335
|
-
const cleanup2 = scenario2.cleanup;
|
|
336
|
-
|
|
337
|
-
const result2 = await client2.callTool('start_development', {
|
|
338
|
-
workflow: 'waterfall',
|
|
339
|
-
commit_behaviour: 'none',
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
const response2 = assertToolSuccess(result2);
|
|
343
|
-
|
|
344
|
-
// Should contain branch-2
|
|
345
|
-
expect(response2.plan_file_path).toContain('branch-2');
|
|
346
|
-
expect(response2.plan_file_path).not.toContain('branch-1');
|
|
347
|
-
|
|
348
|
-
await cleanup2();
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
});
|