nestjs-doctorGitHub

Scoring

Source: src/scorer/index.ts, src/scorer/weights.ts, src/scorer/labels.ts

What

Converts filtered diagnostics into a 0-100 health score with a quality label.

Why

A single number makes it easy to track progress over time, set CI thresholds with --min-score, and compare projects. The weighted formula ensures security errors impact the score more than info-level performance hints.

Input

diagnostics: Diagnostic[]    // filtered diagnostics
fileCount: number            // total files scanned

Output

interface Score {
  value: number    // 0-100, clamped
  label: string    // "Excellent" | "Good" | "Fair" | "Poor" | "Critical"
}

Formula

penalty per diagnostic = SEVERITY_WEIGHT × CATEGORY_MULTIPLIER
total penalty = sum of all diagnostic penalties
score = 100 − (totalPenalty / fileCount) × PENALTY_SCALE

The score is clamped to the 0-100 range.

Severity Weights

SeverityWeight
error3.0
warning1.5
info0.5

Category Multipliers

CategoryMultiplierRationale
security1.5xSecurity issues are the most impactful
correctness1.3xBugs that cause runtime errors
architecture1.0xStructural issues that grow over time
performance0.8xImportant but less critical than correctness

Penalty Scale

PENALTY_SCALE = 10 — a calibration constant. Combined with severity weights and category multipliers, it produces intuitive scores:

ScenarioScore
1 security error per 10 files~95 (Excellent)
1 error per 3 files~85 (Good)
1 error per file~55 (Fair)
2 errors per file~10 (Critical)

Normalization

Score is divided by fileCount so projects of different sizes are comparable. A 500-file project with 10 errors scores the same as a 50-file project with 1 error (same density).

Labels

ScoreLabel
90-100Excellent
75-89Good
50-74Fair
25-49Poor
0-24Critical

Monorepo Scoring

In a monorepo, each sub-project gets its own score. The combined score is calculated from the merged diagnostics of all sub-projects divided by the total file count across all projects.

Debugging Tips

  • If the score seems too low, check for high-severity rules producing many diagnostics. A single security error per file adds 3.0 × 1.5 = 4.5 penalty points.
  • The score is normalized by file count. Adding more files (without new issues) will improve the score.
  • Use --json to see the full diagnostic list and understand exactly what's contributing to the penalty.