/ scripts / fix-misrouted-tasks.js
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!');