/ tests / agents / task-routing-gaps.test.js
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  });