fix-misrouted-tasks.js
1 #!/usr/bin/env node 2 /** 3 * Fix Misrouted Agent Tasks 4 * 5 * Identifies and fixes agent tasks that are assigned to the wrong agent. 6 * Uses the centralized task routing configuration. 7 * 8 * Usage: 9 * node scripts/fix-misrouted-tasks.js [--dry-run] [--status failed,pending] 10 */ 11 12 import { createDatabaseConnection } from '../src/utils/db.js'; 13 import { validateTaskAssignment } from '../src/agents/utils/task-routing.js'; 14 15 const db = createDatabaseConnection(); 16 17 // Parse command line args 18 const args = process.argv.slice(2); 19 const dryRun = args.includes('--dry-run'); 20 const statusArg = args.find(arg => arg.startsWith('--status=')); 21 const statuses = statusArg ? statusArg.split('=')[1].split(',') : ['failed', 'pending', 'blocked']; 22 23 console.log('š Scanning for misrouted agent tasks...'); 24 console.log(` Status filter: ${statuses.join(', ')}`); 25 console.log(` Mode: ${dryRun ? 'DRY RUN' : 'LIVE'}\n`); 26 27 // Get all tasks matching status criteria 28 const placeholders = statuses.map(() => '?').join(','); 29 const tasks = db 30 .prepare( 31 ` 32 SELECT id, task_type, assigned_to, status, priority, parent_task_id, context_json, created_at 33 FROM tel.agent_tasks 34 WHERE status IN (${placeholders}) 35 ORDER BY created_at DESC 36 ` 37 ) 38 .all(...statuses); 39 40 console.log(`Found ${tasks.length} tasks to check\n`); 41 42 const misrouted = []; 43 const corrections = []; 44 45 // Check each task 46 for (const task of tasks) { 47 const validation = validateTaskAssignment(task.task_type, task.assigned_to); 48 49 if (!validation.valid) { 50 misrouted.push({ 51 id: task.id, 52 task_type: task.task_type, 53 wrong_agent: task.assigned_to, 54 correct_agent: validation.correctAgent, 55 status: task.status, 56 created_at: task.created_at, 57 }); 58 59 console.log(`ā Task #${task.id}: ${task.task_type}`); 60 console.log(` Assigned to: ${task.assigned_to} (WRONG)`); 61 console.log(` Should be: ${validation.correctAgent}`); 62 console.log(` Status: ${task.status}`); 63 console.log(` Created: ${task.created_at}\n`); 64 } 65 } 66 67 console.log(`\nš Summary:`); 68 console.log(` Total tasks checked: ${tasks.length}`); 69 console.log(` Misrouted tasks: ${misrouted.length}`); 70 71 if (misrouted.length === 0) { 72 console.log('\nā No misrouted tasks found!'); 73 db.close(); 74 process.exit(0); 75 } 76 77 // Group by task_type for analysis 78 const byType = {}; 79 for (const m of misrouted) { 80 if (!byType[m.task_type]) { 81 byType[m.task_type] = []; 82 } 83 byType[m.task_type].push(m); 84 } 85 86 console.log('\nš Breakdown by task type:'); 87 for (const [taskType, items] of Object.entries(byType)) { 88 console.log(` ${taskType}: ${items.length} tasks`); 89 const wrongAgents = [...new Set(items.map(i => i.wrong_agent))]; 90 console.log(` Wrong agents: ${wrongAgents.join(', ')}`); 91 console.log(` Correct agent: ${items[0].correct_agent}`); 92 } 93 94 if (dryRun) { 95 console.log('\nš” Dry run mode - no changes made'); 96 console.log(' Remove --dry-run to apply fixes'); 97 db.close(); 98 process.exit(0); 99 } 100 101 // Fix misrouted tasks 102 console.log('\nš§ Applying fixes...\n'); 103 104 for (const item of misrouted) { 105 try { 106 // Strategy depends on status: 107 // - failed: Create new task with correct agent, mark old as completed (delegated) 108 // - pending/blocked: Update assigned_to directly 109 110 if (item.status === 'failed') { 111 // Create new task 112 const originalTask = db.prepare('SELECT * FROM tel.agent_tasks WHERE id = ?').get(item.id); 113 114 const newTaskId = db 115 .prepare( 116 ` 117 INSERT INTO tel.agent_tasks (task_type, assigned_to, status, priority, parent_task_id, context_json, created_at) 118 VALUES (?, ?, 'pending', ?, ?, ?, datetime('now')) 119 ` 120 ) 121 .run( 122 item.task_type, 123 item.correct_agent, 124 originalTask.priority || 5, 125 originalTask.parent_task_id, 126 originalTask.context_json 127 ).lastInsertRowid; 128 129 // Mark old task as completed with delegation note 130 db.prepare( 131 ` 132 UPDATE tel.agent_tasks 133 SET status = 'completed', 134 result_json = ?, 135 completed_at = datetime('now') 136 WHERE id = ? 137 ` 138 ).run( 139 JSON.stringify({ 140 delegated: true, 141 new_task_id: newTaskId, 142 correct_agent: item.correct_agent, 143 reason: 'Misrouted task fixed by migration script', 144 migration: 'fix-misrouted-tasks.js', 145 }), 146 item.id 147 ); 148 149 corrections.push({ 150 old_id: item.id, 151 new_id: newTaskId, 152 action: 'created_new_task', 153 }); 154 155 console.log( 156 `ā Task #${item.id} (${item.task_type}): Created new task #${newTaskId} for ${item.correct_agent}` 157 ); 158 } else { 159 // Update directly 160 db.prepare( 161 ` 162 UPDATE tel.agent_tasks 163 SET assigned_to = ?, 164 retry_count = 0 165 WHERE id = ? 166 ` 167 ).run(item.correct_agent, item.id); 168 169 corrections.push({ 170 task_id: item.id, 171 action: 'updated_assignment', 172 }); 173 174 console.log( 175 `ā Task #${item.id} (${item.task_type}): Updated assignment to ${item.correct_agent}` 176 ); 177 } 178 } catch (error) { 179 console.error(`ā Failed to fix task #${item.id}: ${error.message}`); 180 } 181 } 182 183 console.log(`\nā Fixed ${corrections.length} tasks`); 184 185 // Log to agent_logs 186 try { 187 db.prepare( 188 ` 189 INSERT INTO tel.agent_logs (agent_name, log_level, message, metadata_json, created_at) 190 VALUES ('system', 'INFO', ?, ?, datetime('now')) 191 ` 192 ).run( 193 'Misrouted tasks fixed by migration script', 194 JSON.stringify({ 195 script: 'fix-misrouted-tasks.js', 196 total_checked: tasks.length, 197 misrouted_found: misrouted.length, 198 corrections_applied: corrections.length, 199 statuses, 200 }) 201 ); 202 } catch (error) { 203 console.warn('Failed to log to agent_logs:', error.message); 204 } 205 206 db.close(); 207 console.log('\nš Migration complete!');