bc-code-intelligence-mcp
Version:
BC Code Intelligence MCP Server - Complete Specialist Bundle with AI-driven expert consultation, seamless handoffs, and context-preserving workflows
409 lines (404 loc) • 23.7 kB
JavaScript
/**
* Workflow Service - Persona-Driven Development Pipelines
* Orchestrates complete BC development workflows with specialist coordination
*/
/**
* Core workflow orchestration service
* Manages complete BC development pipelines with specialist coordination
*/
export class WorkflowService {
knowledgeService;
methodologyService;
specialistDiscoveryService;
activeSessions = new Map();
pipelineDefinitions;
constructor(knowledgeService, methodologyService, specialistDiscoveryService) {
this.knowledgeService = knowledgeService;
this.methodologyService = methodologyService;
this.specialistDiscoveryService = specialistDiscoveryService;
this.pipelineDefinitions = this.initializePipelineDefinitions();
}
async startWorkflow(requestOrWorkflowType, contextObj) {
// Handle two-parameter calling pattern
if (typeof requestOrWorkflowType === 'string' && contextObj) {
const request = {
workflow_type: requestOrWorkflowType,
project_context: contextObj.context,
bc_version: contextObj.bc_version,
additional_context: contextObj.additional_context
};
return this.startWorkflowInternal(request);
}
// Handle single-parameter calling pattern (existing)
if (typeof requestOrWorkflowType === 'object') {
return this.startWorkflowInternal(requestOrWorkflowType);
}
throw new Error('Invalid parameters provided to startWorkflow');
}
async startWorkflowInternal(request) {
// Validate required parameters
if (!request.project_context || request.project_context.trim() === '') {
throw new Error('project_context is required and cannot be empty');
}
const sessionId = this.generateSessionId();
const pipeline = this.pipelineDefinitions[request.workflow_type];
if (!pipeline) {
throw new Error(`Unknown workflow type: ${request.workflow_type}`);
}
if (!pipeline.phases || pipeline.phases.length === 0) {
throw new Error(`No phases defined for workflow type: ${request.workflow_type}`);
}
// Try to load methodology for validation (this can fail and should propagate)
try {
await this.methodologyService.loadMethodology({
user_request: request.project_context,
domain: request.workflow_type
});
}
catch (error) {
// Re-throw methodology service errors
throw error;
}
// Discover specialists dynamically based on workflow type
const workflowSpecialists = await this.discoverWorkflowSpecialists(request.workflow_type);
const session = {
id: sessionId,
type: request.workflow_type,
current_phase: 0,
specialist_pipeline: workflowSpecialists,
project_context: request.project_context,
bc_version: request.bc_version,
phase_results: [],
methodology_state: {
pipeline_methodology: `${request.workflow_type}-pipeline`,
current_phase_methodology: pipeline.phases[0].methodology_id,
completed_methodologies: [],
validation_results: [],
constitutional_gates: this.initializeConstitutionalGates()
},
created_at: new Date(),
last_updated: new Date(),
status: 'active',
constitutional_gates: this.initializeConstitutionalGates()
};
this.activeSessions.set(sessionId, session);
return session;
}
/**
* Advance workflow to the next phase or check status
*/
async advancePhase(request) {
const session = this.activeSessions.get(request.workflow_id);
if (!session) {
throw new Error(`Workflow session not found: ${request.workflow_id}`);
}
// If only checking status, return current status without advancing
if (request.check_status_only) {
return this.getWorkflowStatus(request.workflow_id);
}
// Record current phase results if provided
if (request.phase_results) {
const currentSpecialistId = session.specialist_pipeline[session.current_phase];
const specialist = await this.specialistDiscoveryService.getSpecialistById(currentSpecialistId);
const phaseResult = {
phase_number: session.current_phase,
specialist_id: currentSpecialistId,
specialist_name: specialist?.title || 'Unknown',
guidance_provided: request.phase_results,
decisions_made: [], // Could be extracted from phase_results
next_steps: [],
artifacts_created: [],
methodology_validation: await this.validatePhaseMethodology(session, request.phase_results),
time_spent: 0, // TODO: Track actual time
confidence_level: 'medium', // TODO: Assess based on validation
collaboration_needed: false
};
session.phase_results.push(phaseResult);
}
// Advance to next phase
session.current_phase++;
session.last_updated = new Date();
// Check if workflow is complete
if (session.current_phase >= session.specialist_pipeline.length) {
session.status = 'completed';
}
return this.getWorkflowStatus(request.workflow_id);
}
/**
* Get current workflow status and guidance
*/
async getWorkflowStatus(workflowId) {
const session = this.activeSessions.get(workflowId);
if (!session) {
throw new Error(`Workflow session not found: ${workflowId}`);
}
const currentSpecialistId = session.specialist_pipeline[session.current_phase];
const currentSpecialist = await this.specialistDiscoveryService.getSpecialistById(currentSpecialistId);
const nextSpecialistId = session.current_phase + 1 < session.specialist_pipeline.length
? session.specialist_pipeline[session.current_phase + 1]
: undefined;
const nextSpecialist = nextSpecialistId ? await this.specialistDiscoveryService.getSpecialistById(nextSpecialistId) : undefined;
const progressPercentage = (session.current_phase / session.specialist_pipeline.length) * 100;
return {
session,
current_specialist: currentSpecialist,
next_specialist: nextSpecialist,
progress_percentage: progressPercentage,
phase_summary: this.generatePhaseSummary(session),
next_actions: this.generateNextActions(session)
};
}
/**
* Get workflow guidance for current phase
*/
async getPhaseGuidance(workflowId, detailed_context) {
const status = await this.getWorkflowStatus(workflowId);
const pipeline = this.pipelineDefinitions[status.session.type];
const currentPhase = pipeline.phases[status.session.current_phase];
// Get specialist-specific guidance
const specialist = status.current_specialist;
const specialistGuidance = specialist ? await this.getSpecialistPhaseGuidance(specialist, currentPhase, status.session.project_context) : '';
// Get methodology guidance for this phase
const methodologyGuidance = await this.getPhaseMethodologyGuidance(currentPhase.methodology_id, detailed_context);
return `# ${currentPhase.title} - ${specialist?.name}
${currentPhase.description}
## Specialist Guidance
${specialistGuidance}
## Methodology Framework
${methodologyGuidance}
## Context
Project: ${status.session.project_context}
${status.session.bc_version ? `BC Version: ${status.session.bc_version}` : ''}
## Progress
Phase ${status.session.current_phase + 1} of ${status.session.specialist_pipeline.length} (${Math.round(status.progress_percentage)}% complete)
`;
}
/**
* Get all active workflows
*/
async getActiveWorkflows() {
// Return current in-memory active sessions
const activeSessions = Array.from(this.activeSessions.values()).filter(session => session.status === 'active');
return activeSessions.map(session => ({
workflow_id: session.id,
workflow_type: session.type,
current_phase: session.current_phase,
total_phases: session.specialist_pipeline.length,
progress_percentage: (session.current_phase / session.specialist_pipeline.length) * 100,
created_at: session.created_at,
last_updated: session.last_updated,
project_context: session.project_context
}));
}
/**
* Get workflow methodology for a specific workflow
*/
async getWorkflowMethodology(workflowId) {
const status = await this.getWorkflowStatus(workflowId);
const pipeline = this.pipelineDefinitions[status.session.type];
return {
workflow_id: workflowId,
workflow_type: status.session.type,
total_phases: pipeline.phases.length,
phases: pipeline.phases,
specialists: pipeline.specialists,
methodology_overview: `This workflow follows a ${pipeline.phases.length}-phase methodology for ${status.session.type}.`
};
}
/**
* Dynamically discover specialists relevant to a workflow type
* Uses the specialist discovery service to suggest appropriate specialists
*/
async discoverWorkflowSpecialists(workflowType) {
try {
// Define workflow descriptions for specialist suggestion
const workflowDescriptions = {
'new-bc-app': 'Create a new Business Central application with architecture, implementation, testing, and documentation',
'enhance-bc-app': 'Enhance existing BC application with performance optimization and error handling',
'review-bc-code': 'Review BC code for quality, security, performance, and architecture compliance',
'debug-bc-issues': 'Debug and troubleshoot performance issues and errors in BC applications',
'modernize-bc-code': 'Modernize legacy BC code with current architecture and security practices',
'onboard-developer': 'Onboard new developer with mentoring and best practices guidance',
'upgrade-bc-version': 'Upgrade BC application to newer version with architecture and testing',
'add-ecosystem-features': 'Add ecosystem integration features with API design and security',
'document-bc-solution': 'Create comprehensive documentation for BC solution architecture',
'app_takeover': 'Take over existing BC application with legacy migration, security, and testing'
};
const description = workflowDescriptions[workflowType] || `Workflow for ${workflowType}`;
// Use specialist discovery service to suggest specialists
const suggestions = await this.specialistDiscoveryService.suggestSpecialists({
query: description
}, 6);
// Extract specialist IDs from suggestions
const specialistIds = suggestions.map(suggestion => suggestion.specialist.specialist_id);
// Ensure we have at least some specialists
if (specialistIds.length === 0) {
// Fallback to basic set that should exist
return ['alex-architect', 'sam-coder', 'quinn-tester'];
}
return specialistIds;
}
catch (error) {
console.error('Error discovering workflow specialists:', error);
// Fallback to basic set that should exist
return ['alex-architect', 'sam-coder', 'quinn-tester'];
}
}
/**
* Initialize pipeline definitions for all workflow types
* Now uses dynamic specialist discovery instead of hard-coded lists
*/
initializePipelineDefinitions() {
return {
'new-bc-app': {
specialists: [], // Will be populated dynamically
phases: [
{ methodology_id: 'analysis-architecture', title: 'Architecture Specification', description: 'Business requirements to BC data model design' },
{ methodology_id: 'coding-implementation', title: 'Implementation Planning', description: 'AL code structure and development approach' },
{ methodology_id: 'error-handling', title: 'Error Handling Strategy', description: 'Exception management and defensive programming' },
{ methodology_id: 'ux-design', title: 'User Experience Design', description: 'Interface design and usability optimization' },
{ methodology_id: 'verification-review', title: 'Design Review', description: 'Code quality gates and maintainability assessment' },
{ methodology_id: 'testing-strategy', title: 'Testing Strategy', description: 'Test coverage planning and quality assurance' },
{ methodology_id: 'security-implementation', title: 'Security Implementation', description: 'Permission model and data access controls' },
{ methodology_id: 'documentation-creation', title: 'Documentation Creation', description: 'User and technical documentation' }
]
},
'enhance-bc-app': {
specialists: [], // Will be populated dynamically
phases: [
{ methodology_id: 'analysis-impact', title: 'Impact Analysis', description: 'Architectural impact and integration considerations' },
{ methodology_id: 'performance-assessment', title: 'Performance Assessment', description: 'Performance impact and optimization opportunities' },
{ methodology_id: 'coding-feature', title: 'Feature Implementation', description: 'Implementation strategy and code integration' },
{ methodology_id: 'error-handling', title: 'Error Handling', description: 'Error handling for new features' },
{ methodology_id: 'verification-change', title: 'Change Review', description: 'Change impact and regression prevention' },
{ methodology_id: 'testing-feature', title: 'Feature Validation', description: 'Feature testing and integration validation' }
]
},
'review-bc-code': {
specialists: [], // Will be populated dynamically
phases: [
{ methodology_id: 'analysis-legacy', title: 'Legacy Pattern Assessment', description: 'Outdated pattern identification and technical debt analysis' },
{ methodology_id: 'verification-quality', title: 'Code Quality Audit', description: 'Quality metrics and maintainability assessment' },
{ methodology_id: 'performance-analysis', title: 'Performance Analysis', description: 'Bottleneck identification and optimization opportunities' },
{ methodology_id: 'security-assessment', title: 'Security Assessment', description: 'Vulnerability identification and compliance review' },
{ methodology_id: 'error-review', title: 'Error Handling Review', description: 'Exception handling and defensive programming analysis' },
{ methodology_id: 'testing-analysis', title: 'Testability Analysis', description: 'Test coverage gaps and improvement suggestions' },
{ methodology_id: 'ux-evaluation', title: 'User Experience Evaluation', description: 'Interface design and usability assessment' },
{ methodology_id: 'architecture-review', title: 'Architectural Review', description: 'Architectural coherence and design pattern consistency' }
]
},
'debug-bc-issues': {
specialists: [],
phases: [
{ methodology_id: 'analysis-debugging', title: 'Issue Analysis', description: 'Analyze and reproduce the issue' },
{ methodology_id: 'diagnosis-root-cause', title: 'Root Cause Analysis', description: 'Identify the underlying cause' },
{ methodology_id: 'coding-fix', title: 'Solution Implementation', description: 'Implement and test the fix' }
]
},
'modernize-bc-code': {
specialists: [],
phases: [
{ methodology_id: 'analysis-legacy', title: 'Legacy Assessment', description: 'Assess current code patterns and technical debt' },
{ methodology_id: 'architecture-modernization', title: 'Modernization Planning', description: 'Plan modernization approach and architecture' },
{ methodology_id: 'coding-upgrade', title: 'Code Modernization', description: 'Implement modern patterns and best practices' }
]
},
'onboard-developer': {
specialists: [], // Will be populated dynamically
phases: [
{ methodology_id: 'developer-introduction', title: 'BC Development Fundamentals', description: 'Introduction to Business Central development fundamentals and environment setup' },
{ methodology_id: 'coding-basics', title: 'AL Language Fundamentals', description: 'Core AL language concepts, syntax, and coding standards' },
{ methodology_id: 'architecture-intro', title: 'BC Architecture Overview', description: 'Understanding BC architecture patterns and best practices' },
{ methodology_id: 'debugging-intro', title: 'Debugging and Diagnostics', description: 'Debugging techniques and diagnostic tools for BC development' },
{ methodology_id: 'testing-intro', title: 'Testing Fundamentals', description: 'Testing strategies and quality assurance practices' },
{ methodology_id: 'code-review-intro', title: 'Code Review Process', description: 'Code review standards and collaborative development practices' }
]
},
'upgrade-bc-version': {
specialists: [],
phases: [
{ methodology_id: 'analysis-version-impact', title: 'Version Impact Analysis', description: 'Analyze impact of version upgrade' },
{ methodology_id: 'migration-planning', title: 'Migration Planning', description: 'Plan the upgrade process and compatibility' },
{ methodology_id: 'coding-migration', title: 'Code Migration', description: 'Update code for new BC version' }
]
},
'add-ecosystem-features': {
specialists: [],
phases: [
{ methodology_id: 'analysis-ecosystem', title: 'Ecosystem Analysis', description: 'Analyze integration requirements' },
{ methodology_id: 'architecture-integration', title: 'Integration Architecture', description: 'Design integration patterns and APIs' },
{ methodology_id: 'coding-integration', title: 'Feature Implementation', description: 'Implement ecosystem integration features' }
]
},
'document-bc-solution': {
specialists: [],
phases: [
{ methodology_id: 'analysis-documentation', title: 'Documentation Analysis', description: 'Analyze documentation requirements' },
{ methodology_id: 'documentation-planning', title: 'Documentation Planning', description: 'Plan documentation structure and content' },
{ methodology_id: 'documentation-creation', title: 'Content Creation', description: 'Create comprehensive documentation' }
]
},
'app_takeover': {
specialists: [], // Will be populated dynamically
phases: [
{ methodology_id: 'analysis-legacy', title: 'Legacy App Analysis', description: 'Understanding existing application structure and technical debt' },
{ methodology_id: 'architecture-migration', title: 'Migration Architecture', description: 'Planning the migration strategy and new architecture' },
{ methodology_id: 'coding-refactor', title: 'Code Refactoring', description: 'Modernizing existing code and implementing new patterns' },
{ methodology_id: 'error-migration', title: 'Error Handling Upgrade', description: 'Improving error handling and defensive programming' },
{ methodology_id: 'verification-takeover', title: 'Takeover Review', description: 'Code quality assessment for the taken over application' },
{ methodology_id: 'testing-migration', title: 'Migration Testing', description: 'Testing the migration and ensuring functionality preservation' },
{ methodology_id: 'documentation-takeover', title: 'Documentation Update', description: 'Updating documentation for the migrated application' }
]
}
};
}
async validatePhaseMethodology(session, phaseResults) {
// TODO: Integrate with MethodologyService to validate phase completion
return {
methodology_id: session.methodology_state.current_phase_methodology,
checklist_items: [],
completion_percentage: 85, // TODO: Calculate based on actual validation
quality_score: 78,
recommendations: [],
blocking_issues: []
};
}
async getSpecialistPhaseGuidance(specialist, phase, projectContext) {
// TODO: Use KnowledgeService to get specialist-specific guidance
return `${specialist.consultation_style}\n\nFor this ${phase.title} phase, focus on: ${phase.description}`;
}
async getPhaseMethodologyGuidance(methodologyId, context) {
// TODO: Integrate with MethodologyService to get detailed methodology guidance
return `Methodology guidance for ${methodologyId}`;
}
generatePhaseSummary(session) {
const pipeline = this.pipelineDefinitions[session.type];
const currentPhase = pipeline.phases[session.current_phase];
return `Currently in ${currentPhase?.title || 'Unknown Phase'} phase of ${session.type} workflow`;
}
generateNextActions(session) {
const pipeline = this.pipelineDefinitions[session.type];
const currentPhase = pipeline.phases[session.current_phase];
return [
`Complete ${currentPhase?.title || 'current phase'} with specialist guidance`,
'Document decisions and outcomes',
'Validate methodology requirements',
'Advance to next phase when ready'
];
}
initializeConstitutionalGates() {
return {
extensibility_compliance: false,
performance_consideration: false,
test_coverage_planned: false,
permission_model_defined: false,
documentation_planned: false,
bc_version_compliance: false,
integration_patterns: false
};
}
generateSessionId() {
return `workflow-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
}
//# sourceMappingURL=workflow-service.js.map