@codemcp/workflows-core 3.1.22 → 3.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/package.json +8 -3
- package/resources/templates/architecture/arc42/arc42-template-EN.md +1077 -0
- package/resources/templates/architecture/arc42/images/01_2_iso-25010-topics-EN.drawio-2023.png +0 -0
- package/resources/templates/architecture/arc42/images/01_2_iso-25010-topics-EN.drawio.png +0 -0
- package/resources/templates/architecture/arc42/images/05_building_blocks-EN.png +0 -0
- package/resources/templates/architecture/arc42/images/08-concepts-EN.drawio.png +0 -0
- package/resources/templates/architecture/arc42/images/arc42-logo.png +0 -0
- package/resources/templates/architecture/c4.md +224 -0
- package/resources/templates/architecture/freestyle.md +53 -0
- package/resources/templates/architecture/none.md +17 -0
- package/resources/templates/design/comprehensive.md +207 -0
- package/resources/templates/design/freestyle.md +37 -0
- package/resources/templates/design/none.md +17 -0
- package/resources/templates/requirements/ears.md +90 -0
- package/resources/templates/requirements/freestyle.md +42 -0
- package/resources/templates/requirements/none.md +17 -0
- package/resources/workflows/big-bang-conversion.yaml +539 -0
- package/resources/workflows/boundary-testing.yaml +334 -0
- package/resources/workflows/bugfix.yaml +185 -0
- package/resources/workflows/business-analysis.yaml +671 -0
- package/resources/workflows/c4-analysis.yaml +485 -0
- package/resources/workflows/epcc.yaml +161 -0
- package/resources/workflows/greenfield.yaml +189 -0
- package/resources/workflows/minor.yaml +127 -0
- package/resources/workflows/posts.yaml +207 -0
- package/resources/workflows/slides.yaml +256 -0
- package/resources/workflows/tdd.yaml +157 -0
- package/resources/workflows/waterfall.yaml +195 -0
- package/.turbo/turbo-build.log +0 -4
- package/src/config-manager.ts +0 -96
- package/src/conversation-manager.ts +0 -489
- package/src/database.ts +0 -427
- package/src/file-detection-manager.ts +0 -302
- package/src/git-manager.ts +0 -64
- package/src/index.ts +0 -28
- package/src/instruction-generator.ts +0 -210
- package/src/interaction-logger.ts +0 -109
- package/src/logger.ts +0 -353
- package/src/path-validation-utils.ts +0 -261
- package/src/plan-manager.ts +0 -323
- package/src/project-docs-manager.ts +0 -523
- package/src/state-machine-loader.ts +0 -365
- package/src/state-machine-types.ts +0 -72
- package/src/state-machine.ts +0 -370
- package/src/system-prompt-generator.ts +0 -122
- package/src/template-manager.ts +0 -328
- package/src/transition-engine.ts +0 -386
- package/src/types.ts +0 -60
- package/src/workflow-manager.ts +0 -606
- package/test/unit/conversation-manager.test.ts +0 -179
- package/test/unit/custom-workflow-loading.test.ts +0 -174
- package/test/unit/directory-linking-and-extensions.test.ts +0 -338
- package/test/unit/file-linking-integration.test.ts +0 -256
- package/test/unit/git-commit-integration.test.ts +0 -91
- package/test/unit/git-manager.test.ts +0 -86
- package/test/unit/install-workflow.test.ts +0 -138
- package/test/unit/instruction-generator.test.ts +0 -247
- package/test/unit/list-workflows-filtering.test.ts +0 -68
- package/test/unit/none-template-functionality.test.ts +0 -224
- package/test/unit/project-docs-manager.test.ts +0 -337
- package/test/unit/state-machine-loader.test.ts +0 -234
- package/test/unit/template-manager.test.ts +0 -217
- package/test/unit/validate-workflow-name.test.ts +0 -150
- package/test/unit/workflow-domain-filtering.test.ts +0 -75
- package/test/unit/workflow-enum-generation.test.ts +0 -92
- package/test/unit/workflow-manager-enhanced-path-resolution.test.ts +0 -369
- package/test/unit/workflow-manager-path-resolution.test.ts +0 -150
- package/test/unit/workflow-migration.test.ts +0 -155
- package/test/unit/workflow-override-by-name.test.ts +0 -116
- package/test/unit/workflow-prioritization.test.ts +0 -38
- package/test/unit/workflow-validation.test.ts +0 -303
- package/test/utils/e2e-test-setup.ts +0 -453
- package/test/utils/run-server-in-dir.sh +0 -27
- package/test/utils/temp-files.ts +0 -308
- package/test/utils/test-access.ts +0 -79
- package/test/utils/test-helpers.ts +0 -286
- package/test/utils/test-setup.ts +0 -78
- package/tsconfig.build.json +0 -21
- package/tsconfig.json +0 -8
- package/vitest.config.ts +0 -18
package/test/utils/temp-files.ts
DELETED
@@ -1,308 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Temporary File Management for Integration Tests
|
3
|
-
*
|
4
|
-
* Provides utilities for creating and managing real temporary files
|
5
|
-
* for integration tests that spawn server processes.
|
6
|
-
*/
|
7
|
-
|
8
|
-
import { mkdirSync, writeFileSync, rmSync, existsSync } from 'node:fs';
|
9
|
-
import { join } from 'node:path';
|
10
|
-
import { tmpdir } from 'node:os';
|
11
|
-
|
12
|
-
/**
|
13
|
-
* Temporary test project configuration
|
14
|
-
*/
|
15
|
-
export interface TempProjectOptions {
|
16
|
-
/** Custom state machine YAML content */
|
17
|
-
customStateMachine?: string;
|
18
|
-
/** Project name (used for directory name) */
|
19
|
-
projectName?: string;
|
20
|
-
/** Git branch name */
|
21
|
-
gitBranch?: string;
|
22
|
-
/** Additional files to create */
|
23
|
-
additionalFiles?: Record<string, string>;
|
24
|
-
/** Base directory for the project (defaults to OS temp dir) */
|
25
|
-
baseDirectory?: string;
|
26
|
-
}
|
27
|
-
|
28
|
-
/**
|
29
|
-
* Default state machine YAML for testing
|
30
|
-
*/
|
31
|
-
export const DEFAULT_STATE_MACHINE_YAML = `
|
32
|
-
name: "Development Workflow"
|
33
|
-
description: "State machine for guiding feature development workflow"
|
34
|
-
initial_state: "idle"
|
35
|
-
states:
|
36
|
-
idle:
|
37
|
-
description: "Waiting for feature requests"
|
38
|
-
transitions:
|
39
|
-
- trigger: "new_feature_request"
|
40
|
-
to: "requirements"
|
41
|
-
instructions: "Start requirements analysis by asking the user clarifying questions about WHAT they need. Focus on understanding their goals, scope, and constraints. Break down their needs into specific, actionable tasks and document them in the plan file. Mark completed requirements tasks as you progress."
|
42
|
-
transition_reason: "New feature request detected, starting requirements analysis"
|
43
|
-
requirements:
|
44
|
-
description: "Gathering requirements"
|
45
|
-
transitions:
|
46
|
-
- trigger: "requirements_complete"
|
47
|
-
to: "design"
|
48
|
-
instructions: "Help the user design the technical solution. Ask about quality goals, technology preferences, and architectural decisions. Document the design decisions and update the plan file. Mark completed requirements tasks as done."
|
49
|
-
transition_reason: "Requirements gathering complete, starting design phase"
|
50
|
-
design:
|
51
|
-
description: "Designing solution"
|
52
|
-
transitions:
|
53
|
-
- trigger: "design_complete"
|
54
|
-
to: "implementation"
|
55
|
-
instructions: "Guide the user through implementing the solution. Follow coding best practices, provide structure guidance, and track implementation progress. Update the plan file and mark completed design tasks."
|
56
|
-
transition_reason: "Design phase complete, starting implementation"
|
57
|
-
implementation:
|
58
|
-
description: "Implementing solution"
|
59
|
-
transitions:
|
60
|
-
- trigger: "implementation_complete"
|
61
|
-
to: "qa"
|
62
|
-
instructions: "Guide code review and quality validation. Ensure requirements are properly met, help with testing and documentation. Update the plan file and mark completed implementation tasks."
|
63
|
-
transition_reason: "Implementation phase complete, starting QA"
|
64
|
-
qa:
|
65
|
-
description: "Quality assurance"
|
66
|
-
transitions:
|
67
|
-
- trigger: "qa_complete"
|
68
|
-
to: "testing"
|
69
|
-
instructions: "Guide comprehensive testing strategies. Help create and execute test plans, validate feature completeness. Update the plan file and mark completed QA tasks."
|
70
|
-
transition_reason: "QA phase complete, starting testing"
|
71
|
-
testing:
|
72
|
-
description: "Testing solution"
|
73
|
-
transitions:
|
74
|
-
- trigger: "testing_complete"
|
75
|
-
to: "complete"
|
76
|
-
instructions: "Feature development is complete! All phases have been finished successfully. The feature is ready for delivery."
|
77
|
-
transition_reason: "Testing phase complete, feature development finished"
|
78
|
-
complete:
|
79
|
-
description: "Feature complete"
|
80
|
-
transitions: []
|
81
|
-
|
82
|
-
direct_transitions:
|
83
|
-
- state: "idle"
|
84
|
-
instructions: "Returned to idle state"
|
85
|
-
transition_reason: "Direct transition to idle state"
|
86
|
-
- state: "requirements"
|
87
|
-
instructions: "Starting requirements analysis"
|
88
|
-
transition_reason: "Direct transition to requirements phase"
|
89
|
-
- state: "design"
|
90
|
-
instructions: "Starting design phase"
|
91
|
-
transition_reason: "Direct transition to design phase"
|
92
|
-
- state: "implementation"
|
93
|
-
instructions: "Starting implementation phase"
|
94
|
-
transition_reason: "Direct transition to implementation phase"
|
95
|
-
- state: "qa"
|
96
|
-
instructions: "Starting QA phase"
|
97
|
-
transition_reason: "Direct transition to QA phase"
|
98
|
-
- state: "testing"
|
99
|
-
instructions: "Starting testing phase"
|
100
|
-
transition_reason: "Direct transition to testing phase"
|
101
|
-
- state: "complete"
|
102
|
-
instructions: "Feature development complete"
|
103
|
-
transition_reason: "Direct transition to complete phase"
|
104
|
-
`;
|
105
|
-
|
106
|
-
/**
|
107
|
-
* Custom state machine YAML for testing
|
108
|
-
*/
|
109
|
-
export const CUSTOM_STATE_MACHINE_YAML = `
|
110
|
-
name: "Custom Test State Machine"
|
111
|
-
description: "Simple two-phase state machine for testing"
|
112
|
-
initial_state: "phase1"
|
113
|
-
states:
|
114
|
-
phase1:
|
115
|
-
description: "First test phase"
|
116
|
-
transitions:
|
117
|
-
- trigger: "move_to_phase2"
|
118
|
-
to: "phase2"
|
119
|
-
instructions: "Moving to phase 2"
|
120
|
-
transition_reason: "Transition to phase 2 triggered"
|
121
|
-
phase2:
|
122
|
-
description: "Second test phase"
|
123
|
-
transitions: []
|
124
|
-
direct_transitions:
|
125
|
-
- state: "phase1"
|
126
|
-
instructions: "Direct to phase 1"
|
127
|
-
transition_reason: "Direct transition to phase 1"
|
128
|
-
- state: "phase2"
|
129
|
-
instructions: "Direct to phase 2"
|
130
|
-
transition_reason: "Direct transition to phase 2"
|
131
|
-
`;
|
132
|
-
|
133
|
-
/**
|
134
|
-
* Temporary project manager
|
135
|
-
*/
|
136
|
-
export class TempProject {
|
137
|
-
public readonly projectPath: string;
|
138
|
-
private readonly cleanupPaths: string[] = [];
|
139
|
-
|
140
|
-
constructor(options: TempProjectOptions = {}) {
|
141
|
-
const {
|
142
|
-
projectName = `test-project-${Date.now()}`,
|
143
|
-
gitBranch = 'main',
|
144
|
-
customStateMachine,
|
145
|
-
additionalFiles = {},
|
146
|
-
baseDirectory = tmpdir(),
|
147
|
-
} = options;
|
148
|
-
|
149
|
-
// Create temporary project directory
|
150
|
-
this.projectPath = join(
|
151
|
-
baseDirectory,
|
152
|
-
'responsible-vibe-tests',
|
153
|
-
projectName
|
154
|
-
);
|
155
|
-
this.cleanupPaths.push(this.projectPath);
|
156
|
-
|
157
|
-
// Create directory structure
|
158
|
-
mkdirSync(this.projectPath, { recursive: true });
|
159
|
-
mkdirSync(join(this.projectPath, '.vibe'), { recursive: true });
|
160
|
-
mkdirSync(join(this.projectPath, '.git'), { recursive: true });
|
161
|
-
|
162
|
-
// Create basic project files
|
163
|
-
writeFileSync(
|
164
|
-
join(this.projectPath, 'package.json'),
|
165
|
-
JSON.stringify(
|
166
|
-
{
|
167
|
-
name: projectName,
|
168
|
-
version: '1.0.0',
|
169
|
-
},
|
170
|
-
null,
|
171
|
-
2
|
172
|
-
)
|
173
|
-
);
|
174
|
-
|
175
|
-
// Create git branch file
|
176
|
-
writeFileSync(
|
177
|
-
join(this.projectPath, '.git', 'HEAD'),
|
178
|
-
`ref: refs/heads/${gitBranch}`
|
179
|
-
);
|
180
|
-
|
181
|
-
// Create custom state machine if provided
|
182
|
-
if (customStateMachine) {
|
183
|
-
writeFileSync(
|
184
|
-
join(this.projectPath, '.vibe', 'workflow.yaml'),
|
185
|
-
customStateMachine
|
186
|
-
);
|
187
|
-
}
|
188
|
-
|
189
|
-
// Create additional files
|
190
|
-
for (const [filePath, content] of Object.entries(additionalFiles)) {
|
191
|
-
const fullPath = join(this.projectPath, filePath);
|
192
|
-
const dir = fullPath.substring(0, fullPath.lastIndexOf('/'));
|
193
|
-
mkdirSync(dir, { recursive: true });
|
194
|
-
writeFileSync(fullPath, content);
|
195
|
-
}
|
196
|
-
}
|
197
|
-
|
198
|
-
/**
|
199
|
-
* Add a file to the project
|
200
|
-
*/
|
201
|
-
addFile(relativePath: string, content: string): void {
|
202
|
-
const fullPath = join(this.projectPath, relativePath);
|
203
|
-
const dir = fullPath.substring(0, fullPath.lastIndexOf('/'));
|
204
|
-
mkdirSync(dir, { recursive: true });
|
205
|
-
writeFileSync(fullPath, content);
|
206
|
-
}
|
207
|
-
|
208
|
-
/**
|
209
|
-
* Check if a file exists in the project
|
210
|
-
*/
|
211
|
-
hasFile(relativePath: string): boolean {
|
212
|
-
return existsSync(join(this.projectPath, relativePath));
|
213
|
-
}
|
214
|
-
|
215
|
-
/**
|
216
|
-
* Add mock project documents to satisfy artifact checking
|
217
|
-
*/
|
218
|
-
addMockProjectDocs(): void {
|
219
|
-
this.addFile(
|
220
|
-
'.vibe/docs/architecture.md',
|
221
|
-
'# Architecture\n\nMock architecture document for testing.'
|
222
|
-
);
|
223
|
-
this.addFile(
|
224
|
-
'.vibe/docs/requirements.md',
|
225
|
-
'# Requirements\n\nMock requirements document for testing.'
|
226
|
-
);
|
227
|
-
this.addFile(
|
228
|
-
'.vibe/docs/design.md',
|
229
|
-
'# Design\n\nMock design document for testing.'
|
230
|
-
);
|
231
|
-
}
|
232
|
-
|
233
|
-
/**
|
234
|
-
* Clean up the temporary project
|
235
|
-
*/
|
236
|
-
cleanup(): void {
|
237
|
-
for (const path of this.cleanupPaths) {
|
238
|
-
if (existsSync(path)) {
|
239
|
-
rmSync(path, { recursive: true, force: true });
|
240
|
-
}
|
241
|
-
}
|
242
|
-
}
|
243
|
-
}
|
244
|
-
|
245
|
-
/**
|
246
|
-
* Create a temporary project with custom state machine
|
247
|
-
*/
|
248
|
-
export function createTempProjectWithCustomStateMachine(
|
249
|
-
customStateMachine: string = CUSTOM_STATE_MACHINE_YAML,
|
250
|
-
baseDirectory?: string
|
251
|
-
): TempProject {
|
252
|
-
const project = new TempProject({
|
253
|
-
customStateMachine,
|
254
|
-
projectName: `custom-sm-${Date.now()}`,
|
255
|
-
baseDirectory,
|
256
|
-
});
|
257
|
-
|
258
|
-
// Add mock project documents to satisfy artifact checking
|
259
|
-
project.addMockProjectDocs();
|
260
|
-
|
261
|
-
return project;
|
262
|
-
}
|
263
|
-
|
264
|
-
/**
|
265
|
-
* Create a temporary project with default state machine (no custom one)
|
266
|
-
*/
|
267
|
-
export function createTempProjectWithDefaultStateMachine(
|
268
|
-
baseDirectory?: string
|
269
|
-
): TempProject {
|
270
|
-
const project = new TempProject({
|
271
|
-
projectName: `default-sm-${Date.now()}`,
|
272
|
-
baseDirectory,
|
273
|
-
});
|
274
|
-
|
275
|
-
// Add mock project documents to satisfy artifact checking
|
276
|
-
project.addMockProjectDocs();
|
277
|
-
|
278
|
-
return project;
|
279
|
-
}
|
280
|
-
|
281
|
-
/**
|
282
|
-
* Helper to safely parse JSON responses from server, handling error cases
|
283
|
-
*/
|
284
|
-
export function safeParseServerResponse(
|
285
|
-
content: Array<{ text?: string }>
|
286
|
-
): unknown {
|
287
|
-
if (!content || content.length === 0) {
|
288
|
-
throw new Error('No content in server response');
|
289
|
-
}
|
290
|
-
|
291
|
-
const text = content[0].text;
|
292
|
-
if (!text) {
|
293
|
-
throw new Error('No text content in server response');
|
294
|
-
}
|
295
|
-
|
296
|
-
// If the response starts with "Error:", it's an error message, not JSON
|
297
|
-
if (typeof text === 'string' && text.startsWith('Error:')) {
|
298
|
-
throw new Error(`Server error: ${text}`);
|
299
|
-
}
|
300
|
-
|
301
|
-
try {
|
302
|
-
return JSON.parse(text);
|
303
|
-
} catch {
|
304
|
-
throw new Error(
|
305
|
-
`Failed to parse server response as JSON: ${text.substring(0, 100)}...`
|
306
|
-
);
|
307
|
-
}
|
308
|
-
}
|
@@ -1,79 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Test Access Utilities
|
3
|
-
*
|
4
|
-
* Clean utilities for accessing private methods and properties in tests
|
5
|
-
* without using @ts-ignore or unsafe type assertions.
|
6
|
-
*
|
7
|
-
* Note: Uses 'any' types intentionally for test utilities to access private members
|
8
|
-
*/
|
9
|
-
|
10
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
11
|
-
|
12
|
-
/**
|
13
|
-
* Safely access a private property for testing purposes
|
14
|
-
* @param instance - The class instance
|
15
|
-
* @param propertyName - The name of the private property
|
16
|
-
* @returns The property value
|
17
|
-
*/
|
18
|
-
export function getPrivateProperty<T, K extends keyof T>(
|
19
|
-
instance: T,
|
20
|
-
propertyName: K
|
21
|
-
): T[K] {
|
22
|
-
return (instance as any)[propertyName];
|
23
|
-
}
|
24
|
-
|
25
|
-
/**
|
26
|
-
* Safely set a private property for testing purposes (e.g., injecting mocks)
|
27
|
-
* @param instance - The class instance
|
28
|
-
* @param propertyName - The name of the private property
|
29
|
-
* @param value - The value to set
|
30
|
-
*/
|
31
|
-
export function setPrivateProperty<T, K extends keyof T>(
|
32
|
-
instance: T,
|
33
|
-
propertyName: K,
|
34
|
-
value: T[K]
|
35
|
-
): void {
|
36
|
-
(instance as any)[propertyName] = value;
|
37
|
-
}
|
38
|
-
|
39
|
-
/**
|
40
|
-
* Safely call a private method for testing purposes
|
41
|
-
* @param instance - The class instance
|
42
|
-
* @param methodName - The name of the private method
|
43
|
-
* @param args - Arguments to pass to the method
|
44
|
-
* @returns The method return value
|
45
|
-
*/
|
46
|
-
export function callPrivateMethod<T>(
|
47
|
-
instance: T,
|
48
|
-
methodName: string,
|
49
|
-
...args: unknown[]
|
50
|
-
): unknown {
|
51
|
-
return (instance as any)[methodName](...args);
|
52
|
-
}
|
53
|
-
|
54
|
-
/**
|
55
|
-
* Type-safe helper specifically for common test scenarios
|
56
|
-
*/
|
57
|
-
export class TestAccess {
|
58
|
-
/**
|
59
|
-
* Inject a mock dependency into a private property
|
60
|
-
*/
|
61
|
-
static injectMock<T>(
|
62
|
-
instance: T,
|
63
|
-
propertyName: string,
|
64
|
-
mockValue: unknown
|
65
|
-
): void {
|
66
|
-
setPrivateProperty(instance, propertyName as keyof T, mockValue);
|
67
|
-
}
|
68
|
-
|
69
|
-
/**
|
70
|
-
* Call a private method with proper typing
|
71
|
-
*/
|
72
|
-
static callMethod<T>(
|
73
|
-
instance: T,
|
74
|
-
methodName: string,
|
75
|
-
...args: unknown[]
|
76
|
-
): unknown {
|
77
|
-
return callPrivateMethod(instance, methodName, ...args);
|
78
|
-
}
|
79
|
-
}
|
@@ -1,286 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Shared Test Utilities
|
3
|
-
*
|
4
|
-
* Common utilities to eliminate repetition across test files
|
5
|
-
*/
|
6
|
-
|
7
|
-
import { mkdirSync, writeFileSync, existsSync } from 'node:fs';
|
8
|
-
import { execSync } from 'node:child_process';
|
9
|
-
import { join } from 'node:path';
|
10
|
-
import { vi, expect } from 'vitest';
|
11
|
-
import {
|
12
|
-
ResponsibleVibeMCPServer,
|
13
|
-
createResponsibleVibeMCPServer,
|
14
|
-
StartDevelopmentResult,
|
15
|
-
} from '../../packages/mcp-server/src/server.js';
|
16
|
-
import type { ServerContext } from '../../packages/mcp-server/src/types';
|
17
|
-
import { TempProject } from './temp-files.js';
|
18
|
-
|
19
|
-
/**
|
20
|
-
* Mock project documents content
|
21
|
-
*/
|
22
|
-
export const MOCK_DOCS = {
|
23
|
-
architecture: '# Architecture\n\nMock architecture document for testing.',
|
24
|
-
requirements: '# Requirements\n\nMock requirements document for testing.',
|
25
|
-
design: '# Design\n\nMock design document for testing.',
|
26
|
-
} as const;
|
27
|
-
|
28
|
-
/**
|
29
|
-
* Git repository setup utilities
|
30
|
-
*/
|
31
|
-
export class GitTestHelper {
|
32
|
-
static initializeRepo(projectPath: string): void {
|
33
|
-
execSync('git init', { cwd: projectPath });
|
34
|
-
execSync('git config user.email "test@example.com"', { cwd: projectPath });
|
35
|
-
execSync('git config user.name "Test User"', { cwd: projectPath });
|
36
|
-
}
|
37
|
-
|
38
|
-
static createInitialCommit(projectPath: string): void {
|
39
|
-
writeFileSync(join(projectPath, 'README.md'), '# Test Project');
|
40
|
-
execSync('git add .', { cwd: projectPath });
|
41
|
-
execSync('git commit -m "Initial commit"', { cwd: projectPath });
|
42
|
-
}
|
43
|
-
|
44
|
-
static createFeatureBranch(
|
45
|
-
projectPath: string,
|
46
|
-
branchName: string = 'feature/test'
|
47
|
-
): void {
|
48
|
-
execSync(`git checkout -b ${branchName}`, { cwd: projectPath });
|
49
|
-
}
|
50
|
-
|
51
|
-
static setupFullRepo(projectPath: string, branchName?: string): void {
|
52
|
-
this.initializeRepo(projectPath);
|
53
|
-
this.createInitialCommit(projectPath);
|
54
|
-
if (branchName) {
|
55
|
-
this.createFeatureBranch(projectPath, branchName);
|
56
|
-
}
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
/**
|
61
|
-
* Server test utilities
|
62
|
-
*/
|
63
|
-
export class ServerTestHelper {
|
64
|
-
static async createServer(
|
65
|
-
projectPath: string,
|
66
|
-
options: { enableLogging?: boolean } = {}
|
67
|
-
): Promise<ResponsibleVibeMCPServer> {
|
68
|
-
const server = await createResponsibleVibeMCPServer({
|
69
|
-
projectPath,
|
70
|
-
enableLogging: options.enableLogging ?? false,
|
71
|
-
});
|
72
|
-
await server.initialize();
|
73
|
-
return server;
|
74
|
-
}
|
75
|
-
|
76
|
-
static async cleanupServer(server: ResponsibleVibeMCPServer): Promise<void> {
|
77
|
-
if (server) {
|
78
|
-
await server.cleanup();
|
79
|
-
}
|
80
|
-
}
|
81
|
-
}
|
82
|
-
|
83
|
-
/**
|
84
|
-
* Mock project documents utilities
|
85
|
-
*/
|
86
|
-
export class MockDocsHelper {
|
87
|
-
static addToProject(projectPath: string): void {
|
88
|
-
const docsDir = join(projectPath, '.vibe', 'docs');
|
89
|
-
mkdirSync(docsDir, { recursive: true });
|
90
|
-
|
91
|
-
for (const [docType, content] of Object.entries(MOCK_DOCS)) {
|
92
|
-
writeFileSync(join(docsDir, `${docType}.md`), content);
|
93
|
-
}
|
94
|
-
}
|
95
|
-
|
96
|
-
static addToTempProject(tempProject: TempProject): void {
|
97
|
-
tempProject.addMockProjectDocs();
|
98
|
-
}
|
99
|
-
|
100
|
-
static ensureExists(projectPath: string): void {
|
101
|
-
if (!existsSync(join(projectPath, '.vibe', 'docs'))) {
|
102
|
-
this.addToProject(projectPath);
|
103
|
-
}
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
/**
|
108
|
-
* Mock context factory for unit tests
|
109
|
-
*/
|
110
|
-
export class MockContextFactory {
|
111
|
-
static createBasicContext(
|
112
|
-
projectPath: string,
|
113
|
-
overrides: Partial<ServerContext> = {}
|
114
|
-
) {
|
115
|
-
return {
|
116
|
-
projectPath,
|
117
|
-
workflowManager: {
|
118
|
-
validateWorkflowName: vi.fn().mockReturnValue(true),
|
119
|
-
getWorkflowNames: vi
|
120
|
-
.fn()
|
121
|
-
.mockReturnValue(['waterfall', 'epcc', 'greenfield']),
|
122
|
-
loadProjectWorkflows: vi.fn(),
|
123
|
-
loadWorkflowForProject: vi.fn().mockReturnValue({
|
124
|
-
initial_state: 'requirements',
|
125
|
-
states: {
|
126
|
-
requirements: {
|
127
|
-
description: 'Define requirements',
|
128
|
-
instructions: 'Create detailed requirements for the project.',
|
129
|
-
},
|
130
|
-
},
|
131
|
-
}),
|
132
|
-
},
|
133
|
-
conversationManager: {
|
134
|
-
createConversationContext: vi.fn().mockResolvedValue({
|
135
|
-
conversationId: 'test-conversation',
|
136
|
-
currentPhase: 'requirements',
|
137
|
-
projectPath,
|
138
|
-
planFilePath: join(projectPath, '.vibe', 'plan.md'),
|
139
|
-
gitBranch: 'feature-branch',
|
140
|
-
}),
|
141
|
-
updateConversationState: vi.fn(),
|
142
|
-
},
|
143
|
-
transitionEngine: {
|
144
|
-
handleExplicitTransition: vi.fn().mockResolvedValue({
|
145
|
-
newPhase: 'requirements',
|
146
|
-
}),
|
147
|
-
},
|
148
|
-
planManager: {
|
149
|
-
setStateMachine: vi.fn(),
|
150
|
-
ensurePlanFile: vi.fn(),
|
151
|
-
},
|
152
|
-
...overrides,
|
153
|
-
};
|
154
|
-
}
|
155
|
-
|
156
|
-
static createProjectDocsManagerMock(projectPath: string) {
|
157
|
-
return {
|
158
|
-
getProjectDocsInfo: vi.fn(),
|
159
|
-
getVariableSubstitutions: vi.fn().mockReturnValue({
|
160
|
-
$ARCHITECTURE_DOC: join(
|
161
|
-
projectPath,
|
162
|
-
'.vibe',
|
163
|
-
'docs',
|
164
|
-
'architecture.md'
|
165
|
-
),
|
166
|
-
$REQUIREMENTS_DOC: join(
|
167
|
-
projectPath,
|
168
|
-
'.vibe',
|
169
|
-
'docs',
|
170
|
-
'requirements.md'
|
171
|
-
),
|
172
|
-
$DESIGN_DOC: join(projectPath, '.vibe', 'docs', 'design.md'),
|
173
|
-
}),
|
174
|
-
templateManager: {
|
175
|
-
getAvailableTemplates: vi.fn().mockResolvedValue({
|
176
|
-
architecture: ['arc42', 'freestyle'],
|
177
|
-
requirements: ['ears', 'freestyle'],
|
178
|
-
design: ['comprehensive', 'freestyle'],
|
179
|
-
}),
|
180
|
-
getDefaults: vi.fn().mockResolvedValue({
|
181
|
-
architecture: 'freestyle',
|
182
|
-
requirements: 'freestyle',
|
183
|
-
design: 'freestyle',
|
184
|
-
}),
|
185
|
-
},
|
186
|
-
};
|
187
|
-
}
|
188
|
-
}
|
189
|
-
|
190
|
-
/**
|
191
|
-
* Test workflow patterns
|
192
|
-
*/
|
193
|
-
export const TEST_WORKFLOWS = {
|
194
|
-
simple: {
|
195
|
-
initial_state: 'requirements',
|
196
|
-
states: {
|
197
|
-
requirements: {
|
198
|
-
description: 'Define requirements',
|
199
|
-
instructions: 'Create detailed requirements for the project.',
|
200
|
-
},
|
201
|
-
},
|
202
|
-
},
|
203
|
-
|
204
|
-
withArchDoc: {
|
205
|
-
initial_state: 'design',
|
206
|
-
states: {
|
207
|
-
design: {
|
208
|
-
description: 'Create design',
|
209
|
-
instructions:
|
210
|
-
'Review the architecture in $ARCHITECTURE_DOC and create detailed design.',
|
211
|
-
},
|
212
|
-
},
|
213
|
-
},
|
214
|
-
|
215
|
-
withMultipleDocs: {
|
216
|
-
initial_state: 'implementation',
|
217
|
-
states: {
|
218
|
-
implementation: {
|
219
|
-
description: 'Implement solution',
|
220
|
-
instructions:
|
221
|
-
'Follow the architecture in $ARCHITECTURE_DOC and implement according to $DESIGN_DOC requirements.',
|
222
|
-
},
|
223
|
-
testing: {
|
224
|
-
description: 'Test solution',
|
225
|
-
instructions: 'Verify all requirements from $REQUIREMENTS_DOC are met.',
|
226
|
-
},
|
227
|
-
},
|
228
|
-
},
|
229
|
-
|
230
|
-
// Test workflows with requiresDocumentation: true
|
231
|
-
requiredArchDoc: {
|
232
|
-
initial_state: 'design',
|
233
|
-
metadata: {
|
234
|
-
requiresDocumentation: true,
|
235
|
-
},
|
236
|
-
states: {
|
237
|
-
design: {
|
238
|
-
description: 'Create design',
|
239
|
-
instructions:
|
240
|
-
'Review the architecture in $ARCHITECTURE_DOC and create detailed design.',
|
241
|
-
},
|
242
|
-
},
|
243
|
-
},
|
244
|
-
|
245
|
-
requiredMultipleDocs: {
|
246
|
-
initial_state: 'implementation',
|
247
|
-
metadata: {
|
248
|
-
requiresDocumentation: true,
|
249
|
-
},
|
250
|
-
states: {
|
251
|
-
implementation: {
|
252
|
-
description: 'Implement solution',
|
253
|
-
instructions:
|
254
|
-
'Follow the architecture in $ARCHITECTURE_DOC and implement according to $DESIGN_DOC requirements.',
|
255
|
-
},
|
256
|
-
testing: {
|
257
|
-
description: 'Test solution',
|
258
|
-
instructions: 'Verify all requirements from $REQUIREMENTS_DOC are met.',
|
259
|
-
},
|
260
|
-
},
|
261
|
-
},
|
262
|
-
} as const;
|
263
|
-
|
264
|
-
/**
|
265
|
-
* Common test assertions
|
266
|
-
*/
|
267
|
-
export class TestAssertions {
|
268
|
-
static expectValidResult(result: StartDevelopmentResult): void {
|
269
|
-
expect(result).toBeTypeOf('object');
|
270
|
-
expect(result.phase).toBeDefined();
|
271
|
-
expect(result.instructions).toBeDefined();
|
272
|
-
}
|
273
|
-
|
274
|
-
static expectArtifactSetupPhase(result: StartDevelopmentResult): void {
|
275
|
-
expect(result.phase).toBe('artifact-setup');
|
276
|
-
expect(result.instructions).toContain('Referenced Variables');
|
277
|
-
}
|
278
|
-
|
279
|
-
static expectNormalPhase(
|
280
|
-
result: StartDevelopmentResult,
|
281
|
-
expectedPhase: string
|
282
|
-
): void {
|
283
|
-
expect(result.phase).toBe(expectedPhase);
|
284
|
-
expect(result.instructions).toBeDefined();
|
285
|
-
}
|
286
|
-
}
|