UNPKG

vibe-coder-mcp

Version:

Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.

195 lines (194 loc) 7.46 kB
import { getStorageManager } from '../core/storage/storage-manager.js'; import { getEpicContextResolver } from '../services/epic-context-resolver.js'; import logger from '../../../logger.js'; export class EpicValidator { static instance; constructor() { } static getInstance() { if (!EpicValidator.instance) { EpicValidator.instance = new EpicValidator(); } return EpicValidator.instance; } async validateAndEnsureEpic(epicId, projectId, taskContext) { try { logger.debug({ epicId, projectId }, 'Validating epic existence'); const storageManager = await getStorageManager(); const epicExists = await storageManager.epicExists(epicId); if (epicExists) { return { valid: true, epicId, exists: true, created: false }; } logger.info({ epicId, projectId }, 'Epic does not exist, attempting to create'); const creationResult = await this.createMissingEpic(epicId, projectId, taskContext); if (creationResult.valid) { return creationResult; } const contextResolver = getEpicContextResolver(); const resolverParams = { projectId, taskContext }; const contextResult = await contextResolver.resolveEpicContext(resolverParams); return { valid: true, epicId: contextResult.epicId, exists: contextResult.source === 'existing', created: contextResult.created || false }; } catch (error) { logger.error({ err: error, epicId, projectId }, 'Epic validation failed'); return { valid: false, epicId, exists: false, created: false, error: error instanceof Error ? error.message : 'Unknown error' }; } } async validateEpicForTask(task) { if (!task.epicId || !task.projectId) { return { valid: false, epicId: task.epicId || 'unknown', exists: false, created: false, error: 'Missing epic ID or project ID' }; } const taskContext = task.title && task.description ? { title: task.title, description: task.description, type: task.type || 'development', tags: task.tags || [] } : undefined; return this.validateAndEnsureEpic(task.epicId, task.projectId, taskContext); } async batchValidateEpics(tasks) { const results = new Map(); const uniqueEpics = new Map(); for (const task of tasks) { if (task.epicId && task.projectId) { const key = `${task.projectId}:${task.epicId}`; if (!uniqueEpics.has(key)) { const taskContext = task.title && task.description ? { title: task.title, description: task.description, type: task.type || 'development', tags: task.tags || [] } : undefined; uniqueEpics.set(key, { epicId: task.epicId, projectId: task.projectId, taskContext }); } } } for (const [key, epicInfo] of uniqueEpics) { try { const result = await this.validateAndEnsureEpic(epicInfo.epicId, epicInfo.projectId, epicInfo.taskContext); results.set(key, result); } catch (error) { logger.error({ err: error, key, epicInfo }, 'Batch epic validation failed'); results.set(key, { valid: false, epicId: epicInfo.epicId, exists: false, created: false, error: error instanceof Error ? error.message : 'Unknown error' }); } } return results; } async createMissingEpic(epicId, projectId, taskContext) { try { const functionalArea = this.extractFunctionalAreaFromEpicId(epicId); if (functionalArea) { const contextResolver = getEpicContextResolver(); const resolverParams = { projectId, functionalArea, taskContext }; const contextResult = await contextResolver.resolveEpicContext(resolverParams); return { valid: true, epicId: contextResult.epicId, exists: false, created: contextResult.created || false }; } const contextResolver = getEpicContextResolver(); const resolverParams = { projectId, taskContext }; const contextResult = await contextResolver.resolveEpicContext(resolverParams); return { valid: true, epicId: contextResult.epicId, exists: contextResult.source === 'existing', created: contextResult.created || false }; } catch (error) { logger.warn({ err: error, epicId, projectId }, 'Failed to create missing epic'); return { valid: false, epicId, exists: false, created: false, error: error instanceof Error ? error.message : 'Epic creation failed' }; } } extractFunctionalAreaFromEpicId(epicId) { const match = epicId.match(/^.+-(.+)-epic$/); if (match && match[1]) { const functionalArea = match[1].toLowerCase(); const knownAreas = [ 'auth', 'video', 'api', 'docs', 'ui', 'database', 'test', 'config', 'security', 'multilingual', 'accessibility', 'interactive', 'main' ]; if (knownAreas.includes(functionalArea)) { return functionalArea; } } return null; } isValidEpicIdFormat(epicId) { return /^E\d{3}$/.test(epicId) || /^.+-\w+-epic$/.test(epicId); } suggestEpicId(projectId, taskContext) { if (!taskContext) { return `${projectId}-main-epic`; } const contextResolver = getEpicContextResolver(); const functionalArea = contextResolver.extractFunctionalArea(taskContext); if (functionalArea) { return `${projectId}-${functionalArea}-epic`; } return `${projectId}-main-epic`; } } export function getEpicValidator() { return EpicValidator.getInstance(); } export async function validateAndEnsureEpic(epicId, projectId, taskContext) { const validator = getEpicValidator(); return validator.validateAndEnsureEpic(epicId, projectId, taskContext); } export async function validateEpicForTask(task) { const validator = getEpicValidator(); return validator.validateEpicForTask(task); }