task-routing-gaps.test.js
1 /** 2 * Task Routing Gap Coverage Tests 3 * 4 * Targets remaining uncovered paths in src/agents/utils/task-routing.js (85% → ~100%): 5 * - getTaskTypesForAgent: returns empty array for unknown agent 6 * - getTaskTypesForAgent: covers all agents including 'monitor' and 'triage' 7 * - validateTaskAssignment: unknown task type (routes to triage by default) 8 * - isValidTaskType: tests for newer task types added after initial test suite 9 * - TASK_ROUTING: newer task types (exploratory_testing, generate_sbom, bootstrap_monitor, design_optimization) 10 * - Complete routing table verification (all task types map to correct agent) 11 */ 12 13 import { test, describe } from 'node:test'; 14 import assert from 'node:assert/strict'; 15 import { 16 TASK_ROUTING, 17 getAgentForTaskType, 18 isValidTaskType, 19 getTaskTypesForAgent, 20 validateTaskAssignment, 21 } from '../../src/agents/utils/task-routing.js'; 22 23 describe('task-routing gap coverage', () => { 24 // ─── getTaskTypesForAgent: unknown agent ─────────────────────────────── 25 26 describe('getTaskTypesForAgent - unknown agent', () => { 27 test('returns empty array for unknown agent name', () => { 28 const types = getTaskTypesForAgent('nonexistent_agent'); 29 assert.ok(Array.isArray(types)); 30 assert.equal(types.length, 0); 31 }); 32 33 test('returns empty array for empty string agent', () => { 34 const types = getTaskTypesForAgent(''); 35 assert.ok(Array.isArray(types)); 36 assert.equal(types.length, 0); 37 }); 38 39 test('returns empty array for null agent', () => { 40 const types = getTaskTypesForAgent(null); 41 assert.ok(Array.isArray(types)); 42 assert.equal(types.length, 0); 43 }); 44 }); 45 46 // ─── getTaskTypesForAgent: complete agent coverage ───────────────────── 47 48 describe('getTaskTypesForAgent - all agents', () => { 49 test('monitor agent has all expected task types', () => { 50 const types = getTaskTypesForAgent('monitor'); 51 assert.ok(types.includes('scan_logs')); 52 assert.ok(types.includes('check_agent_health')); 53 assert.ok(types.includes('check_process_compliance')); 54 assert.ok(types.includes('detect_anomaly')); 55 assert.ok(types.includes('check_pipeline_health')); 56 assert.ok(types.includes('check_slo_compliance')); 57 assert.ok(types.includes('bootstrap_monitor')); 58 }); 59 60 test('triage agent has all expected task types', () => { 61 const types = getTaskTypesForAgent('triage'); 62 assert.ok(types.includes('classify_error')); 63 assert.ok(types.includes('route_task')); 64 assert.ok(types.includes('prioritize_tasks')); 65 }); 66 67 test('security agent has all expected task types', () => { 68 const types = getTaskTypesForAgent('security'); 69 assert.ok(types.includes('audit_code')); 70 assert.ok(types.includes('scan_dependencies')); 71 assert.ok(types.includes('verify_compliance')); 72 assert.ok(types.includes('scan_secrets')); 73 assert.ok(types.includes('threat_model')); 74 assert.ok(types.includes('fix_security_issue')); 75 assert.ok(types.includes('review_dependency_update')); 76 assert.ok(types.includes('generate_sbom')); 77 }); 78 79 test('qa agent has all expected task types', () => { 80 const types = getTaskTypesForAgent('qa'); 81 assert.ok(types.includes('write_test')); 82 assert.ok(types.includes('verify_fix')); 83 assert.ok(types.includes('check_coverage')); 84 assert.ok(types.includes('run_tests')); 85 assert.ok(types.includes('exploratory_testing')); 86 }); 87 88 test('architect agent has all expected task types', () => { 89 const types = getTaskTypesForAgent('architect'); 90 assert.ok(types.includes('design_proposal')); 91 assert.ok(types.includes('technical_review')); 92 assert.ok(types.includes('review_design')); 93 assert.ok(types.includes('suggest_refactor')); 94 assert.ok(types.includes('update_documentation')); 95 assert.ok(types.includes('check_documentation_freshness')); 96 assert.ok(types.includes('check_complexity')); 97 assert.ok(types.includes('audit_documentation')); 98 assert.ok(types.includes('check_branch_health')); 99 assert.ok(types.includes('profile_performance')); 100 assert.ok(types.includes('review_documentation')); 101 assert.ok(types.includes('design_optimization')); 102 }); 103 104 test('developer agent has all expected task types', () => { 105 const types = getTaskTypesForAgent('developer'); 106 assert.ok(types.includes('fix_bug')); 107 assert.ok(types.includes('implement_feature')); 108 assert.ok(types.includes('refactor_code')); 109 assert.ok(types.includes('apply_feedback')); 110 assert.ok(types.includes('implementation_plan')); 111 assert.equal(types.length, 5); 112 }); 113 }); 114 115 // ─── validateTaskAssignment: unknown task types ──────────────────────── 116 117 describe('validateTaskAssignment - unknown task types', () => { 118 test('unknown task type defaults to triage, so assigning to triage is valid', () => { 119 const result = validateTaskAssignment('completely_unknown_type', 'triage'); 120 assert.equal(result.valid, true); 121 }); 122 123 test('unknown task type assigned to non-triage agent is invalid', () => { 124 const result = validateTaskAssignment('completely_unknown_type', 'developer'); 125 assert.equal(result.valid, false); 126 assert.equal(result.correctAgent, 'triage'); 127 assert.ok(result.reason.includes('triage')); 128 assert.ok(result.reason.includes('developer')); 129 }); 130 131 test('unknown task type reason message includes task type', () => { 132 const result = validateTaskAssignment('my_custom_task', 'qa'); 133 assert.equal(result.valid, false); 134 assert.ok(result.reason.includes('my_custom_task')); 135 }); 136 }); 137 138 // ─── isValidTaskType: newer task types ───────────────────────────────── 139 140 describe('isValidTaskType - newer task types', () => { 141 test('exploratory_testing is valid', () => { 142 assert.equal(isValidTaskType('exploratory_testing'), true); 143 }); 144 145 test('generate_sbom is valid', () => { 146 assert.equal(isValidTaskType('generate_sbom'), true); 147 }); 148 149 test('bootstrap_monitor is valid', () => { 150 assert.equal(isValidTaskType('bootstrap_monitor'), true); 151 }); 152 153 test('design_optimization is valid', () => { 154 assert.equal(isValidTaskType('design_optimization'), true); 155 }); 156 157 test('check_slo_compliance is valid', () => { 158 assert.equal(isValidTaskType('check_slo_compliance'), true); 159 }); 160 161 test('check_branch_health is valid', () => { 162 assert.equal(isValidTaskType('check_branch_health'), true); 163 }); 164 165 test('prioritize_tasks is valid', () => { 166 assert.equal(isValidTaskType('prioritize_tasks'), true); 167 }); 168 }); 169 170 // ─── getAgentForTaskType: newer task types ───────────────────────────── 171 172 describe('getAgentForTaskType - newer task types', () => { 173 test('exploratory_testing routes to qa', () => { 174 assert.equal(getAgentForTaskType('exploratory_testing'), 'qa'); 175 }); 176 177 test('generate_sbom routes to security', () => { 178 assert.equal(getAgentForTaskType('generate_sbom'), 'security'); 179 }); 180 181 test('bootstrap_monitor routes to monitor', () => { 182 assert.equal(getAgentForTaskType('bootstrap_monitor'), 'monitor'); 183 }); 184 185 test('design_optimization routes to architect', () => { 186 assert.equal(getAgentForTaskType('design_optimization'), 'architect'); 187 }); 188 189 test('fix_security_issue routes to security', () => { 190 assert.equal(getAgentForTaskType('fix_security_issue'), 'security'); 191 }); 192 193 test('scan_secrets routes to security', () => { 194 assert.equal(getAgentForTaskType('scan_secrets'), 'security'); 195 }); 196 197 test('threat_model routes to security', () => { 198 assert.equal(getAgentForTaskType('threat_model'), 'security'); 199 }); 200 201 test('detect_anomaly routes to monitor', () => { 202 assert.equal(getAgentForTaskType('detect_anomaly'), 'monitor'); 203 }); 204 205 test('check_process_compliance routes to monitor', () => { 206 assert.equal(getAgentForTaskType('check_process_compliance'), 'monitor'); 207 }); 208 209 test('prioritize_tasks routes to triage', () => { 210 assert.equal(getAgentForTaskType('prioritize_tasks'), 'triage'); 211 }); 212 }); 213 214 // ─── TASK_ROUTING: complete verification ─────────────────────────────── 215 216 describe('TASK_ROUTING - complete table verification', () => { 217 test('every routing entry maps to a valid agent', () => { 218 const validAgents = ['developer', 'qa', 'security', 'architect', 'triage', 'monitor']; 219 for (const [taskType, agent] of Object.entries(TASK_ROUTING)) { 220 assert.ok( 221 validAgents.includes(agent), 222 `Task type '${taskType}' maps to invalid agent '${agent}'` 223 ); 224 } 225 }); 226 227 test('routing table has expected minimum size', () => { 228 const count = Object.keys(TASK_ROUTING).length; 229 // Should have at least 30 task types 230 assert.ok(count >= 30, `Expected at least 30 task types, got ${count}`); 231 }); 232 233 test('all task types are strings', () => { 234 for (const key of Object.keys(TASK_ROUTING)) { 235 assert.equal(typeof key, 'string'); 236 assert.ok(key.length > 0, 'Task type should not be empty'); 237 } 238 }); 239 240 test('all agent values are strings', () => { 241 for (const value of Object.values(TASK_ROUTING)) { 242 assert.equal(typeof value, 'string'); 243 assert.ok(value.length > 0, 'Agent name should not be empty'); 244 } 245 }); 246 }); 247 248 // ─── validateTaskAssignment: exhaustive for newer types ──────────────── 249 250 describe('validateTaskAssignment - newer types exhaustive', () => { 251 test('exploratory_testing assigned to qa is valid', () => { 252 const result = validateTaskAssignment('exploratory_testing', 'qa'); 253 assert.equal(result.valid, true); 254 }); 255 256 test('exploratory_testing assigned to developer is invalid', () => { 257 const result = validateTaskAssignment('exploratory_testing', 'developer'); 258 assert.equal(result.valid, false); 259 assert.equal(result.correctAgent, 'qa'); 260 }); 261 262 test('generate_sbom assigned to security is valid', () => { 263 const result = validateTaskAssignment('generate_sbom', 'security'); 264 assert.equal(result.valid, true); 265 }); 266 267 test('generate_sbom assigned to architect is invalid', () => { 268 const result = validateTaskAssignment('generate_sbom', 'architect'); 269 assert.equal(result.valid, false); 270 assert.equal(result.correctAgent, 'security'); 271 }); 272 273 test('bootstrap_monitor assigned to monitor is valid', () => { 274 const result = validateTaskAssignment('bootstrap_monitor', 'monitor'); 275 assert.equal(result.valid, true); 276 }); 277 278 test('design_optimization assigned to architect is valid', () => { 279 const result = validateTaskAssignment('design_optimization', 'architect'); 280 assert.equal(result.valid, true); 281 }); 282 283 test('design_optimization assigned to developer is invalid', () => { 284 const result = validateTaskAssignment('design_optimization', 'developer'); 285 assert.equal(result.valid, false); 286 assert.equal(result.correctAgent, 'architect'); 287 }); 288 }); 289 });