@codemcp/workflows 4.10.2 → 4.10.3

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 (43) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/components/beads/beads-instruction-generator.d.ts +1 -4
  3. package/dist/components/beads/beads-instruction-generator.d.ts.map +1 -1
  4. package/dist/components/beads/beads-instruction-generator.js +24 -52
  5. package/dist/components/beads/beads-instruction-generator.js.map +1 -1
  6. package/dist/tool-handlers/get-tool-info.d.ts +0 -1
  7. package/dist/tool-handlers/get-tool-info.d.ts.map +1 -1
  8. package/dist/tool-handlers/get-tool-info.js +0 -1
  9. package/dist/tool-handlers/get-tool-info.js.map +1 -1
  10. package/dist/tool-handlers/proceed-to-phase.d.ts +0 -2
  11. package/dist/tool-handlers/proceed-to-phase.d.ts.map +1 -1
  12. package/dist/tool-handlers/proceed-to-phase.js +0 -2
  13. package/dist/tool-handlers/proceed-to-phase.js.map +1 -1
  14. package/dist/tool-handlers/resume-workflow.d.ts +0 -1
  15. package/dist/tool-handlers/resume-workflow.d.ts.map +1 -1
  16. package/dist/tool-handlers/resume-workflow.js +0 -1
  17. package/dist/tool-handlers/resume-workflow.js.map +1 -1
  18. package/dist/tool-handlers/start-development.d.ts +0 -3
  19. package/dist/tool-handlers/start-development.d.ts.map +1 -1
  20. package/dist/tool-handlers/start-development.js +0 -6
  21. package/dist/tool-handlers/start-development.js.map +1 -1
  22. package/dist/tool-handlers/whats-next.d.ts +0 -2
  23. package/dist/tool-handlers/whats-next.d.ts.map +1 -1
  24. package/dist/tool-handlers/whats-next.js +0 -2
  25. package/dist/tool-handlers/whats-next.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/components/beads/beads-instruction-generator.ts +28 -60
  28. package/src/tool-handlers/get-tool-info.ts +0 -2
  29. package/src/tool-handlers/proceed-to-phase.ts +0 -4
  30. package/src/tool-handlers/resume-workflow.ts +0 -2
  31. package/src/tool-handlers/start-development.ts +0 -8
  32. package/src/tool-handlers/whats-next.ts +0 -4
  33. package/test/e2e/beads-plugin-integration.test.ts +4 -19
  34. package/test/e2e/core-functionality.test.ts +3 -12
  35. package/test/e2e/mcp-contract.test.ts +0 -31
  36. package/test/e2e/plugin-system-integration.test.ts +7 -315
  37. package/test/e2e/state-management.test.ts +1 -5
  38. package/test/e2e/workflow-integration.test.ts +2 -11
  39. package/test/unit/beads-instruction-generator.test.ts +235 -103
  40. package/test/unit/beads-phase-task-id-integration.test.ts +7 -29
  41. package/test/unit/resume-workflow.test.ts +0 -1
  42. package/test/unit/server-tools.test.ts +0 -1
  43. package/tsconfig.build.tsbuildinfo +1 -1
