Skip to content

Commit 7494076

Browse files
Lalitclaude
andcommitted
feat(qcsd): wire MCP task_orchestrate to auto-execute workflows
Issue #206: Fix gap where ideation-assessment tasks submitted via task_orchestrate would only spawn agents but not execute the qcsd-ideation-swarm workflow. Changes: - Add WorkflowOrchestrator to MCP FleetState - Initialize and register domain workflow actions during fleet_init - Add TASK_WORKFLOW_MAP mapping TaskType to workflow IDs - Modify handleTaskOrchestrate to execute workflows for mapped types - Return status 'workflow-started' with execution ID for workflow tasks Now calling task_orchestrate with QCSD keywords automatically executes the qcsd-ideation-swarm workflow with proper input mapping. Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 87a415c commit 7494076

File tree

2 files changed

+121
-2
lines changed

2 files changed

+121
-2
lines changed

v3/src/mcp/handlers/core-handlers.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { QEKernel } from '../../kernel/interfaces';
88
import { QEKernelImpl } from '../../kernel/kernel';
99
import { ALL_DOMAINS, DomainName } from '../../shared/types';
1010
import { QueenCoordinator, createQueenCoordinator } from '../../coordination/queen-coordinator';
11+
import { WorkflowOrchestrator } from '../../coordination/workflow-orchestrator';
1112

1213
/**
1314
* User-facing QE domains (excludes internal 'coordination' domain)
@@ -32,6 +33,10 @@ import {
3233
DomainStatusResult,
3334
} from '../types';
3435

36+
// Import domain plugins that register workflow actions
37+
import type { RequirementsValidationExtendedAPI } from '../../domains/requirements-validation/index.js';
38+
import type { VisualAccessibilityAPI } from '../../domains/visual-accessibility/index.js';
39+
3540
// ============================================================================
3641
// Fleet State
3742
// ============================================================================
@@ -41,6 +46,7 @@ interface FleetState {
4146
kernel: QEKernel | null;
4247
queen: QueenCoordinator | null;
4348
router: CrossDomainEventRouter | null;
49+
workflowOrchestrator: WorkflowOrchestrator | null;
4450
initialized: boolean;
4551
initTime: Date | null;
4652
}
@@ -50,6 +56,7 @@ const state: FleetState = {
5056
kernel: null,
5157
queen: null,
5258
router: null,
59+
workflowOrchestrator: null,
5360
initialized: false,
5461
initTime: null,
5562
};
@@ -134,6 +141,18 @@ export async function handleFleetInit(
134141
);
135142
await state.queen.initialize();
136143

144+
// Create Workflow Orchestrator for workflow execution
145+
state.workflowOrchestrator = new WorkflowOrchestrator(
146+
state.kernel.eventBus,
147+
state.kernel.memory,
148+
state.kernel.coordinator
149+
);
150+
await state.workflowOrchestrator.initialize();
151+
152+
// Register domain workflow actions (Issue #206)
153+
// This enables workflows like qcsd-ideation-swarm to execute their actions
154+
registerDomainWorkflowActions(state.kernel, state.workflowOrchestrator);
155+
137156
state.initialized = true;
138157
state.initTime = new Date();
139158

@@ -321,6 +340,10 @@ export async function disposeFleet(): Promise<void> {
321340
resetTaskExecutor();
322341
resetAllToolCaches();
323342

343+
if (state.workflowOrchestrator) {
344+
await state.workflowOrchestrator.dispose();
345+
state.workflowOrchestrator = null;
346+
}
324347
if (state.queen) {
325348
await state.queen.dispose();
326349
state.queen = null;
@@ -337,3 +360,30 @@ export async function disposeFleet(): Promise<void> {
337360
state.fleetId = null;
338361
state.initTime = null;
339362
}
363+
364+
// ============================================================================
365+
// Domain Workflow Action Registration (Issue #206)
366+
// ============================================================================
367+
368+
/**
369+
* Register domain-specific workflow actions with the WorkflowOrchestrator.
370+
* This enables workflows like qcsd-ideation-swarm to execute their actions.
371+
*/
372+
function registerDomainWorkflowActions(
373+
kernel: QEKernel,
374+
orchestrator: WorkflowOrchestrator
375+
): void {
376+
// Register requirements-validation domain actions (including QCSD Ideation)
377+
const reqValAPI = kernel.getDomainAPI<RequirementsValidationExtendedAPI>('requirements-validation');
378+
if (reqValAPI?.registerWorkflowActions) {
379+
reqValAPI.registerWorkflowActions(orchestrator);
380+
console.log('[Fleet] Registered requirements-validation workflow actions (includes QCSD Ideation)');
381+
}
382+
383+
// Register visual-accessibility domain actions
384+
const visA11yAPI = kernel.getDomainAPI<VisualAccessibilityAPI>('visual-accessibility');
385+
if (visA11yAPI?.registerWorkflowActions) {
386+
visA11yAPI.registerWorkflowActions(orchestrator);
387+
console.log('[Fleet] Registered visual-accessibility workflow actions');
388+
}
389+
}

