How StackHealth scores a repo

Formula version v1.0. Every weight and threshold is defined below. The same formula lives in code at the formula spec and runs locally in our worker.

Overall score

Each scan produces a 0–100 composite score and an A+ to F letter grade. The composite weights four dimensions:

Security30%
Quality25%
Hygiene25%
Community20%
overall = round(
  0.30 * security
+ 0.25 * quality
+ 0.25 * hygiene
+ 0.20 * community
)

Grade boundaries: A+ ≥95 · A ≥90 · A- ≥85 · B+ ≥80 · B ≥75 · B- ≥70 · C+ ≥65 · C ≥60 · C- ≥55 · D ≥50 · F <50

1. Security (30%)

OpenSSF Scorecard40% of security · 12% overall
Semgrep p/security-audit40% of security · 12% overall
Trivy dependency CVEs20% of security · 6% overall

Semgrep findings are LoC-normalised so a 100-finding repo at 1M LoC isn't penalised the same as a 100-finding repo at 1k LoC. Dependency CVEs are absolute: one critical vulnerability is one critical vulnerability regardless of project size.

2. Quality (25%)

Cyclomatic complexity (lizard)30% · avg ≤5 → 100
Lint density (ruff / eslint / golangci)25% · issues per kLoC
Code duplication (jscpd)20% · 0% dup → 100
Test signal (no execution)15% · directories + CI runners
File size10% · penalises files >1000 LoC

3. Hygiene (25%)

A binary checklist. Total possible: 100 points.

README.md exists, >300 chars15
LICENSE present15
LICENSE is OSI-approved5
CONTRIBUTING.md8
CODE_OF_CONDUCT.md5
SECURITY.md7
.github/workflows/ or .gitlab-ci.yml10
A workflow triggers on pull_request5
tests/ directory10
.gitignore3
Repo description on GitHub5
Repo topics on GitHub5
Pushed within last 365 days7

4. Community (20%)

Activity (recent commits)35% of community · 7% overall
Contributors (last 365d, log2 scale)25% · 5% overall
Popularity (stars, log10 scale)20% · 4% overall
Responsiveness (median time-to-first-response)20% · 4% overall

Popularity is capped at 4% of overall so a repo cannot earn an A just by being popular.

Reproducibility

Every scan stores:

If you can fetch the raw outputs and the published formula doesn't reproduce the score, that's a bug we'll fix.

What we do NOT score

We deliberately exclude code aesthetics (no AI prose review), documentation depth (only README presence), runtime performance, stars growth rate, author identity, and language choice. These are either gameable, subjective, or unfair across projects.

How the formula evolves

Patch (v1.0 → v1.0.1) — bug fixes only, same inputs → same score. Minor (v1.0 → v1.1) — threshold tweaks; old scans aren't re-scored. Major (v1 → v2) — structural changes, always preceded by a 30-day public RFC.

All changes are pull requests against the public formula repo.