@@ -101,20 +101,13 @@ export class BeadsInstructionGenerator implements IInstructionGenerator {
101
101
  baseInstructions: string,
102
102
  context: InstructionContext
103
103
  ): Promise<string> {
104
- const {
105
- phase,
106
- conversationContext,
107
- transitionReason,
108
- isModeled,
109
- planFileExists,
110
- } = context;
104
+ const { planFileExists } = context;
111
105
 
112
106
  // Generate beads-specific task management guidance
113
- const beadsTaskGuidance = await this.generateBeadsTaskGuidance(context);
107
+ const beadsTaskGuidance = await this.generateBeadsCLIGuidance(context);
114
108
 
115
109
  // Beads-optimized instruction structure
116
- const enhanced = `You are in the ${phase} phase.
117
- ${baseInstructions}
110
+ let enhanced = `${baseInstructions}
118
111
 
119
112
  **Plan File Guidance:**
120
113
  Use the plan file as memory for the current objective
@@ -122,92 +115,67 @@ Use the plan file as memory for the current objective
122
115
  - Add relevant notes to help maintain context
123
116
  - Do NOT enter tasks in the plan file, use beads CLI exclusively for task management
124
117
 
125
- **🔧 BD CLI Task Management:**
126
118
  ${beadsTaskGuidance}`;
127
119
 
128
- // Add project context
129
- const enhancedWithContext =
130
- enhanced +
131
- `\n\n**Project Context:**
132
- - Project: ${conversationContext.projectPath}
133
- - Branch: ${conversationContext.gitBranch}
134
- - Current Phase: ${phase}`;
135
-
136
- // Add transition context if this is a modeled transition
137
- let final = enhancedWithContext;
138
- if (isModeled && transitionReason) {
139
- final += `\n\n**Phase Context:**
140
- - ${transitionReason}`;
141
- }
142
-
143
120
  // Add plan file creation note if needed
144
121
  if (!planFileExists) {
145
- final +=
122
+ enhanced +=
146
123
  '\n\n**Note**: Plan file will be created when you first update it.';
147
124
  }
148
125
 
149
126
  // Add beads-specific reminders
150
- final += `\n\n**Important Reminders:**
127
+ enhanced += `\n\n**Important Reminders:**
151
128
  - Use ONLY bd CLI tool for task management - do not use your own task management tools
152
129
  - Call whats_next() after the next user message to maintain the development workflow`;
153
130
 
154
- return final;
131
+ return enhanced;
155
132
  }
156
133
 
157
134
  /**
158
135
  * Generate beads-specific task management guidance
159
136
  */
160
- private async generateBeadsTaskGuidance(
137
+ private async generateBeadsCLIGuidance(
161
138
  context: InstructionContext
162
139
  ): Promise<string> {
163
- const { phase, instructionSource } = context;
140
+ const { instructionSource } = context;
164
141
 
165
- // For explicit phase transitions (proceed_to_phase), provide minimal guidance
166
- // The detailed guidance is better suited for whats_next which analyzes context
167
- if (instructionSource === 'proceed_to_phase') {
168
- return `- Use bd CLI tool exclusively for task management
169
- - Do not use your own task management tools`;
170
- }
142
+ // For whats_next, provide detailed guidance
143
+ if (instructionSource === 'whats_next') {
144
+ let additionalInstructions = `**bd Task Management:**
145
+ `;
171
146
 
172
- // For implicit transitions (whats_next), provide detailed guidance
173
- // Extract phase task ID from plan file (this would need to be implemented)
174
- const phaseTaskId = await this.extractPhaseTaskId(context);
147
+ const phaseTaskId = await this.extractPhaseTaskId(context);
175
148
 
176
- if (!phaseTaskId) {
177
- return `- Use bd CLI tool exclusively
149
+ if (!phaseTaskId) {
150
+ return (
151
+ additionalInstructions +
152
+ `- Use bd CLI tool exclusively
178
153
  - **Start by listing ready tasks**: \`bd list --parent <phase-task-id> --status open\`
179
154
  - **Create new tasks**: \`bd create 'Task title' --parent <phase-task-id> -p <priority>\`
180
155
  - **Update status when working**: \`bd update <task-id> --status in_progress\`
181
156
  - **Complete tasks**: \`bd close <task-id>\`
182
157
  - **Focus on ready tasks first** - let beads handle dependencies
183
- - Add new tasks as they are identified during your work with the user`;
184
- }
185
-
186
- return `
187
- You are currently in the ${this.capitalizePhase(phase)} phase. All work items should be created as children of ${phaseTaskId}.
158
+ - Add new tasks as they are identified during your work with the user`
159
+ );
160
+ }
188
161
 
189
- **Focus on ${this.capitalizePhase(phase)} Phase Tasks** (subtasks of \`${phaseTaskId}\`):
162
+ return (
163
+ additionalInstructions +
164
+ `
165
+ **Focus on subtasks of \`${phaseTaskId}\`**:
190
166
  • \`bd list --parent ${phaseTaskId} --status open\` - List ready work items
191
167
  • \`bd update <task-id> --status in_progress\` - Start working on a specific task
192
168
  • \`bd close <task-id>\` - Mark task complete when finished
193
169
 
194
170
  **New Tasks for Current Phase**:
195
171
  • \`bd create 'Task description' --parent ${phaseTaskId} -p <priority>\` - Create work item under current phase
196
- • \`bd dep add <task-id> <depends-on-id>\` - Define dependencies for a task:
197
-
198
-
199
- **Essential bd Commands**:
200
- • \`bd list --parent ${phaseTaskId} --status open\` - List ready work items
201
- • \`bd update <task-id> --status in_progress\` - Start working
202
- • \`bd close <task-id>\` - Complete work item
203
- • \`bd show ${phaseTaskId}\` - View phase and its work items
172
+ • \`bd dep add <task-id> <depends-on-id>\` - Define dependencies for a task:`
173
+ );
174
+ }
204
175
 
