refactor.js
1 /** 2 * Code Refactoring Workflow 3 * 4 * Automated workflow: Architect → Developer → QA 5 * 6 * Usage: 7 * import { createRefactorWorkflow } from './workflows/refactor.js'; 8 * const workflowId = await createRefactorWorkflow('src/complex-module.js', reason); 9 */ 10 11 import { createAgentTask } from '../utils/task-manager.js'; 12 import Logger from '../../utils/logger.js'; 13 import { getAll } from '../../utils/db.js'; 14 15 const logger = new Logger('RefactorWorkflow'); 16 17 /** 18 * Create a code refactoring workflow 19 * 20 * @param {string} filePath - File to refactor 21 * @param {string} reason - Reason for refactoring 22 * @param {Object} [options] - Additional options 23 * @param {number} [options.priority=4] - Task priority (1-10, default lower for refactoring) 24 * @param {string} [options.created_by='system'] - Who created the workflow 25 * @param {Array<string>} [options.complexity_issues=[]] - Specific complexity issues 26 * @returns {Promise<number>} - Workflow parent task ID 27 */ 28 export async function createRefactorWorkflow(filePath, reason, options = {}) { 29 const { priority = 4, created_by = 'system', complexity_issues = [] } = options; 30 31 logger.info('Creating refactor workflow', { 32 file: filePath, 33 reason, 34 }); 35 36 // Step 1: Architect suggests refactoring approach 37 const architectTaskId = await createAgentTask({ 38 task_type: 'suggest_refactor', 39 assigned_to: 'architect', 40 created_by, 41 priority, 42 context: { 43 file_path: filePath, 44 reason, 45 complexity_issues, 46 workflow_type: 'refactor', 47 }, 48 }); 49 50 logger.info('Refactor workflow created', { 51 workflow_id: architectTaskId, 52 file: filePath, 53 }); 54 55 return architectTaskId; 56 } 57 58 /** 59 * Create bulk refactor workflows for files exceeding complexity thresholds 60 * 61 * @param {Array<Object>} files - Array of file objects 62 * @param {string} files[].path - File path 63 * @param {number} files[].lines - Line count 64 * @param {number} files[].complexity - Cyclomatic complexity 65 * @param {number} files[].depth - Max nesting depth 66 * @returns {Promise<Array<number>>} - Array of workflow IDs 67 */ 68 export async function createBulkRefactorWorkflows(files) { 69 const workflowIds = []; 70 71 for (const file of files) { 72 const issues = []; 73 if (file.lines > 150) { 74 issues.push(`File exceeds 150 lines (${file.lines})`); 75 } 76 if (file.complexity > 15) { 77 issues.push(`Complexity exceeds 15 (${file.complexity})`); 78 } 79 if (file.depth > 4) { 80 issues.push(`Nesting depth exceeds 4 (${file.depth})`); 81 } 82 83 if (issues.length > 0) { 84 try { 85 const workflowId = await createRefactorWorkflow( 86 file.path, 87 `ESLint thresholds exceeded: ${issues.join(', ')}`, 88 { 89 complexity_issues: issues, 90 created_by: 'monitor', 91 priority: 4, 92 } 93 ); 94 workflowIds.push(workflowId); 95 } catch (err) { 96 logger.error('Failed to create refactor workflow', { 97 file: file.path, 98 err: err.message, 99 }); 100 } 101 } 102 } 103 104 return workflowIds; 105 } 106 107 /** 108 * Get refactor workflow status 109 * 110 * @param {number} workflowId - Parent task ID 111 * @returns {Promise<Object>} - Workflow status 112 */ 113 export async function getRefactorWorkflowStatus(workflowId) { 114 // Get all tasks in the workflow chain 115 const tasks = await getAll( 116 `WITH RECURSIVE workflow_chain AS ( 117 SELECT * FROM tel.agent_tasks WHERE id = $1 118 UNION ALL 119 SELECT t.* FROM tel.agent_tasks t 120 INNER JOIN workflow_chain wc ON t.parent_task_id = wc.id 121 ) 122 SELECT * FROM workflow_chain 123 ORDER BY id ASC`, 124 [workflowId] 125 ); 126 127 const status = { 128 workflow_id: workflowId, 129 created_at: tasks[0]?.created_at, 130 stages: tasks.map(t => ({ 131 agent: t.assigned_to, 132 task_type: t.task_type, 133 status: t.status, 134 started_at: t.started_at, 135 completed_at: t.completed_at, 136 error_message: t.error_message, 137 })), 138 current_stage: tasks.find(t => t.status === 'running' || t.status === 'pending'), 139 is_complete: tasks.every(t => t.status === 'completed'), 140 has_failures: tasks.some(t => t.status === 'failed'), 141 is_blocked: tasks.some(t => t.status === 'blocked'), 142 }; 143 144 return status; 145 }