# Methodology

> The complete inspect.software methodology — versioned formulas, category weights, rating bands, missing-data rules, and the organization assessment.


This page is the human-readable specification of how every value in the
public record is computed. The methodology is **versioned as a whole** —
currently **v1.13.0** — and every report records the version that produced
it. Per-metric detail lives in the [wiki](/wiki); this page states the
system.

<div class="md-callout"><span class="md-callout-icon">◇</span><div><b>Signals, not warranties.</b> A high value reflects publicly visible good practice; it is not a code audit and not a security guarantee. See <a href="/wiki/signals-not-warranties">how to read the results</a>.</div></div>

## The standardized scale

Every measurement — component, metric, category, overall — is an integer in
**1–100**, higher is better, mapped to five standardized
[rating bands](/wiki/scoring-bands): *excellent* (85–100), *good* (70–84),
*moderate* (50–69), *at risk* (30–49), *critical* (1–29). Band thresholds
are part of the versioned methodology.

## The three-level hierarchy

Values roll up transparently: **components → metrics → categories →
overall** (detailed in [the health index](/wiki/health-index)).

1. A **metric** is normally a weighted sum of components; component weights sum
   to 100. Every component is reported with its earned and maximum points
   and a status — met, partial, missed, or excluded. Four documented policies
   are the exception: a dependency reported as a malicious package multiplies
   and caps Security posture, confirmed high-risk jurisdiction exposure does
   the same at a looser ceiling, a confirmed inorganic growth finding
   discounts the stars and forks components of popularity, and an abandonment
   finding multiplies the health index itself.
2. A **category** is normally the weighted mean of its available metrics.
   All four policies are penalty multipliers only — none can improve the
   metric it acts on, and none carries additive weight of its own.
3. The **overall health index** begins as the weighted mean of the available
   categories. Where a policy fires it applies its multiplier, and some also
   impose a ceiling: **29 (critical)** for a malicious dependency or a declared
   abandonment, **49 (at risk)** for high-risk jurisdiction exposure or a
   likely abandonment. Where several fire, only the strictest applies — they
   never compound.

### Missing data is never a zero

When a component's underlying data is unavailable, it is **excluded and the
remaining weights renormalized** — a project is measured only on what can be
observed. The same rule applies to whole metrics and categories, and every
renormalization is recorded in the affected metric's note.

## Red flags

Most evidence in this methodology is scored: it earns points, those points sum
into a metric, and the metric averages into a category. A **red flag** is the
exception — a finding that does not score into a value but *adjusts* one, and
that the report presents as a named alert rather than as a number.

The class exists because some findings cannot be averaged away honestly. A
dependency reported as malicious is not eight points of engineering practice;
it is a state. Stars that arrived on a delivery schedule are not a low score
for popularity; they are a reason to stop believing the count. Scoring either
as points off would let a strong showing elsewhere absorb it, which is exactly
the wrong outcome.

Every red flag in this methodology obeys the same five rules:

1. **It only ever moves a value downward.** No red flag carries additive
   weight, and a clean result never raises anything. Absence of a finding is
   not a credential.
2. **It is stated, not merely subtracted.** The finding appears as an alert on
   the report, names its evidence, and links to the guide that defines it. A
   reader must be able to see *why* a rating moved.
3. **It describes an observation, never an intent.** Each is a statement about
   public evidence — a location a profile published, a package an advisory
   database names, the timing of star events. None establishes motive,
   responsibility, or wrongdoing by any person.
4. **Unanswerable is not clean.** Where the evidence a flag needs was never
   collected, the report says so. A repository that could not be assessed is
   never presented as one that passed.
5. **Only the strictest applies.** Where more than one flag fires, the gravest
   governs the score alone and the rest are reported without moving it again. A
   multiplier states how serious a finding is; multiplying several together
   produces a number no policy chose.

The flags currently defined are the
[Inorganic Growth Policy](/wiki/growth-authenticity), the
[Abandonment Policy](/wiki/abandonment), the
[Malicious Dependency Policy](/wiki/malicious-dependencies), and the
[High-Risk Jurisdiction Policy](/wiki/jurisdiction-exposure), each specified
below. How often each is found across the whole record is published in the
[aggregate statistics](/insights).

## Repository categories and weights

