/ src / agents / workflows / refactor.js
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  }