@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.
Files changed (77) hide show
  1. package/package.json +6 -2
  2. package/skill/SKILL.md +23 -0
  3. package/.prettierignore +0 -2
  4. package/.turbo/turbo-build.log +0 -4
  5. package/.vibe/conversation-state.sqlite +0 -0
  6. package/src/components/beads/beads-instruction-generator.ts +0 -230
  7. package/src/components/beads/beads-plan-manager.ts +0 -333
  8. package/src/components/beads/beads-task-backend-client.ts +0 -229
  9. package/src/index.ts +0 -93
  10. package/src/notification-service.ts +0 -23
  11. package/src/plugin-system/beads-plugin.ts +0 -649
  12. package/src/plugin-system/commit-plugin.ts +0 -252
  13. package/src/plugin-system/index.ts +0 -20
  14. package/src/plugin-system/plugin-interfaces.ts +0 -153
  15. package/src/plugin-system/plugin-registry.ts +0 -190
  16. package/src/resource-handlers/conversation-state.ts +0 -55
  17. package/src/resource-handlers/development-plan.ts +0 -48
  18. package/src/resource-handlers/index.ts +0 -73
  19. package/src/resource-handlers/system-prompt.ts +0 -55
  20. package/src/resource-handlers/workflow-resource.ts +0 -132
  21. package/src/response-renderer.ts +0 -116
  22. package/src/server-config.ts +0 -760
  23. package/src/server-helpers.ts +0 -245
  24. package/src/server-implementation.ts +0 -277
  25. package/src/server.ts +0 -9
  26. package/src/tool-handlers/base-tool-handler.ts +0 -151
  27. package/src/tool-handlers/conduct-review.ts +0 -190
  28. package/src/tool-handlers/get-tool-info.ts +0 -273
  29. package/src/tool-handlers/index.ts +0 -115
  30. package/src/tool-handlers/list-workflows.ts +0 -78
  31. package/src/tool-handlers/no-idea.ts +0 -47
  32. package/src/tool-handlers/proceed-to-phase.ts +0 -296
  33. package/src/tool-handlers/reset-development.ts +0 -90
  34. package/src/tool-handlers/resume-workflow.ts +0 -378
  35. package/src/tool-handlers/setup-project-docs.ts +0 -232
  36. package/src/tool-handlers/start-development.ts +0 -746
  37. package/src/tool-handlers/whats-next.ts +0 -246
  38. package/src/types.ts +0 -135
  39. package/src/version-info.ts +0 -213
  40. package/test/e2e/beads-plugin-integration.test.ts +0 -1623
  41. package/test/e2e/commit-plugin-integration.test.ts +0 -222
  42. package/test/e2e/core-functionality.test.ts +0 -167
  43. package/test/e2e/git-branch-detection.test.ts +0 -351
  44. package/test/e2e/mcp-contract.test.ts +0 -509
  45. package/test/e2e/plan-management.test.ts +0 -334
  46. package/test/e2e/plugin-system-integration.test.ts +0 -1410
  47. package/test/e2e/state-management.test.ts +0 -387
  48. package/test/e2e/workflow-integration.test.ts +0 -498
  49. package/test/unit/beads-instruction-generator.test.ts +0 -979
  50. package/test/unit/beads-phase-task-id-integration.test.ts +0 -535
  51. package/test/unit/beads-plugin-behavioral.test.ts +0 -545
  52. package/test/unit/beads-plugin.test.ts +0 -117
  53. package/test/unit/commit-plugin.test.ts +0 -196
  54. package/test/unit/conduct-review.test.ts +0 -151
  55. package/test/unit/conversation-not-found-error.test.ts +0 -120
  56. package/test/unit/plugin-error-handling.test.ts +0 -240
  57. package/test/unit/proceed-to-phase-plugin-integration.test.ts +0 -150
  58. package/test/unit/reset-functionality.test.ts +0 -72
  59. package/test/unit/resume-workflow.test.ts +0 -193
  60. package/test/unit/server-config-plugin-registry.test.ts +0 -99
  61. package/test/unit/server-tools.test.ts +0 -310
  62. package/test/unit/setup-project-docs-handler.test.ts +0 -268
  63. package/test/unit/start-development-artifact-detection.test.ts +0 -387
  64. package/test/unit/start-development-gitignore.test.ts +0 -178
  65. package/test/unit/start-development-goal-extraction.test.ts +0 -226
  66. package/test/unit/system-prompt-resource.test.ts +0 -102
  67. package/test/unit/tool-handlers/no-idea.test.ts +0 -40
  68. package/test/utils/e2e-test-setup.ts +0 -451
  69. package/test/utils/run-server-in-dir.sh +0 -27
  70. package/test/utils/temp-files.ts +0 -320
  71. package/test/utils/test-access.ts +0 -79
  72. package/test/utils/test-helpers.ts +0 -288
  73. package/test/utils/test-setup.ts +0 -77
  74. package/tsconfig.build.json +0 -10
  75. package/tsconfig.build.tsbuildinfo +0 -1
  76. package/tsconfig.json +0 -12
  77. package/vitest.config.ts +0 -19