| Category | Weight | Metrics (weight within category) |
| -------- | ------ | -------------------------------- |
| [Vitality](/wiki/vitality) | 22% | [development activity](/wiki/development-activity) (60%), [release discipline](/wiki/release-discipline) (40%), × [Abandonment Policy](/wiki/abandonment) |
| [Community & Adoption](/wiki/community-adoption) | 18% | [popularity](/wiki/popularity) (40%) × [Inorganic Growth Policy](/wiki/growth-authenticity), [community health](/wiki/community-health) (35%), [ecosystem adoption](/wiki/ecosystem-adoption) (25%) |
| [Sustainability & Governance](/wiki/sustainability-governance) | 24% | [maintainer resilience](/wiki/maintainer-resilience) (30%), [responsiveness](/wiki/responsiveness) (25%), [stewardship](/wiki/stewardship) (25%), [package maintenance](/wiki/package-maintenance) (20%) |
| [Engineering Quality](/wiki/engineering-quality) | 20% | [engineering practices](/wiki/engineering-practices) (60%), [documentation](/wiki/documentation) (40%) |
| [Security](/wiki/security) | 16% | [security posture](/wiki/security-posture) (80%), [dependency advisories](/wiki/dependency-advisories) (20%), × [Malicious Dependency Policy](/wiki/malicious-dependencies), × [High-Risk Jurisdiction Policy](/wiki/jurisdiction-exposure) |
| [AI Readiness](/wiki/ai-readiness) | 0% | [agent context](/wiki/ai-agent-context) (30%), [verify loop](/wiki/ai-verify-loop) (40%), [code legibility](/wiki/ai-code-legibility) (15%), [interfaces](/wiki/ai-interfaces) (15%) |

### Inorganic Growth Policy

A GitHub star is the most widely read trust signal in open source, and the only
one with no issuer: stars and forks are sold openly, in bulk. The per-day star
and fork history collected for each report is therefore read for growth whose
shape organic attention does not produce — a burst that arrived on a schedule,
brought no forks, left no tail, or preceded anything the project had released.

A burst alone is never a finding; real projects launch and trend. A window is
confirmed only when at least two independent signals corroborate it. One
confirmed window discounts the stars and forks components of popularity by 40%,
two or more by 70%. Watchers and every other category are untouched, and a
clean history never raises a score.

Repositories whose collected history cannot answer the question — no history,
under 100 stars, or a window spanning under 60 days — read **unverified** and
are not penalized. Collection is bounded to a recent window, so manipulation
older than it is invisible to the policy; *unverified* means unanswerable, not
clean. The complete [growth authenticity guide](/wiki/growth-authenticity)
states the thresholds, the four states, and the limits of the evidence.

This is a statement about the timing of public events. It does not establish
that attention was purchased, or that a repository's maintainers were involved
if it was.

### Abandonment Policy

**A project is not abandoned because it is quiet.** Every tool in this space
answers "is this dead?" with days since the last commit, and every one of them
is wrong about the same projects: a small, complete library that has not needed
a commit in three years is finished, not abandoned.

So the finding rests on a different question — abandonment is an *unmet
obligation*, not an absence of noise. A quiet repository with nothing open owes
nobody anything. A quiet repository with fifteen unreviewed pull requests, or a
year-old advisory whose patch shipped the same week, is not resting.

Silence is necessary and never sufficient. A drought is measured from the last
**human** commit, and it only becomes a finding when unmet obligations
corroborate it: an unanswered contribution queue, issues a maintainer never
replied to, an unfixed advisory in a direct dependency, a release stall
measured against the project's own cadence, a failing or year-stale CI, or a
sole maintainer absent from the whole commit window. Readings that *explain*
the silence — a maintainer answering the tracker, nothing open to answer, a
release within the year, clean dependencies — hold the result at **dormant**,
and dormant carries no penalty at all. Quiet is already priced inside
[development activity](/wiki/development-activity); charging for it twice would
punish exactly the finished, stable libraries that deserve confidence.

Findings multiply the health index: 85% *at risk*, 60% *likely abandoned* with
an at-risk ceiling of 49, and 40% *declared* with a critical ceiling of 29.
*Declared* is the maintainer's own statement quoted rather than inferred — the
repository is archived, or every package it publishes has been deprecated or
yanked. Repositories with no commit sample, an unreadable tracker, or under 180
days of history read **unverified** and are not penalized. The complete
[abandonment guide](/wiki/abandonment) states every threshold, signal and
guard.