v3/src/mcp/handlers/task-handlers.ts

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Task submission, status, and management handlers
44
*
55
* ADR-051: Integrated with Model Router for intelligent tier selection
6+
* Issue #206: Workflow auto-execution for task types with associated workflows
67
*/
78

89
import { getFleetState, isFleetInitialized } from './core-handlers';
@@ -28,6 +29,18 @@ import {
2829
} from '../services/reasoning-bank-service';
2930
import type { ModelTier } from '../../integrations/agentic-flow';
3031

32+
// ============================================================================
33+
// Task Type to Workflow Mapping (Issue #206)
34+
// Maps TaskTypes to their associated workflow IDs for auto-execution
35+
// ============================================================================
36+
37+
const TASK_WORKFLOW_MAP: Partial<Record<TaskType, string>> = {
38+
'ideation-assessment': 'qcsd-ideation-swarm',
39+
// Add more mappings as workflows are created:
40+
// 'generate-tests': 'comprehensive-testing',
41+
// 'test-accessibility': 'visual-accessibility-workflow',
42+
};
43+
3144
// ============================================================================
3245
// Task Submit Handler
3346
// ============================================================================
@@ -287,7 +300,7 @@ export async function handleTaskOrchestrate(
287300
};
288301
}
289302

290-
const { queen } = getFleetState();
303+
const { queen, workflowOrchestrator } = getFleetState();
291304

292305
try {
293306
// ADR-051: Route task to optimal model tier BEFORE execution
@@ -305,7 +318,63 @@ export async function handleTaskOrchestrate(
305318
const taskType = inferTaskType(params.task);
306319
const priority = mapPriority(params.priority || 'medium');
307320

308-
// Submit the task with routing decision included in payload
321+
// Issue #206: Check if this task type has an associated workflow
322+
const workflowId = TASK_WORKFLOW_MAP[taskType];
323+
324+
if (workflowId && workflowOrchestrator) {
325+
// Execute the associated workflow directly
326+
console.log(`[TaskOrchestrate] Task type '${taskType}' has workflow '${workflowId}' - executing workflow`);
327+
328+
// Build workflow input from task params and context
329+
const workflowInput: Record<string, unknown> = {
330+
// Pass through context fields as workflow input
331+
targetId: params.context?.project || `task-${Date.now()}`,
332+
targetType: 'epic', // Default for QCSD ideation
333+
description: params.task,
334+
acceptanceCriteria: params.context?.requirements || [],
335+
// Include routing info for downstream processing
336+
routing: {
337+
tier: routingResult.decision.tier,
338+
modelId: routingResult.modelId,
339+
executionStrategy: routingResult.executionStrategy,
340+
complexity: routingResult.decision.complexityAnalysis.overall,
341+
},
342+
};
343+
344+
const workflowResult = await workflowOrchestrator.executeWorkflow(workflowId, workflowInput);
345+
346+
if (!workflowResult.success) {
347+
return {
348+
success: false,
349+
error: `Workflow execution failed: ${workflowResult.error.message}`,
350+
};
351+
}
352+
353+
return {
354+
success: true,
355+
data: {
356+
taskId: workflowResult.value, // This is the workflow execution ID
357+
type: taskType,
358+
priority,
359+
strategy: params.strategy || 'adaptive',
360+
status: 'workflow-started',
361+
message: `Workflow '${workflowId}' started for task: ${params.task}`,
362+
routing: {
363+
tier: routingResult.decision.tier,
364+
tierName: routingResult.tierInfo.name,
365+
modelId: routingResult.modelId,
366+
executionStrategy: routingResult.executionStrategy,
367+
complexity: routingResult.decision.complexityAnalysis.overall,
368+
confidence: routingResult.decision.confidence,
369+
useAgentBooster: routingResult.useAgentBooster,
370+
rationale: routingResult.decision.rationale,
371+
decisionTimeMs: routingResult.decision.metadata.decisionTimeMs,
372+
},
373+
},
374+
};
375+
}
376+
377+
// No workflow - submit as a regular task
309378
const result = await queen!.submitTask({
310379
type: taskType,
311380
priority,

0 commit comments

Comments
 (0)