How scoring works
Every Plumb score is built from individual checks that measure something observable — code, config, metadata, or activity history. Never stars, followers, or reputation. This page explains how those checks become scores.
Categories
Checks are grouped into three categories, each scored independently from 0 to 100. The composite score is their weighted combination.
| Category | Composite weight | Measures |
|---|---|---|
| Security | 55% | How likely the package is to become a vector for compromise or known-vulnerability exposure. |
| Maintenance | 30% | How likely the package is to be patched and supported over time. |
| Ecosystem | 15% | Compatibility and integration health with the broader PHP, Laravel, and Symfony ecosystem. |
Within a category, each check carries a weight reflecting its signal strength. The category score is the weighted average of its check results: a passing check contributes full credit, a failing check none, and a warning partial credit on a scale each check defines for itself.
Check statuses
Every check ends in one of six statuses. Only the first three affect the score.
- Pass
- The check's condition holds. Contributes full credit to the category score.
- Warn
- The condition partially holds. Contributes partial credit on the check's own documented scale.
- Fail
- The condition does not hold. Contributes no credit, lowering the weighted average.
- Not applicable
- The question does not apply to this package — for example, a JavaScript dependency check on a package with no JavaScript dependencies. The check is left out of the score entirely: no penalty, no credit.
- Unassessable
- The question applies, but the evidence could not be observed — most commonly because the repository is not hosted on GitHub. Also left out of the score, but it reduces the category's evidence coverage. A category where less than 80% of the applicable check weight could be assessed is shown as unscored rather than given a misleading number.
- Error
- Something went wrong while fetching or evaluating — a transient problem on our side, not a finding about the package. Excluded from the score and from coverage.
Vetoes
A few checks carry a veto: if the check fails, it caps the maximum possible score of its category, no matter how well every other check scores.
Vetoes exist for active, present-condition problems where no amount of good practice elsewhere should compensate — an unpatched security advisory, a package its maintainer has declared abandoned. The cap applies after the normal weighted calculation; if the category already scores below the cap, the veto changes nothing. A veto never skips or removes a check — the check still runs, still appears in the breakdown, and its failure already counts against the weighted average. The veto is an additional ceiling on top.
| Veto check | Effect when it fails |
|---|---|
| Abandoned or archived | Maintenance score capped at 20/100 |
| Open security advisories | Security score capped at 30/100 |
When a veto is active, the package page shows both the capped score and what the score would have been without the veto, and the check is marked with a red "veto active" badge. Veto-capable checks that are not currently capping anything carry a neutral "veto check" badge instead.