### Malicious Dependency Policy

A vulnerable dependency is a mistake; a malicious one is an attack. Each report
matches the resolved dependency graph against the OpenSSF malicious-packages
corpus, which OSV.dev serves alongside ordinary advisories — so the check costs
no request the report was not already making.

A malicious package carries no severity rating and no fixed version, because it
has neither: it is a state, not a degree, and the remedy is removal or moving
off the compromised name rather than an upgrade. Where the registry has since
pulled the exact version a repository resolves to, nothing installable remains:
the finding is reported for the record and not scored. Scoring it as an advisory therefore understated it, and it is
instead removed from the advisory findings and treated as a flag. Any confirmed
report applies a 35% multiplier and a **Critical ceiling of 29** to Security
posture and to the weighted overall score — one band stricter than the
jurisdiction ceiling, because this is a confirmed compromise rather than an
exposure to risk. Direct and indirect dependencies count alike: an install-time
payload runs at any depth in the graph.

The finding is rare by construction — registries remove malicious packages
within days, and a pre-release run over 46,889 resolved dependencies found
none. It concerns the package as published, not the maintainers of the scanned
repository, which may have resolved it unknowingly. The complete
[malicious dependencies guide](/wiki/malicious-dependencies) states the source,
the scoring, and the limits of the claim.

### High-Risk Jurisdiction Policy

High-confidence, self-published public profile evidence within the current
Russia, Iran, and North Korea scope creates a High-Risk Jurisdiction Policy
alert. Owner evidence multiplies Security posture by 20%, displayed
top-contributor evidence by 50%, and a contributor's public organization
affiliation by 75%. Ambiguous and missing location data do not reduce the
score. This is an enhanced-review signal, not an inference of nationality,
citizenship, sanctions status, intent, or trustworthiness.

Any confirmed match applies the same multiplier and **At risk ceiling of 49**
to Security posture and to the weighted overall score. Security reflects the
adjusted posture without multiplying twice. Base and adjusted values remain in
the report for transparency. The complete
[high-risk jurisdiction exposure guide](/wiki/jurisdiction-exposure)
explains the enterprise use cases, evidence safeguards, and proportionate
review actions behind the policy.

A metric's effective weight is normally *category weight × within-category
weight*. The Inorganic Growth, Abandonment, Malicious Dependency and
High-Risk Jurisdiction policies are the multiplier exceptions, and none has
additive weight of its own.
[AI Readiness](/wiki/ai-readiness) carries weight 0: an independent,
additive badge that never changes the health index.

The registry-backed metrics ([ecosystem adoption](/wiki/ecosystem-adoption),
[package maintenance](/wiki/package-maintenance)) apply only to repositories
that publish a package — see
[supported ecosystems](/wiki/supported-ecosystems).

### Dependency advisories

A repository's dependencies are matched against [OSV](https://osv.dev), the
open advisory database aggregating GHSA, PYSEC, RUSTSEC and others. Affected
packages are reported with their severity, the advisories concerned, and the
version each was fixed in.

**What is measured is what a consumer installs.** For a repository that
publishes a package, the assessed set is that package's runtime dependency
closure — the packages an installation actually pulls in. Only where a
repository publishes nothing is its own dependency graph used instead, and
that graph also contains development and test pins that never ship. Every
report states which of the two it assessed, and names the package.

The distinction changes results materially. Flask's repository graph carries
advisories against old versions of Werkzeug and Jinja pinned for its own test
matrix; installing Flask pulls in six packages, none of them affected. Only
the second fact is about the software anyone depends on.

Runtime closures are resolvable today for npm, PyPI, crates.io and Maven.
Packages published elsewhere are assessed against the repository graph until
the index covers them.

This is a **separate metric from security posture, deliberately**. Scorecard's
own vulnerabilities check already queries the same database and already
contributes to posture; scoring a second signal from it inside the same metric
would count one body of evidence twice. The two answer different questions —
posture asks whether the project carries known-vulnerable dependencies at all,
this asks which, how severe, and what fixes them.

