> ## Documentation Index
> Fetch the complete documentation index at: https://reikon.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Formulas & Methodology

> The exact math behind every score Reikon shows.

# Formulas & Methodology

Reikon's signals are deterministic — every number on screen comes from a formula you
can read here, not a black box. This page documents the actual math, the same math the
app runs, so you can decide for yourself whether to trust a number.

***

## Health Score

The core 5-signal math below lives in one place in the actual codebase —
`src/shared/health-score.ts` — shared by the desktop app, saved snapshots, and the
`rei` CLI, so all three report the same number for the same repo state.

The health score is a weighted average of up to 6 signals, each scored 0–100.

### Bus factor

Bus factor is "how many people would need to leave before the project loses 80% of its
recent commit activity." Concretely: sort active contributors by commit count
descending, then count how many it takes — starting from the top — for their combined
commits to reach 80% of all commits. That count is the bus factor.

```
busScore = min(100, round(max(0, (busFactor - 1) / 4 * 100)))
```

A bus factor of 1 (one person is 80%+ of activity) scores 0 — maximum risk. A bus
factor of 5 or more scores 100. The curve is linear in between.

### Commit quality

Each commit message is checked against a set of patterns that flag low-information
messages: very short (≤6 characters), just a version number, or a generic single word
like "fix", "wip", "update", "stuff" with no further context. `commitQuality.goodPct`
is the percentage of commits that *don't* match any of those patterns, and that
percentage is used directly as the signal score — no further transformation.

### TODO density

```
todoDensity = (todoCount / totalCodeLines) * 1000
todoScore   = round(max(0, min(100, 100 - todoDensity * 10)))
```

This measures TODOs per thousand lines of code, not a raw count — a 5,000-line project
with 10 TODOs is in a different situation than a 500,000-line project with 10 TODOs,
even though the raw count is identical.

### Duplicate code

```
dupScore = round(max(0, min(100, 100 - duplicateCount * 2)))
```

Each detected duplicate block costs 2 points, floored at 0.

### Churn stability

```
churnScore = hotspotRatio > 0
  ? round(max(0, min(100, 100 - hotspotRatio * 100)))
  : 100
```

where `hotspotRatio` is the fraction of churned files that have been changed more than
10 times. A codebase where most churn concentrates in a few volatile files scores lower
than one where churn is spread evenly — frequent change isn't inherently bad, but a
small number of files absorbing most of it usually signals a design problem.

### Dependency health *(optional — only when a dependency manifest exists and its security scanner ran)*

```
auditScore    = max(0, 100 - critical*20 - high*8 - moderate*3 - low*1)
outdatedScore = max(0, 100 - majorOutdated*5 - (totalOutdated - majorOutdated)*1)
depScore      = round(auditScore * 0.6 + outdatedScore * 0.4)
```

Audit severity dominates the score (60% weight) — a handful of critical CVEs hurts more
than a long tail of minor version lag.

### Combining the signals

```
rawWeights = { bus: 0.20, quality: 0.20, todos: 0.17, dupes: 0.11, churn: 0.11, dep: 0.07 }
```

Dependency health is read from whichever ecosystem the project uses — npm, pip (Python),
Cargo (Rust), Go, Ruby, PHP, or Java — by running that ecosystem's official audit and
outdated tools (for Java, by reading an existing OWASP dependency-check report). If the
project has no recognized dependency manifest, or its security scanner isn't installed,
the `dep` weight drops to 0 and the remaining weights are re-normalized so
they still sum to 1 — the other 5 signals simply carry more weight, rather than the
overall score being computed over a smaller denominator (and never inflated by a fake
"no vulnerabilities" reading from a scanner that never ran). Each weight can also be overridden per-project (0–2× multiplier) via
`.reikon/config.json`'s `healthWeights` — see the
[config reference](./config-schema). User overrides are applied, then weights are
re-normalized again so they always sum to 1.

```
overall = round(sum(score_k * weight_k) for each signal k)
```

### The overall label

```
overall ≥ 80   → Healthy
overall ≥ 60   → Needs attention
overall ≥ 40   → At risk
overall < 40   → Critical
```

### Two consumers, same formula

* **The in-app Health Card and saved snapshots** use the **identical** calculation —
  the core 5 signals plus dependency health, with the same weights and any per-project
  weight overrides applied. The number on the dashboard is exactly the number recorded
  in a snapshot for that analysis, so trend history and period-over-period comparison
  line up with what you saw at the time.

* **The `rei` CLI** uses the core 5 with no optional signals at all — no dependency
  audit data is wired into it — so its weights are just the core 5 re-normalized on
  their own, without anything added on top.

***

## Tech debt estimate

```
debtHours = round(avgComplexity × (churnCount / totalCommits) × (lines / 100))
```

This is a heuristic, not a real estimate of engineering hours — it combines three
independent risk factors (how complex the code is, how often it changes relative to the
project's overall commit volume, and how big the file is) into one comparable number per
file, so you can rank files rather than take the absolute hour figure literally.

Severity bands used in the UI: **Critical** ≥25h, **High** ≥10h, **Medium** ≥4h, **Low**
below that.

## Tech debt validation signal

A heuristic is only useful if it's actually predictive. This signal checks that:
for every file flagged High Risk (debt ≥10h), Reikon looks at its commit history over
the last 60 days and checks whether any commit message matches a fix/bug pattern
(`fix`, `fixes`, `fixed`, `bug`, `bugfix`, `hotfix` — case-insensitive, anywhere in the
message). The percentage of High Risk files with at least one such commit is the
validation rate — shown as a stat tile in Code Quality → Debt. A high validation rate
means the files Reikon flags as risky are, in fact, the files that keep needing
hotfixes; a low rate would be a signal that the heuristic isn't tracking real pain in
your specific codebase.

## Risk files (ownership concentration)

A file is flagged as a "risk file" when:

* One contributor owns **60% or more** of its commit touches, and
* It has **3 or fewer** total contributors, and
* It's been touched **5 or more times** total (filters out files too new to have a
  meaningful ownership signal)

This is the same underlying data used for "who should review this" suggestions in the
Review tab and the contributor risk alert on the Dashboard.
