Skip to Content
ScanningQuality Ratings (A–E) + Tech Debt

Quality Ratings

Every completed scan gets five A–E ratings + a total tech-debt estimate. This page shows the exact math.

The Five Ratings

RatingWhat it measuresPrimary inputs
OverallComposite — worst of the four belowmin(reliability, maintainability, coverage, duplication)
ReliabilityLikelihood of runtime bugscomplexity + dead-code + SAST critical/high
MaintainabilityChange safetycomplexity + duplication + dead-code
CoverageTest completenessingested coverage reports, aggregate line %
DuplicationCopy-paste codejscpd summary (total duplication % of LOC)

Missing data (no coverage report, no jscpd summary) → rating is null, not a fake grade. The dashboard renders a greyed-out badge with a shield icon.

A–E Thresholds

Severity-driven ratings (reliability, maintainability)

RatingCriterion (counts findings of matching type + severity in scan)
A0 critical + 0 high
B0 critical + ≤ 2 high
C0 critical + ≤ 10 high
D≤ 2 critical
E3+ critical

Coverage rating

RatingCoverage % (from ingested lcov/cobertura/jacoco/clover)
A≥ 90%
B≥ 80%
C≥ 60%
D≥ 40%
E< 40%

Duplication rating

RatingDuplication % (from jscpd summary)
A< 1%
B< 3%
C< 5%
D< 10%
E≥ 10%

Composite

composite = max(reliability, maintainability, coverage, duplication) — the worst letter wins (since letters are ordered A..E lexicographically, max = worst).

Missing ratings are ignored (they don’t drag the composite down).

Tech Debt Hours

CodeStax implements a simplified SQALE model. Every rule maps to a remediation-minute estimate:

Rule Minutes ───────────────────────────────────── radon-cc-C (complexity C) 20 radon-cc-D 45 radon-cc-E 90 radon-cc-F (very complex) 180 lizard-cc-* 20-180 radon-mi (maintainability) 60 cognitive-complexity 30 vulture-unused 5 knip-unused-file 10 knip-unused-export 5 jscpd-duplicate 30 coverage-below-threshold 15 default (unknown rule) 10

The scan’s total tech_debt_minutes = sum of above for non-FP findings. Exposed as:

  • tech_debt_minutes (raw) on ScanResult
  • tech_debt_hours = round(minutes / 60, 2)
  • tech_debt_engineer_days = round(minutes / 480, 2) (8-hour days)

API:

GET /api/quality/tech-debt/{scan_id} { "scan_id": 12345, "total_minutes": 847, "total_hours": 14.12, "total_engineer_days": 1.76, "findings_by_type": { "complexity": 23, "dead_code": 8, "duplication": 5, "coverage_gap": 12 } }

FP-Marked Findings

Findings with user_marked_fp = true are excluded from tech-debt totals + rating counts. See Mark False Positives.

Deterministic

Ratings are a pure function of the findings list. Same scan → same ratings. See Reproducibility.

Parse Coverage

Each scan also reports parse coverage — the % of files the scanner could successfully read. Low parse coverage = underestimates in ratings. Visible in Quality Insights → collapsible “Scan metadata”:

parse_coverage_pct: 98.2 files_parsed: 1847 files_skipped: 34

If parse coverage < 95%, the dashboard surfaces it in yellow as a warning.

Viewing Ratings

  • Scan detail page — Quality Insights panel shows all 5 ratings as badges + tech-debt hours + engineer-days
  • API: GET /api/quality/ratings/:scan_id
  • Historical trend — coming soon (ratings are recorded per scan; aggregation view on roadmap)