config-audit/scanners/lib/severity.mjs
Kjell Tore Guttormsen caee558e79 feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command
Add /ultraresearch-local for structured research combining local codebase
analysis with external knowledge via parallel agent swarms. Produces research
briefs with triangulation, confidence ratings, and source quality assessment.

New command: /ultraresearch-local with modes --quick, --local, --external, --fg.
New agents: research-orchestrator (opus), docs-researcher, community-researcher,
security-researcher, contrarian-researcher, gemini-bridge (all sonnet).
New template: research-brief-template.md.

Integration: --research flag in /ultraplan-local accepts pre-built research
briefs (up to 3), enriches the interview and exploration phases. Planning
orchestrator cross-references brief findings during synthesis.

Design principle: Context Engineering — right information to right agent at
right time. Research briefs are structured artifacts in the pipeline:
ultraresearch → brief → ultraplan --research → plan → ultraexecute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 08:58:35 +02:00

75 lines
2 KiB
JavaScript

/**
* Severity constants, risk scoring, and verdict logic for config-audit scanners.
* Zero external dependencies.
*/
export const SEVERITY = Object.freeze({
critical: 'critical',
high: 'high',
medium: 'medium',
low: 'low',
info: 'info',
});
const WEIGHTS = { critical: 25, high: 10, medium: 4, low: 1, info: 0 };
/**
* Calculate a 0-100 risk score from severity counts.
* @param {{ critical?: number, high?: number, medium?: number, low?: number, info?: number }} counts
* @returns {number}
*/
export function riskScore(counts) {
let score = 0;
for (const [sev, weight] of Object.entries(WEIGHTS)) {
score += (counts[sev] || 0) * weight;
}
return Math.min(score, 100);
}
/**
* Determine overall verdict from severity counts.
* @param {{ critical?: number, high?: number, medium?: number, low?: number, info?: number }} counts
* @returns {'FAIL' | 'WARNING' | 'PASS'}
*/
export function verdict(counts) {
const score = riskScore(counts);
if ((counts.critical || 0) >= 1 || score >= 61) return 'FAIL';
if ((counts.high || 0) >= 1 || score >= 21) return 'WARNING';
return 'PASS';
}
/**
* Map a risk score to a human-readable band.
* @param {number} score
* @returns {'Low' | 'Medium' | 'High' | 'Critical' | 'Extreme'}
*/
export function riskBand(score) {
if (score <= 10) return 'Low';
if (score <= 30) return 'Medium';
if (score <= 60) return 'High';
if (score <= 80) return 'Critical';
return 'Extreme';
}
/**
* Grade from a quality pass rate (0-100%).
* @param {number} passRate - 0-100
* @returns {'A' | 'B' | 'C' | 'D' | 'F'}
*/
export function gradeFromPassRate(passRate) {
if (passRate >= 90) return 'A';
if (passRate >= 75) return 'B';
if (passRate >= 60) return 'C';
if (passRate >= 40) return 'D';
return 'F';
}
/** Config audit quality categories */
export const QUALITY_CATEGORIES = Object.freeze({
STRUCTURE: 'Structure & Format',
CONTENT: 'Content Quality',
HIERARCHY: 'Hierarchy & Scope',
SECURITY: 'Security',
FEATURES: 'Feature Utilization',
COHERENCE: 'Cross-file Coherence',
});