@@ -1,535 +0,0 @@
1
- /**
2
- * Phase-Specific Task ID Integration Tests for BeadsInstructionGenerator
3
- *
4
- * Tests that validate BeadsInstructionGenerator's ability to extract phase task IDs
5
- * from plan files and integrate them properly into bd commands.
6
- */
7
-
8
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
9
- import { BeadsInstructionGenerator } from '../../src/components/beads/beads-instruction-generator.js';
10
- import type {
11
- InstructionContext,
12
- ConversationContext,
13
- } from '@codemcp/workflows-core';
14
- import { mkdir, writeFile, rm } from 'node:fs/promises';
15
- import { join } from 'node:path';
16
-
17
- describe('Phase-Specific Task ID Integration Tests', () => {
18
- let beadsInstructionGenerator: BeadsInstructionGenerator;
19
- let mockInstructionContext: InstructionContext;
20
- let mockConversationContext: ConversationContext;
21
- let testTempDir: string;
22
- let testPlanFilePath: string;
23
-
24
- beforeEach(async () => {
25
- beadsInstructionGenerator = new BeadsInstructionGenerator();
26
-
27
- // Create temporary directory for test files
28
- testTempDir = join(process.cwd(), 'temp-test-' + Date.now());
29
- await mkdir(testTempDir, { recursive: true });
30
-
31
- testPlanFilePath = join(testTempDir, 'plan.md');
32
-
33
- // Set up mock contexts with temp directory
34
- mockConversationContext = {
35
- conversationId: 'test-conversation',
36
- projectPath: testTempDir,
37
- planFilePath: testPlanFilePath,
38
- gitBranch: 'main',
39
- currentPhase: 'design',
40
- workflowName: 'epcc',
41
- };
42
-
43
- mockInstructionContext = {
44
- phase: 'design',
45
- conversationContext: mockConversationContext,
46
- instructionSource: 'whats_next',
47
- transitionReason: 'test transition',
48
- isModeled: false,
49
- planFileExists: true,
50
- };
51
- });
52
-
53
- afterEach(async () => {
54
- // Clean up temp files
55
- try {
56
- await rm(testTempDir, { recursive: true, force: true });
57
- } catch {
58
- // Ignore cleanup errors
59
- }
60
- });
61
-
62
- describe('Phase Task ID Extraction from Plan Files', () => {
63
- it('should extract phase task ID from properly formatted plan file', async () => {
64
- const planContent = `# Project Plan
65
-
66
- ## Explore
67
- Some exploration tasks here.
68
-
69
- ## Design
70
- <!-- beads-phase-id: project-epic-1.2 -->
71
- - Design the system architecture
72
- - Create wireframes
73
- - Review requirements
74
-
75
- ## Implementation
76
- Some implementation tasks here.
77
- `;
78
-
79
- await writeFile(testPlanFilePath, planContent);
80
-
81
- const result = await beadsInstructionGenerator.generateInstructions(
82
- 'Work on design tasks.',
83
- mockInstructionContext
84
- );
85
-
86
- // Should include specific phase task ID in commands
87
- expect(result.instructions).toContain(
88
- 'bd list --parent project-epic-1.2 --status open'
89
- );
90
- expect(result.instructions).toContain(
91
- "bd create 'Task description' --parent project-epic-1.2"
92
- );
93
- // Removed 'bd show' expectation - no longer part of minimal output
94
- });
95
-
96
- it('should handle phase task IDs with various formats', async () => {
97
- const testCases = [
98
- { id: 'epic-123', phase: 'design' },
99
- { id: 'project-1.2.3', phase: 'design' },
100
- { id: 'feature-456.1', phase: 'design' },
101
- { id: 'milestone-x', phase: 'design' },
102
- ];
103
-
104
- for (const testCase of testCases) {
105
- const planContent = `# Project Plan
106
-
107
- ## Design
108
- <!-- beads-phase-id: ${testCase.id} -->
109
- - Task 1
110
- - Task 2
111
- `;
112
-
113
- await writeFile(testPlanFilePath, planContent);
114
-
115
- const result = await beadsInstructionGenerator.generateInstructions(
116
- 'Work on tasks.',
117
- { ...mockInstructionContext, phase: testCase.phase }
118
- );
119
-
120
- expect(
121
- result.instructions,
122
- `Should extract ID: ${testCase.id}`
123
- ).toContain(`bd list --parent ${testCase.id} --status open`);
124
- expect(
125
- result.instructions,
126
- `Should use ID in create command: ${testCase.id}`
127
- ).toContain(
128
- `bd create 'Task description' --parent ${testCase.id} -p <priority>`
129
- );
130
- }
131
- });
132
-
133
- it('should handle different phase names with underscore formatting', async () => {
134
- const phaseMappings = [
135
- { phase: 'design', header: 'Design' },
136
- { phase: 'implementation', header: 'Implementation' },
137
- { phase: 'code_review', header: 'Code Review' },
138
- { phase: 'system_test', header: 'System Test' },
139
- ];
140
-
141
- for (const mapping of phaseMappings) {
142
- const planContent = `# Project Plan
143
-
144
- ## ${mapping.header}
145
- <!-- beads-phase-id: phase-${mapping.phase}-123 -->
146
- - Some tasks here
147
- `;
148
-
149
- await writeFile(testPlanFilePath, planContent);
150
-
151
- const result = await beadsInstructionGenerator.generateInstructions(
152
- 'Work on phase tasks.',
153
- { ...mockInstructionContext, phase: mapping.phase }
154
- );
155
-
156
- expect(
157
- result.instructions,
158
- `Should find task ID for phase: ${mapping.phase}`
159
- ).toContain(
160
- `bd list --parent phase-${mapping.phase}-123 --status open`
161
- );
162
- }
163
- });
164
-
165
- it('should handle multiple phases and extract correct phase task ID', async () => {
166
- const planContent = `# Project Plan
167
-
168
- ## Explore
169
- <!-- beads-phase-id: explore-task-1 -->
170
- - Research requirements
171
- - Analyze existing solutions
172
-
173
- ## Design
174
- <!-- beads-phase-id: design-task-2 -->
175
- - Create system design
176
- - Design database schema
177
-
178
- ## Implementation
179
- <!-- beads-phase-id: impl-task-3 -->
180
- - Write core functionality
181
- - Implement API endpoints
182
- `;
183
-
184
- await writeFile(testPlanFilePath, planContent);
185
-
186
- // Test design phase extraction
187
- const designResult = await beadsInstructionGenerator.generateInstructions(
188
- 'Work on design.',
189
- { ...mockInstructionContext, phase: 'design' }
190
- );
191
-
192
- expect(designResult.instructions).toContain(
193
- 'bd list --parent design-task-2 --status open'
194
- );
195
- expect(designResult.instructions).not.toContain('explore-task-1');
196
- expect(designResult.instructions).not.toContain('impl-task-3');
197
-
198
- // Test implementation phase extraction
199
- const implResult = await beadsInstructionGenerator.generateInstructions(
200
- 'Work on implementation.',
201
- { ...mockInstructionContext, phase: 'implementation' }
202
- );
203
-
204
- expect(implResult.instructions).toContain(
205
- 'bd list --parent impl-task-3 --status open'
206
- );
207
- expect(implResult.instructions).not.toContain('design-task-2');
208
- expect(implResult.instructions).not.toContain('explore-task-1');
209
- });
210
- });
211
-
212
- describe('Graceful Handling of Missing Phase Task IDs', () => {
213
- it('should provide generic commands when no phase task ID is found', async () => {
214
- const planContent = `# Project Plan
215
-
216
- ## Design
217
- - Some tasks without beads-phase-id
218
- - More tasks here
219
- `;
220
-
221
- await writeFile(testPlanFilePath, planContent);
222
-
223
- const result = await beadsInstructionGenerator.generateInstructions(
224
- 'Work on design tasks.',
225
- mockInstructionContext
226
- );
227
-
228
- // Should fall back to generic placeholder commands
229
- expect(result.instructions).toContain(
230
- 'bd list --parent <phase-task-id> --status open'
231
- );
232
- expect(result.instructions).toContain(
233
- "bd create 'Task title' --parent <phase-task-id> -p <priority>"
234
- );
235
- expect(result.instructions).toContain('Use bd CLI tool exclusively');
236
- expect(result.instructions).not.toContain('bd list --parent design-');
237
- });
238
-
239
- it('should handle malformed beads-phase-id comments gracefully', async () => {
240
- // Test cases that should fall back to generic commands (don't match regex)
241
- const genericFallbackCases = [
242
- '<!-- beads-phase-id -->', // No colon
243
- '<!-- beads-phase-id: @#$% -->', // Invalid characters (should not match regex)
244
- ];
245
-
246
- for (const malformedComment of genericFallbackCases) {
247
- const planContent = `# Project Plan
248
-
249
- ## Design
250
- ${malformedComment}
251
- - Some tasks here
252
- `;
253
-
254
- await writeFile(testPlanFilePath, planContent);
255
-
256
- const result = await beadsInstructionGenerator.generateInstructions(
257
- 'Work on tasks.',
258
- mockInstructionContext
259
- );
260
-
261
- expect(
262
- result.instructions,
263
- `Should fall back to generic for malformed comment: ${malformedComment}`
264
- ).toContain('bd list --parent <phase-task-id> --status open');
265
- }
266
-
267
- // Test cases that extract unexpected values due to regex matching behavior
268
- const edgeCases = [
269
- { comment: '<!-- beads-phase-id: -->', extracted: '--' },
270
- { comment: '<!-- beads-phase-id:no-space -->', extracted: 'no-space' },
271
- ];
272
-
273
- for (const edgeCase of edgeCases) {
274
- const planContent = `# Project Plan
275
-
276
- ## Design
277
- ${edgeCase.comment}
278
- - Some tasks here
279
- `;
280
-
281
- await writeFile(testPlanFilePath, planContent);
282
-
283
- const result = await beadsInstructionGenerator.generateInstructions(
284
- 'Work on tasks.',
285
- mockInstructionContext
286
- );
287
-
288
- // Note: These cases currently extract values due to regex behavior
289
- // This could be considered edge case behavior that should be improved
290
- expect(
291
- result.instructions,
292
- `Should extract value from edge case: ${edgeCase.comment}`
293
- ).toContain(`bd list --parent ${edgeCase.extracted} --status open`);
294
- }
295
- });
296
-
297
- it('should handle non-existent plan file gracefully', async () => {
298
- const contextWithMissingFile = {
299
- ...mockInstructionContext,
300
- planFileExists: false,
301
- conversationContext: {
302
- ...mockConversationContext,
303
- planFilePath: '/non/existent/plan.md',
304
- },
305
- };
306
-
307
- const result = await beadsInstructionGenerator.generateInstructions(
308
- 'Work on tasks.',
309
- contextWithMissingFile
310
- );
311
-
312
- // Should provide generic guidance without crashing
313
- expect(result.instructions).toContain(
314
- 'bd list --parent <phase-task-id> --status open'
315
- );
316
- expect(result.instructions).toContain('Use bd CLI tool exclusively');
317
- expect(result.instructions).toContain(
318
- 'Plan file will be created when you first update it'
319
- );
320
- });
321
-
322
- it('should handle plan file with no matching phase section', async () => {
323
- const planContent = `# Project Plan
324
-
325
- ## Explore
326
- <!-- beads-phase-id: explore-123 -->
327
- - Exploration tasks
328
-
329
- ## Implementation
330
- <!-- beads-phase-id: impl-456 -->
331
- - Implementation tasks
332
- `;
333
-
334
- await writeFile(testPlanFilePath, planContent);
335
-
336
- // Request instructions for a phase not in the plan file
337
- const result = await beadsInstructionGenerator.generateInstructions(
338
- 'Work on design tasks.',
339
- { ...mockInstructionContext, phase: 'design' }
340
- );
341
-
342
- // Should fall back to generic commands
343
- expect(result.instructions).toContain(
344
- 'bd list --parent <phase-task-id> --status open'
345
- );
346
- expect(result.instructions).not.toContain('explore-123');
347
- expect(result.instructions).not.toContain('impl-456');
348
- });
349
- });
350
-
351
- describe('bd Command Integration', () => {
352
- it('should integrate extracted phase task ID into all relevant bd commands', async () => {
353
- const planContent = `# Project Plan
354
-
355
- ## Design
356
- <!-- beads-phase-id: design-epic-789 -->
357
- - Design system architecture
358
- `;
359
-
360
- await writeFile(testPlanFilePath, planContent);
361
-
362
- const result = await beadsInstructionGenerator.generateInstructions(
363
- 'Work on design.',
364
- mockInstructionContext
365
- );
366
-
367
- // Should mention the specific task ID in context
368
- expect(result.instructions).toContain('design-epic-789');
369
- expect(result.instructions).toContain('subtasks of `design-epic-789`');
370
- });
371
-
372
- it('should provide immediate action guidance with extracted task ID', async () => {
373
- const planContent = `# Project Plan
374
-
375
- ## Implementation
376
- <!-- beads-phase-id: feature-impl-999 -->
377
- - Implement core features
378
- `;
379
-
380
- await writeFile(testPlanFilePath, planContent);
381
-
382
- const result = await beadsInstructionGenerator.generateInstructions(
383
- 'Start implementation.',
384
- { ...mockInstructionContext, phase: 'implementation' }
385
- );
386
-
387
- // Should provide specific immediate action
388
- expect(result.instructions).toContain(
389
- '--parent feature-impl-999 --status open'
390
- );
391
- });
392
-
393
- it('should handle phase task ID extraction consistently across multiple calls', async () => {
394
- const planContent = `# Project Plan
395
-
396
- ## Code
397
- <!-- beads-phase-id: consistent-id-123 -->
398
- - Write tests
399
- - Implement features
400
- `;
401
-
402
- await writeFile(testPlanFilePath, planContent);
403
-
404
- // Generate instructions multiple times
405
- const results = await Promise.all([
406
- beadsInstructionGenerator.generateInstructions('Call 1', {
407
- ...mockInstructionContext,
408
- phase: 'code',
409
- }),
410
- beadsInstructionGenerator.generateInstructions('Call 2', {
411
- ...mockInstructionContext,
412
- phase: 'code',
413
- }),
414
- beadsInstructionGenerator.generateInstructions('Call 3', {
415
- ...mockInstructionContext,
416
- phase: 'code',
417
- }),
418
- ]);
419
-
420
- // All results should contain the same extracted task ID
421
- for (const result of results) {
422
- expect(result.instructions).toContain(
423
- 'bd list --parent consistent-id-123 --status open'
424
- );
425
- expect(result.instructions).toContain('consistent-id-123');
426
- }
427
- });
428
- });
429
-
430
- describe('Phase Name Capitalization and Matching', () => {
431
- it('should correctly capitalize phase names for header matching', async () => {
432
- const testCases = [
433
- { input: 'design', expected: 'Design' },
434
- { input: 'code_review', expected: 'Code Review' },
435
- { input: 'system_test', expected: 'System Test' },
436
- { input: 'integration_testing', expected: 'Integration Testing' },
437
- ];
438
-
439
- for (const testCase of testCases) {
440
- const planContent = `# Project Plan
441
-
442
- ## ${testCase.expected}
443
- <!-- beads-phase-id: test-id-${testCase.input} -->
444
- - Some tasks
445
- `;
446
-
447
- await writeFile(testPlanFilePath, planContent);
448
-
449
- const result = await beadsInstructionGenerator.generateInstructions(
450
- 'Work on phase.',
451
- { ...mockInstructionContext, phase: testCase.input }
452
- );
453
-
454
- expect(
455
- result.instructions,
456
- `Should extract ID for phase: ${testCase.input} -> ${testCase.expected}`
457
- ).toContain(`bd list --parent test-id-${testCase.input} --status open`);
458
- }
459
- });
460
-
461
- it('should handle case-insensitive phase header matching', async () => {
462
- const planContent = `# Project Plan
463
-
464
- ## design
465
- <!-- beads-phase-id: lowercase-header-123 -->
466
- - Tasks with lowercase header
467
- `;
468
-
469
- await writeFile(testPlanFilePath, planContent);
470
-
471
- // Should still find the phase despite case difference
472
- const result = await beadsInstructionGenerator.generateInstructions(
473
- 'Work on design.',
474
- mockInstructionContext
475
- );
476
-
477
- // Note: The current implementation is case-sensitive, so this tests the expected behavior
478
- // If the implementation should be case-insensitive, this test would need to be updated
479
- expect(result.instructions).toContain(
480
- 'bd list --parent <phase-task-id> --status open'
481
- );
482
- });
483
- });
484
-
485
- describe('Error Recovery and Robustness', () => {
486
- it('should handle plan files with multiple beads-phase-id comments in same section', async () => {
487
- const planContent = `# Project Plan
488
-
489
- ## Design
490
- <!-- beads-phase-id: first-id-123 -->
491
- <!-- beads-phase-id: second-id-456 -->
492
- - Tasks with multiple IDs
493
- `;
494
-
495
- await writeFile(testPlanFilePath, planContent);
496
-
497
- const result = await beadsInstructionGenerator.generateInstructions(
498
- 'Work on design.',
499
- mockInstructionContext
500
- );
501
-
502
- // Should use the first found ID
503
- expect(result.instructions).toContain(
504
- 'bd list --parent first-id-123 --status open'
505
- );
506
- expect(result.instructions).not.toContain('second-id-456');
507
- });
508
-
509
- it('should handle plan files with beads-phase-id in wrong sections', async () => {
510
- const planContent = `# Project Plan
511
-
512
- ## Design
513
- - Design tasks
514
-
515
- ## Implementation
516
- <!-- beads-phase-id: impl-id-789 -->
517
- - Implementation tasks
518
- `;
519
-
520
- await writeFile(testPlanFilePath, planContent);
521
-
522
- // Request design phase but ID is in implementation section
523
- const result = await beadsInstructionGenerator.generateInstructions(
524
- 'Work on design.',
525
- mockInstructionContext
526
- );
527
-
528
- // Should not use the ID from wrong section
529
- expect(result.instructions).toContain(
530
- 'bd list --parent <phase-task-id> --status open'
531
- );
532
- expect(result.instructions).not.toContain('impl-id-789');
533
- });
534
- });
535
- });