# churn-risk

Customer churn-risk and account-health scoring for SaaS retention & customer-success teams: score turns a bundle of usage/engagement/support/billing signals (login recency, usage trend, feature...


An intelligent microservice adapter pack that scores customer churn risk and account health for SaaS
retention / customer-success teams. The weighted-signal scoring engine is deterministic and runs fully
offline. Only the optional "save narrative" on `score` (with `options.narrate`) uses the shared LLM
helper, and it silently falls back to a templated recommendation offline. Hybrid results are tagged
`{ mode: 'heuristic' | 'llm' }` — the score is always exact regardless of mode.

## Tools

| Tool | What it does |
|---|---|
| `score` | Turns a bundle of `signals` into a 0-100 risk score, a band (low/moderate/high/critical) and per-signal contributions. **Optional LLM narrative.** |
| `drivers` | Ranks the top risk factors and the protective factors behind the score. |
| `segment` | Buckets the account into a lifecycle segment (champion / healthy / passive / at-risk / dormant / likely-churn) with a recommended play. |
| `healthScore` | Inverse 0-100 health index with an A–F grade and status. |
| `cohortRisk` | Aggregates many `accounts` into a cohort distribution, at-risk MRR, expected revenue loss and the highest-risk accounts. |
| `renewalLikelihood` | Estimates the probability the account renews and an expected renewal note. |

## Signals

All optional — provide any subset; missing signals are dropped and the weights re-normalize:

```
daysSinceLogin, usageTrend (-1..1 or %), featureAdoption (0-1), seatUtilization (0-1),
nps (0-10), sentiment (-1..1), supportTickets, openBugs, paymentFailures,
daysToRenewal, monthsTenure, mrr
```

## Usage

```js
import pack from './index.js';

const signals = { daysSinceLogin: 21, usageTrend: -0.4, nps: 5, featureAdoption: 0.3, paymentFailures: 1, daysToRenewal: 25 };

await pack.adapters.score({ signals });          // { riskScore, band, contributions, ... }
pack.adapters.drivers({ signals });              // top risk + protective factors
pack.adapters.segment({ signals });              // lifecycle segment + play
pack.adapters.healthScore({ signals });          // health index + grade
pack.adapters.renewalLikelihood({ signals });    // renewal probability

pack.adapters.cohortRisk({ accounts: [ { id: 'A', mrr: 500, signals }, { id: 'B', mrr: 1200, signals: { nps: 9, usageTrend: 0.2 } } ] });
```

Custom `weights` (per-signal importance) can override the defaults for any tool.

## DRY boundary notes

- Not generic stats: `numbers` / `statistics` provide series primitives; this pack encodes the
  retention scoring model, lifecycle segments and recommended plays on top of the domain signals.
- Not billing/finance: it consumes MRR/payment signals but does no invoicing or interest math
  (`invoice` / `finance` own those).
- Self-contained: no cross-pack imports except `../_shared/llm.js`.


---
Source: shared/engines/adapters/domain/churn-risk/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/churn-risk