205
- **Immediate Action**: Run \`bd list --parent ${phaseTaskId} --status open\` to see ready tasks.`;
176
+ return '';
206
177
  }
207
178
 
208
- /**
209
- * Extract phase task ID from plan file (simplified implementation)
210
- */
211
179
  private async extractPhaseTaskId(
212
180
  context: InstructionContext
213
181
  ): Promise<string | null> {
@@ -73,7 +73,6 @@ interface GetToolInfoResponse {
73
73
 
74
74
  workflow_states?: {
75
75
  current_phase?: string;
76
- conversation_id?: string;
77
76
  plan_file_path?: string;
78
77
  };
79
78
  }
@@ -195,7 +194,6 @@ export class GetToolInfoHandler extends BaseToolHandler<
195
194
  await context.conversationManager.getConversationContext();
196
195
  workflowState = {
197
196
  current_phase: conversationContext.currentPhase,
198
- conversation_id: conversationContext.conversationId,
199
197
  plan_file_path: conversationContext.planFilePath,
200
198
  };
201
199
  } catch (error) {
@@ -27,8 +27,6 @@ export interface ProceedToPhaseResult {
27
27
  instructions: string;
28
28
  plan_file_path: string;
29
29
  transition_reason: string;
30
- is_modeled_transition: boolean;
31
- conversation_id: string;
32
30
  }
33
31
 
34
32
  /**
@@ -173,8 +171,6 @@ export class ProceedToPhaseHandler extends ConversationRequiredToolHandler<
173
171
  instructions: finalInstructions,
174
172
  plan_file_path: conversationContext.planFilePath,
175
173
  transition_reason: transitionResult.transitionReason,
176
- is_modeled_transition: transitionResult.isModeled,
177
- conversation_id: conversationContext.conversationId,
178
174
  };
179
175
 
180
176
  // Log interaction
@@ -61,7 +61,6 @@ interface WorkflowRecommendations {
61
61
  */
62
62
  export interface ResumeWorkflowResult {
63
63
  workflow_status: {
64
- conversation_id: string;
65
64
  current_phase: string;
66
65
  project_path: string;
67
66
  git_branch: string;
@@ -132,7 +131,6 @@ export class ResumeWorkflowHandler extends ConversationRequiredToolHandler<
132
131
  const response: ResumeWorkflowResult = {
133
132
  // Core workflow resumption info
134
133
  workflow_status: {
135
- conversation_id: conversationContext.conversationId,
136
134
  current_phase: conversationContext.currentPhase,
137
135
  project_path: conversationContext.projectPath,
138
136
  git_branch: conversationContext.gitBranch,
@@ -38,8 +38,6 @@ export interface StartDevelopmentResult {
38
38
  phase: string;
39
39
  instructions: string;
40
40
  plan_file_path: string;
41
- conversation_id: string;
42
- workflow: YamlStateMachine;
43
41
  workflowDocumentationUrl?: string;
44
42
  }
45
43
 
@@ -134,8 +132,6 @@ export class StartDevelopmentHandler extends BaseToolHandler<
134
132
  phase: 'branch-prompt',
135
133
  instructions: `You're currently on the ${currentBranch} branch. It's recommended to create a feature branch for development. Propose a branch creation by suggesting a branch command to the user call start_development again.\n\nSuggested command: \`git checkout -b ${suggestedBranchName}\`\n\nPlease create a new branch and then call start_development again to begin development.`,
136
134
  plan_file_path: '',
137
- conversation_id: '',
138
- workflow: {} as YamlStateMachine,
139
135
  };
140
136
 
141
137
  this.logger.debug(
@@ -270,8 +266,6 @@ export class StartDevelopmentHandler extends BaseToolHandler<
270
266
  phase: transitionResult.newPhase,
271
267
  instructions: finalInstructions,
272
268
  plan_file_path: conversationContext.planFilePath,
273
- conversation_id: conversationContext.conversationId,
274
- workflow: stateMachine,
275
269
  workflowDocumentationUrl,
276
270
  };
277
271
 
@@ -377,8 +371,6 @@ export class StartDevelopmentHandler extends BaseToolHandler<
377
371
  phase: 'artifact-setup',
378
372
  instructions: setupGuidance,
379
373
  plan_file_path: '',
380
- conversation_id: '',
381
- workflow: {} as YamlStateMachine,
382
374
  };
383
375
  } catch (error) {
384
376
  this.logger.warn(
@@ -30,8 +30,6 @@ export interface WhatsNextResult {
30
30
  phase: string;
31
31
  instructions: string;
32
32
  plan_file_path: string;
33
- is_modeled_transition: boolean;
34
- conversation_id: string;
35
33
  }
36
34
 
37
35
  /**
@@ -189,8 +187,6 @@ export class WhatsNextHandler extends ConversationRequiredToolHandler<
189
187
  phase: transitionResult.newPhase,
190
188
  instructions: finalInstructions,
191
189
  plan_file_path: conversationContext.planFilePath,
192
- is_modeled_transition: transitionResult.isModeled,
193
- conversation_id: conversationContext.conversationId,
194
190
  };
195
191
 
196
192
  // Log interaction
@@ -153,7 +153,7 @@ function validateBeadsInstructions(instructions: string): void {
153
153
  expect(instructions.toLowerCase()).toContain('task');
154
154
 
155
155
  // Should have beads-specific guidance
156
- expect(instructions).toContain('🔧 BD CLI Task Management');
156
+ expect(instructions).toContain('bd');
157
157
 
158
158
  // Should mention using ONLY bd CLI
159
159
  expect(instructions).toContain('Use ONLY bd CLI tool');
@@ -506,11 +506,11 @@ describe('Beads Plugin Comprehensive Integration', () => {
506
506
 
507
507
  // VALIDATE: WITH beads mentions bd CLI
508
508
  expect(instructionsWithBeads.toLowerCase()).toContain('bd');
509
- expect(instructionsWithBeads).toContain('BD CLI Task Management');
509
+ expect(instructionsWithBeads).toContain('bd Task Management');
510
510
 
511
511
  // VALIDATE: WITHOUT beads does NOT mention bd CLI
512
512
  expect(instructionsWithout.toLowerCase()).not.toContain('bd cli');
513
- expect(instructionsWithout).not.toContain('BD CLI Task Management');
513
+ expect(instructionsWithout).not.toContain('bd Task Management');
514
514
  });
515
515
 
516
516
  it('should maintain identical response contracts regardless of beads', async () => {
@@ -548,12 +548,10 @@ describe('Beads Plugin Comprehensive Integration', () => {
548
548
  await scenarioWithout.cleanup();
549
549
 
550
550
  // VALIDATE: Both responses have identical properties
551
- expect(responseWith).toHaveProperty('conversation_id');
552
551
  expect(responseWith).toHaveProperty('phase');
553
552
  expect(responseWith).toHaveProperty('plan_file_path');
554
553
  expect(responseWith).toHaveProperty('instructions');
555
554
 
556
- expect(responseWithout).toHaveProperty('conversation_id');
557
555
  expect(responseWithout).toHaveProperty('phase');
558
556
  expect(responseWithout).toHaveProperty('plan_file_path');
559
557
  expect(responseWithout).toHaveProperty('instructions');
@@ -722,7 +720,6 @@ describe('Beads Plugin Comprehensive Integration', () => {
722
720
 
723
721
  // VALIDATE: Has all required response fields
724
722
  const response = assertToolSuccess(result) as StartDevelopmentResult;
725
- expect(response).toHaveProperty('conversation_id');
726
723
  expect(response).toHaveProperty('phase');
727
724
  expect(response).toHaveProperty('plan_file_path');
728
725
  expect(response).toHaveProperty('instructions');
@@ -827,9 +824,6 @@ describe('Beads Plugin Comprehensive Integration', () => {
827
824
  expect(whatsNextResponse.plan_file_path).toBe(
828
825
  startResponse.plan_file_path
829
826
  );
830
- expect(whatsNextResponse.conversation_id).toBe(
831
- startResponse.conversation_id
832
- );
833
827
 
834
828
  // VALIDATE: Plan file is still valid
835
829
  const planContent = await fs.readFile(
@@ -1344,10 +1338,7 @@ describe('Beads Plugin Comprehensive Integration', () => {
1344
1338
  commit_behaviour: 'none',
1345
1339
  });
1346
1340
 
1347
- const startResponse = assertToolSuccess(
1348
- startResult
1349
- ) as StartDevelopmentResult;
1350
- const conversationId = startResponse.conversation_id;
1341
+ assertToolSuccess(startResult) as StartDevelopmentResult;
1351
1342
 
1352
1343
  // Get whats_next
1353
1344
  const whatsNextResult = await client.callTool('whats_next', {
@@ -1361,10 +1352,6 @@ describe('Beads Plugin Comprehensive Integration', () => {
1361
1352
  whatsNextResult
1362
1353
  ) as WhatsNextResult;
1363
1354
 
1364
- // VALIDATE: Conversation ID preserved after hook execution
1365
- expect(whatsNextResponse.conversation_id).toBe(conversationId);
1366
-
1367
- // VALIDATE: Phase information consistent
1368
1355
  expect(whatsNextResponse.phase).toBe('explore');
1369
1356
  });
1370
1357
  });
@@ -1510,11 +1497,9 @@ describe('Beads Plugin Comprehensive Integration', () => {
1510
1497
  ) as StartDevelopmentResult;
1511
1498
 
1512
1499
  // VALIDATE: All standard response properties present
1513
- expect(startResponse).toHaveProperty('conversation_id');
1514
1500
  expect(startResponse).toHaveProperty('phase');
1515
1501
  expect(startResponse).toHaveProperty('plan_file_path');
1516
1502
  expect(startResponse).toHaveProperty('instructions');
1517
- expect(startResponse).toHaveProperty('workflow');
1518
1503
 
1519
1504
  // VALIDATE: Can transition phases normally
1520
1505
  const transitionResult = await client.callTool('proceed_to_phase', {
@@ -69,7 +69,6 @@ describe('Core Functionality', () => {
69
69
 
70
70
  expect(response.phase).toBeTruthy();
71
71
  expect(response.instructions).toBeTruthy();
72
- expect(response.conversation_id).toBeTruthy();
73
72
  expect(response.plan_file_path).toBeTruthy();
74
73
  });
75
74
 
@@ -148,29 +147,21 @@ describe('Core Functionality', () => {
148
147
 
149
148
  describe('Basic Conversation Management', () => {
150
149
  it('should create new conversations', async () => {
151
- const result = await client.callTool('whats_next', {
150
+ await client.callTool('whats_next', {
152
151
  user_input: 'new feature request',
153
152
  });
154
- const response = assertToolSuccess(result);
155
-
156
- expect(response.conversation_id).toBeTruthy();
157
- expect(response.conversation_id).toMatch(/^default-sm-/);
158
153
  });
159
154
 
160
155
  it('should maintain conversation state across calls', async () => {
161
156
  const first = await client.callTool('whats_next', {
162
157
  user_input: 'start project',
163
158
  });
164
- const firstResponse = assertToolSuccess(first);
159
+ assertToolSuccess(first);
165
160
 
166
161
  const second = await client.callTool('whats_next', {
167
162
  user_input: 'continue project',
168
163
  });
169
- const secondResponse = assertToolSuccess(second);
170
-
171
- expect(firstResponse.conversation_id).toBe(
172
- secondResponse.conversation_id
173
- );
164
+ assertToolSuccess(second);
174
165
  });
175
166
  });
176
167
  });
@@ -206,7 +206,6 @@ describe('MCP Contract Validation', () => {
206
206
  const responseText = textContent!.text;
207
207
  expect(responseText).toContain('phase');
208
208
  expect(responseText).toContain('instructions');
209
- expect(responseText).toContain('conversation_id');
210
209
  });
211
210
 
212
211
  it('should execute proceed_to_phase tool successfully', async () => {
@@ -334,7 +333,6 @@ describe('MCP Contract Validation', () => {
334
333
 
335
334
  // Should contain valid JSON with state information
336
335
  const stateData = JSON.parse(content.text);
337
- expect(stateData.conversationId).toBeTruthy();
338
336
  expect(stateData.currentPhase).toBeTruthy();
339
337
  expect(stateData.projectPath).toBeTruthy();
340
338
  });
@@ -386,34 +384,6 @@ describe('MCP Contract Validation', () => {
386
384
  expect(Array.isArray(results[3].resources)).toBe(true);
387
385
  });
388
386
 
389
- it('should maintain conversation state across multiple interactions', async () => {
390
- // First interaction
391
- const result1 = await client.callTool({
392
- name: 'whats_next',
393
- arguments: {
394
- user_input: 'start new project',
395
- },
396
- });
397
-
398
- const response1 = JSON.parse(result1.content[0].text);
399
- const conversationId1 = response1.conversation_id;
400
-
401
- // Second interaction in the same session
402
- const result2 = await client.callTool({
403
- name: 'whats_next',
404
- arguments: {
405
- user_input: 'continue project',
406
- },
407
- });
408
-
409
- const response2 = JSON.parse(result2.content[0].text);
410
- const conversationId2 = response2.conversation_id;
411
-
412
- // Should maintain same conversation ID within the same MCP session
413
- // Note: Each MCP client connection maintains its own conversation context
414
- expect(conversationId1).toBe(conversationId2);
415
- });
416
-
417
387
  it('should handle malformed requests appropriately', async () => {
418
388
  // Test with missing required parameters
419
389
  try {
@@ -534,7 +504,6 @@ describe('MCP Contract Validation', () => {
534
504
  const response = JSON.parse(result.content[0].text);
535
505
  expect(response.phase).toBeTruthy();
536
506
  expect(response.instructions).toBeTruthy();
537
- expect(response.conversation_id).toBeTruthy();
538
507
  });
539
508
  });
540
509
  });