What it does not claim: an advisory here means a resolved version falls inside
an advisory's affected range. Reachability is not analysed, and most
advisories in a large dependency closure are not exploitable in context. Every
report states its coverage — how many dependencies were assessed and how many
could not be.

Repositories where neither set can be resolved are not penalized: the metric
is excluded and the remaining weight renormalized, exactly as any other
unavailable input.

## Shared Scorecard evidence

Security posture remains the complete risk-weighted OpenSSF Scorecard assessment.
Seven checks also substantiate the other dimensions they plainly describe:
maintenance, signed releases, contributors, code review, license, CI tests,
and pinned dependencies. Six appear in their destination metric as small
additive cards while keeping their Security contribution. The seventh,
license, is different: it is one input to the license signal in
[community health](/wiki/community-health) rather than the whole of it — see
below. This intentional cross-category influence is documented per metric;
Scorecard `n/a` and unavailable results are excluded everywhere.

## Licensing

A repository's licence resolves to one of three states, from every available
source together — the repository's own licence metadata, GitHub's community
profile, and the OpenSSF Scorecard `License` check. A file that any one source
sees counts as present, so a single unavailable endpoint cannot report a
licence as missing.

| State | Meaning | Credit |
|---|---|---|
| Standard | A recognized licence, identified by SPDX code | full |
| Custom | A licence file is present, but its text is not a recognized licence | three quarters |
| None | No source found a licence file | none |

A custom licence is a real licence and scores most of the weight. It does not
score all of it: a licence that automated tooling cannot identify is a genuine
obstacle to adoption, because policy tooling, corporate review and package
registries all key off recognized identifiers, and a reader cannot establish
what they are permitted to do without reading the text themselves.

Before v1.3.0 custom licences already scored slightly lower, as an artefact of
how Scorecard grades them rather than as a stated position. The tier above is
deliberate, and it is now the whole licence signal.

## Organization assessment

Organizations are assessed on the same scale and bands, in two categories —
Activity & Reach (75%) and Governance & Profile (25%) — detailed in
[organization assessment](/wiki/organization-assessment). A repository's
report also embeds its owning account's profile, which drives the
[stewardship](/wiki/stewardship) metric.

## Configuration

A scan can disable a component, metric, or category; the exclusion works
exactly like missing data and is **embedded in the report**, so every result
is reproducible as published. Configuration never alters a formula, weight,
or threshold — see [scan configuration](/wiki/scan-configuration).

## Versioning

Any change to a formula, weight, or band threshold bumps the metrics
version. The complete dated history — from 0.1.0 to the current 1.13.0 — is
in [methodology versions](/wiki/methodology-versions).

## Worked example

pallets/flask (organization-owned), inspected 2026-07-16 under methodology
1.4.0 — the live figures are always in the
[full report](/software/pallets/flask):

| Category | Value | Weight | Contribution |
| -------- | ----: | -----: | -----------: |
| [Vitality](/wiki/vitality) | 70 | 22% | 15.40 |
| [Community & Adoption](/wiki/community-adoption) | 96 | 18% | 17.28 |
| [Sustainability & Governance](/wiki/sustainability-governance) | 74 | 24% | 17.76 |
| [Engineering Quality](/wiki/engineering-quality) | 96 | 20% | 19.20 |
| [Security](/wiki/security) | 69 | 16% | 11.04 |
| **Overall** | | | **80.68 → 81, good** |

[AI Readiness](/wiki/ai-readiness) stands at 58 and carries weight 0, so it
is absent from the sum.

The same repository under a personal account with the same following would
lose the organization-backing margin and the verified-domain component of
[stewardship](/wiki/stewardship), pulling the Governance category down with
it. That ownership influence is deliberate, explicit, and auditable.

Every figure above is a snapshot. Values move as the evidence changes and as
the methodology is versioned; the linked report always carries the current
ones.

## Roadmap (not yet measured)

- Issue and PR latency percentiles, time-windowed rather than lifetime.
- Dependency freshness: how many dependencies are deprecated upstream,
  archived, or years past their last release. Known advisories are now
  measured — see [dependency advisories](/wiki/dependency-advisories) — but
  freshness is a separate signal and is not yet scored.
- Popularity-normalized expectations (a 50-star repository is not held to a
  50,000-star repository's baseline).
- Test coverage and CI pass-rate signals.

Each arrives with a version bump, never silently.
