@codemcp/workflows 5.0.0 → 5.1.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.
Files changed (77) hide show
  1. package/SKILL.md +23 -0
  2. package/package.json +6 -2
  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,451 +0,0 @@
1
- /**
2
- * End-to-End Test Setup Utilities
3
- *
4
- * Provides utilities for testing the MCP server end-to-end without
5
- * spawning separate processes or using transport layers. Tests the
6
- * server's public interface directly for true consumer perspective testing.
7
- */
8
-
9
- import { vi } from 'vitest';
10
- import {
11
- ResponsibleVibeMCPServer,
12
- createResponsibleVibeMCPServer,
13
- ServerConfig,
14
- } from '../../src/server.js';
15
- import { TempProject } from './temp-files.js';
16
- import { join } from 'node:path';
17
- import { tmpdir } from 'node:os';
18
- import { mkdirSync, rmSync, existsSync } from 'node:fs';
19
- import type { ServerContext } from '../../src/types';
20
-
21
- // Disable fs mocking for E2E tests
22
- vi.unmock('fs');
23
- vi.unmock('fs/promises');
24
-
25
- /**
26
- * Suite-level test isolation manager
27
- * Ensures each test suite gets its own isolated temporary directory
28
- */
29
- export class TestSuiteIsolation {
30
- private static suiteDirectories = new Map<string, string>();
31
- private static cleanupCallbacks = new Map<string, (() => void)[]>();
32
-
33
- /**
34
- * Get or create an isolated directory for a test suite
35
- */
36
- static getSuiteDirectory(suiteName: string): string {
37
- if (!this.suiteDirectories.has(suiteName)) {
38
- // Create unique directory for this suite
39
- const suiteId = `${suiteName.replace(/[^a-zA-Z0-9]/g, '-')}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
40
- const suiteDir = join(tmpdir(), 'responsible-vibe-e2e-suites', suiteId);
41
-
42
- // Ensure directory exists
43
- mkdirSync(suiteDir, { recursive: true });
44
-
45
- this.suiteDirectories.set(suiteName, suiteDir);
46
- this.cleanupCallbacks.set(suiteName, []);
47
- }
48
-
49
- const directory = this.suiteDirectories.get(suiteName);
50
- if (!directory) {
51
- throw new Error(`Suite directory not found for ${suiteName}`);
52
- }
53
- return directory;
54
- }
55
-
56
- /**
57
- * Register a cleanup callback for a suite
58
- */
59
- static registerCleanup(suiteName: string, cleanup: () => void): void {
60
- const callbacks = this.cleanupCallbacks.get(suiteName) || [];
61
- callbacks.push(cleanup);
62
- this.cleanupCallbacks.set(suiteName, callbacks);
63
- }
64
-
65
- /**
66
- * Clean up all resources for a test suite
67
- */
68
- static async cleanupSuite(suiteName: string): Promise<void> {
69
- // Run all registered cleanup callbacks
70
- const callbacks = this.cleanupCallbacks.get(suiteName) || [];
71
- for (const cleanup of callbacks) {
72
- try {
73
- cleanup();
74
- } catch (error) {
75
- console.warn(`Cleanup callback failed for suite ${suiteName}:`, error);
76
- }
77
- }
78
-
79
- // Remove the suite directory
80
- const suiteDir = this.suiteDirectories.get(suiteName);
81
- if (suiteDir && existsSync(suiteDir)) {
82
- try {
83
- rmSync(suiteDir, { recursive: true, force: true });
84
- } catch (error) {
85
- console.warn(`Failed to remove suite directory ${suiteDir}:`, error);
86
- }
87
- }
88
-
89
- // Clean up tracking
90
- this.suiteDirectories.delete(suiteName);
91
- this.cleanupCallbacks.delete(suiteName);
92
- }
93
-
94
- /**
95
- * Clean up all suites (for global teardown)
96
- */
97
- static async cleanupAll(): Promise<void> {
98
- const suiteNames = Array.from(this.suiteDirectories.keys());
99
- for (const suiteName of suiteNames) {
100
- await this.cleanupSuite(suiteName);
101
- }
102
- }
103
- }
104
-
105
- /**
106
- * E2E test context that provides direct access to MCP server
107
- */
108
- export interface E2ETestContext {
109
- server: ResponsibleVibeMCPServer;
110
- tempProject: TempProject;
111
- cleanup: () => Promise<void>;
112
- }
113
-
114
- /**
115
- * Direct Server Interface
116
- * Provides a consumer-like interface that calls server methods directly
117
- * without going through MCP transport layer
118
- */
119
- export class DirectServerInterface {
120
- constructor(private server: ResponsibleVibeMCPServer) {}
121
-
122
- /**
123
- * Call a tool on the server directly
124
- */
125
- async callTool<T = unknown>(name: string, arguments_: unknown): Promise<T> {
126
- try {
127
- // Call the server's tool handlers directly based on tool name
128
- switch (name) {
129
- case 'whats_next':
130
- return await this.server.handleWhatsNext(arguments_);
131
-
132
- case 'proceed_to_phase':
133
- return await this.server.handleProceedToPhase(arguments_);
134
-
135
- case 'start_development':
136
- return await this.server.handleStartDevelopment(arguments_);
137
-
138
- default:
139
- throw new Error(`Unknown tool: ${name}`);
140
- }
141
- } catch (error) {
142
- // Return errors as objects instead of throwing them
143
- // This matches the expected behavior in tests
144
- return {
145
- error: error instanceof Error ? error.message : String(error),
146
- };
147
- }
148
- }
149
-
150
- /**
151
- * Read a resource from the server directly
152
- */
153
- async readResource<T = unknown>(uri: string): Promise<T> {
154
- // Call the server's resource handlers directly based on URI
155
- switch (uri) {
156
- case 'state://current':
157
- return await this.getConversationState();
158
-
159
- case 'plan://current':
160
- return await this.getDevelopmentPlan();
161
-
162
- case 'system-prompt://':
163
- return await this.getSystemPrompt();
164
-
165
- default:
166
- throw new Error(`Unknown resource URI: ${uri}`);
167
- }
168
- }
169
-
170
- /**
171
- * Get conversation state directly
172
- */
173
- private async getConversationState(): Promise<unknown> {
174
- const conversationManager = this.server.getConversationManager();
175
- const conversationContext =
176
- await conversationManager.getConversationContext();
177
-
178
- const stateData = {
179
- conversationId: conversationContext.conversationId,
180
- currentPhase: conversationContext.currentPhase,
181
- projectPath: conversationContext.projectPath,
182
- timestamp: new Date().toISOString(),
183
- };
184
-
185
- return {
186
- contents: [
187
- {
188
- uri: 'state://current',
189
- mimeType: 'application/json',
190
- text: JSON.stringify(stateData, null, 2),
191
- },
192
- ],
193
- };
194
- }
195
-
196
- /**
197
- * Get development plan directly
198
- */
199
- private async getDevelopmentPlan(): Promise<unknown> {
200
- const conversationManager = this.server.getConversationManager();
201
- const planManager = this.server.getPlanManager();
202
-
203
- const conversationContext =
204
- await conversationManager.getConversationContext();
205
- const planFilePath = conversationContext.planFilePath;
206
-
207
- let planContent: string;
208
- try {
209
- planContent = await planManager.getPlanFileContent(planFilePath);
210
- } catch {
211
- // If plan file doesn't exist yet, return a default message
212
- planContent = `# Development Plan\n\nPlan file will be created when development begins.\n\nConversation ID: ${conversationContext.conversationId}`;
213
- }
214
-
215
- return {
216
- contents: [
217
- {
218
- uri: 'plan://current',
219
- mimeType: 'text/markdown',
220
- text: planContent,
221
- },
222
- ],
223
- };
224
- }
225
-
226
- /**
227
- * Get system prompt resource directly
228
- */
229
- async getSystemPrompt(): Promise<unknown> {
230
- // Use the system prompt handler directly with the default workflow
231
- const { SystemPromptResourceHandler } =
232
- await import('../../src/resource-handlers/system-prompt.js');
233
- const handler = new SystemPromptResourceHandler();
234
-
235
- // Create a minimal context - system prompt doesn't need full server context
236
- const result = await handler.handle(
237
- new URL('system-prompt://'),
238
- {} as ServerContext
239
- );
240
-
241
- return {
242
- contents: [
243
- {
244
- uri: 'system-prompt://',
245
- mimeType: result.mimeType,
246
- text: result.text,
247
- },
248
- ],
249
- };
250
- }
251
-
252
- /**
253
- * List available tools (for testing completeness)
254
- */
255
- async listTools(): Promise<{ tools: { name: string }[] }> {
256
- return {
257
- tools: [{ name: 'whats_next' }, { name: 'proceed_to_phase' }],
258
- };
259
- }
260
-
261
- /**
262
- * List available resources (for testing completeness)
263
- */
264
- async listResources(): Promise<{ resources: { uri: string }[] }> {
265
- return {
266
- resources: [
267
- { uri: 'state://current' },
268
- { uri: 'plan://current' },
269
- { uri: 'system-prompt://' },
270
- ],
271
- };
272
- }
273
-
274
- /**
275
- * Get a prompt (if we add prompt support later)
276
- */
277
- async getPrompt(name: string, arguments_: unknown = {}): Promise<unknown> {
278
- // For now, just return a placeholder
279
- return {
280
- description: `Prompt for ${name}`,
281
- messages: [
282
- {
283
- role: 'user',
284
- content: {
285
- type: 'text',
286
- text: `Prompt: ${name} with args: ${JSON.stringify(arguments_)}`,
287
- },
288
- },
289
- ],
290
- };
291
- }
292
- }
293
-
294
- /**
295
- * Setup end-to-end test environment with real MCP server
296
- */
297
- export async function setupE2ETest(
298
- options: {
299
- tempProject: TempProject;
300
- serverConfig?: Partial<ServerConfig>;
301
- } = {} as {
302
- tempProject: TempProject;
303
- serverConfig?: Partial<ServerConfig>;
304
- }
305
- ): Promise<E2ETestContext> {
306
- const { tempProject, serverConfig = {} } = options;
307
-
308
- // Create server with test configuration
309
- const server = await createResponsibleVibeMCPServer({
310
- projectPath: tempProject.projectPath,
311
- enableLogging: false, // Disable logging in tests
312
- ...serverConfig,
313
- });
314
-
315
- // Initialize server
316
- await server.initialize();
317
-
318
- return {
319
- server,
320
- tempProject,
321
- cleanup: async () => {
322
- await server.cleanup();
323
- },
324
- };
325
- }
326
-
327
- /**
328
- * Create direct server interface for testing
329
- */
330
- export function createDirectServerInterface(
331
- server: ResponsibleVibeMCPServer
332
- ): DirectServerInterface {
333
- return new DirectServerInterface(server);
334
- }
335
-
336
- /**
337
- * Helper to safely parse JSON responses, handling both success and error cases
338
- */
339
- export function parseToolResponse(result: unknown): unknown {
340
- // If result is already an object (direct server call), return as-is
341
- if (typeof result === 'object' && result !== null) {
342
- return result;
343
- }
344
-
345
- // If it's a string, try to parse as JSON
346
- if (typeof result === 'string') {
347
- try {
348
- return JSON.parse(result);
349
- } catch {
350
- return { error: result };
351
- }
352
- }
353
-
354
- return result;
355
- }
356
-
357
- /**
358
- * Assert that a tool call was successful and return the response
359
- */
360
- export function assertToolSuccess(result: unknown): CallToolResult {
361
- // Parse result if it's a string
362
- const parsed = typeof result === 'string' ? JSON.parse(result) : result;
363
-
364
- if (parsed.error) {
365
- throw new Error(`Tool call failed: ${parsed.error}`);
366
- }
367
-
368
- return parsed;
369
- }
370
-
371
- /**
372
- * Initialize development for tests by calling start_development with a workflow
373
- * This must be called before any other tools in tests due to the new requirement
374
- *
375
- * @param client - The DirectServerInterface instance
376
- * @param workflow - The workflow to use (defaults to 'waterfall')
377
- * @param commitBehaviour - The commit behavior to use (defaults to 'none' for tests)
378
- * @returns The response from start_development
379
- */
380
- export async function initializeDevelopment(
381
- client: DirectServerInterface,
382
- workflow: string = 'waterfall',
383
- commitBehaviour: 'step' | 'phase' | 'end' | 'none' = 'none'
384
- ): Promise<unknown> {
385
- const result = await client.callTool('start_development', {
386
- workflow,
387
- commit_behaviour: commitBehaviour,
388
- });
389
- return assertToolSuccess(result);
390
- }
391
-
392
- /**
393
- * Helper to create a complete E2E test scenario
394
- */
395
- export async function createE2EScenario(options: {
396
- tempProject: TempProject;
397
- serverConfig?: Partial<ServerConfig>;
398
- }): Promise<{
399
- client: DirectServerInterface;
400
- server: ResponsibleVibeMCPServer;
401
- tempProject: TempProject;
402
- cleanup: () => Promise<void>;
403
- }> {
404
- const context = await setupE2ETest(options);
405
- const client = createDirectServerInterface(context.server);
406
-
407
- return {
408
- client,
409
- server: context.server,
410
- tempProject: context.tempProject,
411
- cleanup: context.cleanup,
412
- };
413
- }
414
-
415
- /**
416
- * Create a suite-isolated E2E scenario
417
- * Each test suite gets its own isolated temporary directory
418
- */
419
- export async function createSuiteIsolatedE2EScenario(options: {
420
- suiteName: string;
421
- tempProjectFactory: (baseDir?: string) => TempProject;
422
- serverConfig?: Partial<ServerConfig>;
423
- }): Promise<{
424
- client: DirectServerInterface;
425
- server: ResponsibleVibeMCPServer;
426
- tempProject: TempProject;
427
- cleanup: () => Promise<void>;
428
- }> {
429
- const { suiteName, tempProjectFactory, serverConfig = {} } = options;
430
-
431
- // Get suite-isolated directory
432
- const suiteDir = TestSuiteIsolation.getSuiteDirectory(suiteName);
433
-
434
- // Create temp project in the suite directory
435
- const tempProject = tempProjectFactory(suiteDir);
436
-
437
- // Register temp project cleanup with the suite
438
- TestSuiteIsolation.registerCleanup(suiteName, () => {
439
- tempProject.cleanup();
440
- });
441
-
442
- const context = await setupE2ETest({ tempProject, serverConfig });
443
- const client = createDirectServerInterface(context.server);
444
-
445
- return {
446
- client,
447
- server: context.server,
448
- tempProject: context.tempProject,
449
- cleanup: context.cleanup,
450
- };
451
- }
@@ -1,27 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Server Runner Script
4
- #
5
- # This script changes the current working directory to the specified path
6
- # before running the server. This ensures that the server operates in the
7
- # correct directory context for testing.
8
- #
9
- # This is necessary because the server uses process.cwd() to determine the project path,
10
- # and the StdioClientTransport's cwd option doesn't properly isolate the server process.
11
- # By explicitly changing directory in a wrapper script, we ensure the server operates
12
- # on a clean test directory rather than the current project directory.
13
-
14
- # Get the target directory from command line arguments
15
- TARGET_DIR="$1"
16
- SERVER_PATH="$2"
17
-
18
- if [ -z "$TARGET_DIR" ] || [ -z "$SERVER_PATH" ]; then
19
- echo "Usage: ./run-server-in-dir.sh <target-directory> <server-path>"
20
- exit 1
21
- fi
22
-
23
- # Change to the target directory
24
- cd "$TARGET_DIR" || exit 1
25
-
26
- # Run the server
27
- node "$SERVER_PATH"