({ severityThreshold, categories } = {})
| 1396 | // categories: Set<string>, // lowercase enum members; empty when disabled |
| 1397 | // } |
| 1398 | function buildPolicy({ severityThreshold, categories } = {}) { |
| 1399 | let routeBySeverity = false; |
| 1400 | let severityRank = -1; |
| 1401 | if (severityThreshold != null) { |
| 1402 | const norm = String(severityThreshold).trim().toLowerCase(); |
| 1403 | if (SEVERITY_RANK.has(norm)) { |
| 1404 | routeBySeverity = true; |
| 1405 | severityRank = SEVERITY_RANK.get(norm); |
| 1406 | } |
| 1407 | // Any other value (empty, unknown, garbage) leaves routeBySeverity=false |
| 1408 | // (fail-open for the policy: unknown threshold -> no routing). |
| 1409 | } |
| 1410 | |
| 1411 | let routeByCategory = false; |
| 1412 | const categorySet = new Set(); |
| 1413 | if (categories != null) { |
| 1414 | const tokens = String(categories) |
| 1415 | .split(",") |
| 1416 | .map((t) => t.trim().toLowerCase()) |
| 1417 | .filter((t) => t.length > 0); |
| 1418 | for (const t of tokens) { |
| 1419 | if (CATEGORIES.includes(t)) categorySet.add(t); |
| 1420 | // Unknown category tokens are silently dropped (fail-open: an unknown |
| 1421 | // category in the policy never matches a finding's category, so including |
| 1422 | // it would be a no-op anyway; dropping keeps the set clean). |
| 1423 | } |
| 1424 | if (categorySet.size > 0) routeByCategory = true; |
| 1425 | } |
| 1426 | |
| 1427 | if (!routeBySeverity && !routeByCategory) return NO_ROUTING; |
| 1428 | return { routeBySeverity, severityRank, routeByCategory, categories: categorySet }; |
| 1429 | } |
| 1430 | |
| 1431 | // Decide whether a comment routes to the summary per the policy. Returns |
| 1432 | // { routed: true, reason } or { routed: false }. A finding matches when its |
no outgoing calls