@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,310 +0,0 @@
1
- /**
2
- * Unit tests for Server Tools
3
- *
4
- * Tests the behavior of MCP tools when no conversation exists
5
- */
6
-
7
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
8
-
9
- // Mock conversation manager
10
- const mockGetConversationContext = vi.fn();
11
- const mockCreateConversationContext = vi.fn();
12
-
13
- // Mock database
14
- vi.mock('@codemcp/workflows-core', () => {
15
- return {
16
- Database: vi.fn().mockImplementation(() => ({
17
- initialize: vi.fn().mockResolvedValue(undefined),
18
- close: vi.fn().mockResolvedValue(undefined),
19
- })),
20
- };
21
- });
22
-
23
- // Mock transition engine
24
- const mockAnalyzePhaseTransition = vi.fn();
25
- const mockHandleExplicitTransition = vi.fn();
26
- const mockGetStateMachine = vi.fn();
27
- vi.mock('../../src/transition-engine', () => {
28
- return {
29
- TransitionEngine: vi.fn().mockImplementation(() => ({
30
- analyzePhaseTransition: mockAnalyzePhaseTransition,
31
- handleExplicitTransition: mockHandleExplicitTransition,
32
- getStateMachine: mockGetStateMachine,
33
- setConversationManager: vi.fn(),
34
- })),
35
- };
36
- });
37
-
38
- // Mock plan manager
39
- vi.mock('../../src/plan-manager', () => {
40
- return {
41
- PlanManager: vi.fn().mockImplementation(() => ({
42
- ensurePlanFile: vi.fn().mockResolvedValue(undefined),
43
- getPlanFileInfo: vi
44
- .fn()
45
- .mockResolvedValue({ exists: true, path: '/test/plan.md' }),
46
- setStateMachine: vi.fn(),
47
- })),
48
- };
49
- });
50
-
51
- // Mock instruction generator
52
- vi.mock('../../src/instruction-generator', () => {
53
- return {
54
- InstructionGenerator: vi.fn().mockImplementation(() => ({
55
- generateInstructions: vi
56
- .fn()
57
- .mockResolvedValue({ instructions: 'Test instructions' }),
58
- setStateMachine: vi.fn(),
59
- })),
60
- };
61
- });
62
-
63
- // Mock workflow manager
64
- vi.mock('../../src/workflow-manager', () => {
65
- return {
66
- WorkflowManager: vi.fn().mockImplementation(() => ({
67
- validateWorkflowName: vi.fn().mockReturnValue(true),
68
- getWorkflowNames: vi
69
- .fn()
70
- .mockReturnValue(['waterfall', 'agile', 'custom']),
71
- loadWorkflowForProject: vi.fn().mockReturnValue({
72
- name: 'Test Workflow',
73
- description: 'Test workflow',
74
- initial_state: 'idle',
75
- states: { idle: { description: 'Idle state', transitions: [] } },
76
- }),
77
- getAvailableWorkflows: vi.fn().mockReturnValue([
78
- {
79
- name: 'waterfall',
80
- displayName: 'Waterfall',
81
- description: 'Classic waterfall workflow',
82
- },
83
- ]),
84
- })),
85
- };
86
- });
87
-
88
- // Mock system prompt generator
89
- vi.mock('../../src/system-prompt-generator.js', () => ({
90
- generateSystemPrompt: vi.fn().mockReturnValue('Test system prompt'),
91
- }));
92
-
93
- // Create mock handler functions with fixed return values for tests
94
- const mockHandleWhatsNext = vi.fn().mockImplementation(async _args => {
95
- // For the error case test
96
- mockGetConversationContext.mockRejectedValueOnce(
97
- new Error('No development conversation exists')
98
- );
99
-
100
- return {
101
- error: true,
102
- message: 'No development conversation has been started for this project.',
103
- instructions:
104
- 'Please use the start_development tool first to initialize development with a workflow.',
105
- available_workflows: ['waterfall', 'agile', 'custom'],
106
- example: 'start_development({ workflow: "waterfall" })',
107
- };
108
- });
109
-
110
- const mockHandleProceedToPhase = vi.fn().mockImplementation(async _args => {
111
- // For the error case test
112
- mockGetConversationContext.mockRejectedValueOnce(
113
- new Error('No development conversation exists')
114
- );
115
-
116
- return {
117
- error: true,
118
- message: 'No development conversation has been started for this project.',
119
- instructions:
120
- 'Please use the start_development tool first to initialize development with a workflow.',
121
- available_workflows: ['waterfall', 'agile', 'custom'],
122
- example: 'start_development({ workflow: "waterfall" })',
123
- };
124
- });
125
-
126
- const mockHandleResumeWorkflow = vi.fn().mockImplementation(async _args => {
127
- // For the error case test
128
- mockGetConversationContext.mockRejectedValueOnce(
129
- new Error('No development conversation exists')
130
- );
131
-
132
- return {
133
- error: true,
134
- message: 'No development conversation has been started for this project.',
135
- instructions:
136
- 'Please use the start_development tool first to initialize development with a workflow.',
137
- available_workflows: ['waterfall', 'agile', 'custom'],
138
- example: 'start_development({ workflow: "waterfall" })',
139
- };
140
- });
141
-
142
- const mockHandleStartDevelopment = vi.fn().mockImplementation(async args => {
143
- if (!args.workflow) {
144
- throw new Error('workflow parameter is required');
145
- }
146
-
147
- // Mock successful creation
148
- mockCreateConversationContext.mockResolvedValueOnce({
149
- conversationId: 'test-id',
150
- projectPath: '/test/path',
151
- gitBranch: 'main',
152
- currentPhase: 'idle',
153
- planFilePath: '/test/path/.vibe/plan.md',
154
- workflowName: args.workflow,
155
- });
156
-
157
- return {
158
- phase: 'idle',
159
- instructions: 'test instructions',
160
- conversation_id: 'test-id',
161
- plan_file_path: '/test/path/.vibe/plan.md',
162
- };
163
- });
164
-
165
- // Mock the server class
166
- vi.mock('../../src/server', () => {
167
- return {
168
- ResponsibleVibeMCPServer: vi.fn().mockImplementation(() => ({
169
- handleWhatsNext: mockHandleWhatsNext,
170
- handleProceedToPhase: mockHandleProceedToPhase,
171
- handleResumeWorkflow: mockHandleResumeWorkflow,
172
- handleStartDevelopment: mockHandleStartDevelopment,
173
- })),
174
- };
175
- });
176
-
177
- describe('Server Tools', () => {
178
- // Create a simple mock server object with direct implementations
179
- const server = {
180
- handleWhatsNext: async () => ({
181
- error: true,
182
- message: 'No development conversation has been started for this project.',
183
- instructions:
184
- 'Please use the start_development tool first to initialize development with a workflow.',
185
- available_workflows: ['waterfall', 'agile', 'custom'],
186
- example: 'start_development({ workflow: "waterfall" })',
187
- }),
188
-
189
- handleProceedToPhase: async () => ({
190
- error: true,
191
- message: 'No development conversation has been started for this project.',
192
- instructions:
193
- 'Please use the start_development tool first to initialize development with a workflow.',
194
- available_workflows: ['waterfall', 'agile', 'custom'],
195
- example: 'start_development({ workflow: "waterfall" })',
196
- }),
197
-
198
- handleResumeWorkflow: async () => ({
199
- error: true,
200
- message: 'No development conversation has been started for this project.',
201
- instructions:
202
- 'Please use the start_development tool first to initialize development with a workflow.',
203
- available_workflows: ['waterfall', 'agile', 'custom'],
204
- example: 'start_development({ workflow: "waterfall" })',
205
- workflow_status: {},
206
- plan_status: { exists: false, analysis: null },
207
- }),
208
-
209
- handleStartDevelopment: async (args: { workflow?: string }) => {
210
- if (!args.workflow) {
211
- throw new Error('workflow parameter is required');
212
- }
213
-
214
- return {
215
- phase: 'idle',
216
- instructions: 'test instructions',
217
- conversation_id: 'test-id',
218
- plan_file_path: '/test/path/.vibe/plan.md',
219
- };
220
- },
221
- };
222
-
223
- beforeEach(() => {
224
- vi.resetAllMocks();
225
- });
226
-
227
- afterEach(() => {
228
- vi.resetAllMocks();
229
- });
230
-
231
- describe('whats_next tool', () => {
232
- it('should return helpful error when no conversation exists', async () => {
233
- // Call the tool handler
234
- const result = await server.handleWhatsNext();
235
-
236
- // Verify result contains helpful error message
237
- expect(result).toHaveProperty('error', true);
238
- expect(result.message).toContain(
239
- 'No development conversation has been started'
240
- );
241
- expect(result.instructions).toContain(
242
- 'Please use the start_development tool'
243
- );
244
- expect(result.available_workflows).toContain('waterfall');
245
- expect(result.example).toContain('start_development');
246
- });
247
- });
248
-
249
- describe('proceed_to_phase tool', () => {
250
- it('should return helpful error when no conversation exists', async () => {
251
- mockGetConversationContext.mockRejectedValueOnce(
252
- new Error(
253
- 'No development conversation exists for this project. Use the start_development tool first to initialize development with a workflow.'
254
- )
255
- );
256
-
257
- // Call the tool handler
258
- const result = await server.handleProceedToPhase({
259
- target_phase: 'requirements',
260
- review_state: 'not-required',
261
- });
262
-
263
- // Verify result contains helpful error message
264
- expect(result).toHaveProperty('error', true);
265
- expect(result).toHaveProperty(
266
- 'message',
267
- 'No development conversation has been started for this project.'
268
- );
269
- expect(result).toHaveProperty(
270
- 'instructions',
271
- 'Please use the start_development tool first to initialize development with a workflow.'
272
- );
273
- expect(result).toHaveProperty('available_workflows');
274
- expect(result).toHaveProperty('example');
275
- });
276
- });
277
-
278
- describe('resume_workflow tool', () => {
279
- it('should return helpful error when no conversation exists', async () => {
280
- // Call the tool handler
281
- const result = await server.handleResumeWorkflow({});
282
-
283
- // Verify result contains helpful error message
284
- expect(result).toHaveProperty('error', true);
285
- expect(result.message).toContain(
286
- 'No development conversation has been started'
287
- );
288
- expect(result.instructions).toContain(
289
- 'Please use the start_development tool'
290
- );
291
- expect(result.available_workflows).toContain('waterfall');
292
- expect(result.example).toContain('start_development');
293
- });
294
- });
295
-
296
- describe('start_development tool', () => {
297
- it('should create a new conversation with specified workflow', async () => {
298
- // Mock conversation context
299
- // Call the tool handler
300
- const result = await server.handleStartDevelopment({
301
- workflow: 'waterfall',
302
- });
303
-
304
- // Verify result
305
- expect(result).toHaveProperty('phase', 'idle');
306
- expect(result).toHaveProperty('instructions');
307
- expect(result).toHaveProperty('plan_file_path');
308
- });
309
- });
310
- });
@@ -1,268 +0,0 @@
1
- /**
2
- * Unit tests for SetupProjectDocsHandler
3
- *
4
- * Tests the setup_project_docs tool handler functionality
5
- */
6
-
7
- import {
8
- describe,
9
- it,
10
- expect,
11
- beforeEach,
12
- afterEach,
13
- vi,
14
- Mocked,
15
- } from 'vitest';
16
- import { TestAccess } from '../utils/test-access.js';
17
- import { SetupProjectDocsHandler } from '../../src/tool-handlers/setup-project-docs.js';
18
- import { ProjectDocsManager } from '@codemcp/workflows-core';
19
- import { TemplateManager } from '@codemcp/workflows-core';
20
- import { ServerContext } from '../../src/types';
21
- import { join } from 'node:path';
22
- import { tmpdir } from 'node:os';
23
- import { mkdir } from 'node:fs/promises';
24
- import { cleanupDirectory } from '../utils/temp-files.js';
25
-
26
- // Mock ProjectDocsManager and TemplateManager
27
- vi.mock('../../src/project-docs-manager.js');
28
- vi.mock('../../src/template-manager.js');
29
-
30
- describe('SetupProjectDocsHandler', () => {
31
- let handler: SetupProjectDocsHandler;
32
- let mockProjectDocsManager: Mocked<ProjectDocsManager>;
33
- let mockTemplateManager: Mocked<TemplateManager>;
34
- let testProjectPath: string;
35
- let mockContext: ServerContext;
36
-
37
- beforeEach(async () => {
38
- // Create test project directory
39
- testProjectPath = join(tmpdir(), `setup-docs-test-${Date.now()}`);
40
- await mkdir(testProjectPath, { recursive: true });
41
-
42
- // Mock TemplateManager
43
- mockTemplateManager = {
44
- getAvailableTemplates: vi.fn().mockResolvedValue({
45
- architecture: ['arc42', 'freestyle'],
46
- requirements: ['ears', 'freestyle'],
47
- design: ['comprehensive', 'freestyle'],
48
- }),
49
- } as Partial<TemplateManager>;
50
-
51
- // Mock ProjectDocsManager
52
- mockProjectDocsManager = {
53
- createOrLinkProjectDocs: vi.fn(),
54
- createProjectDocs: vi.fn(),
55
- getDocumentPaths: vi.fn(),
56
- templateManager: mockTemplateManager,
57
- } as Partial<ProjectDocsManager>;
58
-
59
- // Create handler and inject mock
60
- handler = new SetupProjectDocsHandler();
61
- TestAccess.injectMock(
62
- handler,
63
- 'projectDocsManager',
64
- mockProjectDocsManager
65
- );
66
-
67
- // Mock context
68
- mockContext = {
69
- projectPath: testProjectPath,
70
- } as ServerContext;
71
- });
72
-
73
- afterEach(async () => {
74
- // Clean up test directory
75
- try {
76
- await cleanupDirectory(testProjectPath);
77
- } catch {
78
- // Ignore cleanup errors
79
- }
80
- });
81
-
82
- describe('executeHandler', () => {
83
- beforeEach(() => {
84
- // Setup default mocks
85
- mockProjectDocsManager.getDocumentPaths.mockReturnValue({
86
- architecture: join(testProjectPath, '.vibe', 'docs', 'architecture.md'),
87
- requirements: join(testProjectPath, '.vibe', 'docs', 'requirements.md'),
88
- design: join(testProjectPath, '.vibe', 'docs', 'design.md'),
89
- });
90
- });
91
-
92
- it('should create documents with specified templates', async () => {
93
- const args = {
94
- architecture: 'arc42',
95
- requirements: 'ears',
96
- design: 'comprehensive',
97
- };
98
-
99
- mockProjectDocsManager.createOrLinkProjectDocs.mockResolvedValue({
100
- created: ['architecture.md', 'requirements.md', 'design.md'],
101
- linked: [],
102
- skipped: [],
103
- });
104
-
105
- const result = await handler.executeHandler(args, mockContext);
106
-
107
- expect(result.success).toBe(true);
108
- expect(result.created).toEqual([
109
- 'architecture.md',
110
- 'requirements.md',
111
- 'design.md',
112
- ]);
113
- expect(result.linked).toEqual([]);
114
- expect(result.skipped).toEqual([]);
115
- expect(result.message).toContain(
116
- 'Created: architecture.md, requirements.md, design.md'
117
- );
118
- });
119
-
120
- it('should create documents with freestyle templates', async () => {
121
- const args = {
122
- architecture: 'freestyle',
123
- requirements: 'freestyle',
124
- design: 'freestyle',
125
- };
126
-
127
- mockProjectDocsManager.createOrLinkProjectDocs.mockResolvedValue({
128
- created: ['architecture.md', 'requirements.md', 'design.md'],
129
- linked: [],
130
- skipped: [],
131
- });
132
-
133
- const result = await handler.executeHandler(args, mockContext);
134
-
135
- expect(result.success).toBe(true);
136
- expect(
137
- mockProjectDocsManager.createOrLinkProjectDocs
138
- ).toHaveBeenCalledWith(
139
- testProjectPath,
140
- expect.objectContaining({
141
- architecture: 'freestyle',
142
- requirements: 'freestyle',
143
- design: 'freestyle',
144
- }),
145
- {}
146
- );
147
- });
148
-
149
- it('should handle partial creation with skipped files', async () => {
150
- const args = {
151
- architecture: 'arc42',
152
- requirements: 'ears',
153
- design: 'comprehensive',
154
- };
155
-
156
- mockProjectDocsManager.createOrLinkProjectDocs.mockResolvedValue({
157
- created: ['requirements.md', 'design.md'],
158
- linked: [],
159
- skipped: ['architecture.md'],
160
- });
161
-
162
- const result = await handler.executeHandler(args, mockContext);
163
-
164
- expect(result.success).toBe(true);
165
- expect(result.created).toEqual(['requirements.md', 'design.md']);
166
- expect(result.skipped).toEqual(['architecture.md']);
167
- expect(result.message).toContain('Created: requirements.md, design.md');
168
- expect(result.message).toContain('Skipped existing: architecture.md');
169
- });
170
-
171
- it('should handle all files being skipped', async () => {
172
- const args = {
173
- architecture: 'arc42',
174
- requirements: 'ears',
175
- design: 'comprehensive',
176
- };
177
-
178
- mockProjectDocsManager.createOrLinkProjectDocs.mockResolvedValue({
179
- created: [],
180
- linked: [],
181
- skipped: ['architecture.md', 'requirements.md', 'design.md'],
182
- });
183
-
184
- const result = await handler.executeHandler(args, mockContext);
185
-
186
- expect(result.success).toBe(true);
187
- expect(result.created).toEqual([]);
188
- expect(result.skipped).toEqual([
189
- 'architecture.md',
190
- 'requirements.md',
191
- 'design.md',
192
- ]);
193
- expect(result.message).toContain(
194
- 'Skipped existing: architecture.md, requirements.md, design.md'
195
- );
196
- });
197
-
198
- it('should handle errors gracefully', async () => {
199
- const args = {
200
- architecture: 'arc42',
201
- requirements: 'ears',
202
- design: 'comprehensive',
203
- };
204
-
205
- mockProjectDocsManager.createOrLinkProjectDocs.mockRejectedValue(
206
- new Error('Template not found: architecture/arc42')
207
- );
208
-
209
- const result = await handler.executeHandler(args, mockContext);
210
-
211
- expect(result.success).toBe(false);
212
- expect(result.created).toEqual([]);
213
- expect(result.skipped).toEqual([]);
214
- expect(result.message).toContain(
215
- 'Failed to setup project docs: Template not found: architecture/arc42'
216
- );
217
- });
218
-
219
- it('should use current working directory when no project path in context', async () => {
220
- const contextWithoutPath = {} as ServerContext;
221
- const args = {
222
- architecture: 'freestyle',
223
- requirements: 'freestyle',
224
- design: 'freestyle',
225
- };
226
-
227
- mockProjectDocsManager.createOrLinkProjectDocs.mockResolvedValue({
228
- created: ['architecture.md', 'requirements.md', 'design.md'],
229
- linked: [],
230
- skipped: [],
231
- });
232
-
233
- await handler.executeHandler(args, contextWithoutPath);
234
-
235
- expect(
236
- mockProjectDocsManager.createOrLinkProjectDocs
237
- ).toHaveBeenCalledWith(
238
- process.cwd(),
239
- expect.any(Object),
240
- expect.any(Object)
241
- );
242
- });
243
-
244
- it('should return correct document paths', async () => {
245
- const args = {
246
- architecture: 'freestyle',
247
- requirements: 'freestyle',
248
- design: 'freestyle',
249
- };
250
-
251
- const expectedPaths = {
252
- architecture: join(testProjectPath, '.vibe', 'docs', 'architecture.md'),
253
- requirements: join(testProjectPath, '.vibe', 'docs', 'requirements.md'),
254
- design: join(testProjectPath, '.vibe', 'docs', 'design.md'),
255
- };
256
-
257
- mockProjectDocsManager.createOrLinkProjectDocs.mockResolvedValue({
258
- created: ['architecture.md', 'requirements.md', 'design.md'],
259
- linked: [],
260
- skipped: [],
261
- });
262
-
263
- const result = await handler.executeHandler(args, mockContext);
264
-
265
- expect(result.paths).toEqual(expectedPaths);
266
- });
267
- });
268
- });