# inspect.software
> A public record of open-source software health. Repositories are measured
> against a transparent, versioned methodology spanning maintainability,
> engineering quality, security posture, ecosystem adoption, and governance;
> results are published as reports, 1–100 health indices, and embeddable
> badges. Results are signals, not warranties, and are independent of payment.
Every page below is served as source Markdown at the linked .md URL; the same
content renders as HTML without the extension (e.g. /methodology.md → /methodology).
The full corpus in one file: https://inspect.software/llms-full.txt
## Institution
- [About inspect.software](https://inspect.software/about.md): A public record of open-source software health — every repository inspected by one published method, versioned methodology, results independent of payment.
- [Methodology](https://inspect.software/methodology.md): The complete inspect.software methodology — versioned formulas, category weights, rating bands, missing-data rules, the organization assessment, and the open-source engine that computes them.
- [Certification & pricing](https://inspect.software/pricing.md): Free public-interest inspection for high-value open-source repositories; paid certification for private and niche repositories. Payment never changes a result.
- [GitHub badges](https://inspect.software/badges.md): Embeddable inspect.software badges — a live health signal for any inspected repository, updated automatically after every scan. Markdown and HTML snippets.
- [Frequently asked questions](https://inspect.software/faq.md): Answers about inspect.software — how repositories are inspected, what results mean, free vs. paid coverage, badges, corrections, and independence.
- [Contact](https://inspect.software/contact.md): How to reach inspect.software — certification enquiries, data corrections, security disclosures, and general questions.
- [Press & brand assets](https://inspect.software/press.md): Logos, colours, boilerplate texts and usage rules for inspect.software — the media kit for journalists, directories, conference organizers and integration documentation.
## Concepts
- [The health index](https://inspect.software/wiki/health-index.md): How inspect.software computes the 1–100 open-source health index — components, metrics, weighted categories, and the rules for missing data.
- [Rating bands](https://inspect.software/wiki/scoring-bands.md): The seven standardized rating bands — exceptional, excellent, good, moderate, weak, at risk, critical — and the letter grades used across every inspect.software health metric and category.
- [Certification levels](https://inspect.software/wiki/certification-levels.md): The three inspect.software certification levels — Certified (A), Certified with Excellence (AA), and Certified AAA — how each maps to the calibrated health index, what a level asserts, and how levels change.
- [Signals, not warranties](https://inspect.software/wiki/signals-not-warranties.md): What an inspect.software result does and does not claim — the honest boundary between visible practice signals and a formal audit or guarantee.
- [Methodology versions](https://inspect.software/wiki/methodology-versions.md): The complete version history of the inspect.software metrics methodology — every formula, weight, and threshold change, dated and documented.
- [Supported package ecosystems](https://inspect.software/wiki/supported-ecosystems.md): The package ecosystems inspect.software reads — nine registries with published-package facts, plus dependency manifests across all of them.
- [Software classification](https://inspect.software/wiki/software-classification.md): How inspect.software determines what a repository builds — the multi-label reading of whether software is consumed as code, run as a program, or installed into a host.
- [Scan configuration](https://inspect.software/wiki/scan-configuration.md): How parts of the inspect.software methodology can be switched off per scan — and how every report documents exactly what was and was not measured.
## Scoring categories
- [Vitality](https://inspect.software/wiki/vitality.md): The Vitality category of the inspect.software health index — whether code is actively written and versioned releases actually ship. Weight: 21% of the overall index.
- [Community & Adoption](https://inspect.software/wiki/community-adoption.md): The Community & Adoption category — users, downloads, attention, and a welcoming contributor setup. Weight: 17% of the inspect.software health index.
- [Sustainability & Governance](https://inspect.software/wiki/sustainability-governance.md): The heaviest category of the inspect.software health index (23%) — bus factor, responsiveness, organizational stewardship, and package upkeep.
- [Engineering Quality](https://inspect.software/wiki/engineering-quality.md): The Engineering Quality category — CI, tests, linting, and documentation practice. Weight: 19% of the inspect.software health index.
- [Security](https://inspect.software/wiki/security.md): The Security category — visible OpenSSF Scorecard hygiene and known-vulnerable dependencies, under two red-flag policies. Weight: 16% of the inspect.software health index.
- [AI Readiness](https://inspect.software/wiki/ai-readiness.md): The AI Readiness badge — how well a repository supports AI coding agents: agent context, verify loop, code legibility, machine-readable interfaces.
## Repository metrics
- [Development activity](https://inspect.software/wiki/development-activity.md): How inspect.software measures development activity — push recency, weekly commit cadence, and commit volume. 12.6% of the overall health index.
- [Release discipline](https://inspect.software/wiki/release-discipline.md): How inspect.software measures release discipline — whether versioned releases ship, how recently, and on what cadence. 8.4% of the overall health index.
- [Popularity](https://inspect.software/wiki/popularity.md): How inspect.software measures repository popularity — stars, forks, and watchers on a logarithmic scale. 6.8% of the overall health index.
- [Community health](https://inspect.software/wiki/community-health.md): How inspect.software measures community health — README, license, contributing guide, code of conduct, and issue/PR templates. 5.95% of the overall index.
- [Ecosystem adoption](https://inspect.software/wiki/ecosystem-adoption.md): How inspect.software measures real package adoption — registry downloads and dependents across npm, PyPI, Packagist, and more. 4.25% of the overall index.
- [Maintainer resilience](https://inspect.software/wiki/maintainer-resilience.md): How inspect.software measures bus factor, contributor concentration, and breadth — whether a project can survive losing its top maintainer. 6.9% of the index.
- [Responsiveness](https://inspect.software/wiki/responsiveness.md): How inspect.software measures responsiveness — issue resolution, lifetime pull-request acceptance, and how a project treats first-time contributors. 5.75% of the overall index.
- [Stewardship](https://inspect.software/wiki/stewardship.md): How inspect.software measures who stands behind a repository — organization vs. personal ownership, verified domain, reach, and track record. 5.75% of the index.
- [Package maintenance](https://inspect.software/wiki/package-maintenance.md): How inspect.software measures registry upkeep — publish recency, version history, and deprecation state of published packages. 4.6% of the overall index.
- [Engineering practices](https://inspect.software/wiki/engineering-practices.md): How inspect.software measures baseline engineering hygiene — CI, tests, linting, pre-commit hooks, and editorconfig. 11.4% of the overall health index.
- [Documentation](https://inspect.software/wiki/documentation.md): How inspect.software measures documentation — README, docs directory, documentation site, description, topics, and wiki. 7.6% of the overall health index.
- [Security posture](https://inspect.software/wiki/security-posture.md): How inspect.software measures security posture with the OpenSSF Scorecard — risk-weighted, tool-agnostic checks with a documented fallback. 16% of the index.
- [Dependency advisories](https://inspect.software/wiki/dependency-advisories.md): How inspect.software matches a repository's resolved dependencies against the OSV advisory database — severity, fix versions, coverage, and the limits of the signal. 20% of the Security category.
## AI Readiness metrics
- [AI agent context](https://inspect.software/wiki/ai-agent-context.md): How inspect.software measures agent guidance — CLAUDE.md, AGENTS.md, Cursor rules, Copilot instructions, llms.txt, and whether the commit history states its intent. Part of the AI Readiness badge.
- [AI verify loop](https://inspect.software/wiki/ai-verify-loop.md): How inspect.software measures the agent verify loop — one-command bootstrap, tests, lint, type checking, reproducible environments. The heaviest AI Readiness metric.
- [AI code legibility](https://inspect.software/wiki/ai-code-legibility.md): How inspect.software measures code legibility for AI models — type-checkable code and manageable file sizes. Part of the AI Readiness badge.
- [AI interfaces](https://inspect.software/wiki/ai-interfaces.md): How inspect.software measures machine-readable interfaces — API schemas, MCP servers, and runnable examples. Part of the AI Readiness badge.
## Red flags and policies
- [Abandonment](https://inspect.software/wiki/abandonment.md): How inspect.software decides a project has been left unmaintained — why silence alone is never the finding, what counts as an unmet obligation, and what holds the assessment back.
- [Malicious dependencies](https://inspect.software/wiki/malicious-dependencies.md): How inspect.software identifies dependencies reported as malicious packages by the OpenSSF corpus, why they are scored apart from vulnerabilities, and what the finding does and does not claim.
- [High-Risk Jurisdiction Exposure](https://inspect.software/wiki/jurisdiction-exposure.md): How inspect.software turns public repository-profile evidence into an explainable high-risk jurisdiction exposure signal for repository review.
- [Growth Authenticity](https://inspect.software/wiki/growth-authenticity.md): How inspect.software reads a repository's day-by-day star and fork history for growth that organic attention does not produce, and what the Inorganic Growth Policy does about it.
## Organization assessment
- [Organization assessment](https://inspect.software/wiki/organization-assessment.md): How inspect.software assesses GitHub organizations — portfolio activity, community reach, and profile completeness on the same 1–100 scale and bands.
- [Portfolio activity](https://inspect.software/wiki/portfolio-activity.md): How inspect.software measures an organization's portfolio activity — recently active repos, yearly activity, portfolio size, and original work. 45% of the org index.
- [Community reach](https://inspect.software/wiki/community-reach.md): How inspect.software measures an organization's community reach — followers and portfolio-wide stars on logarithmic scales. 30% of the organization index.
- [Profile completeness](https://inspect.software/wiki/profile-completeness.md): How inspect.software measures organization profile completeness — verified domain, description, homepage, contact, and identity fields. 25% of the org index.
## Inspection reports
The record itself — one report per inspected repository, ~26,000 of them. Every
report page is served as Markdown at the same .md convention used above:
- Report (Markdown): https://inspect.software/software/{owner}/{name}.md — the health index, every category and metric, the per-criterion breakdown behind each number, and the repository facts they were derived from
- Report (HTML): https://inspect.software/software/{owner}/{name} — the same report rendered for readers
- Browse or filter the record: https://inspect.software/api/catalog (JSON), or https://inspect.software/sitemap.xml for every report URL
## Machine-readable data
- [OpenAPI schema](https://inspect.software/api/openapi.json): machine-readable description of every endpoint below
- [Sitemap](https://inspect.software/sitemap.xml): every published page and inspection record
- [Catalogue API](https://inspect.software/api/catalog): JSON list of inspected repositories (filters: q, ecosystem, language, band, scanned_within_days, growth, sort)
- [Insights API](https://inspect.software/api/insights): aggregate statistics over the record — health distribution, practice adoption, stewardship, ecosystem comparison (optional ?ecosystem=; rendered at /insights)
- Report API: https://inspect.software/api/repositories/{owner}/{name}/report — the full JSON inspection report, including every metric's inputs and per-component points
- Related API: https://inspect.software/api/repositories/{owner}/{name}/related — inspected repositories sharing this one's catalogue tags and ecosystems
- Badge: https://inspect.software/badge/v1/{owner}/{name}.svg — live health badge for any repository in the record
## Optional
- [Terms of service](https://inspect.software/terms.md): The terms under which inspect.software publishes inspection results, issues badges, and accepts public-repository submissions.
- [Privacy](https://inspect.software/privacy.md): What personal data inspect.software processes, on what legal basis, how long it is kept, who receives it, and the rights that apply.
---
# About inspect.software
> A public record of open-source software health — every repository inspected by one published method, versioned methodology, results independent of payment.
**inspect.software** keeps a public record of open-source software health.
Each repository is assessed with the same published, versioned methodology
across maintainability, engineering quality, security posture, ecosystem
adoption, and governance. The weights and production scanner are public, and
payment cannot change a result.
## Mission
Make the health, quality, and security of open-source software **legible and
trustworthy** for everyone who depends on it — developers choosing a library,
security teams reviewing a supply chain, procurement functions approving a
vendor's stack.
## Who operates it
inspect.software is run by **Vitalii Stepanenko**, from València, Spain. The
full identification is in section 10 of the [terms](/terms); enquiries go
through [contact](/contact).
## The problem the record exists to solve
Modern software is assembled from thousands of open-source dependencies, yet
the signals used to judge them are weak. Stars measure popularity, not
health. Bus factor is invisible: a package with fifty million weekly
downloads maintained by one exhausted volunteer is a systemic risk — the
pattern behind left-pad, Log4Shell, and the xz-utils backdoor. Security
practice is opaque, and maintenance velocity takes manual digging to read.
No consistent, transparent, third-party signal aggregated these into
something a developer, a security team, or a CTO could act on. The public
record exists to be that signal.
Technical health is only part of an enterprise dependency decision. The
record also makes policy-defined context visible through signals such as
[high-risk jurisdiction exposure](/wiki/jurisdiction-exposure), helping
security and procurement teams identify dependencies that merit enhanced
review without turning public profile evidence into a judgement about people.
## Principles
1. **Transparency is the product.** The [methodology](/methodology) and
[wiki](/wiki) document every metric, weight, formula, and threshold. The
AGPL-licensed [scanner](https://github.com/inspect-software/scanner) is the
production engine used to generate reports. Each report includes its
observed evidence so the result can be checked manually or recomputed with
the published code.
2. **Results are independent of payment.** No commercial relationship —
certification fees, sponsorship, vendor alignment — can alter a published
result. Payment buys analysis, privacy, and frequency; never a better
number.
3. **Signals, not warranties.** The record states exactly what it measures
and no more — see
[how to read the results](/wiki/signals-not-warranties).
4. **Versioned and accountable.** Methodology changes are dated, explained,
and recorded in every report — see
[methodology versions](/wiki/methodology-versions).
5. **Public good first.** Inspection of high public-value open-source
software is free and its results are public, permanently.
## How the institution sustains itself
Free public-interest coverage is funded by paid services around it: audits
of private repositories, on-demand certification of niche public
repositories, continuous monitoring, and enterprise reporting — described on
the [certification & pricing](/pricing) page. The guardrail is absolute:
**a higher result is never for sale.**
## The record
The [public record](/#record) lists every inspected repository with its full
report: category profile, per-metric breakdowns, component evidence, and the
raw machine-readable data. Repositories carry
[embeddable badges](/badges) reflecting their current standing.
Questions and corrections are welcome — data errors can be flagged through
the [contact](/contact) channels, and the correction path is part of the
methodology's accountability.
---
# Methodology
> The complete inspect.software methodology — versioned formulas, category weights, rating bands, missing-data rules, the organization assessment, and the open-source engine that computes them.
This page specifies how values in the public record are computed. The
methodology is **versioned as a whole** — currently **v2.10.0** — and each
report records the version used. The production scanner is open source, so the
specification can be checked against its implementation. See *Open-source
implementation* below. Per-metric detail lives in the [wiki](/wiki); this page
describes the complete system.
◇Signals, not warranties. A high value reflects publicly visible good practice; it is not a code audit and not a security guarantee. See
how to read the results.
## The standardized scale
Every measurement — component, metric, category, overall — is an integer in
**1–100**, higher is better, mapped to seven standardized
[rating bands](/wiki/scoring-bands): *exceptional* (93–100), *excellent*
(80–92), *good* (65–79), *moderate* (50–64), *weak* (35–49), *at risk*
(20–34), *critical* (1–19). The overall index is additionally
[calibrated against the distribution of the public record](/wiki/health-index),
so its bands carry percentile meaning. Band thresholds and the calibration
curve 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, calibrated onto the published index scale. Where a policy fires
it applies its multiplier, and some also impose a ceiling: **19
(critical)** for a malicious dependency or a declared abandonment, **34
(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) | 21% | [development activity](/wiki/development-activity) (60%), [release discipline](/wiki/release-discipline) (40%), × [Abandonment Policy](/wiki/abandonment) |
| [Community & Adoption](/wiki/community-adoption) | 17% | [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) | 23% | [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) | 19% | [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) | 4% | [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 34, and 40% *declared* with a Critical ceiling of 19.
*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 19** to Security
posture and to the health index — 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 34**
to Security posture and to the health index. 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 a deliberately small 4% weight,
sized together with the calibration curve so that a repository with no agent
tooling can still reach 100/100.
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 like
missing data and is **embedded in the report**, so its effect on the score can
be reproduced. Configuration never alters a formula, weight, or threshold —
see [scan configuration](/wiki/scan-configuration).
## Open-source implementation
The production scanner is published at
[inspect-software/scanner](https://github.com/inspect-software/scanner) under
the **GNU Affero General Public License v3.0 or later**. The worker imports this
package to produce reports; there is no separate private scoring engine. Its
source contains the category weights, red-flag multipliers and ceilings,
missing-data rules, and calibration curve described above.
A result can be checked at three levels:
1. **Inspect the formula.** The weights, thresholds, and band boundaries are
defined in the source. `METRICS_VERSION` in `src/scanner/metrics.py`
identifies the methodology implemented by that revision and matches
`metrics.metrics_version` in its reports.
2. **Recompute stored evidence.** Download **Raw JSON report** from a report
page. Check out the scanner revision whose `METRICS_VERSION` matches the
report, then use its `data` and `config` as inputs to `compute_metrics`.
3. **Run a new scan.** `inspect-scan OWNER/REPO` collects current GitHub and
registry data and produces the same report schema.
### Reproduction limits
Public reports omit contributor profile details such as name, location,
company, and organization memberships. These fields are used by
[high-risk jurisdiction exposure](/wiki/jurisdiction-exposure), alongside the
owner's profile. Recomputing public JSON can therefore produce a different
jurisdiction adjustment when contributor evidence affected the original
result. An objection under [data-protection law](/privacy) also excludes the
relevant profile from future scans.
A new scan can differ from an earlier report for two further reasons:
- **Repository evidence changes.** Stars, commits, releases, and advisories can
change after a report is published. Each report records when its evidence
was collected.
- **Scorecard is best-effort.** [Security posture](/wiki/security-posture) uses
OpenSSF Scorecard, which requires the `scorecard` binary and a GitHub token.
If it cannot run, the scanner records that fact and uses coarse file checks.
Report engine defects in the scanner's issue tracker. Report vulnerabilities
privately. Disputes about published evidence remain
[correction requests](/contact).
## Versioning
Any change to a formula, weight, band threshold, or the calibration curve
bumps the metrics version. The complete dated history — from 0.1.0 to the
current 2.10.0 — is in [methodology versions](/wiki/methodology-versions).
## Worked example
pallets/flask (organization-owned), with category values as inspected
2026-07-16, recomputed under the current weights — the live figures are
always in the [full report](/software/pallets/flask):
| Category | Value | Weight | Contribution |
| -------- | ----: | -----: | -----------: |
| [Vitality](/wiki/vitality) | 70 | 21% | 14.70 |
| [Community & Adoption](/wiki/community-adoption) | 96 | 17% | 16.32 |
| [Sustainability & Governance](/wiki/sustainability-governance) | 74 | 23% | 17.02 |
| [Engineering Quality](/wiki/engineering-quality) | 96 | 19% | 18.24 |
| [Security](/wiki/security) | 69 | 16% | 11.04 |
| [AI Readiness](/wiki/ai-readiness) | 58 | 4% | 2.32 |
| **Raw weighted mean** | | | **79.64 → 80** |
| **Calibrated health index** | | | **80 → 94, exceptional (AAA)** |
The final row is the [calibration](/wiki/health-index) of the raw mean onto
the published index scale, which is what the report and the badge display.
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.
---
# Certification & pricing
> Free public-interest inspection for high-value open-source repositories; paid certification for private and niche repositories. Payment never changes a result.
The economics of inspect.software follow one rule: **inspection of software
the public depends on is free, and depth and privacy are paid for.** Revenue
from paid services funds the free public record.
◇A higher result is never for sale. Payment buys analysis, privacy, frequency, and reporting — the methodology and the outcome are identical on every tier. See
signals, not warranties.
## Free — the public record
Repositories of high public value are inspected free of charge:
- Full health report against the complete
[versioned methodology](/methodology), published in the
[public record](/#record).
- An embeddable [GitHub badge](/badges) reflecting the current standing.
- Re-inspection when a new scan is submitted or scheduled by an operator.
Eligibility is assessed automatically at submission against documented
public-interest thresholds (adoption, ecosystem presence, activity). Any
GitHub account may submit a public repository for consideration.
## Certification levels
Certification is graded, not binary. A repository whose inspection places it
in one of the top three [rating bands](/wiki/scoring-bands) holds the
corresponding [certification level](/wiki/certification-levels):
| Level | Grade | Band | Health index |
| ----- | ----- | ---- | ------------ |
| **Certified AAA** | AAA | Exceptional | 93–100 |
| **Certified with Excellence** | AA | Excellent | 80–92 |
| **Certified** | A | Good | 65–79 |
The level follows mechanically from the published band — the same rule for a
free public-interest inspection and a paid on-demand one. Payment determines
*whether* an inspection runs, never *what* it finds.
## Paid — certification and depth
Repositories outside the free thresholds, and organizations needing more
than the public record offers:
| Service | For | What it provides |
| ------- | --- | ---------------- |
| **On-demand certification** | Maintainers of niche public repositories | Full inspection and badge now, without waiting for free coverage; paid from an account balance directly at submission |
| **Developer program** | Maintainers inspecting their own work regularly | A subscription covering inspections of repositories the account owns or maintains, however niche — in place of per-inspection credits |
| **Private repository audit** | Organizations with closed source | Planned service; currently arranged only through a separate engagement |
| **Continuous monitoring** | Engineering and security teams | Scheduled re-inspection with alerts on regressions — band drops, security posture changes, bus-factor decline |
| **Deep security review** | Security-conscious organizations | Expanded supply-chain and static-analysis coverage beyond the standard posture signals |
| **Enterprise reporting** | Procurement, platform, and compliance teams | Portfolio views across dependencies and exportable, compliance-ready reporting |
| **API access** | Platforms and developer tools | Programmatic access to published results and metrics |
## Current prices
On-demand certification and the developer program are available today.
Prices are in US dollars; payment is handled by Stripe.
| Offer | Price |
| ----- | ----- |
| **Starting balance** | 100 credits, free with every new account |
| **Inspection of a below-threshold repository** | 20 credits |
| **Credit packs** | $5 — 100 credits · $20 — 450 credits · $50 — 1,250 credits |
| **Developer program** | $10 per month |
Credits are purchased on the [account profile](/profile) or granted by a
code; the profile always shows the prices in force. The remaining services
are being introduced in stages; terms are documented per engagement.
Enquiries: [mail@inspect.software](mailto:mail@inspect.software).
## What payment can never do
- Change a formula, weight, threshold, or published value.
- Remove or suppress an unfavorable published result.
- Buy placement or ranking in the public record.
Where a paid scan narrows the methodology (an agreed
[scan configuration](/wiki/scan-configuration)), the report itself documents
exactly what was measured and what was excluded.
## Why free coverage is sustainable
Free inspection is bounded to genuinely popular, high-public-value software
— the packages whose health is systemic. The reasoning is documented openly
in the [about](/about) page's principles.
---
# GitHub badges
> Embeddable inspect.software badges — a live health signal for any inspected repository, updated automatically after every scan. Markdown and HTML snippets.
Every repository in the public record carries an embeddable **badge**: a
small SVG showing the current health index and
[rating band](/wiki/scoring-bands), linking back to the full report. The
badge is the record made visible where decisions happen — in the README,
next to the installation instructions.
## Embedding a badge
Each report page provides copy-ready snippets for its repository. The
pattern:
```markdown
[](https://inspect.software/software/OWNER/REPO)
```
```html
```
Replace `OWNER/REPO` with the repository's full name, and `O` with the first
character of the owner name in lowercase — badges are filed under that
character so no single directory in the repository grows unbrowsable. Copying
the exact snippets from the repository's report page in the
[public record](/#record) avoids getting it wrong.
## shields.io
For READMEs that standardize on [shields.io](https://shields.io) badges, the
record is also available through shields' *endpoint badge*. Every repository
serves its current state as endpoint JSON at
`https://inspect.software/badge/v1/OWNER/REPO.json`, which shields renders in
its own visual language:
```markdown
[](https://inspect.software/software/OWNER/REPO)
```
The rendered badge states the same index, band vocabulary, and band color as
the native badge — certified repositories lead with their letter grade — and
refreshes on the same hourly schedule. All of shields' style parameters
(`style=`, `logo=`, …) apply as on any other shields badge.
## How badges behave
- **Always current.** The badge reflects the latest published inspection and
updates automatically after every scan — no re-embedding needed.
- **Served from GitHub.** Badge images are published to the public
[inspect-software/badges](https://github.com/inspect-software/badges)
repository and delivered by GitHub's own content network. A README carrying
a badge does not depend on this site being reachable.
- **Versioned path.** The `/v1/` path segment is stable; any future change to
badge semantics arrives as a new version, never as a silent change.
- **Band-colored.** The badge carries the color of the repository's current
band, from *exceptional* deep green to *critical* red, and states the band
in words beside the index.
- **Certified repositories carry a seal.** Repositories in the top three bands
show an embossed rosette bearing their letter grade — **A**, **AA**, or
**AAA** — the visible mark of their
[certification level](/wiki/certification-levels). The seal is a
certification mark, so a repository below *Good* does not carry one; its
badge states the band and the index without it.
- **One fixed size.** Every badge is 137×20 pixels whatever the index says, so
a README never reflows when a score moves and a row of badges stays flush.
- **Never broken.** A repository not yet in the record serves a neutral
badge rather than a broken image.
## What a badge asserts
A badge asserts exactly what the report behind it asserts: measured,
publicly visible practice under a
[versioned methodology](/methodology) — and nothing more. It is a signal for
review, not a warranty of quality or security
(see [signals, not warranties](/wiki/signals-not-warranties)). The linked
report always shows the full category profile, every metric's components,
and the raw data.
## Getting a badge
1. Submit the repository on the [home page](/) (GitHub sign-in required).
2. High public-value repositories are inspected free; others follow the
[certification route](/pricing).
3. Once the report is published, copy the badge snippets from the report
page.
---
# Frequently asked questions
> Answers about inspect.software — how repositories are inspected, what results mean, free vs. paid coverage, badges, corrections, and independence.
## About the results
### What does the health index actually measure?
Publicly visible practice: commit and release history, contributor
distribution, community files, engineering hygiene, security signals, and
registry state — combined through a
[transparent, versioned methodology](/methodology) into one 1–100 index with
seven [rating bands](/wiki/scoring-bands). Full detail per metric is in the
[wiki](/wiki).
### Is a high value a guarantee the software is safe?
No. Results are **signals, not warranties**: no line-by-line audit is
performed, and no methodology can rule out an undiscovered vulnerability.
What a high value does mean is documented precisely in
[signals, not warranties](/wiki/signals-not-warranties).
### Why did a repository's value change without any code changes?
Two legitimate reasons: the observable evidence changed (a release aged past
a threshold, an issue backlog grew), or the methodology version changed —
every formula change is dated and documented in
[methodology versions](/wiki/methodology-versions), and each report records
the version that produced it.
### A metric shows "excluded" components or a null value. Is that a penalty?
The opposite. Data that cannot be observed — no published package, no issue
history — is **excluded and the remaining weights renormalized**, never
counted as zero. The rules are in [the health index](/wiki/health-index).
### Why does organization ownership raise a repository's value?
Organization backing signals shared, accountable stewardship that can
outlive any single maintainer. The lift is deliberate, bounded, and fully
documented in [stewardship](/wiki/stewardship) — one of the few places the
methodology takes an explicit position.
## Submissions and coverage
### How does a repository get into the record?
Any GitHub account may submit a public repository on the [home page](/).
Repositories meeting the documented public-interest thresholds are inspected
free; others can proceed through the paid
[certification route](/pricing) — owners and maintainers can pay from an
account balance directly at submission.
### Which ecosystems are supported?
GitHub repositories in any language, with registry evidence read from npm,
PyPI, Packagist, crates.io, Go, RubyGems, NuGet, and Hex — the full list and
fallback rules are in [supported ecosystems](/wiki/supported-ecosystems).
### Can a private repository be inspected?
Private repository audits are part of the commercial roadmap, but they are not
available through the current self-service product. Contact
[mail@inspect.software](mailto:mail@inspect.software) to
discuss a future engagement.
### Can a repository be removed from the public record?
No. Published results for public repositories stay published. Data errors
are corrected, not removed: see the correction question below.
## Trust and independence
### Can payment improve a result?
No. Payment buys analysis, privacy, and frequency — never a different
number. The methodology and formulas are identical on every tier, and no
commercial relationship can alter a published result. See
[about](/about) for the institutional principles.
### The data about a repository is wrong. How is it corrected?
Flag it through the [contact](/contact) channels with the repository name
and the specific value in question. Confirmed data errors trigger a re-scan;
methodology disagreements are answered with the documented formula — and
sometimes become documented roadmap items.
### Is the scoring engine open source?
Yes. [inspect-software/scanner](https://github.com/inspect-software/scanner)
is the production scanner used to collect evidence and compute the metrics,
bands, and index in each report. It is licensed under the **GNU Affero General
Public License v3.0 or later**. The surrounding platform — the website,
database, and scan queue — is not open source. A commercial licence is
available for uses incompatible with the AGPL; enquire through
[contact](/contact).
### Can the results be reproduced independently?
Yes, by design. Every report embeds its inputs, per-component points, scan
configuration, and methodology version; every formula is published. Any
value in the record can be recomputed by hand from the report's own data.
### Can the published statistics be reused?
The aggregate statistics on the [insights](/insights) pages, and the JSON
endpoint behind them, are published under
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — reuse them in an
article, a chart, or a paper, commercially or not, carrying the attribution
`inspect.software — https://inspect.software` with a link back. The
per-repository record is not covered by that licence and stays under the
[terms](/terms); individual reports may still be cited and quoted.
## Certification and badges
### What do the certification levels mean?
A repository in one of the top three [rating bands](/wiki/scoring-bands)
holds the corresponding [certification level](/wiki/certification-levels):
**Certified** (Good, grade A), **Certified with Excellence** (Excellent,
grade AA), or **Certified AAA** (Exceptional, the record's top ≈5%). The
level follows mechanically from the published band — payment can start an
inspection but can never choose its outcome.
### How is a badge added to a README?
Copy the Markdown or HTML snippet from the repository's report page — the
badge updates automatically after every scan. Details on
[the badges page](/badges).
### What does the badge show for an unscanned repository?
A neutral "pending" badge — never a broken image, and never an invented
number.
---
# Contact
> How to reach inspect.software — certification enquiries, data corrections, security disclosures, and general questions.
The channels below route to the people who operate inspect.software
directly.
## Certification and commercial enquiries
Private repository audits, on-demand certification, monitoring, and
enterprise reporting:
**[mail@inspect.software](mailto:mail@inspect.software)**
The available services and the rules they operate under are described on the
[certification & pricing](/pricing) page — including the rule that payment
never changes a result.
## Data corrections
A factual error in a published report — a mismatched package, stale
evidence, a value that cannot be reproduced from its inputs — should be
flagged with the repository's full name and the specific metric in
question:
**[mail@inspect.software](mailto:mail@inspect.software)**
Confirmed data errors trigger a re-scan. Disagreements with the methodology
itself are answered with the documented formula; well-argued cases inform
the [methodology roadmap](/methodology). If the code and documentation
disagree, open an issue in the scanner's
[public repository](https://github.com/inspect-software/scanner), where the
diagnosis and fix can be reviewed.
## Security
Report a vulnerability in inspect.software or the published scanner privately
to the same address, with *security* in the subject line, before public
disclosure. Do not open a public issue. Reports are acknowledged and handled
with priority.
## Data protection
Requests about personal data — access, correction, erasure, restriction,
portability, or an objection to processing — go to the same address, and are
answered within one month:
**[mail@inspect.software](mailto:mail@inspect.software)**
Two cases come up most often. A **contributor** whose public GitHub profile was
read for a report may have those enriched fields deleted and excluded from
future scans. A **maintainer** whose address was collected from a package
registry may have it deleted the same way. Neither request has to be
justified.
What is processed, on what basis, and for how long is set out on the
[privacy](/privacy) page, which also names the supervisory authority.
## Methodology questions
Most questions are already answered in public documentation:
- [Methodology](/methodology) — the complete specification.
- [Wiki](/wiki) — per-metric and per-category reference.
- [FAQ](/faq) — common questions, including corrections and independence.
- [Scanner source](https://github.com/inspect-software/scanner) — the
AGPL-licensed production engine that computes published values.
---
# Press & brand assets
> Logos, colours, boilerplate texts and usage rules for inspect.software — the media kit for journalists, directories, conference organizers and integration documentation.
Everything on this page may be used to refer to inspect.software in editorial
coverage, conference material, directories, and documentation that mentions
the record. The assets are generated from the running site, so what is
downloaded here is what appears in the header.
## Logo
The lockup is the primary form: the mark and the name together. The mark alone
is for contexts where the name is already established — avatars, app tiles,
favicons.
Every file above, together with a short usage summary:
**[inspect-software-press-kit.zip](/press/inspect-software-press-kit.zip)**.
## Using the assets
- **Keep the proportions.** Scale the files; do not redraw, stretch, rotate,
or rebuild the lockup from its parts.
- **Keep the colours.** The full-colour files are for colour reproduction; the
one-colour files are for everything else. No other recolouring.
- **Leave clear space.** At least the height of the mark on every side, free
of type, rules, and other logos.
- **Respect the minimum size.** The lockup stays legible down to a mark height
of 16 pixels; below that, the mark alone.
- **No effects.** No shadows, outlines, gradients, glows, or containers added
on top of what the files already carry.
- **No implied endorsement.** The assets identify inspect.software. They do
not signal a partnership, a certification, or an approval of the material
they appear in.
△The badge and the certification seal are not brand assets. A
badge states one repository's inspected result, and a seal states its
certification level. Both are certification marks, carried only by the repository that earned them, and neither may be used as decoration or as a general logo for inspect.software.
## Colour
Ink#0F2335
Green#25A86F
Green on dark#3FD39A
Blue#3868FF
Ground#F6F9FF
Ink carries the name, green carries the domain, and blue is reserved for
links and interactive elements. The band colours that appear in reports —
from *exceptional* deep green to *critical* red — belong to the
[rating scale](/wiki/scoring-bands) and are documented there.
## Typography
The site is set in **Geist** and **Geist Mono**, both under the SIL Open Font
License. The wordmark files carry outlines rather than live text, so no font
installation is required to reproduce them.
## The name
inspect.software is written as one word, lowercase, always with the dot —
including at the start of a sentence. Not *Inspect Software*, not
*Inspect.Software*, not *inspect-software* outside of a URL or an account
handle. On first mention in prose, "the public record inspect.software" reads
naturally and avoids a sentence opening on a lowercase word.
## Boilerplate
Approved descriptions, in three lengths. Shortening one further risks losing
the qualifications that make it accurate.
**One line**
> inspect.software keeps a public record of open-source software health.
**Short**
> inspect.software is an independent public record of open-source software
> health. Every repository is assessed by the same published, versioned
> methodology, spanning maintainability, engineering quality, security
> posture, ecosystem adoption, and governance. The scanner that produces the
> results is open source, each report carries the evidence behind it, and no
> payment can change an outcome.
**Long**
> inspect.software is an independent public record of open-source software
> health. Modern software is assembled from thousands of open-source
> dependencies, yet the signals available for judging them are weak: stars
> measure popularity rather than health, and a package with millions of
> weekly downloads maintained by a single volunteer looks, from the outside,
> like any other.
>
> The record inspects repositories against one published, versioned
> methodology, spanning maintainability, engineering quality, security
> posture, ecosystem adoption, and governance, and publishes each result as a
> report, a health index, and an embeddable badge. Weights, formulas and
> thresholds are documented, the production scanner is released under the
> AGPL, and every report carries the observed evidence, so any figure can be
> checked by hand or recomputed from the published code. Results are signals
> rather than warranties, and no commercial relationship can change one.
## Facts
- **What it is** — a public record of open-source software health, published
as reports, health indices, and badges.
- **Methodology** — one published, versioned specification; see
[methodology](/methodology) for the current version and its full text.
- **Scanner** — AGPL-licensed and public at
[inspect-software/scanner](https://github.com/inspect-software/scanner).
- **Independence** — results are independent of payment; see
[certification & pricing](/pricing).
- **Operator** — Vitalii Stepanenko, València, Spain; full identification in
section 10 of the [terms](/terms).
- **Corpus size** — deliberately not stated here, because it changes daily.
The current figures are on the [front page](/) and in the public
`/api/stats` endpoint.
## Contact
Press enquiries, interview requests, and questions about a published result:
**[mail@inspect.software](mailto:mail@inspect.software)**, with *press* in the
subject line.
Corrections to a specific report follow the
[data corrections](/contact) route instead, which triggers a re-scan when an
error is confirmed.
---
# The health index
> How inspect.software computes the 1–100 open-source health index — components, metrics, weighted categories, and the rules for missing data.
Every repository in the public record carries a **health index**: a single
integer between 1 and 100 that summarizes publicly visible engineering,
maintenance, security, and governance practice. The index exists so that a
library can be [compared with its alternatives](/compare) at a glance — but it
is the *top* of a fully transparent hierarchy, never a black box.
◇Signals, not warranties. A high index reflects publicly visible good practice. It is not a code audit and not a security guarantee — see
how to read the results.
## The three-level hierarchy
The index rolls up through three documented levels:
1. **Components** — individual observable facts (a license file exists, the
latest release shipped 40 days ago, the bus factor is 3). Each component
carries a fixed weight inside its metric.
2. **Metrics** — weighted sums of components, each an integer in 1–100.
Examples: [development activity](/wiki/development-activity),
[maintainer resilience](/wiki/maintainer-resilience),
[security posture](/wiki/security-posture).
3. **Categories** — weighted means of their metrics, also in 1–100. The six
weighted categories are [Vitality](/wiki/vitality),
[Community & Adoption](/wiki/community-adoption),
[Sustainability & Governance](/wiki/sustainability-governance),
[Engineering Quality](/wiki/engineering-quality),
[Security](/wiki/security), and — at a deliberately small weight —
[AI Readiness](/wiki/ai-readiness).
The **overall health index** starts as the weighted mean of the available
categories:
| Category | Weight in overall |
| -------- | ----------------- |
| [Sustainability & Governance](/wiki/sustainability-governance) | 23% |
| [Vitality](/wiki/vitality) | 21% |
| [Engineering Quality](/wiki/engineering-quality) | 19% |
| [Community & Adoption](/wiki/community-adoption) | 17% |
| [Security](/wiki/security) | 16% |
| [AI Readiness](/wiki/ai-readiness) | 4% |
A metric's effective weight in the overall index is *category weight ×
within-category weight*. Every report shows this figure on each metric card,
and every published value maps to one of seven [rating bands](/wiki/scoring-bands).
## Calibration to the public record
The weighted mean is then **calibrated onto the published index scale**
through a fixed monotone curve anchored to the empirical distribution of the
public record. Calibration is what gives the bands their percentile meaning —
*Exceptional* is genuinely the record's top tier — and it lets the index use
the whole 1–100 range instead of crowding half the record into twenty points
of it. The curve saturates at the top: a raw weighted mean of 91 or above
publishes as 100, which is also why a repository with no
[AI Readiness](/wiki/ai-readiness) signals (4% of the raw weight) can still
reach 100/100. The raw weighted mean stays visible in every report's
`overall.inputs.weighted_overall_raw`, so the arithmetic remains fully
auditable. Category and metric values are published uncalibrated — the curve
describes, and is fitted to, the overall index only.
## Red flags cap the index
Four policies stand outside the weighted mean. None of them rewards a clean
result — a repository with no finding simply keeps its calibrated index — but a
confirmed finding multiplies the published value and, in the gravest cases,
holds it under a stated ceiling:
| Policy | Applies to | Ceiling |
| ------ | ---------- | ------- |
| [Malicious dependencies](/wiki/malicious-dependencies) | security posture and the overall index | 19 — top of *Critical* |
| [Abandonment](/wiki/abandonment) | the overall index | 34 when likely, 19 when declared |
| [High-Risk Jurisdiction Exposure](/wiki/jurisdiction-exposure) | security posture and the overall index | 34 — top of *At Risk* |
| [Growth authenticity](/wiki/growth-authenticity) | the stars and forks components of [popularity](/wiki/popularity) | none |
Since methodology v1.13.0 the policies do not compound. The strictest one that
fires governs alone and the others are reported without moving the value again:
a multiplier states how serious a finding is, and a value multiplied twice is a
number no policy chose and none can explain. Repositories whose evidence cannot
answer a policy's question read *unverified* and are never penalized for the
gap.
## Missing data is never a zero
If a component's underlying data is unavailable — a registry publishes no
download figures, the contributor list cannot be sampled — the component is
**excluded and the remaining weights renormalized**. The same rule applies one
level up: a metric with no data becomes `null` and its category redistributes
the weight; a category with no scorable metric is dropped from the overall.
This rule is central to fairness. A project is measured only on what can
actually be observed, and absence of evidence is reported as absence — the
metric's `note` field records every renormalization, so a reader always knows
what was and was not measured.
## Reading a report
- **Read the profile, not just the number.** A 74 built on balanced categories
is a different proposition from a 74 masking a Security value of 25. The
report's radar chart makes spike-and-crater profiles visible immediately.
- **Check the bands.** Values map to seven standardized bands from
`exceptional` to `critical`; band thresholds are part of the versioned
methodology.
- **Recompute anything.** Every metric echoes its inputs and per-component
points in the report, so any published value can be verified by hand from
the `data` section of the JSON report.
- **Read candidates against each other.** An index is only meaningful next to
the alternatives actually under consideration. The
[comparison view](/compare) puts up to six records on one set of axes —
category profile, growth trajectory, and every underlying figure — so the
spread between them is visible rather than inferred.
## Versioning
Formulas, weights, and band thresholds are versioned as a whole. Any change
bumps the metrics version recorded in every report, and the full history is
public — see [methodology versions](/wiki/methodology-versions). Parts of the
methodology can be switched off per scan; the report then documents exactly
what was disabled — see [scan configuration](/wiki/scan-configuration).
Related: [rating bands](/wiki/scoring-bands) ·
[certification levels](/wiki/certification-levels) ·
[software classification](/wiki/software-classification) ·
[signals, not warranties](/wiki/signals-not-warranties) ·
[methodology versions](/wiki/methodology-versions)
---
# Rating bands
> The seven standardized rating bands — exceptional, excellent, good, moderate, weak, at risk, critical — and the letter grades used across every inspect.software health metric and category.
Every value in an inspect.software report — components rolled into metrics,
metrics rolled into categories, and the overall health index — lives on one
standardized 1–100 scale, higher is better. To make those numbers readable at
a glance, each value maps to one of **seven standardized bands**, used
consistently across health, security, and quality measurements. Each band also
carries a compact **letter grade** (C to AAA) for surfaces where a word does
not fit.
## What each band means
| Band | Grade | Range | Meaning |
| ---- | ----- | ----- | ------- |
| **Exceptional** | AAA | 93–100 | The record's top tier (≈ top 5%); essentially all checked criteria met |
| **Excellent** | AA | 80–92 | Strong across the board; minor gaps |
| **Good** | A | 65–79 | Healthy; gaps are limited and manageable |
| **Moderate** | BBB | 50–64 | Acceptable with notable gaps; review recommended |
| **Weak** | BB | 35–49 | Material weaknesses across several areas |
| **At Risk** | B | 20–34 | Significant weaknesses; adoption warrants caution |
| **Critical** | C | 1–19 | Severe problems — e.g. abandoned, single-maintainer, no hygiene |
## Calibrated to the public record
Band floors for the overall health index are not arbitrary round numbers: the
index is **calibrated against the empirical distribution of the public
record** (47,516 inspected repositories at the calibration snapshot), so each
band states where a repository stands within inspected open source. On the
uncalibrated weighted mean, half the record crowded into a 20-point stretch of
the scale and the top decile of open source sat in the high 70s — numbers that
used the 1–100 range badly and made every band boundary misleading. After
calibration the bands split the record into meaningful, comparably sized
populations, and *Exceptional* means what a reader assumes it means: roughly
the top 5% of inspected open source.
The calibration curve is a fixed constant of the versioned methodology, not a
live percentile — a repository's score moves only when its own evidence moves,
never because other repositories were inspected. Recalibration against a newer
snapshot is a methodology version bump like any other, recorded in every
report.
Certain [red-flag policies](/wiki/health-index) bound the index regardless of
the weighted result: an unresolved High-Risk Jurisdiction exposure holds the
index at the top of *At Risk* (34), and a confirmed malicious dependency or a
declared-dead project holds it inside *Critical* (19).
## How bands should be read
- **Bands are coarse on purpose.** The difference between 71 and 74 is noise;
the difference between *good* and *at risk* is information. Procurement and
review decisions should key on bands and on the category profile, not on
single-point differences. The [comparison view](/compare) is built around
this: it states the spread between the records on screen in index points,
so a three-point gap can be recognized as one and set aside.
- **Bands apply at every level.** A repository can sit in the *good* band
overall while one category sits in *critical* — the per-category bands exist
precisely so that strength in one area cannot silently mask risk in another.
(Calibration applies to the overall index; category and metric values map to
the same thresholds directly.)
- **Thresholds are versioned.** Band boundaries are part of the methodology
and only change with a version bump recorded in every report — see
[methodology versions](/wiki/methodology-versions).
## Certification levels
The three bands above *Moderate* carry the record's
[certification levels](/wiki/certification-levels): **Certified** (Good,
grade A), **Certified with Excellence** (Excellent, grade AA), and
**Certified AAA** (Exceptional). A level is the band the published evidence
supports, stated as a certification mark — see
[how levels are earned and change](/wiki/certification-levels), and
[certification & pricing](/pricing) for the paid on-demand path.
## Where the bands appear
The bands drive the color coding across the whole record: catalogue cards,
the report gauge, category headers, individual metric cards, and the
[GitHub badge](/badges). A repository with no completed inspection yet shows a
neutral *pending* state rather than a band.
Related: [the health index](/wiki/health-index) explains how the underlying
1–100 values are computed; [signals, not warranties](/wiki/signals-not-warranties)
explains what they do and do not claim.
---
# Certification levels
> The three inspect.software certification levels — Certified (A), Certified with Excellence (AA), and Certified AAA — how each maps to the calibrated health index, what a level asserts, and how levels change.
A repository whose latest inspection places it in one of the top three
[rating bands](/wiki/scoring-bands) holds an inspect.software
**certification level**. The level is nothing more — and nothing less — than
the band the published evidence supports, stated in the vocabulary of a
certification mark:
| Level | Grade | Band | Health index |
| ----- | ----- | ---- | ------------ |
| **Certified AAA** | AAA | Exceptional | 93–100 |
| **Certified with Excellence** | AA | Excellent | 80–92 |
| **Certified** | A | Good | 65–79 |
Repositories below the *Good* band hold no certification level; their reports
state a diagnosis — [Moderate, Weak, At Risk, or Critical](/wiki/scoring-bands)
— not an award. The [calibration of the index](/wiki/health-index) gives each
level percentile meaning across the public record: *Certified AAA* marks
roughly the top 5% of inspected open source.
## What a level asserts
A certification level asserts exactly what the report behind it asserts:
measured, publicly visible engineering, maintenance, security, and governance
practice under a [versioned methodology](/methodology) — nothing more. It is
not a code audit, not a security guarantee, and not an endorsement — see
[signals, not warranties](/wiki/signals-not-warranties). The full evidence for
any level is one click away in the repository's public report.
## How a level is earned
Every inspection — free public-interest coverage or
[on-demand certification](/pricing) — runs the identical methodology, and the
level follows mechanically from the resulting band. Payment buys an
inspection; it cannot buy a level, and no commercial relationship can move a
published result.
## How a level changes
Levels track the latest published inspection. A re-inspection that moves the
index across a band boundary moves the level with it, in either direction —
a certification that could not be lost would assert nothing. Because band
thresholds and the calibration curve are part of the versioned methodology,
any change that could move levels is dated and documented in
[methodology versions](/wiki/methodology-versions).
## Badges
The embeddable [GitHub badge](/badges) is the certification mark. A certified
repository's badge carries an embossed rosette bearing its letter grade —
**A** for Certified, **AA** for Certified with Excellence, **AAA** for
Certified AAA — beside the band word and the index. Repositories below *Good*
show the same badge without a rosette: the seal marks certification, and
nothing else may wear it.
The badge follows the level automatically. A repository that reaches a higher
level at its next inspection gets the higher seal without re-embedding
anything, and one that falls below *Good* loses the rosette the same way —
which is the point of a mark that is re-derived rather than issued once.
Related: [rating bands](/wiki/scoring-bands) ·
[the health index](/wiki/health-index) ·
[signals, not warranties](/wiki/signals-not-warranties) ·
[methodology versions](/wiki/methodology-versions)
---
# Signals, not warranties
> What an inspect.software result does and does not claim — the honest boundary between visible practice signals and a formal audit or guarantee.
Every report, badge, and certification published by inspect.software carries
the same disclaimer: **results are signals, not warranties.** This page states
precisely what that means, because trust in the record depends on never
claiming more than the evidence supports.
## What a result claims
A health index and its underlying metrics reflect **publicly visible
practice**: commit and release history, contributor distribution, community
files, CI and test configuration, registry publishing state, and
security-relevant signals such as those measured by the
[OpenSSF Scorecard](/wiki/security-posture). Every claim is:
- **Observable** — derived from public data anyone can fetch.
- **Reproducible** — reports record their metric inputs and methodology
version. The formulas and production
[scanner](https://github.com/inspect-software/scanner) are published; the
[methodology](/methodology) documents the privacy exception.
- **Versioned** — each report records the metrics version it was produced
under, so a result can be re-derived later.
## What a result does not claim
- **It is not a code audit.** No line-by-line review of correctness,
performance, or vulnerability is performed. A project with exemplary process
can still ship a defect.
- **It is not a security guarantee.** [Security posture](/wiki/security-posture)
measures visible security hygiene — it cannot rule out an undiscovered
vulnerability or a compromised maintainer account.
- **It is not a judgement about a person or country.**
[High-Risk Jurisdiction Exposure](/wiki/jurisdiction-exposure) routes
policy-defined public profile evidence into enhanced review. It does not
determine nationality, citizenship, trustworthiness, sanctions status,
repository permissions, or malicious intent.
- **It is not an endorsement.** Inclusion in the public record means a
repository was inspected, not that inspect.software recommends it.
- **It is not a ranking.** Two records can be read side by side — the
[comparison view](/compare) exists for exactly that — but the index weighs
categories that different projects have different and legitimate reasons to
answer differently. A comparison is a reading, not an order of merit.
- **It is not a prediction.** A well-maintained project can be abandoned next
month. Scores describe the observable present and recent past.
△Certifications are signals, not warranties. They inform review and procurement; they do not replace expert judgement, legal review, or an independent security assessment where one is required.
## Why this boundary is kept strict
The value of the record comes from its restraint. A registry that overstated
its results would be gamed by marketing and discounted by engineers; one that
states exactly what it measures can be relied on for exactly that. The same
restraint appears in the formulas themselves: missing data is excluded and
weights renormalized — never guessed, never counted against a project (see
[the health index](/wiki/health-index)).
## Independence
Published results are independent of payment. Free public-interest scans and
paid certifications run the same versioned methodology, and no commercial
relationship — sponsorship, certification fees, vendor alignment — can alter
a published value. Where a scan intentionally narrows the methodology, the
report says so explicitly (see [scan configuration](/wiki/scan-configuration)).
Related: [the health index](/wiki/health-index) ·
[certification levels](/wiki/certification-levels) ·
[rating bands](/wiki/scoring-bands) ·
[methodology versions](/wiki/methodology-versions)
---
# Methodology versions
> The complete version history of the inspect.software metrics methodology — every formula, weight, and threshold change, dated and documented.
The methodology is **versioned as a whole**. Any change to a formula, a
weight, or a band threshold bumps the metrics version, and every published
report records the version it was produced under (`metrics.metrics_version`).
That makes results auditable over time: a historical value can be re-derived
under the exact rules that produced it.
The current version is **2.10.0**. Its implementation is published at
[inspect-software/scanner](https://github.com/inspect-software/scanner).
A report's `metrics.metrics_version` can be matched to `METRICS_VERSION` in
the repository history to identify the code used to compute it.
Each entry identifies the precise change, its scope, and whether existing
results remain comparable. Dates are part of the public methodology record.
## Version history
### 2.10.0 — 2026-08-22
**An interface is only expected of software that could meaningfully lack it.**
The machine-readable-interfaces metric judged every repository it admitted
against all three of its checks, so a `examples/` directory — which nearly
every library ships — was enough to be told the project was missing an OpenAPI
schema and an MCP server. Just over a quarter of the record entered the metric
on examples alone. A maintainer receiving a badge pull request put it plainly:
he had no idea how either check applied to his database driver, and he was
right. An API schema is now expected only of network services and chat bots,
an MCP server only of network services, and runnable examples of everything;
anything else is excluded and the remaining weights renormalize. Evidence
still counts wherever it exists — a library that does publish a schema earns
the points, because the classification decides whether *absence* is a finding,
never whether evidence is real. No repository enters the metric that was not
already in it, and no score moves downward.
### 2.9.0 — 2026-08-22
**A registry that hosts documentation for everything it publishes counts as
the documentation site.** Version 2.7.0 accepted a documentation URL
*declared* through the registry. crates.io goes further: it builds and serves
a documentation page for every crate it accepts, whether or not the manifest
names one — so a crate that simply skipped the optional key still lost the
points, which measured paperwork rather than documentation. The
[documentation](/wiki/documentation) check now falls back to that hosted page,
after every declared URL has been considered. Only crates.io qualifies today;
an ecosystem joins that list when its hosting has been measured, not when it
looks similar. Reported by maintainers reading their own reports. Scores can
only rise, and the correction applies without rescanning, since it reads what
the report already records.
### 2.8.0 — 2026-08-22
**An organization's verified domain is finally read, and "not read" stops
meaning "unverified."** The [stewardship](/wiki/stewardship) verified-domain
check took its flag from GitHub's user endpoint, which serves organizations
but omits the verified-domain field entirely — only the organization endpoint
carries it. Every organization in the record therefore failed a 20-point
check regardless of its actual status, and 59% of the record is
organization-owned. A maintainer reading his own report found it. Collection
now asks the organization endpoint for organizations only. Scoring changes
with it: an unread flag — in every report written before this change, and
whenever the lookup fails — is now excluded and the remaining weights
renormalized, rather than scored as unverified: a request that did not happen
is not evidence of an unverified domain. Organization scores rise where the
flag was unknown, and settle at the true value on rescan.
### 2.7.0 — 2026-08-20
**Documentation declared through the registry counts.** The
[documentation](/wiki/documentation) metric's documentation-site check
accepted only the GitHub homepage field. Rust libraries document on docs.rs,
declare it with the manifest's `documentation` key — mirrored by crates.io —
and rarely set a GitHub homepage, so an entire ecosystem's libraries lost
these points; a maintainer receiving a badge pull request found the error on
his own report, and syn and serde carried the same one. The check now falls
back to a documentation or homepage URL declared through the package
registry: crates.io `documentation` and `homepage`, PyPI `project_urls`,
RubyGems `documentation_uri`, Hex docs links, the npm and Packagist
homepage, NuGet `projectUrl`. A homepage hosted on github.com restates the
repository link and is ignored. Scores can only rise, and only where a
registry declares what the repository already publishes. Existing reports
gain the correction as they are rescanned, since the registry declaration is
recorded at collection time.
### 2.6.0 — 2026-08-19
**Adoption evidence must point back.** [Ecosystem adoption](/wiki/ecosystem-adoption)
counts downloads and registry dependents only from packages whose registry
entry declares the scanned repository as its own. A package name declared in
the repository's manifests whose registry entry declares *no* repository keeps
the benefit of the doubt for existence, but no longer lends the repository its
download figures: that rule let an unrelated npm package's 25 downloads/month
stand on a report in place of the project's ~14M/month on PyPI — found by the
project's own maintainer. Excluded packages are now named in the metric's
inputs. Repositories whose only figures were unverified show the metric as
no-data and renormalize. Scores move only where unverified numbers were being
counted; verified evidence is unchanged.
### 2.5.0 — 2026-08-04
The [classification](/wiki/software-classification) touches a score for the
first time: the [security posture](/wiki/security-posture) fallback's
**dependency-lockfile expectation** is restored for published applications.
Publication alone used to waive the check, which excused exactly the
repositories the guidance is about — ruff, black and poetry are published
applications, and the package managers' own advice tells applications to
commit the lockfile. A published package whose manifest *declares* an
executable now keeps the expectation.
Two guardrails accompany the change. The standing rule, which every future
connection will follow: **scoring reads manifest declarations only** — a
label inferred from file structure, topics or the description is displayed
but never moves a score. And the blast radius was measured before shipping:
the lockfile component exists only in the fallback used when OpenSSF
Scorecard is unavailable (472 of 49,846 stored reports), and within it
exactly **four reports** change — one gains points, three lose. The change is
effectively prospective: it governs future scans without Scorecard, and makes
the methodology practice its own words.
### 2.4.0 — 2026-08-04
The [classification](/wiki/software-classification) vocabulary becomes an
explicit **two-level tree** — Library · Application · Host extension ·
Notebook, with subtypes under Application and Host extension — replacing the
flat nineteen-label list. **No score is affected.**
Three structural changes. **Five labels merge into Library**: framework, SDK,
API client, middleware and driver had no defensible boundaries — axios is an
API client *and* a library, flask is a framework *and* a library — and no
consumer treated the distinction as meaning anything. **The answer may stop
at the top level**: a Cargo binary target and Go's `cmd/` layout prove an
executable without saying what kind, and such repositories are now classified
simply Application instead of being forced into "command-line tool" at
reduced weight. **Host extensions are subtyped by host class** — plugin,
browser extension, editor extension, theme — because the class determines the
inherited trust surface, while the WordPress-versus-Chrome naming difference
determined nothing.
### 2.3.2 — 2026-08-04
Three classification corrections around Go repositories and code-quality
tools, found by reviewing go-critic — a Go linter whose report read
**Library** on the strength of a single fact: its module resolves on the Go
proxy. **No score is affected.**
**The Go module proxy stops counting as publication.** Every other registry
records an intentional act by the maintainer; the proxy indexes any
repository with a `go.mod` the moment anyone requests it, so existence there
says "this is a Go module", not "this is meant to be depended on" — servers
and command-line tools carry the entry exactly as libraries do. Like the MCP
signal in 2.3.1, it now corroborates rather than decides: repositories whose
only library evidence was the proxy entry lose the label until stronger
evidence arrives.
**Go's file tree is read as the declaration it is.** The language has no
manifest field for what it builds; the `cmd/` layout and the
compiler-enforced `internal/` rule are how it says so. Any source file inside
a `cmd/` directory now marks a binary — previously only a file literally
named `main.go` did, which hid go-critic's second command — and packages the
`internal/` rule does not seal off count toward **Library**, corroborating
the proxy entry.
**Linter and formatter tags carry the command-line reading — except on host
extensions.** A repository tagged `linter` or `formatter` almost always ships
a runnable checker. The exception is systematic rather than random: measured
across the record, 42 of 256 linter-tagged repositories are rule packs or
configs for a host linter, and there the runnable tool is the host. The
contribution is withdrawn entirely whenever independent evidence marks the
repository as a plugin, extension, theme, or editor tooling.
### 2.3.1 — 2026-08-03
A correction to the classification published hours earlier: the Model Context
Protocol signal no longer identifies a repository as an **MCP server** on its
own. **No score is affected.**
That signal fires on `.mcp.json` — the file that configures an editor to *call*
MCP servers — and on any dependency whose name ends in `mcp`, which a client
declares exactly as a server does. It records that a project is set up to work
with coding agents, not that it is one of the servers they call. Measured
across the record it alone accounted for 1,746 of the 3,115 repositories
carrying the label, freeCodeCamp among them. It now requires corroboration; a
genuine server still classifies through its topic or its dependency.
### 2.3.0 — 2026-08-03
Every report now states **what the repository builds**: whether the software
is consumed as code, run as a program, or installed into a host that supplies
its trust model. **No score moves in this version** — the
[classification](/wiki/software-classification) is published as data and is not
yet an input to any metric.
Until now a single proxy stood in for the question: does the repository
publish a package to a registry. That reads every command-line tool on PyPI as
a library, and every application that happens to ship one helper package as one
too — while the expectations that follow differ materially. A published library
is expected *not* to commit a dependency lockfile; the application beside it in
the catalogue is expected to.
The classification carries **every reading the evidence supports**, not one.
Software that is both a published library and a runnable tool is the ordinary
case rather than a contradiction, and such a repository will owe the
obligations of both readings rather than the laxest of them. Evidence is ranked
by how far it can be trusted: what a build manifest declares outright — an
`OutputType`, a Composer `type`, an npm `bin` entry, a console-script entry
point — outweighs file-tree structure, declared dependencies and self-assigned
topics, and no single weak signal carries a reading on its own. Where the
evidence does not answer the question, the report records that instead of
guessing.
Wiring the classification into the metrics that depend on it — dependency
lockfiles first, where the present rule is demonstrably wrong for published
tools — is a separate, dated version.
### 2.2.0 — 2026-08-02
The High-Risk Jurisdiction classifier stops reading a **denial as a
declaration**, and now treats a named place outside the policy scope as
conflicting evidence.
Both faults were found by testing the policy's North Korea scope against live
profiles. Locations reading "not north korea", "def not north korea" and
"Seoul, Korea (not DPRK)" were all returning a confident match: the country was
named precisely in order to be disowned, and the policy recorded it as a
self-declaration. A denial is now honoured — but only where it sits beside the
match, so "No. 5 Lenin St, Moscow, Russia" still declares Russia and retracts
nothing.
The second fault was structural. The packaged place gazetteer holds Russian,
Iranian and North Korean places and nothing else, so a foreign city standing
next to a policy match was invisible and the match read as unopposed:
"Seoul, North Korea" and "New Dehli / Beijing / Hong Kong / Pyongyang" both
scored as confident. Capitals, major cities and technology hubs outside the
scope now make a location ambiguous, exactly as a foreign country name already
did, and US state names apply to every policy country rather than to Russia
alone.
Measured across the whole record before release: of 358 distinct
high-confidence locations, two change — one reading "London, Munich, St.
Petersburg", which is an office list rather than a declaration, and one reading
"Amsterdam, Netherlands / Leningrad, Russia". A single repository loses its
flag. Scores can only rise under this change.
### 2.1.0 — 2026-08-02
**Responsiveness gains a Newcomer PR acceptance component (weight 13.)** Of the
pull requests decided in the last 30 days whose author had no previously merged
pull request in that repository, the component scores the share that were
merged. Bot-authored pull requests are excluded before anything is counted. The
two lifetime components are re-weighted to make room — issue resolution 46.75 →
42, PR acceptance 38.25 → 30 — and the OpenSSF Scorecard `Code-Review`
component stays at 15.
The existing PR acceptance component is a lifetime ratio, and on an established
project it barely moves: a repository with thousands of merged pull requests
cannot shift it inside a year whatever it does now. Nor can it separate a
project that merges its regulars' work promptly from one that merges nothing
arriving from outside that circle. Those two rates come apart often enough that
only the second describes what a first-time contributor should expect.
The component is **excluded, with the metric's remaining weights renormalized**,
when no first-time contributor's pull request was decided in the window. Nobody
knocking is not the same fact as nobody being let in, and only the second is the
project's own doing. The denominator is newcomers' *decided* pull requests
rather than their share of all merges, so a mature project where regulars land
most of the work is not marked down for having regulars.
The evidence is collected during the scan, so it appears only on reports
produced after this version. Earlier reports lack the input and renormalize
without it; the change therefore takes effect as repositories are rescanned
rather than across the record at once. Scores can move in either direction
where the component is present.
**Community health reports the README's status badges, unscored.** How many
badges a README displays, and which services they come from, are now carried in
the report as observations with no weight. Every fact a badge asserts — that CI
runs, that coverage exists, that a release is published — is already measured
directly from the repository, and a badge is one line of Markdown that nothing
verifies as pointing at the project it sits in.
### 2.0.0 — 2026-08-02
The first major revision of the scale itself, in three connected parts. The
whole record was re-scored under it; scores published before and after this
version are **not comparable point-for-point** — bands, not points, are the
unit of comparison across the boundary.
**The overall index is calibrated to the public record.** The weighted
category mean used the 1–100 range badly: measured across all 47,516
inspected repositories, half the record sat between 50 and 69 and the top
decile of open source reached only the high 70s, so most of the scale
distinguished nothing. The published index now applies a fixed monotone
curve — anchored to chosen percentiles of the record's empirical distribution
at a dated snapshot — to the raw weighted mean. Bands thereby carry
percentile meaning, and the raw mean remains in every report
(`overall.inputs.weighted_overall_raw`) for auditability. The curve is a
constant of this version, not a live percentile: a score moves only when the
repository's own evidence moves. The curve saturates at the top of the
scale — a raw mean of 91 or above publishes as 100 — because the last raw
points above that line distinguished nothing a reader should act on.
Category and metric values are published uncalibrated.
**Five bands become seven.** *Weak* (35–49) now sits between *At Risk* and
*Moderate*, and *Exceptional* (93–100) above *Excellent*. New thresholds:
critical 1–19, at risk 20–34, weak 35–49, moderate 50–64, good 65–79,
excellent 80–92, exceptional 93–100 — chosen so the calibrated bands split
the record into comparably sized populations where the old *Moderate* alone
held roughly half of it. Each band also carries a letter grade, C through
AAA. Red-flag ceilings moved with the bands they name: the High-Risk
Jurisdiction and likely-abandonment ceilings are now 34 (top of At Risk,
previously 49), the malicious-dependency and declared-abandonment ceilings
19 (top of Critical, previously 29), and the overall-score policies now act
on the calibrated index, so a report's stated ceiling is the number the page
displays.
**AI Readiness joins the weighted mean at 4%.** The category was measured
and published at weight 0 since its introduction; agent tooling has since
become an ordinary maintenance signal and now carries real — deliberately
small — weight. The other categories yield one point each: Sustainability &
Governance 23%, Vitality 21%, Engineering Quality 19%, Community & Adoption
17%, Security 16% (unchanged). The weight is sized together with the
calibration curve's saturation point so that a repository with zero AI
Readiness signals can still reach 100/100 — the category can nudge an index,
never gate the top of the scale.
### 1.14.0 — 2026-08-02
The High-Risk Jurisdiction Policy now requires a contributor-side match to
carry **commit weight** before it flags: at least 50 commits, or at least 10%
of the sampled human commits. Owner matches are unaffected.
The previous rule flagged a repository for any high-confidence location match
among its displayed top contributors, however small their contribution.
Measured on the production record, 1,763 repositories carried the flag and only
199 through the owner account; of the remainder, 56% rested on a matched
contributor with fewer than ten commits, and 70% on one below 5% of the
project's commit history. Widely used projects were flagged for single
low-ranked contributors near 1% of their history. A location match on an
incidental contributor is disclosure, not exposure, and a flag that fires on it
tells a reviewer nothing about who stewards the software.
Matches below both thresholds remain on the report as recorded, review-only
evidence; they raise no flag and move no score. Scores can only rise under this
change, and only for repositories whose flag rested entirely on sub-threshold
matches. The thresholds are published in every report, and the commit counts
the rule reads were already collected, so existing reports were re-scored
without rescanning.
### 1.13.0 — 2026-07-22
Two corrections, both prompted by the first malicious-dependency finding this
record ever published.
**Red flags stop compounding.** Each policy used to multiply whatever the
previous one left, so a repository carrying two landed on the product of both.
One project went from a weighted 50 to 18 under the malicious-dependency
multiplier and then to 11 under abandonment — a number no policy chose, and
none could be pointed at to explain. A multiplier states how serious a finding
is; it is not a cost to be added up. The strictest policy now governs alone and
the others are reported without moving the score again. Scores can only rise
under this change, and only for repositories carrying more than one flag.
**A withdrawn package is no longer scored as live malware.** Every malicious
finding now asks the registry whether it still serves that exact version. Where
it does not, nothing installable remains: the finding stays on the report,
because the project depends on a name that was compromised, but it raises no
flag and costs no points.
The check asks about the resolved version rather than the package's latest one,
and the distinction decides real cases. After a takedown npm leaves a
placeholder release as the package's latest, which protects everyone resolving
a version range and nobody who pinned the bad version exactly. Reading the
latest version would have cleared the very repository this finding first fired
on, which pins the compromised package at the precise version the registry
still serves. Where the question cannot be answered at all, the finding is
scored as though the package were live — failing to reach a registry is not
evidence that malware was withdrawn.
### 1.12.0 — 2026-07-22
The Abandonment Policy's *declared* tier was over-firing on registry evidence
that did not belong to the repository it was judging.
That tier exists to quote the maintainer rather than infer anything: a project
is declared unmaintained when it is archived, or when every package it
publishes has been retired. Two defects widened it. A package counted as the
project's own unless the registry positively said otherwise — which admitted
entries declaring no repository at all, exactly the shape a squatted name
takes. And a yanked latest release counted as retirement, though withdrawing a
release is usually a bad build with a fix right behind it.
Together they took one 68-rated project to 27 on the strength of a PyPI
placeholder it does not publish. A package must now declare *this* repository
and be deprecated outright; a yanked release no longer contributes. Of 403
repositories in the declared tier, 391 rested on GitHub's own archive flag and
were never in question.
### 1.11.0 — 2026-07-21
**Abandonment** becomes a red flag over the whole report.
Every tool in this space answers "is this project 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. Marking it dead costs a public record its credibility on exactly the
software that deserves the most confidence.
So the assessment rests on a different question — abandonment is an unmet
obligation, not an absence of noise. Silence is measured from the last human
commit and is never a finding on its own; it becomes one only when work is
visibly arriving and not being acted on: an unanswered contribution queue,
issues no maintainer ever 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, a sole maintainer absent from the whole window.
Readings that explain the silence hold the result at *dormant*, which carries
no penalty — quiet is already priced inside development activity, and charging
for it twice would punish the finished libraries the distinction exists to
protect.
Findings multiply the health index: 85% at risk, 60% likely abandoned with an
at-risk ceiling of 49, 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 is deprecated or yanked.
Repositories that cannot be assessed read *unverified* and are not penalized.
See [abandonment](/wiki/abandonment).
**Comparability:** values can only fall relative to 1.10.0, and only for
repositories where a drought is corroborated by unmet obligations. Quiet,
well-kept projects are unaffected by design.
### 1.10.0 — 2026-07-21
Dependencies reported as **malicious packages** become a security red flag of
their own, separate from vulnerability advisories.
The evidence was already arriving. OSV.dev serves the OpenSSF
malicious-packages corpus alongside ordinary advisories, on the same query this
record already made — but a malicious-package report carries no severity rating
and no fixed version, so it was falling through to "unknown severity" and
scoring like a moderate vulnerability. A package found to be malware counted
for slightly less than an average CVE.
Malicious packages are now removed from the advisory findings and scored on
their own terms: a 35% multiplier on security posture and on the weighted
health index, with a Critical ceiling of 29 on both. That is one band stricter
than the high-risk jurisdiction ceiling, because a malicious dependency 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
resolved graph.
The finding is expected to be rare: run over a 300-repository sample covering
46,889 resolved dependencies before release, it found nothing. Registries
remove malicious packages within days, so a lockfile that still resolves to one
is unusual. See [malicious dependencies](/wiki/malicious-dependencies).
**Comparability:** unchanged for every repository with no malicious dependency,
which is nearly all of them. Where one is found, Security and the health index
are not comparable to any earlier version.
### 1.9.0 — 2026-07-21
The human-authorship factor introduced in 1.6.0 stops firing on projects that
simply automate well.
Heavy automation on its own turned out to be a poor signal. Among the
repositories where machines author most of the commit traffic, the healthiest
were indistinguishable from the abandoned ones by share alone: one 59,000-star
project runs roughly three quarters of its commits through a dependency bot and
had a human commit two days ago, and a package registry whose entire purpose is
automated version bumps runs at 93%. Both were being marked down.
The discount now requires a second condition: the machines must also have been
committing alone for more than 90 days. The gap is measured inside the sampled
commit window rather than against the clock, so a stored report always rescores
to the same value. Repositories with a recent human commit are no longer
affected at any level of automation; genuinely automation-sustained projects
keep their discount.
**Comparability:** values can only rise relative to 1.8.0, and only in
Vitality.
### 1.8.0 — 2026-07-21
A signal is withdrawn. [Growth authenticity](/wiki/growth-authenticity)'s
**pre-substance spike** claimed that a burst arriving before a project's first
release was evidence of something. Measured against 795 ordinary repositories,
it fired in every one of the five findings the policy produced — and every one
of those five was an ordinary launch. Publish, attract attention, release
later is how projects work.
The comparison was unsound in a second way. The release list a report carries
is capped at its newest 100 entries, so for any project past that cap the
earliest entry is not its first release, and every burst appears to predate
it.
What replaces it, **no released substance**, keeps only the absolute case: the
project has never published a release at all. It is deliberately weaker, and
it corroborates rather than concludes. Findings across the ordinary population
return to none, and both confirmed findings in the evaluation sample survive.
A published methodology that cannot withdraw a signal it can no longer defend
is not a methodology. This is what the version history is for.
### 1.7.0 — 2026-07-21
[Growth authenticity](/wiki/growth-authenticity) gains a fifth signal,
**star concentration**: the five busiest days holding 80% or more of every
star the scan collected.
It was added after the first live evaluation of the policy, which found it
precise but nearly blind — across 714 ordinary repositories it flagged none,
and across 45 selected for the shape purchased attention leaves it flagged one.
The threshold is read off the record rather than chosen in advance: among 502
ordinary repositories in the 100–1,500 star band, the median puts 6.9% of its
stars in the five busiest days, and none reached 80%.
The signal corroborates a burst; it never concludes on its own. A legitimate
announcement-driven release approaches the same shape — a research model
release measured 73.7% — and a signal that cannot tell those apart must not
decide alone.
Scores can only fall under this change, and only for repositories that already
showed a burst. Nothing else moves.
### 1.6.0 — 2026-07-21
Inputs that can be inflated stop counting at face value.
Added [growth authenticity](/wiki/growth-authenticity). The per-day star and
fork history collected for every report is now read for growth whose shape
organic attention does not produce, and the **Inorganic Growth Policy**
discounts the stars and forks components of [popularity](/wiki/popularity) by
40% for one confirmed window and 70% for more. A burst on its own is never a
finding: confirmation requires at least two independent corroborating
signals, so launches and front-page days read as organic. Repositories whose
collected history cannot answer the question read *unverified* and are not
penalized. The policy carries no additive weight, so a clean history can never
raise a score.
[Development activity](/wiki/development-activity) gains a human-authorship
factor over its commit cadence and commit volume components. A project
sustained entirely by its own robots no longer reads as actively developed;
full marks apply from a 40% human share upward, so heavy but genuine
automation is unaffected. [Maintainer resilience](/wiki/maintainer-resilience)
now counts people only — automation accounts were previously ranked among a
project's maintainers, which flattered exactly the projects that automate
most.
[AI Readiness](/wiki/ai-readiness) stops measuring only which files exist.
[Agent context](/wiki/ai-agent-context) gains a **legible commit history**
component and rebalances away from `llms.txt`: before this change the metric
could only ask whether a rare file had been written, and most projects had no
way to move it at all. [Verify loop](/wiki/ai-verify-loop) gains its
first two components that observe an outcome rather than the presence of a
file: **demonstrated agent practice**, and **automated maintenance** — whether
a dependency bot's machine-authored changes actually land, judged on observed
commits rather than a configuration file, since the most widely used tool is
routinely configured outside the repository. It also now credits a language
toolchain as a one-command bootstrap, which had scored well-run Rust projects
zero for shipping no Makefile. The badge still carries no weight in the health
index.
Existing values remain comparable except in Community & Adoption for
repositories with a confirmed growth finding, and in Vitality and
Sustainability & Governance for repositories whose contributor list is largely
automation. Scores under these changes can only fall, never rise.
### 1.5.0 — 2026-07-20
Added [dependency advisories](/wiki/dependency-advisories). The resolved
dependency set already collected for every report — direct dependencies plus
the transitive closure — is now matched against the
[OSV](https://osv.dev) advisory database, and affected packages are reported
with their severity and the version each was fixed in.
Security becomes a weighted mean of
[security posture](/wiki/security-posture) at 80% and the new metric at 20%.
The [High-Risk Jurisdiction Policy](/wiki/jurisdiction-exposure) multiplier
is unchanged: it still applies to posture and to the weighted overall score,
and carries no additive weight of its own.
The new metric is excluded, with the remaining weight renormalized, whenever
the dependency graph or the advisory lookup was unavailable — a repository is
never penalized for having its dependency graph switched off. Existing values
remain comparable except in Security, where any repository with a dependency
graph is now scored on evidence that was not previously considered.
### 1.4.0 — 2026-07-19
Added [High-Risk Jurisdiction Exposure](/wiki/jurisdiction-exposure) for
high-confidence self-published public profile evidence within the Russia, Iran,
and North Korea policy scope. It is a hierarchy-wide policy multiplier: owner
20%, displayed top contributor
50%, public contributor-organization affiliation 75%, no match 100%. A
confirmed match multiplies and caps [Security posture](/wiki/security-posture)
at 49; Security reflects that adjusted posture. The same multiplier and cap
then apply to the weighted overall score. Missing, ambiguous, and clean
evidence do not reduce either score.
The classifier is offline, adds no API request, excludes internationally
recognized Ukrainian territories from Russia place matching unless Russia is
explicitly self-declared, and publishes only aggregate country/role evidence.
The signal routes a dependency into enhanced review; it does not determine
nationality, citizenship, sanctions status, malicious intent, or individual
trustworthiness.
**Comparability:** affected repositories can move to a lower Security and
overall band. Existing reports contain owner and top-contributor locations
and can be rescored without repository network access. Organization-affiliation
location is available only on new scans because schema 0.15.0 adds it to the
existing batched GraphQL selection.
### 1.3.0 — 2026-07-18
[Community health](/wiki/community-health)'s license signal became a
**three-state tier** — standard, custom, or none — replacing a single
present/absent test. A repository whose license file exists but whose text is
not a recognized license now earns three quarters of the license weight rather
than either full credit or none.
Detection also changed: the state is resolved from **all three** license
sources together (the repository's license metadata, GitHub's community
profile, and the Scorecard `License` check) instead of preferring Scorecard
alone. Presence is a logical OR, so a file that any one source sees counts.
The sources disagree on roughly 1% of repositories.
Custom licenses already scored slightly below standard ones before this
version, because Scorecard grades them 9 out of 10 rather than 10. That gap
was inherited from the tool rather than stated as a position; it is now
deliberate and documented.
**Comparability:** existing results were recomputed under 1.3.0 from the data
already stored in each report — no repository was rescanned, so nothing moved
for any reason other than this change. Movement is small: the license row is
22.5 of 100 points within community health, itself 35% of Community &
Adoption, which is 18% of the index.
### 1.2.0 — 2026-07-14
Published-package registry adapters were added for **Go** (the module proxy),
**Maven Central**, and **NuGet**, and PyPI package identification was extended
to legacy `setup.py` manifests. Repositories publishing in those ecosystems
now carry registry evidence in [package
maintenance](/wiki/package-maintenance) — publish recency, version history,
deprecation state — and NuGet additionally feeds [ecosystem
adoption](/wiki/ecosystem-adoption) through its lifetime download total. Go
and Maven Central publish no download statistics of any kind, so they
contribute no adoption signal. No formulas or weights changed — only which
repositories have registry evidence available.
### 1.1.0 — 2026-07-14
[Community health](/wiki/community-health) now detects a license **once**. It
previously carried two overlapping license components — a GitHub
community-profile flag and a separate `License` shared-evidence card. These are
merged into a single `License` row detected by OpenSSF Scorecard's `License`
check, with the community-profile flag kept only as a fallback for repositories
that have no Scorecard. Scorecard's own `License` check remains a full component
of [Security posture](/wiki/security-posture). The merge removes double-counting
and defers to Scorecard's more reliable detection where the two sources
disagree. This release changes affected `community_health` scores; reports
remain reproducible through their recorded `metrics_version`.
### 1.0.0 — 2026-07-13
OpenSSF Scorecard checks now provide **shared evidence** where a security
practice also substantiates another health dimension. Scorecard remains fully
risk-weighted in [Security posture](/wiki/security-posture); seven selected
checks additionally receive small, documented weights in their destination
metrics: `Maintained`, `Signed-Releases`, `Contributors`, `Code-Review`,
`License`, `CI-Tests`, and `Pinned-Dependencies`.
This is intentional cross-category influence, not a reuse of Scorecard's
security-risk weights. A check reported as `n/a`, or unavailable Scorecard
data, is excluded from the destination metric and its remaining components
are renormalized. This release changes affected repository scores; reports
remain reproducible through their recorded `metrics_version`.
### 0.9.0 — 2026-07-07
The [security posture](/wiki/security-posture) fallback stopped treating a
missing dependency lockfile as a fault for published libraries. Lockfiles are
an application-level practice; many libraries and gems correctly omit them.
For those repositories, the fallback component is now excluded and the
remaining components renormalize. The OpenSSF Scorecard path was unchanged.
### 0.8.0 — 2026-06-30
Added the **[AI Readiness](/wiki/ai-readiness)** category with four metrics:
([agent context](/wiki/ai-agent-context), [verify loop](/wiki/ai-verify-loop),
[code legibility](/wiki/ai-code-legibility), [interfaces](/wiki/ai-interfaces))
assessing whether a repository supports reliable AI-assisted development. The
category carries weight 0.0: it is an independent, additive badge and never
changes the overall health index. Existing repository formulas were unchanged.
### 0.7.0 — 2026-06-20
Supported ecosystems extended. [Ecosystem adoption](/wiki/ecosystem-adoption)
falls back to lifetime total downloads when a registry publishes no monthly
figure (RubyGems), so Ruby and Hex packages now receive adoption values.
RubyGems and Hex registry adapters added; declared-dependency parsing extended
to Go, Maven, RubyGems, NuGet, and Hex. See
[supported ecosystems](/wiki/supported-ecosystems).
### 0.6.0 — 2026-06-09
[Security posture](/wiki/security-posture) rebuilt on the **OpenSSF
Scorecard**: tool-agnostic, risk-weighted checks that no longer penalize
projects for using non-GitHub tooling, with inconclusive checks excluded
rather than counted as zero. Coarse file-tree checks remain as a fallback.
Only the Security category affected.
### 0.5.0 — 2026-05-29
Package-ecosystem metrics added: [ecosystem adoption](/wiki/ecosystem-adoption)
(registry downloads) in Community & Adoption and
[package maintenance](/wiki/package-maintenance) (publish recency,
deprecation) in Sustainability & Governance. Both are `null` for repositories
that publish no package. Category inner weights rebalanced; category weights
and other formulas unchanged.
### 0.4.0 — 2026-05-18
Metrics regrouped into five weighted **categories** with rolled-up values.
Four new repository metrics: [release discipline](/wiki/release-discipline),
[popularity](/wiki/popularity), [stewardship](/wiki/stewardship), and
[documentation](/wiki/documentation). `activity` renamed
[development activity](/wiki/development-activity). The overall index now
rolls up categories rather than individual metrics.
### 0.3.0 — 2026-05-06
Organization metrics added — profile completeness, portfolio activity,
community reach, and an organization overall (see
[organization assessment](/wiki/organization-assessment)). Repository
formulas unchanged.
### 0.2.0 — 2026-04-25
Per-component results added to every metric, so a report shows exactly which
criteria passed, partially passed, or were excluded. Formulas, weights, and
band thresholds unchanged from 0.1.0.
### 0.1.0 — 2026-04-15
Initial methodology.
## What versioning guarantees
- **Reproducibility** — reports record their inputs and methodology version,
and the corresponding scoring implementation is published. The documented
privacy exception for contributor profiles applies.
- **Comparability** — two repositories inspected under the same version are
measured by identical rules.
- **Accountability** — methodology changes are public, dated, and explained;
there are no silent adjustments.
Related: [the health index](/wiki/health-index) ·
[rating bands](/wiki/scoring-bands) ·
[scan configuration](/wiki/scan-configuration)
---
# Supported package ecosystems
> The package ecosystems inspect.software reads — nine registries with published-package facts, plus dependency manifests across all of them.
A repository is more than its GitHub presence: most reusable software ships
through a **package registry**, and the registry holds adoption and
maintenance evidence GitHub cannot show — real download volume, publish
recency, deprecation state. inspect.software resolves the packages a
repository publishes and folds registry data into two metrics:
[ecosystem adoption](/wiki/ecosystem-adoption) and
[package maintenance](/wiki/package-maintenance).
## Registries read today
| Ecosystem | Registry | Adoption figure |
| --------- | -------- | --------------- |
| JavaScript / Node | npm | monthly downloads |
| Python | PyPI | monthly downloads |
| PHP | Packagist | monthly downloads |
| Rust | crates.io | monthly downloads |
| Ruby | RubyGems | lifetime total downloads |
| Elixir / Erlang | Hex | download figures |
| .NET | NuGet | lifetime total downloads |
| Go | Go module proxy | no public download counter |
| Java / JVM | Maven Central | no public package-download counter |
All nine registries contribute published-package facts — latest version,
publish recency, version history, deprecation state — to [package
maintenance](/wiki/package-maintenance). Where a registry publishes no
monthly download figure (RubyGems, NuGet), the adoption metric falls back to
**lifetime total downloads** — whichever figure the registry actually
provides, so no ecosystem is structurally disadvantaged. The Go module proxy
and Maven Central publish no download statistics of any kind. For Go this
leaves maintenance evidence as the only signal; for Maven Central the
dependent-project count published by deps.dev supplies a comparable adoption
measure.
NuGet is incrementally discovered from its official catalog feed. Its public
search metadata supplies lifetime total downloads, which are used for the
catalogue threshold. Maven Central is incrementally discovered from the
official Maven Central Indexer. Central publishes no package download counter,
so eligibility instead relies on the deps.dev dependent-project count together
with a declared GitHub source; packages meeting the dependents threshold are
auto-queued like other ecosystems.
## Go module discovery
The catalogue worker also reads the official public **Go Module Index** to find
new stable releases. The index publishes a module path, version, and timestamp
but no download/adoption counter. Automatic Go candidates therefore need a
direct `github.com/owner/repo` module path and a stable release published within
the last 730 days; they are ranked by release freshness, not by invented
download figures. The normal low-priority catalogue queue and scan still verify
the repository before it appears in the public record.
## Declared dependencies
Independently of publishing, the inspection parses **dependency manifests**
across ecosystems — npm, PyPI, Packagist, crates.io, Go, Maven, RubyGems,
NuGet, and Hex — and records the declared **direct** dependency list in every
report. Resolving those dependencies against registries and vulnerability
databases (freshness, known CVEs) is on the published methodology roadmap.
## All dependencies
Alongside the direct list, the inspection records the repository's **full
resolved dependency set** — direct plus indirect (transitive) — from GitHub's
dependency graph, which covers the transitive closure whenever the repository
commits a lockfile. The report states direct and indirect counts separately
and names the source of the resolved set. This collection is best-effort:
when the dependency graph is unavailable, the report says so explicitly and
every other part of the inspection proceeds unaffected.
## Repositories that publish no package
Applications, infrastructure repositories, and documentation projects often
publish nothing to any registry. For them the two registry-backed metrics are
`null`: **excluded from their categories with weights renormalized**, never
counted as zero. A non-publishing repository is measured purely on its other
evidence — see [the health index](/wiki/health-index) for the missing-data
rules.
## Package-to-repository matching
A package only contributes to a repository's report when the registry entry
verifiably points back to that repository. A package that claims a different
source repository is listed in the report but flagged and left out of the
computation — preventing adoption figures from being borrowed or spoofed.
## Multi-ecosystem, multi-language repositories
One codebase can legitimately live in several ecosystems at once — a Rust
core with Python bindings and an npm wrapper publishes to crates.io, PyPI,
and npm from a single repository. Scoring already treats this soundly:
download counts are summed across every verified package. Wherever the
public record *lists* a repository's ecosystems — catalogue cards, filters,
report chips — the order reflects **evidence strength**, not the alphabet:
ecosystems with verified published packages come first, ranked by download
volume; ecosystems seen only in dependency manifests follow. A package that
points at a different source repository never leads the list.
Languages follow the same discipline. The languages shown for a repository
are those holding **at least 10% of its code by volume**, largest first —
so CI scripts and generated markup do not masquerade as a project language,
and a genuinely bilingual codebase is presented as one. Catalogue cards show
up to three ecosystems and three languages per repository.
Related: [ecosystem adoption](/wiki/ecosystem-adoption) ·
[package maintenance](/wiki/package-maintenance) ·
[software classification](/wiki/software-classification) ·
[methodology versions](/wiki/methodology-versions)
---
# Software classification
> How inspect.software determines what a repository builds — the multi-label reading of whether software is consumed as code, run as a program, or installed into a host.
A repository is not simply "a project". It builds something, and what it builds
decides which practices are reasonable to expect from it. A published library
is expected **not** to commit a dependency lockfile — the versions it pins
would be ignored by everyone installing it. The application beside it in the
catalogue is expected to commit one, because the versions it pins are exactly
what gets deployed. Judging both by one rule misreads one of them.
Until metrics 2.3.0 a single proxy stood in for the question: does the
repository publish a package to a registry. That reads every command-line tool
on PyPI as a library, and every application that happens to ship one helper
package as one too.
## Every reading the evidence supports
The classification is **multi-label**. Software that is both a published
library and a runnable tool is the ordinary case, not a contradiction to be
resolved: ripgrep is a crate and a binary, esbuild is an npm package and an
executable. A repository therefore keeps every reading its evidence supports.
The vocabulary is a **two-level tree**. The top level answers the question
that matters — how the software is consumed — and a repository can carry more
than one branch:
| Top level | What it makes reasonable to expect |
| --- | --- |
| **Library** — consumed as code | A stable interface, a changelog, versioning other software can depend on |
| **Application** — run as a program | Pinned dependencies, deployment and configuration hygiene |
| **Host extension** — installed into a host | The host supplies the trust model and the release cadence |
| **Notebook** | None of the above — it is read and run by a person, imported by nothing, installed into nothing |
Where both apply, both apply — a hybrid owes the obligations of every reading
it carries, never the most lenient one.
## The subtypes
Subtypes exist only where the finer answer changes what a reader should
expect: an application's interface modality, or the host class an extension
inherits its trust surface from.
| Application | Host extension |
| --- | --- |
| Command-line tool | Plugin |
| Terminal interface | Browser extension |
| Desktop | Editor extension |
| Mobile | Theme |
| Web interface | |
| Network service | |
| Chat bot | |
| MCP server | |
**Library has no subtypes on purpose.** Earlier revisions distinguished
framework, SDK, API client, middleware and driver, and those boundaries do not
exist: axios is an API client *and* a library, flask is a framework *and* a
library — a question with no right answer. What a library connects to is
recorded elsewhere, as an integration fact, not here.
**The answer may stop at the top level.** A Cargo binary target and Go's
`cmd/` layout prove that the repository builds *an executable* — not whether
it is a command-line tool or a server. Such a repository is classified simply
**Application**, and gains the subtype only when evidence for it exists. A
generic answer supported by evidence beats a specific one that would be a
guess.
## How the answer is reached
Evidence is ranked by how far it can be trusted, and **no single weak signal
produces a label**.
| Evidence | Examples | Weight |
| --- | --- | --- |
| **Declared in a build manifest** | an npm `bin` entry, a `console_scripts` entry point, `Exe`, Composer's `type`, Maven's ``, a Cargo `[lib]` target | Decisive |
| **Declared by the registry** | a Packagist type, a NuGet package type, a crates.io category | Strong |
| **Declared dependencies** | a web framework, a CLI argument parser, a chat-platform client | Moderate |
| **File-tree structure** | `cmd/…/main.go`, `src-tauri/`, a Helm chart, a browser-extension manifest | Supporting |
| **Repository topics and registry keywords** | `cli`, `wordpress-plugin`, `self-hosted` | Weak — self-assigned |
| **The repository description** | "a CLI for…", "a library for…" | Weak — self-assigned |
The first two are the strongest because they are not opinions: a maintainer who
writes `Exe` is not describing the software, the build
would not work otherwise. A topic is an opinion, and two of them agreeing is
the minimum that carries anything at all.
Evidence also runs the other way. A Cargo package with `publish = false`, a
Composer `type` of `project`, a `.NET` tool, a Maven `war` — each **rules out**
being something other software can depend on, whatever else the repository
looks like.
## Where the answer is absent
Three situations produce no classification, and all three are ordinary:
- **The report predates the classification.** Every stored report was
reclassified from the facts it already carried, but the manifest evidence is
collected during a scan — so reports gathered earlier carry the weaker tiers
only, and gain the full reading when the repository is next inspected.
- **The evidence does not answer the question.** Many repositories publish no
manifest, carry no informative topics, and describe themselves in prose that
states nothing structural.
- **The answer would be a guess.** Where signals are present but too weak to
cross the threshold, nothing is claimed.
In all three the report simply shows no classification. **Absence is never
presented as a finding**, nothing is scored on it, and a repository without one
is not marked, ranked, or penalized in any way.
## Repositories that build several things
A monorepo holding a deployable service beside three published libraries is not
one artifact, and rolling it up to a single answer would lose the fact that
both readings are true. Each manifest is therefore classified on its own
declarations, and the repository carries the union.
One consequence is worth stating plainly: the single **primary** label shown
for such a repository is the best-supported one, which in a large monorepo can
be a published build tool rather than the product the project is known for. The
primary label exists for display and for grouping comparable repositories — it
is never the basis of a scoring decision.
## What it affects today
One check, under a standing rule. Since metrics 2.5.0 the
[security posture](/wiki/security-posture) fallback's **dependency-lockfile
expectation** reads the classification: a published package whose manifest
declares an executable counts as an application and keeps the expectation,
where publication alone used to waive it.
The standing rule is that **scoring reads manifest declarations only**. A
label inferred from file structure, topics or the description is displayed and
recorded, but never moves a score — only what a build manifest states outright
(a `bin` entry, a console-script entry point, an `OutputType`) can. Everything
else about the classification remains data: `metrics.classification` in every
report, alongside the evidence that produced it. Further connections will be
recorded in the [methodology versions](/wiki/methodology-versions) as they
land.
Related: [supported ecosystems](/wiki/supported-ecosystems) ·
[the health index](/wiki/health-index) ·
[security posture](/wiki/security-posture) ·
[scan configuration](/wiki/scan-configuration) ·
[signals, not warranties](/wiki/signals-not-warranties)
---
# Scan configuration
> How parts of the inspect.software methodology can be switched off per scan — and how every report documents exactly what was and was not measured.
A scan can switch off any part of the methodology — a single **component**, a
whole **metric**, or an entire **category**. This exists for legitimate
narrowing (an internal policy that excludes popularity signals, a
security-only certification) while keeping every published result honest:
the configuration is **embedded in the report itself**, so it is always
explicit what was and was not measured.
## How disabling works
Disabling behaves exactly like missing data (see
[the health index](/wiki/health-index)): the disabled item is excluded and
the remaining weights are **renormalized**. The result stays on the 1–100
scale and is never dragged down by a zero for something deliberately not
measured. Disabling every metric in a category — or the category itself —
drops that category from the overall index, with its weight redistributed.
```jsonc
// scan-config.json
{
"disabled_categories": ["security"],
"disabled_metrics": ["popularity"],
"disabled_components": {
"documentation": ["Wiki", "Topics"]
}
}
```
Category and metric keys are the identifiers documented in each wiki article
(`security`, `popularity`, `security_posture`, …); component names are the
exact display names shown on metric cards (`Wiki`, `Stars`, `README`, …).
Unknown keys are reported as warnings and ignored.
## What configuration cannot do
Configuration selects *which* parts of the fixed methodology are active — it
never changes a formula, a weight, or a band threshold. Those remain governed
by the versioned methodology (see
[methodology versions](/wiki/methodology-versions)). There is no mechanism,
paid or otherwise, to adjust how an active metric is computed.
## How a configured scan reads
- Every report carries its configuration at the top level, so the result is
reproducible as published.
- The report renders a **scan configuration** section listing everything that
was disabled — or states that the full methodology ran.
- Each affected metric's `note` records the renormalization, at the exact
place a reader would look.
◇Transparency rule. A narrowed scan is a valid measurement of a narrower question — and the report always says which question was asked.
Related: [the health index](/wiki/health-index) ·
[signals, not warranties](/wiki/signals-not-warranties)
---
# Vitality
> The Vitality category of the inspect.software health index — whether code is actively written and versioned releases actually ship. Weight: 21% of the overall index.
**Vitality** answers the most basic question about an open-source project:
*is it alive?* Code that stopped moving stops absorbing bug reports, security
fixes, and compatibility work — and dependency on a dormant project is one of
the most common, least visible risks in a software supply chain.
The category carries **21% of the overall health index**, second only to
[Sustainability & Governance](/wiki/sustainability-governance).
## Metrics in this category
| Metric | Weight in category | Weight in overall |
| ------ | ------------------ | ----------------- |
| [Development activity](/wiki/development-activity) | 60% | 12.6% |
| [Release discipline](/wiki/release-discipline) | 40% | 8.4% |
[Development activity](/wiki/development-activity) measures whether code is
being written: push recency, weekly commit cadence over the last year, and
commit volume. [Release discipline](/wiki/release-discipline) measures
whether that work actually reaches users as versioned releases — recency and
cadence of published releases.
Scorecard's `Maintained` and `Signed-Releases` checks are also shared evidence
in these two metrics. This intentionally lets observable maintenance and
release provenance influence both Vitality and Security, with different weights.
The split is deliberate. A repository can show constant commits yet never cut
a release users can adopt; another can ship tidy quarterly releases from a
low-traffic default branch. Healthy projects do both, and the category
rewards exactly that combination.
## Reading the category value
- A **high Vitality with weak Governance** often marks a fast-moving project
carried by one person — cross-check
[maintainer resilience](/wiki/maintainer-resilience).
- A **low Vitality on a mature library** is not automatically fatal: some
foundational packages are genuinely finished and change rarely. The category
reports observable motion; judgement about whether motion is *required*
belongs to the reader.
- When release data is unavailable, release discipline is `null` and the
category renormalizes onto development activity alone — the report's notes
say so (see [the health index](/wiki/health-index)).
## Improving Vitality
- Keep the default branch moving: merge maintained work regularly rather than
batching months of changes.
- Publish versioned releases on a predictable cadence, even for small
changes; recency and rhythm both count.
- If a project is intentionally in maintenance mode, state it in the README —
the record cannot read intent, but downstream users can.
Related: [abandonment](/wiki/abandonment) ·
[rating bands](/wiki/scoring-bands) ·
[methodology versions](/wiki/methodology-versions)
---
# Community & Adoption
> The Community & Adoption category — users, downloads, attention, and a welcoming contributor setup. Weight: 17% of the inspect.software health index.
**Community & Adoption** measures whether a project has users, attention, and
a setup that welcomes contributors. Adoption is evidence: widely installed
software is exercised against more environments, more edge cases, and more
eyes than software nobody runs — and a project set up to receive contributors
converts that attention into maintenance capacity.
The category carries **17% of the overall health index**.
## Metrics in this category
| Metric | Weight in category | Weight in overall |
| ------ | ------------------ | ----------------- |
| [Popularity](/wiki/popularity) | 40% | 6.8% |
| [Community health](/wiki/community-health) | 35% | 5.95% |
| [Ecosystem adoption](/wiki/ecosystem-adoption) | 25% | 4.25% |
[Popularity](/wiki/popularity) reads GitHub attention — stars, forks,
watchers — on a logarithmic scale. [Community health](/wiki/community-health)
is a checklist of the files that make participation possible: README,
license, contributing guide, code of conduct, issue and PR templates.
[Ecosystem adoption](/wiki/ecosystem-adoption) goes past GitHub to the
package registries, where real download volume beats stars as an adoption
signal.
## Reading the category value
- **Registry downloads outrank stars.** Stars measure attention; downloads
measure use. A package with modest stars and a million monthly installs is
more load-bearing than a viral repository nobody depends on.
- **Repositories that publish no package** are not penalized: ecosystem
adoption is `null` for them and the category renormalizes onto the other
two metrics (see [supported ecosystems](/wiki/supported-ecosystems)).
- **Small-but-healthy is visible.** The community-health checklist does not
depend on scale, so a young project with complete contributor
infrastructure reads well even before adoption arrives.
## Improving Community & Adoption
- Complete the participation files: README, LICENSE, CONTRIBUTING, code of
conduct, and issue/PR templates each carry documented weight.
- Publish to the ecosystem's registry and keep the package's repository link
accurate — adoption evidence only counts when the package verifiably points
back to the repository.
- Popularity follows use; the durable lever is making the project easy to
adopt, document, and contribute to.
Related: [growth authenticity](/wiki/growth-authenticity) ·
[rating bands](/wiki/scoring-bands) ·
[the health index](/wiki/health-index)
---
# Sustainability & Governance
> The heaviest category of the inspect.software health index (23%) — bus factor, responsiveness, organizational stewardship, and package upkeep.
**Sustainability & Governance** asks whether a project will survive its
people. Most open-source risk is not technical: it is a lone maintainer
burning out, an issue tracker going quiet, a package abandoned on its
registry while the repository still looks alive. This category measures the
structures that make a project durable.
It is the **heaviest category — 23% of the overall health index** — a
deliberate statement that continuity risk outweighs any single technical
signal.
## Metrics in this category
| Metric | Weight in category | Weight in overall |
| ------ | ------------------ | ----------------- |
| [Maintainer resilience](/wiki/maintainer-resilience) | 30% | 6.9% |
| [Responsiveness](/wiki/responsiveness) | 25% | 5.75% |
| [Stewardship](/wiki/stewardship) | 25% | 5.75% |
| [Package maintenance](/wiki/package-maintenance) | 20% | 4.6% |
[Maintainer resilience](/wiki/maintainer-resilience) measures the bus factor
and contributor concentration. [Responsiveness](/wiki/responsiveness) reads
how issues and pull requests are actually handled.
[Stewardship](/wiki/stewardship) examines who stands behind the repository —
organization or personal account, verified domain, track record.
[Package maintenance](/wiki/package-maintenance) checks that the published
package is current and not deprecated, because registry upkeep is distinct
from GitHub activity.
## Reading the category value
- This category is where **organization backing** influences the index: an
organization signals shared, accountable stewardship that can outlive any
single person. The lift is deliberate, documented, and auditable — see
[stewardship](/wiki/stewardship).
- A strong [Vitality](/wiki/vitality) with weak Sustainability describes a
productive project one departure away from stalling — the classic
single-maintainer profile.
- Metrics with no observable data (no issues yet, no published package) are
excluded and renormalized, never counted as zero.
## Improving Sustainability & Governance
- Grow the maintainer circle: review rights and merge rights for more than
one person move the bus factor — the single heaviest component.
- Keep the issue tracker decided: triage, close, or merge; unresolved volume
reads as risk.
- Move flagship projects from personal accounts to an organization, and
verify the organization's domain.
- Keep registry releases current and never leave a deprecated latest version
standing without a successor.
Related: [organization assessment](/wiki/organization-assessment) ·
[the health index](/wiki/health-index)
---
# Engineering Quality
> The Engineering Quality category — CI, tests, linting, and documentation practice. Weight: 19% of the inspect.software health index.
**Engineering Quality** measures whether baseline engineering and
documentation practices are in place: continuous integration, automated
tests, lint and formatting discipline, and documentation a newcomer can
actually learn from. These are the practices that make change safe — for
human contributors and, increasingly, for
[AI coding agents](/wiki/ai-readiness).
The category carries **19% of the overall health index**.
## Metrics in this category
| Metric | Weight in category | Weight in overall |
| ------ | ------------------ | ----------------- |
| [Engineering practices](/wiki/engineering-practices) | 60% | 11.4% |
| [Documentation](/wiki/documentation) | 40% | 7.6% |
[Engineering practices](/wiki/engineering-practices) is a weighted checklist
of hygiene evidence: CI workflows, a test suite, linter configuration,
pre-commit hooks, and an `.editorconfig`.
[Documentation](/wiki/documentation) measures whether the project explains
itself: README, a documentation directory or site, repository description,
topics, and wiki.
## What this category deliberately measures
The signals are **presence-based**: they confirm the infrastructure exists,
not how good it is. That restraint is intentional — grading test *quality*
or documentation *prose* from the outside would be guesswork presented as
measurement. Presence signals are cheap to verify, hard to argue with, and
already separate disciplined projects from undisciplined ones remarkably
well. Deeper signals (coverage, CI pass rates) are on the
[methodology roadmap](/methodology) and will arrive with a version bump.
## Reading the category value
- A low value here rarely lies: missing CI and missing tests are visible
facts, not judgement calls.
- A high value means the *scaffolding* of quality is present. It does not
certify that the code inside is good — see
[signals, not warranties](/wiki/signals-not-warranties).
- Documentation weighs 40%: a well-tested project that explains nothing to
newcomers is measurably less adoptable, and the category reflects that.
## Improving Engineering Quality
- Add CI that runs the test suite on every push and pull request — the two
heaviest components in [engineering practices](/wiki/engineering-practices).
- Commit linter and formatter configuration; add pre-commit hooks and an
`.editorconfig` for full marks.
- Maintain a real README, a `docs/` directory or documentation site, a
repository description, and topics — each is an individually weighted
component of [documentation](/wiki/documentation).
Related: [AI readiness](/wiki/ai-readiness) ·
[the health index](/wiki/health-index)
---
# Security
> The Security category — visible OpenSSF Scorecard hygiene and known-vulnerable dependencies, under two red-flag policies. Weight: 16% of the inspect.software health index.
**Security** measures visible security and supply-chain practice: dependency
update automation, static analysis, signed releases, least-privilege CI
tokens, known-vulnerable dependencies, security policy, and policy-defined
high-risk jurisdiction exposure.
It answers the question a dependency reviewer actually asks: *does this
project practice security in the open?*
The category carries **16% of the overall health index**. Two metrics combine
as a weighted mean; two red-flag policies carry no additive weight and are
applied to security posture before the category is assembled, so clean
evidence can never lift weak hygiene:
`Security = 0.8 × adjusted_security_posture + 0.2 × dependency_advisories`
## Metrics in this category
| Metric | Weight in category | Weight in overall |
| ------ | ------------------ | ----------------- |
| [Security posture](/wiki/security-posture) | 80% | 12.8% |
| [Dependency advisories](/wiki/dependency-advisories) | 20% | 3.2% |
| [Malicious dependencies](/wiki/malicious-dependencies) | red flag | multiplier and ceiling on posture |
| [High-Risk Jurisdiction Exposure](/wiki/jurisdiction-exposure) | red flag | multiplier and ceiling on posture |
[Dependency advisories](/wiki/dependency-advisories) sits at 20% rather than
higher because well-run projects genuinely do not ship known-vulnerable
dependencies: the metric is near-constant across the record, and a signal that
rarely varies must not outweigh the one that does. Where the dependency graph
or the advisory lookup is unavailable, the metric is excluded and posture
carries the category alone — a repository is never penalized for the gap.
Only the strictest red flag that fires governs the result; since methodology
v1.13.0 the policies no longer compound. A dependency reported as
[malicious](/wiki/malicious-dependencies) is scored apart from ordinary
advisories, because it is a confirmed compromise rather than an exposure to
risk.
The jurisdiction risk signal uses only high-confidence, self-published public
profile evidence within the current Russia, Iran, and North Korea scope.
Ambiguous evidence and missing locations never reduce the score. A confirmed
match creates an enhanced-review priority; it is not an inference of
nationality, citizenship, sanctions status, malicious intent, or individual
trustworthiness. See the full [evidence, scoring, and enterprise interpretation
guide](/wiki/jurisdiction-exposure).
[Security posture](/wiki/security-posture) is backed by the
**OpenSSF Scorecard**, the neutral, versioned security standard maintained by
the Open Source Security Foundation. Each Scorecard check becomes a
component, weighted by Scorecard's own risk level, and checks Scorecard
cannot determine are excluded rather than counted as zero. When the Scorecard
tooling is unavailable, the metric falls back to coarse file-tree signals and
the report says so.
Some Scorecard practices also substantiate another health dimension. Since
methodology v1.0.0, seven selected checks provide small shared-evidence
components in their relevant cards while retaining their full Security weight.
The mappings and category-specific weights are published in
[Security posture](/wiki/security-posture) and
[methodology versions](/wiki/methodology-versions).
## Why tool-agnostic
The methodology deliberately rewards the *practice*, not a vendor's config
file: any accepted dependency-update tool (Dependabot, Renovate, …), any SAST
(CodeQL, Semgrep, …). Projects on non-GitHub tooling are not structurally
penalized — a fairness property inherited from Scorecard and preserved by
excluding inconclusive checks (see
[methodology versions](/wiki/methodology-versions), 0.6.0).
## Reading the category value
△A security value is not a security guarantee. It reflects visible hygiene — it cannot rule out an undiscovered vulnerability, a malicious release, or a compromised account. See
signals, not warranties.
- The full per-check breakdown — every Scorecard check, its score, and its
reasoning — is rendered in each report, with links to Scorecard's own
documentation per check.
- A *critical* Security band on an otherwise healthy project is the classic
case where the overall index must not be read alone: the per-category bands
exist to surface exactly this.
## Improving Security
- Publish a `SECURITY.md` with a disclosure channel.
- Turn on automated dependency updates and a SAST workflow — any accepted
tool counts.
- Grant CI workflows least-privilege tokens, pin dependencies where
appropriate, and sign releases.
- Address known-vulnerable dependencies promptly; that check carries
Scorecard's highest risk weighting.
Related: [security posture](/wiki/security-posture) ·
[dependency advisories](/wiki/dependency-advisories) ·
[malicious dependencies](/wiki/malicious-dependencies) ·
[high-risk jurisdiction exposure](/wiki/jurisdiction-exposure) ·
[the health index](/wiki/health-index)
---
# AI Readiness
> The AI Readiness badge — how well a repository supports AI coding agents: agent context, verify loop, code legibility, machine-readable interfaces.
**AI Readiness** measures how well a repository is equipped to be developed
and maintained **with AI coding agents**: whether an agent arriving in the
codebase finds guidance, can set up and verify its own changes, can read the
code within model constraints, and can discover machine-readable interfaces.
The category carries a **deliberately small weight of 4%** in the overall
health index. Agent tooling has become a real maintenance signal — but the
weight is sized, together with the index's
[calibration curve](/wiki/health-index), so that its absence never gates the
top of the scale: a solid pre-AI-era project with zero AI Readiness signals
can still reach 100/100. A project that invests in agent tooling earns a
visible distinction and a few index points; one that does not is never pushed
out of any band's reach by that fact alone.
## Metrics in this category
| Metric | Weight in category |
| ------ | ------------------ |
| [AI verify loop](/wiki/ai-verify-loop) | 40% |
| [AI agent context](/wiki/ai-agent-context) | 30% |
| [AI code legibility](/wiki/ai-code-legibility) | 15% |
| [AI interfaces](/wiki/ai-interfaces) | 15% |
The [verify loop](/wiki/ai-verify-loop) carries the heaviest weight because
it is the crux of autonomous work: an agent that can bootstrap the project,
run the tests, and check its own change is categorically more useful than one
that cannot. [Agent context](/wiki/ai-agent-context) covers instruction files
(`CLAUDE.md`, `AGENTS.md`, …) and machine-readable docs (`llms.txt`).
[Code legibility](/wiki/ai-code-legibility) measures type-checkability and
manageable file sizes. [Interfaces](/wiki/ai-interfaces) looks for API
schemas, MCP servers, and runnable examples.
## Measurement honesty
Signals are **presence- and size-based** heuristics from the file tree — no
file contents are graded. They show that the infrastructure exists, not how
good it is. Substance is weighted where it is cheap to detect: an
instruction file below ~200 bytes registers as a stub and earns partial
credit, a specific defense against gaming the badge.
Metrics that do not apply produce `null`, never a penalty: a docs-only
repository is not judged on code legibility, and a plain library with no API
surface is not judged on interface schemas.
## Reading the badge
- The badge answers a genuinely new procurement question — *can a team point
agents at this codebase productively?* — that the classic health signals
were never designed to capture.
- At 4% of the raw weight — inside a calibration curve that saturates at raw
91 — AI Readiness can nudge the health index but can neither make nor break
a rating: every band, including a 100/100, remains reachable with the
category at zero.
## Improving AI Readiness
- Add a substantive `CLAUDE.md` or `AGENTS.md` and an `llms.txt`.
- Provide a one-command bootstrap (Makefile, justfile, …), automated tests,
lint config, and type checking — the verify loop.
- Keep source files below ~1,500 lines and adopt type checking.
- Ship OpenAPI/GraphQL/protobuf schemas, an MCP server, or runnable examples
where they fit the project's nature.
Related: [engineering quality](/wiki/engineering-quality) ·
[methodology versions](/wiki/methodology-versions)
---
# Development activity
> How inspect.software measures development activity — push recency, weekly commit cadence, and commit volume. 12.6% of the overall health index.
**Development activity** answers the first question anyone asks of an
open-source dependency: *is code actively being written?* It reads the
repository's push and commit history over the last year and rewards recency,
rhythm, and volume — in that order of weight.
- **Category:** [Vitality](/wiki/vitality) (60% within category)
- **Weight in overall index:** 12.6%
- **Metric key:** `development_activity`
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Push recency | 36 | same thresholds as v0.9.0, scaled to 36 points |
| Commit cadence | 36 | share of the last 52 weeks with at least one commit, × the human-authorship factor |
| Commit volume | 18 | log-scaled; roughly 100 commits per year earns full points, × the human-authorship factor |
| OpenSSF Scorecard: Maintained | 10 | Scorecard's 0–10 result, scaled to 10 points |
The value is the weighted sum, rounded and clamped to 1–100, and maps to a
[rating band](/wiki/scoring-bands). Components without data are excluded and
the remaining weights renormalized (see
[the health index](/wiki/health-index)).
`Maintained` is shared evidence, not a replacement for the scanner's own
commit history: it also remains a full component of
[Security posture](/wiki/security-posture). If Scorecard is unavailable or
marks the check `n/a`, this component is excluded.
## The human-authorship factor
Cadence and volume count commits, and a commit made by a robot counts exactly
like a commit made by a maintainer. A repository whose dependency bot opens and
merges an update every week therefore reads as one under continuous
development.
The newest 100 commits are checked for who authored them, and the two
commit-counting components are multiplied by the human share of that window,
reaching full marks at 40% and above.
Two conditions must hold together. A low human share alone means only that a
project automates heavily, which the best-maintained ones often do — a
59,000-star tool runs roughly three quarters of its commits through a
dependency bot, and a package registry whose product *is* automated version
bumps runs higher still. Both have human commits days old. So the discount also
requires that no human has committed for more than 90 days: it is the silence,
not the automation, that marks a project as sustained by its robots.
The gap is measured inside the commit window itself — the newest commit against
the newest human one — so a stored report always rescores to the same value
rather than drifting as it ages.
It applies no additive weight of its own — it can lower a value, never raise
one — and it is skipped entirely when the commit sample is unavailable or
smaller than 20 commits, so nothing is inferred from too little evidence.
Only automation carrying a GitHub App identity is recognized; a bot operating
under an ordinary user account still counts as a person.
## Why cadence outweighs volume
A repository with a commit every week for a year is more dependable evidence
of maintenance than the same number of commits landed in one burst. Cadence
measures *sustained* attention; volume is log-scaled precisely so that commit
count cannot be inflated into a high value — the difference between 100 and
1,000 yearly commits is small by design.
## Reading the result
- **Recency dominates short-term change.** A project that pauses for six
months loses the recency component first; the cadence component then decays
as inactive weeks accumulate.
- **Genuinely finished software exists.** A stable, feature-complete library
can read low here while remaining safe to use — this is why development
activity is one metric inside a weighted index, not a verdict. Cross-read
with [release discipline](/wiki/release-discipline) and
[responsiveness](/wiki/responsiveness).
- **Monorepos and mirrors:** activity is read from the repository being
inspected; work happening in a different repository does not count.
## Improving the value
- Merge maintained work continuously instead of batching long-lived branches.
- Keep at least a weekly heartbeat of real changes where the project
genuinely needs maintenance — bug fixes and reviewed dependency updates
count, and so do automated updates as long as human work continues
alongside them.
- Avoid empty activity: the log scale on volume makes synthetic commit
inflation nearly worthless, and commits authored by automation are
discounted once they crowd out human ones.
Related: [release discipline](/wiki/release-discipline) ·
[Vitality](/wiki/vitality)
---
# Release discipline
> How inspect.software measures release discipline — whether versioned releases ship, how recently, and on what cadence. 8.4% of the overall health index.
**Release discipline** measures whether a project ships versioned releases —
the mechanism by which work in the repository actually reaches users.
Downstream consumers pin versions, read changelogs, and upgrade on release
boundaries; a project that never cuts releases forces every user onto
unversioned snapshots.
- **Category:** [Vitality](/wiki/vitality) (40% within category)
- **Weight in overall index:** 8.4%
- **Metric key:** `release_discipline`
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Ships releases | 27 | any published releases; same condition as v0.9.0, scaled to 27 points |
| Release recency | 36 | same thresholds as v0.9.0, scaled to 36 points |
| Release cadence | 27 | same thresholds as v0.9.0, scaled to 27 points |
| OpenSSF Scorecard: Signed-Releases | 10 | Scorecard's 0–10 result, scaled to 10 points |
When release data is unavailable the metric is `null` — excluded from
[Vitality](/wiki/vitality) with weights renormalized, never counted as zero.
The Scorecard component is likewise excluded when Scorecard is unavailable or
reports `n/a`; it remains a full Security signal as well.
## Why releases are measured separately from commits
Commit activity and shipping are different disciplines. A repository can show
constant motion on its default branch while users wait a year for a release
containing the fixes; the inverse — calm branches, punctual releases — also
exists. Splitting [development activity](/wiki/development-activity) from
release discipline makes both patterns visible instead of letting one hide
the other.
## Reading the result
- **Recency is the heaviest component.** A project with a strong release
history that stopped releasing eighteen months ago reads materially lower
than one that shipped last quarter.
- **Cadence rewards rhythm, not frequency for its own sake.** A steady
quarterly cycle earns most of the cadence points; the top tier simply
reflects the short iteration loops common in actively developed libraries.
- **GitHub releases are the source.** Projects that tag versions without
publishing releases, or release only through a registry, may read lower
here; registry publish recency is measured separately in
[package maintenance](/wiki/package-maintenance).
## Improving the value
- Publish releases through the repository's release mechanism, not only as
tags.
- Release on a predictable cadence — small, regular releases outscore rare
large ones and serve users better for the same reason.
- After any dormant period, a single fresh release immediately restores the
recency component.
Related: [development activity](/wiki/development-activity) ·
[package maintenance](/wiki/package-maintenance)
---
# Popularity
> How inspect.software measures repository popularity — stars, forks, and watchers on a logarithmic scale. 6.8% of the overall health index.
**Popularity** measures how much adoption and attention a repository has
gathered on GitHub itself: stars, forks, and watchers. Attention is weak
evidence compared to real installation data — but it is universal (every
repository has it, packaged or not) and correlates with the size of the
community that would notice a problem.
- **Category:** [Community & Adoption](/wiki/community-adoption) (40% within category)
- **Weight in overall index:** 6.8%
- **Metric key:** `popularity`
## How the value is computed
All three components are **logarithmically scaled** — each order of magnitude
matters roughly equally, so the difference between 50 and 500 stars counts
about as much as between 500 and 5,000.
| Component | Weight | Saturates around |
| --------- | ------ | ---------------- |
| Stars | 60 | ~5,000 |
| Forks | 25 | ~1,000 |
| Watchers | 15 | ~500 |
A count of 1 or 2 earns no points — a single star or fork is noise rather than
adoption — so each component only begins scoring from 3 upward.
## Stars and forks can be bought
They are the only inputs in the model with no issuer, and they are sold openly
in bulk. Where a repository's collected day-by-day history shows growth that
organic attention does not produce, the
[Inorganic Growth Policy](/wiki/growth-authenticity) discounts the stars and
forks components — by 40% for one confirmed burst, 70% for more. Watchers are
untouched, a clean history never raises the value, and a repository whose
history cannot answer the question is not penalized at all.
## Why the log scale
A linear scale would make the metric a proxy for fame, dominated by a handful
of mega-projects and useless for comparing everything else. The log scale
compresses the top and stretches the middle, where most real dependency
decisions are made. Saturation points mean that beyond ~5,000 stars,
additional attention adds nothing — the metric has answered its question.
## Reading the result
- **Popularity is the weakest form of adoption evidence.** Stars accumulate
and never decay, so old attention lingers. Where the project publishes a
package, [ecosystem adoption](/wiki/ecosystem-adoption) — real download
volume — is the stronger signal, and the category weights reflect that
hierarchy.
- **Forks carry independent information**: they indicate people working with
the code, not just bookmarking it.
- **Low popularity is not a defect.** Young or niche projects read low here
by nature; the metric is 6.8% of the overall precisely so that quality and
governance evidence can outweigh fame.
## Improving the value
There is no direct lever, and that is by design — attention follows
usefulness. The durable path is the same as for
[Community & Adoption](/wiki/community-adoption) generally: make the project
easy to discover, adopt, and contribute to, and publish it where its users
already are.
Related: [ecosystem adoption](/wiki/ecosystem-adoption) ·
[community health](/wiki/community-health)
---
# Community health
> How inspect.software measures community health — README, license, contributing guide, code of conduct, and issue/PR templates. 5.95% of the overall index.
**Community health** measures whether a repository is set up to receive users
and contributors: the standard files that tell a newcomer what the project
is, on what terms it may be used, and how to participate. These files are the
difference between a codebase and a community.
- **Category:** [Community & Adoption](/wiki/community-adoption) (35% within category)
- **Weight in overall index:** 5.95%
- **Metric key:** `community_health`
## How the value is computed
A weighted checklist of the standard files, each present or absent (the
license row can also earn partial credit — see below):
| Component | Weight |
| --------- | ------ |
| README | 22.5 |
| License | 22.5 |
| CONTRIBUTING guide | 18 |
| Code of conduct | 13.5 |
| Issue template | 7.2 |
| PR template | 6.3 |
## How the license is detected
License presence is checked once, from three sources considered together: the
repository's own license metadata, GitHub's community profile, and
[OpenSSF Scorecard](https://github.com/ossf/scorecard)'s published,
tool-neutral `License` check. A file that **any** source sees counts as
present — the sources disagree on roughly 1% of repositories, and a single
unavailable endpoint must not report a license as missing.
The result is one of three states:
| State | Meaning | Credit |
| ----- | ------- | ------ |
| Standard | A recognized license, identified by SPDX code | 22.5 |
| Custom | A license file is present, but its text is not a recognized license | 16.9 |
| None | No source found a license file | 0 |
A **custom license** is a real license and earns most of the weight. It does
not earn all of it: a license 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. GitHub
reports this case as `NOASSERTION` — a license it found but could not
classify, which is not the same as no license at all.
The Scorecard result remains a component of the
[security](/wiki/security-posture) metric; here it is one input among three,
shown simply as `License`.
## Why these files carry weight
- **README and license are load-bearing.** A repository without a README is
unadoptable; a repository without a license is legally unusable in most
organizations — no downstream legal team will approve a dependency whose
terms are undefined. Together they carry half the metric.
- **CONTRIBUTING and a code of conduct** convert drive-by interest into
sustained participation, which feeds directly into the continuity measured
by [maintainer resilience](/wiki/maintainer-resilience).
- **Templates** raise the signal quality of incoming issues and pull
requests, reducing maintainer triage load — a small but real factor in the
[responsiveness](/wiki/responsiveness) a project can sustain.
## Reading the result
- The checklist is scale-independent: a week-old project can reach 100 before
its first star, and a famous project missing a license reads visibly
incomplete. That is intended — this metric measures preparation, not
traction.
- Presence is what is verified, not prose quality — see the measurement
honesty note in [signals, not warranties](/wiki/signals-not-warranties).
## Improving the value
Every component is directly actionable within an hour:
- Write a README covering what the project does, installation, and a minimal
example.
- Add a `LICENSE` file with a recognized SPDX license.
- Add `CONTRIBUTING.md`, a `CODE_OF_CONDUCT.md`, and issue/PR templates under
`.github/`.
This is typically the fastest metric to move in the entire methodology.
Related: [Community & Adoption](/wiki/community-adoption) ·
[documentation](/wiki/documentation)
---
# Ecosystem adoption
> How inspect.software measures real package adoption — registry downloads and dependents across npm, PyPI, Packagist, and more. 4.25% of the overall index.
**Ecosystem adoption** measures how widely a package is actually installed,
using the package registries themselves — npm, PyPI, Packagist, crates.io,
RubyGems, Hex, and the other [supported ecosystems](/wiki/supported-ecosystems).
Real download volume beats GitHub stars as adoption evidence: downloads
measure use, stars measure attention.
- **Category:** [Community & Adoption](/wiki/community-adoption) (25% within category)
- **Weight in overall index:** 4.25%
- **Metric key:** `ecosystem_adoption`
- **Applies to:** repositories that publish at least one package; otherwise `null`
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Monthly downloads | 80 | summed across the repository's packages, log-scaled — ~1,000,000/month saturates |
| Total downloads | 80 | fallback when a registry publishes no monthly figure (e.g. RubyGems); log-scaled, ~50,000,000 all-time saturates |
| Registry dependents | 20 | log-scaled; reported by some ecosystems only, excluded elsewhere |
The download component uses the monthly figure where available and the
lifetime total otherwise — whichever the registry provides, so no ecosystem
is structurally disadvantaged.
## Fairness rules
- **Non-publishing repositories are not penalized.** Applications and
infrastructure projects that ship nothing to a registry get `null` here,
and [Community & Adoption](/wiki/community-adoption) renormalizes onto its
other metrics.
- **Packages must point back.** A registry package only counts when its
metadata verifiably references the inspected repository; mismatched
packages are listed in the report but excluded from the computation.
- **Log scaling** keeps the metric meaningful across the whole range — a
package going from 1,000 to 10,000 monthly downloads moves as much as one
going from 100,000 to 1,000,000.
## Reading the result
- Within its category, this is the strongest adoption evidence available —
stronger than [popularity](/wiki/popularity), which is why a heavily
downloaded but modestly starred package can outread a famous one.
- Download figures vary by registry in meaning (mirrors, CI traffic); the log
scale absorbs most of that noise, and the exact inputs are echoed in every
report for inspection.
## Improving the value
- Publish the package to its ecosystem's registry and keep the repository
link in the package metadata accurate.
- Beyond that, downloads follow genuine use — the honest lever is the
project's usefulness and discoverability, not the metric.
Related: [package maintenance](/wiki/package-maintenance) ·
[supported ecosystems](/wiki/supported-ecosystems)
---
# Maintainer resilience
> How inspect.software measures bus factor, contributor concentration, and breadth — whether a project can survive losing its top maintainer. 6.9% of the index.
**Maintainer resilience** asks the uncomfortable question: *can this project
survive losing its most important person?* The pattern it measures — a
single maintainer carrying essentially all of the work — is the most common
structural failure mode in open source, and it is invisible in commit counts
and stars.
- **Category:** [Sustainability & Governance](/wiki/sustainability-governance) (30% within category)
- **Weight in overall index:** 6.9%
- **Metric key:** `maintainer_resilience`
- **`null`** when the contributor list is unavailable, or when every
contributor turned out to be an automation account
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Bus factor | 54 | v0.9.0 bus-factor curve, scaled to 54 points |
| Commit distribution | 22.5 | `(1 − top contributor's share of human commits) × 22.5` |
| Contributor breadth | 13.5 | `min(13.5, human contributors sampled × 1.35)` |
| OpenSSF Scorecard: Contributors | 10 | Scorecard's 0–10 result, scaled to 10 points |
The **bus factor** is the smallest number of contributors who together
account for the majority of the work — the number of people whose departure
would stall the project.
Every figure here counts **people only**. Automation accounts are removed
before the bus factor, the distribution, or the breadth is derived, because a
release robot cannot inherit a project. The removal is not cosmetic: in
several widely used repositories, dependency bots rank second and third among
all contributors by commit count, and counting them made the maintainer base
look broader and less concentrated than it is. Only automation carrying a
GitHub App identity is recognized, so a bot operating under an ordinary user
account is still counted as a person.
The Scorecard component measures contributing organizations/companies, a
useful complementary signal of institutional resilience. It also remains part
of Security and is excluded here if unavailable or `n/a`.
## Why the curve is shaped this way
The jump from a bus factor of 1 to 2 (10 → 28 points) is the largest single
step in the methodology, because it is the largest real-world risk
reduction: the difference between a project with a single point of failure
and one without. Returns diminish beyond 4–5 — once several people genuinely
share the work, adding more changes little.
Commit distribution complements the bus factor: a project can technically
have five contributors while one person authors 95% of the changes. The
distribution component makes that concentration visible.
## Reading the result
- A **low value on a high-[Vitality](/wiki/vitality) project** is the classic
solo-maintainer profile: productive today, fragile tomorrow.
- Cross-read with [stewardship](/wiki/stewardship) — organization backing
mitigates (but does not remove) the risk this metric measures.
- Contributor data is sampled from the repository's public history. Automation
accounts are reported — the count removed is echoed in the report alongside
the other inputs — but they are excluded from every figure scored here.
- For the displayed top ten contributors, authenticated scans also collect
self-published GitHub profile name, location, company, and public organization
memberships in one batched request. This enrichment is not used in the score
and is withheld from public API and HTML reports; it supports internal
identity-resolution research without changing the bus-factor calculation.
## Improving the value
- Grant review and merge rights to at least one more person — moving the bus
factor from 1 to 2 is the single biggest gain available.
- Actively distribute work: route reviews and releases across maintainers
rather than through one person.
- Convert recurring contributors into maintainers; breadth counts, and the
pipeline starts with [community health](/wiki/community-health).
Related: [stewardship](/wiki/stewardship) ·
[Sustainability & Governance](/wiki/sustainability-governance)
---
# Responsiveness
> How inspect.software measures responsiveness — issue resolution, lifetime pull-request acceptance, and how a project treats first-time contributors. 5.75% of the overall index.
**Responsiveness** measures whether the work arriving at a project — bug
reports, feature requests, contributed patches — actually gets handled. An
issue tracker where reports accumulate unanswered, or a queue of pull
requests closed without engagement, predicts the experience every future
user and contributor will have.
- **Category:** [Sustainability & Governance](/wiki/sustainability-governance) (25% within category)
- **Weight in overall index:** 5.75%
- **Metric key:** `responsiveness`
- **`null`** when the repository has no issues and no decided pull requests
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Issue resolution | 42 | ratio of closed to total issues × 42 |
| PR acceptance | 30 | `merged / (merged + closed unmerged) × 30` |
| Newcomer PR acceptance | 13 | merged share of the pull requests decided in the last 30 days whose author had no previously merged pull request here |
| OpenSSF Scorecard: Code-Review | 15 | Scorecard's 0–10 result, scaled to 15 points |
The first two counts are lifetime totals. Newcomer PR acceptance reads a
30-day window instead; it excludes bot-authored pull requests, and it is
excluded itself — with the remaining weights renormalized — when no first-time
contributor's pull request was decided in that window. It appears only on
reports produced under methodology 2.1.0 or later (see
[methodology versions](/wiki/methodology-versions)). Latency percentiles —
*how fast* issues and pull requests are decided — remain on the published
roadmap.
`Code-Review` is complementary shared evidence: it checks approvals on
changesets, whereas PR acceptance measures merge outcomes. It remains a
Security component and is excluded here if Scorecard is unavailable or `n/a`.
## What the ratios mean
- **Issue resolution** reads the fraction of filed issues that reached a
decision. Projects that triage honestly — fixing, answering, or closing
with a reason — read well; projects where issues silently pile up read
low.
- **PR acceptance** reads what happens to contributed code among pull
requests that reached a decision. A very low merge share often marks a
project that receives contributions but cannot or will not absorb them.
- **Newcomer PR acceptance** reads the same outcome for authors with no
previously merged pull request in the repository. A project can be quick and
generous with its regulars and merge nothing arriving from outside that
circle; the two rates come apart often enough that only this one describes
what a first-time contributor should expect.
## Reading the result
- **Closing is deciding.** The metric does not require that every issue be
fixed — a maintained "wontfix" is a decision. What it penalizes is
unbounded accumulation.
- **Lifetime ratios move slowly.** A project that recently improved its
triage will see this metric recover gradually; the roadmap's time-windowed
latency measures will make recent behavior more visible.
- **A window with no newcomers is not a low score.** Nobody knocking is not
the same fact as nobody being let in, and only the second is the project's
own doing, so the component is excluded rather than scored as zero. The
denominator is newcomers' *decided* pull requests, not their share of all
merges: a mature project where regulars land most of the work is not marked
down for having regulars.
- Repositories with issues disabled and no PR history are `null` here, with
weights renormalized — see [the health index](/wiki/health-index).
## Improving the value
- Triage on a schedule: label, answer, and close stale reports with a stated
reason rather than leaving them open indefinitely.
- Decide pull requests both ways — merging good ones and explicitly declining
unsuitable ones both count as stewardship.
- Templates from [community health](/wiki/community-health) raise incoming
quality and make sustained triage cheaper.
Related: [maintainer resilience](/wiki/maintainer-resilience) ·
[Sustainability & Governance](/wiki/sustainability-governance)
---
# Stewardship
> How inspect.software measures who stands behind a repository — organization vs. personal ownership, verified domain, reach, and track record. 5.75% of the index.
**Stewardship** examines who stands behind a repository. Ownership is a
governance fact with long-term consequences: an organization signals shared,
accountable stewardship that can outlive any single person, while a
personal-account project — however excellent — carries the continuity risk of
its one owner.
This is the one place in the methodology where **organization backing
deliberately influences the health index**, and the lift is documented to the
point.
- **Category:** [Sustainability & Governance](/wiki/sustainability-governance) (25% within category)
- **Weight in overall index:** 5.75%
- **Metric key:** `stewardship`
- **`null`** when the owner profile is unavailable
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Ownership backing | 30 | organization → 30 pts, personal (user) account → 10 |
| Verified domain | 20 | organization with a verified domain → 20, without → 0; **excluded for personal accounts** |
| Owner reach | 25 | followers of the owning account, log-scaled — ~3,000 saturates |
| Track record | 25 | account age (≥6 years → 12 pts) + public repositories (log-scaled → 13 pts) |
For personal accounts the verified-domain component is excluded and weights
renormalize — a person is not penalized for a check that cannot apply to
them. The remaining gap is the ownership-backing margin itself.
## The organization lift, made explicit
A repository moved from a personal account to an organization gains up to 20
points of backing plus access to the verified-domain component. Worked
through the weights, that is the difference between a *moderate* and a *good*
governance profile for many projects — a deliberate, transparent preference
for structures that survive their founders. The full arithmetic is in the
[methodology](/methodology).
## Reading the result
- **Verified domains bind identity.** An organization that verified its
domain has proven control of a real-world identity — meaningful
supply-chain evidence, not decoration.
- **Reach and track record are secondary.** They add texture (an established
account with history versus a fresh one) but cannot substitute for the
structural components.
- The owner profile also records GitHub's self-published location alongside
name, company, website, and avatar. Location is evidence for identity
resolution only and does not affect the stewardship score.
- Stewardship measures the *owner*, not the code — read alongside
[maintainer resilience](/wiki/maintainer-resilience), which measures the
people doing the work.
## Improving the value
- Move flagship projects from personal accounts into a GitHub organization.
- Verify the organization's domain in GitHub settings.
- Maintain a complete organization profile — it also feeds the
[organization assessment](/wiki/organization-assessment) when the org
itself is inspected.
Related: [organization assessment](/wiki/organization-assessment) ·
[Sustainability & Governance](/wiki/sustainability-governance)
---
# Package maintenance
> How inspect.software measures registry upkeep — publish recency, version history, and deprecation state of published packages. 4.6% of the overall index.
**Package maintenance** checks that a project's published package is current,
resolvable, and not deprecated on its registry. Registry upkeep is distinct
from GitHub activity: a library can go stale — or be explicitly marked
abandoned — on npm or Packagist while its repository still sees commits, and
users install the package, not the repository.
- **Category:** [Sustainability & Governance](/wiki/sustainability-governance) (20% within category)
- **Weight in overall index:** 4.6%
- **Metric key:** `package_maintenance`
- **Applies to:** repositories that publish at least one package; otherwise `null`
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Published & resolvable | 25 | at least one of the repository's packages resolves on its registry |
| Publish recency | 35 | latest publish ≤180 days → 35 pts, ≤365 → 26, ≤730 → 14, older → 4 |
| Version history | 20 | ≥5 published versions → 20, ≥2 → 12, otherwise 4 |
| Not deprecated | 20 | deprecated (npm), abandoned (Packagist), or yanked latest → 0; otherwise 20 |
## Why each component matters
- **Resolvable** is the baseline: the package installs from the registry a
user would actually reach for.
- **Publish recency** catches the silent failure where fixes land in the
repository but never ship — the registry copy quietly ages while the
repository looks alive.
- **Version history** distinguishes a maintained release line from a
one-shot publish.
- **Deprecation** is the registry's own strongest signal, set by the
maintainers themselves; a deprecated latest version zeroes the component
outright.
## Reading the result
- Cross-read with [release discipline](/wiki/release-discipline): GitHub
releases and registry publishes usually move together, and divergence
between them is itself informative.
- Only packages whose registry metadata verifiably points to the inspected
repository are counted — see
[supported ecosystems](/wiki/supported-ecosystems) for the matching rule.
- Non-publishing repositories are `null` here and their category
renormalizes — never a penalty for being an application.
## Improving the value
- Publish releases to the registry as part of the release process, not as an
afterthought.
- Keep at least a yearly publish cadence for maintained packages — even a
patch release restores recency.
- Never leave a deprecated or yanked version as the latest; publish a
successor or clear the flag.
Related: [ecosystem adoption](/wiki/ecosystem-adoption) ·
[release discipline](/wiki/release-discipline)
---
# Engineering practices
> How inspect.software measures baseline engineering hygiene — CI, tests, linting, pre-commit hooks, and editorconfig. 11.4% of the overall health index.
**Engineering practices** measures baseline engineering hygiene: the
infrastructure that makes change safe. Continuous integration and an
automated test suite are the two practices with the strongest documented
relationship to sustainable quality, and together they carry most of this
metric.
- **Category:** [Engineering Quality](/wiki/engineering-quality) (60% within category)
- **Weight in overall index:** 11.4%
- **Metric key:** `engineering_practices`
## How the value is computed
A weighted checklist of visible practice evidence:
| Component | Weight | Evidence |
| --------- | ------ | -------- |
| CI workflows | 24 | continuous-integration configuration present |
| Tests present | 24 | a test suite exists in the repository |
| Linter config | 16 | lint/format configuration committed |
| Pre-commit hooks | 9.6 | pre-commit configuration present |
| .editorconfig | 6.4 | editor conventions committed |
| OpenSSF Scorecard: CI-Tests | 20 | Scorecard's 0–10 result, scaled to 20 points |
## Why these five
- **CI plus tests** form the verification loop: every change is exercised
against the suite before it lands. Their combined 60 weight reflects that
no other visible practice substitutes for it.
- **Linting** enforces consistency mechanically, keeping review attention on
substance.
- **Pre-commit hooks and `.editorconfig`** are smaller signals of a project
that has invested in contributor ergonomics — changes arrive pre-checked
and consistently formatted regardless of who wrote them.
The same evidence feeds the [AI verify loop](/wiki/ai-verify-loop): the
infrastructure that lets a human contributor verify a change is exactly what
lets an AI coding agent verify one.
Scorecard's `CI-Tests` is shared evidence: unlike the local presence checks,
it asks whether merged pull requests were checked by CI. It also remains a
full Security component. `n/a` or unavailable Scorecard evidence is excluded.
## Reading the result
- These are **presence signals** — they confirm the scaffolding exists, not
how rigorous it is. Coverage percentages and CI pass rates are on the
[methodology roadmap](/methodology).
- A missing test suite is one of the most reliable negative signals in the
entire methodology; very few disciplined projects lack one.
## Improving the value
- Add a CI workflow that runs the test suite on every push and pull request
— the two heaviest components, often achievable in a single afternoon.
- Commit the linter and formatter configuration the project already uses
locally.
- Add a pre-commit configuration and an `.editorconfig` for the remaining
points.
Related: [documentation](/wiki/documentation) ·
[AI verify loop](/wiki/ai-verify-loop)
---
# Documentation
> How inspect.software measures documentation — README, docs directory, documentation site, description, topics, and wiki. 7.6% of the overall health index.
**Documentation** measures whether a newcomer can learn what a project is and
how to use it. Undocumented software externalizes its cost onto every user;
documented software scales its maintainers' knowledge. For a dependency
decision, documentation is also evidence of care — projects that explain
themselves tend to be projects that maintain themselves.
- **Category:** [Engineering Quality](/wiki/engineering-quality) (40% within category)
- **Weight in overall index:** 7.6%
- **Metric key:** `documentation`
## How the value is computed
A weighted checklist:
| Component | Weight | Evidence |
| --------- | ------ | -------- |
| README | 30 | a README file at the repository root |
| Documentation directory | 25 | a `docs/` (or equivalent) directory |
| Documentation / homepage site | 15 | the GitHub homepage field, or a documentation/homepage URL declared through the package registry |
| Repository description | 10 | the one-line description set on GitHub |
| Topics | 10 | GitHub topics assigned |
| Wiki | 10 | repository wiki enabled |
## The layers, from essential to discoverable
- **README (30)** is the front door; nothing else is read if it is missing.
- **A docs directory (25)** marks documentation that grew past one file —
usually guides, reference, or architecture notes.
- **A documentation site (15)** signals sustained investment: rendered,
navigable docs for users rather than repository visitors. The evidence is
the GitHub homepage field or, failing that, a documentation or homepage
URL the project declares through its package registry — the `documentation`
key in `Cargo.toml` mirrored by crates.io (docs.rs), PyPI's
`project_urls`, RubyGems' `documentation_uri`, Hex's docs links, or the
homepage in `package.json` and its equivalents. A homepage that merely
restates the repository link is not counted.
- **Description, topics, and wiki (30 combined)** are discoverability
metadata: they determine whether the project can be found and classified
at all — by people, package indexes, and increasingly by AI tooling.
## Reading the result
- Presence is what is measured, not prose quality — the honest limit of
external inspection (see
[signals, not warranties](/wiki/signals-not-warranties)).
- Cross-read with [community health](/wiki/community-health): README overlaps
as the shared foundation, but the two metrics answer different questions —
*can it be learned* versus *can it be participated in*.
## Improving the value
- Keep a substantive README: purpose, installation, minimal example, links
onward.
- Move growing documentation into `docs/` and publish it as a site (GitHub
Pages or any generator) — the two steps together carry 40 points.
- Set the repository description and topics; enable the wiki where it fits
the project's workflow.
Related: [community health](/wiki/community-health) ·
[Engineering Quality](/wiki/engineering-quality)
---
# Security posture
> How inspect.software measures security posture with the OpenSSF Scorecard — risk-weighted, tool-agnostic checks with a documented fallback. 16% of the index.
**Security posture** measures visible security hygiene, backed by the
**[OpenSSF Scorecard](https://github.com/ossf/scorecard)** — the neutral,
versioned, tool-agnostic security standard maintained by the Open Source
Security Foundation. It supplies the base value of the
[Security](/wiki/security) category, which carries **16% of the overall index**;
[high-risk jurisdiction exposure](/wiki/jurisdiction-exposure) can only
reduce that base through the published policy multiplier and rating ceiling.
- **Category:** [Security](/wiki/security) (base value before multiplier)
- **Weight in overall index:** 16% before the jurisdiction policy adjustment
- **Metric key:** `security_posture`
## How the value is computed
Each Scorecard check becomes a component, **weighted by Scorecard's own risk
level**:
| Scorecard risk level | Component weight |
| -------------------- | ---------------- |
| Critical | 10 |
| High | 7.5 |
| Medium | 5 |
| Low | 2.5 |
The rolled-up 1–100 value therefore tracks Scorecard's 0–10 aggregate
(`value ≈ aggregate × 10`). Checks Scorecard reports as **inconclusive** —
for example Branch-Protection without an admin token — are **excluded and
renormalized**, never counted as zero. That rule is what keeps well-run
projects on non-GitHub tooling from reading near zero, and it is documented
in [methodology versions](/wiki/methodology-versions) (0.6.0).
Every report renders the full per-check breakdown — score, reasoning, and a
link to Scorecard's documentation for each check.
## Shared evidence
Security keeps the complete risk-weighted Scorecard result. Seven checks also
substantiate other health dimensions. Six provide small, separately weighted
`OpenSSF Scorecard: …` components there: `Maintained`, `Signed-Releases`,
`Contributors`, `Code-Review`, `CI-Tests`, and `Pinned-Dependencies`. The
seventh, `License`, is the sole license signal in
[community health](/wiki/community-health) — shown there generically as
`License`, with a fallback to GitHub's community profile when no Scorecard is
available. This is an intentional cross-category influence, not reuse of
Scorecard's security risk weights. Inconclusive (`n/a`) checks remain excluded
everywhere.
## What the checks reward
The practice, never a vendor's config file:
- **Dependency update automation** — Dependabot, Renovate, or any accepted tool.
- **Static analysis (SAST)** — CodeQL, Semgrep, or equivalent.
- **No known-vulnerable dependencies** — the highest-risk check.
- **Least-privilege workflow tokens**, **pinned dependencies**,
**signed releases**, a **security policy**, and more.
## The fallback path
Running Scorecard requires its CLI; when unavailable, the metric falls back
to coarse file-tree signals, and the report marks the source explicitly
(`inputs.source == "file_signals"`):
| Fallback component | Weight | Note |
| ------------------ | ------ | ---- |
| Security policy (SECURITY.md) | 30 | |
| Dependabot configuration | 25 | |
| Dependency lockfiles | 25 | applications only — libraries conventionally publish without committing a lockfile, so the check is excluded for them. A published package whose manifest declares an executable counts as an application and keeps the expectation (see the [software classification](/wiki/software-classification) and metrics 2.5.0) |
| CodeQL workflow | 20 | |
## Reading the result
△Not a vulnerability scan of the code. A strong value means strong visible practice; it cannot rule out an undiscovered flaw or a compromised account. See
signals, not warranties.
- Compare the aggregate with the per-check table: a middling value with one
failed critical check is a different situation from uniform mediocrity.
- `n/a` rows are inconclusive checks — excluded, not failed.
## Improving the value
- Publish `SECURITY.md`, enable automated dependency updates, and add a SAST
workflow.
- Resolve known-vulnerable dependencies first — highest risk weight, highest
real-world payoff.
- Set explicit least-privilege permissions on CI workflows and pin
third-party actions.
Related: [Security](/wiki/security) ·
[high-risk jurisdiction exposure](/wiki/jurisdiction-exposure) ·
[methodology versions](/wiki/methodology-versions)
---
# Dependency advisories
> How inspect.software matches a repository's resolved dependencies against the OSV advisory database — severity, fix versions, coverage, and the limits of the signal. 20% of the Security category.
**Dependency advisories** asks a narrow, checkable question: do the
dependency versions this repository actually resolves to appear in any
published security advisory?
It carries **20% of the [Security](/wiki/security) category**, alongside
[security posture](/wiki/security-posture) at 80%.
The weight is deliberately modest. Calibration against sixteen widely used
packages found fifteen with no known advisories at all: well-maintained
projects genuinely do not ship vulnerable dependencies, so a clean result here
is the norm rather than a distinction. A signal that is nearly always full
marks must not outweigh the one that actually varies.
## What is measured: what a consumer installs
For a repository that **publishes a package**, the assessed set is that
package's **runtime dependency closure** — every package an installation
actually pulls in, direct and transitive — resolved from the open
[deps.dev](https://deps.dev) index. The report names the exact package and
version assessed.
Only where a repository publishes nothing does the inspection fall back to the
repository's **own dependency graph**, computed by the hosting platform from
committed manifests and lockfiles. That graph is a different thing: it also
contains development and test pins, which no installer ever downloads. Reports
in this scope say so.
Runtime closures are currently resolvable for **npm, PyPI, crates.io and
Maven** packages. Repositories publishing to Go, NuGet, RubyGems, Packagist or
Hex are assessed against their repository graph until the index covers them —
a limit of the data source, not a judgement about those ecosystems.
The distinction is not academic. Flask's repository graph contains old
versions of Werkzeug and Jinja that the project deliberately pins to test
against; they carry advisories, and none of them reaches anyone who installs
Flask. The published closure is six packages, none affected. Measuring the
first would report on Flask's test matrix while appearing to report on Flask.
Either set is matched against **[OSV](https://osv.dev)**, the open advisory
database maintained by the Open Source Security Foundation, which aggregates
GitHub Security Advisories, PYSEC, RUSTSEC, Go's vulnerability database and
others behind one schema. OSV is free, public, and versioned — the same
properties that make the Scorecard a defensible backbone for
[security posture](/wiki/security-posture).
The same query also returns packages reported as **malicious**. Those are not
vulnerabilities and are not counted here: they carry no severity and no fixed
version, and are reported and scored separately as
[malicious dependencies](/wiki/malicious-dependencies). A package appearing
there does not also appear in the counts on this page.
## What is reported
For each affected package: the resolved version, whether it is a direct or an
indirect dependency, the worst severity across its advisories, how many
advisories apply, their identifiers, and — where the advisory states one —
**the version the problem was fixed in**.
Severity comes from the advisory database's own label. Records that carry no
severity, common for PYSEC entries, are reported as *unknown* rather than
assigned a guessed value.
## How it scores
Three components:
| Component | Weight |
| --------- | -----: |
| Direct dependencies free of known advisories | 35 |
| Indirect dependencies free of known advisories | 25 |
| No advisories left outstanding | 40 |
Direct dependencies weigh more than transitive ones because they are the
project's own declared choice; transitive ones arrive with them.
**Severity is the published CVSS base score**, not a coarse label. Each
affected package contributes its score on a 0–1 scale. The database's own
`critical`/`high`/`moderate`/`low` wording is used only where an advisory
publishes no CVSS vector.
Within the first two components the **single worst finding dominates**, and
the remaining volume matters progressively less. One critical-severity
dependency costs about three quarters of its component; eight low-severity
ones cost about a third. That ordering is deliberate — a hundred trivial
advisories are not equivalent to one critical — and the volume term never
drives a component to zero, so a project with 300 findings still scores below
one with 30 rather than tying with it.
The third component asks a different question: **how long has the fix been
available?** Being hit by an advisory published last week is bad luck. Still
resolving to a version affected by one published a year ago is a failure to
track dependencies. A package counts here once its oldest advisory passes
90 days. Where no advisory carries a publication date the component is
excluded and its weight renormalized, never assumed clean.
A dependency set with no known advisories scores full marks on all three.
## Coverage is stated, never assumed
Some entries in a dependency graph carry no recorded version. A package
without a version cannot be matched against a version range, so it is skipped
and **counted** — every report states how many dependencies were assessed and
how many were not.
Repositories whose dependency graph is unavailable or switched off are not
penalized. The metric is excluded and the remaining Security weight
renormalized, exactly as with any other unavailable input — see
[the health index](/wiki/health-index).
## What this does not claim
An advisory here means one thing precisely: **the version recorded in the
dependency graph falls inside an advisory's affected range.**
It does not mean the vulnerable code path is reachable from this project, and
it does not mean the project is exploitable. Most advisories in a large
transitive closure are not exploitable in context.
Where a report falls back to the repository's own dependency graph — because
the repository publishes no package — it cannot separate what the project
ships from what it uses to build and test itself. Those reports say which
scope they used, and their findings should be read as being about the
repository's development environment as much as its software.
Read alongside [signals, not warranties](/wiki/signals-not-warranties): a
clean result is not a security guarantee, and a finding is a prompt to look,
not a verdict.
## Why it is separate from security posture
The Scorecard's own vulnerabilities check queries the same advisory database
and already contributes to [security posture](/wiki/security-posture).
Scoring a second signal derived from OSV inside that same metric would count
one body of evidence twice.
Keeping them apart also keeps them honest about their different granularity.
Security posture asks whether a project carries known-vulnerable dependencies
at all, as one check among nineteen. This metric asks which packages, at what
severity, and fixed in which version — the form an answer has to take before
anyone can act on it.
Related: [Security](/wiki/security) ·
[security posture](/wiki/security-posture) ·
[malicious dependencies](/wiki/malicious-dependencies) ·
[supported ecosystems](/wiki/supported-ecosystems) ·
[signals, not warranties](/wiki/signals-not-warranties)
---
# AI agent context
> How inspect.software measures agent guidance — CLAUDE.md, AGENTS.md, Cursor rules, Copilot instructions, llms.txt, and whether the commit history states its intent. Part of the AI Readiness badge.
**AI agent context** measures whether a repository gives AI coding agents
guidance and machine-readable documentation. An agent dropped into an
unfamiliar codebase faces the same problem as a new hire — except it reads
the onboarding material in milliseconds, every session. Projects that write
that material down get measurably better agent output.
- **Category:** [AI Readiness](/wiki/ai-readiness) (30% within category)
- **Weight in overall index:** 1.2%
- **Metric key:** `ai_agent_context`
## How the value is computed
| Component | Weight | Evidence |
| --------- | ------ | -------- |
| Agent instructions | 45 | `CLAUDE.md`, `AGENTS.md`, `.cursor/rules`, Copilot instructions, `GEMINI.md`, or equivalent; a file below ~200 bytes registers as a stub and earns partial credit |
| Machine-readable docs | 15 | `llms.txt` or `llms-full.txt` present |
| Legible commit history | 40 | share of human commits that state their intent; full marks from 75% upward |
## Why the commit history counts
Written guidance is a file someone had to decide to create, and most projects
never have. The commit history is different: every project produces one
already, and an agent consults it before changing unfamiliar code — to learn
why the surrounding decisions were made, not just what the code does.
A commit counts as stating its intent when its subject is structured — in
conventional-commit form, or referencing the issue or pull request behind the
change — **or** when its body explains the change rather than restating the
subject. Either form qualifies, because either requirement alone would be
parochial: the Linux kernel writes no conventional prefixes and almost always
explains itself, while other projects run a fully conventional history with
one-line messages. Both are legible; both count.
Commits made by automation are excluded, since machine-generated subjects are
uniformly well-formed and say nothing about the project's own practice.
## What good agent context contains
An effective instruction file tells an agent what the README tells a human,
plus what only maintainers know: how to build and test, which directories
matter, project conventions, and the traps ("the container serves built
images — rebuild after editing"). The `llms.txt` convention complements it by
giving language models a curated index of the project's documentation.
The stub rule exists because presence signals can be gamed: an empty
`CLAUDE.md` created for the badge is detectably different from a real one,
and the methodology weights substance where it is cheap to detect.
## Reading the result
- Signals are presence- and size-based from the file tree; content is not
graded — the honest limit stated across the
[AI Readiness](/wiki/ai-readiness) category.
- Any of the recognized instruction conventions counts; the methodology is
vendor-neutral across agent tooling, mirroring the tool-agnostic stance of
[security posture](/wiki/security-posture).
## Improving the value
- Write a substantive `CLAUDE.md` or `AGENTS.md`: build and test commands,
layout, conventions, and known pitfalls. Keep it current — it is
documentation with an executable audience.
- Add an `llms.txt` indexing the project's documentation for language-model
consumption.
- Reference the issue or pull request in commit subjects, or explain the
change in the body. Both are ordinary review discipline; both leave the
history readable by whoever — or whatever — maintains the project next.
Related: [AI verify loop](/wiki/ai-verify-loop) ·
[AI Readiness](/wiki/ai-readiness)
---
# AI verify loop
> How inspect.software measures the agent verify loop — one-command bootstrap, tests, lint, type checking, reproducible environments. The heaviest AI Readiness metric.
**AI verify loop** measures whether an AI coding agent can set up the
project, run it, and verify its own change without human help. This is the
crux of autonomous agent work — an agent that can check its work compounds;
one that cannot merely generates plausible text — and it carries the
heaviest weight in the [AI Readiness](/wiki/ai-readiness) badge.
- **Category:** [AI Readiness](/wiki/ai-readiness) (40% within category)
- **Weight in overall index:** 1.6%
- **Metric key:** `ai_verify_loop`
## How the value is computed
| Component | Weight | Evidence |
| --------- | ------ | -------- |
| One-command bootstrap | 18 | Makefile, Taskfile, justfile, mise, or noxfile earns full credit; a toolchain that defines the command itself (`Cargo.toml`, `go.mod`, `mix.exs`, Maven, Gradle, `.csproj`) earns most of it |
| Automated tests | 22 | a test suite the agent can run to self-check (shared with [engineering practices](/wiki/engineering-practices)) |
| Lint / format config | 11 | shared with the engineering linter signal |
| Static type checking | 11 | a statically typed language, or a type-check configuration (mypy, pyright, tsconfig, `py.typed`) |
| Reproducible environment | 10 | devcontainer, Dockerfile, Nix, or a dependency lockfile |
| Demonstrated agent practice | 10 | share of recent commits authored or co-authored by a coding agent; full marks from 5% upward |
| Automated maintenance | 8 | dependency-update bot commits observed in the sample; a configuration with nothing observed earns partial credit |
| OpenSSF Scorecard: Pinned-Dependencies | 10 | Scorecard's 0–10 result, scaled to 10 points |
`Pinned-Dependencies` is shared evidence: it adds supply-chain reproducibility
information to the agent verification loop while remaining a full Security
component. It is excluded when Scorecard is unavailable or reports `n/a`.
## Evidence, not only equipment
Every other component here reads the repository's files: a task runner exists,
a lockfile exists. Each is a proxy for a loop nobody has watched run.
Commits authored by a coding agent — or credited to one in a `Co-authored-by`
trailer — are the one available record that the loop was actually closed. A
change was proposed, verified, and merged with an agent in the loop, and the
project's own history says so.
A dependency bot's pull request is machine-authored too, and it must clear the
same gates: the tests run, the checks pass, it merges. A project already
absorbing that traffic has shown the pathway an agent needs, which is why
**automated maintenance** is scored beside agent practice rather than folded
into it — either can be present without the other.
What counts is the observed commits, not the configuration file. A
`dependabot.yml` can sit in a repository with the integration switched off, and
Renovate is commonly configured outside the repository altogether: two widely
used projects run it across roughly a third of their commits while carrying no
recognizable config file at all. Only bots that author their own content
qualify — a robot that merges other people's work is not writing changes.
The same commits count *against* a repository in
[development activity](/wiki/development-activity), where automation crowding
out human work is a warning sign. That is deliberate. The two metrics ask
different questions: whether people still maintain a project, and whether
machines can contribute to it. Both answers can be true at once.
This evidences **adoption, not autonomy**. A maintainer working interactively
with an agent leaves the same trace as an unattended run, and public data
cannot tell the two apart, which is why the component carries a modest weight
and makes no claim about how much of the work the agent did. Detection also
recognizes only the agents it knows about, so a project using an unrecognized
tool simply reads as having no evidence — never as failing.
The component is excluded rather than scored as zero when no commit sample was
collected.
## Why the toolchain counts as a bootstrap
`cargo test` and `go test ./...` are the canonical verify loops of their
languages. Crediting only task runners charged those ecosystems for having
better defaults — well-run Rust projects scored zero on this component for
shipping no Makefile. `package.json` and `pyproject.toml` are deliberately not
credited: npm and Python define no universal test command, and whether a given
project defines one lives inside file contents this metric does not read.
## Why this loop decides agent usefulness
Each component removes one failure mode of autonomous work:
- **Bootstrap** — the agent can go from clone to running without archaeology.
- **Tests** — the agent can prove a change did what was intended.
- **Lint and types** — entire classes of error are caught mechanically,
before review.
- **Reproducible environment** — "works in the agent's sandbox" means works
elsewhere too.
Notably, this is the same infrastructure that serves human contributors —
the metric rewards no agent-specific exotica beyond what a disciplined
project already has. A strong [Engineering Quality](/wiki/engineering-quality)
project typically starts strong here.
## Reading the result
- Signals confirm the loop's *existence*, not its speed or coverage — the
presence-based honesty rule of the whole badge.
- A high verify loop with a stub
[agent context](/wiki/ai-agent-context) usually means a well-engineered
project that simply has not written agent guidance yet — the cheapest
possible improvement.
## Improving the value
- Add a Makefile (or justfile/Taskfile) exposing `install`, `test`, and
`lint` targets.
- Keep an automated test suite runnable locally in one command.
- Adopt type checking — even a minimal mypy/tsconfig counts.
- Commit a lockfile, Dockerfile, or devcontainer for environment
reproducibility.
- Where agents are already used, keep the `Co-authored-by` trailer the tools
add by default. Stripping it removes the only public evidence that the loop
closes in practice.
Related: [AI code legibility](/wiki/ai-code-legibility) ·
[engineering practices](/wiki/engineering-practices)
---
# AI code legibility
> How inspect.software measures code legibility for AI models — type-checkable code and manageable file sizes. Part of the AI Readiness badge.
**AI code legibility** measures whether a codebase is legible to a language
model: whether the code carries machine-checkable type information and
whether files fit comfortably in a model's working context. The same
properties that help a human navigate an unfamiliar codebase help a model —
but for models, oversized files are a hard constraint rather than an
annoyance.
- **Category:** [AI Readiness](/wiki/ai-readiness) (15% within category)
- **Weight in overall index:** 0.6%
- **Metric key:** `ai_code_legibility`
- **`null`** for repositories with no detectable source files — docs-only projects are not penalized
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Type-checkable code | 45 | statically typed language → 45 pts; dynamically typed with a type-check configuration → 27; neither → 0 |
| Manageable file sizes | 55 | `(1 − oversized / total) × 55`, where a source file over ~60 KB (~1,500 lines) counts as oversized; vendored and generated paths are excluded |
## Why these two signals
- **Types are compressed documentation.** A typed signature tells a model
what a function accepts and returns without reading its body — and a
type-checker turns the model's misunderstandings into immediate, mechanical
errors instead of latent bugs. Partial credit for dynamically typed
projects with a checker (mypy, pyright, tsconfig) reflects that gradual
typing captures much of the benefit.
- **File size distribution** determines whether a model can hold a unit of
code in context whole. A codebase of focused modules can be read
piecewise; a 5,000-line file forces truncation, and truncation is where
agent errors concentrate.
Vendored and generated code is excluded so that a committed `vendor/` tree or
generated bindings do not distort the measurement.
## Reading the result
- The metric reads structure, not style — naming, comments, and
architecture are not graded (see the honesty rules in
[AI Readiness](/wiki/ai-readiness)).
- The file-size component is proportional: one oversized file among fifty
costs little; a codebase of monoliths reads accordingly.
## Improving the value
- Adopt a type checker; in dynamic languages, even a permissive initial
configuration earns the partial credit and creates the ratchet.
- Split files approaching ~1,500 lines along their natural seams.
- Keep generated and vendored code in conventionally named paths so it is
excluded from measurement.
Related: [AI verify loop](/wiki/ai-verify-loop) ·
[AI interfaces](/wiki/ai-interfaces)
---
# AI interfaces
> How inspect.software measures machine-readable interfaces — API schemas, MCP servers, and runnable examples. Part of the AI Readiness badge.
**AI interfaces** measures whether a project exposes machine-readable
interfaces: formal API schemas, a Model Context Protocol server, or runnable
examples. Where they exist, an AI agent can consume the software through a
contract instead of reverse-engineering behavior from source.
- **Category:** [AI Readiness](/wiki/ai-readiness) (15% within category)
- **Weight in overall index:** 0.6%
- **Metric key:** `ai_interfaces`
- **`null`** when the repository exposes none of the signals — absence is treated as not-applicable, never as a penalty
## How the value is computed
| Component | Weight | Evidence |
| --------- | ------ | -------- |
| API schema | 40 | OpenAPI/Swagger, GraphQL SDL, protobuf, or AsyncAPI files |
| MCP server | 20 | a Model Context Protocol server dependency or `mcp.json` configuration |
| Runnable examples | 40 | `examples/`, `recipes/`, or `samples/` directories, or notebooks |
## The null rule, explained
A plain utility library legitimately has no API schema, no MCP surface, and
possibly no examples directory — and it would be wrong to mark it down for
its nature. The metric therefore only produces a value when at least one
signal is present; otherwise it is `null` and the
[AI Readiness](/wiki/ai-readiness) category renormalizes onto its other
metrics, following the methodology-wide missing-data rule
(see [the health index](/wiki/health-index)).
## Why these three signals
- **API schemas** are contracts a model can read exactly — endpoints, types,
and errors without inference.
- **An MCP server** is the strongest possible statement of agent readiness:
the project ships a first-class interface for AI tooling.
- **Runnable examples** are executable documentation. For an agent, a
working example is a verified starting point rather than prose to
interpret — and examples double as a de-facto test of the public API.
## Improving the value
- Publish the API schema the project already implies: generate OpenAPI from
the framework, commit the `.proto` or GraphQL SDL files.
- Maintain an `examples/` directory with small, runnable programs kept
current in CI.
- Where the project naturally serves tooling, consider shipping an MCP
server.
Related: [AI agent context](/wiki/ai-agent-context) ·
[AI Readiness](/wiki/ai-readiness)
---
# Abandonment
> How inspect.software decides a project has been left unmaintained — why silence alone is never the finding, what counts as an unmet obligation, and what holds the assessment back.
Every tool in this field answers the question with one number — days since the
last commit — and every one of them is wrong about the same projects. A small,
complete library that has needed no changes in three years is not abandoned. It
is finished. Marking it dead costs a record its credibility precisely on the
software that deserves the most confidence.
So silence is never the finding here. The assessment rests on a different
proposition:
> Abandonment is an unmet obligation, not an absence of noise.
A project incurs obligations when work arrives from outside it — a pull request
that wants review, an issue that wants an answer, a published fix for a
vulnerability in something it ships. A quiet project with no such demands owes
nobody anything and cannot be failing them. A quiet project with fifteen pull
requests nobody has looked at in two years, and a year-old advisory whose patch
shipped the same week, is not resting.
- **Category:** [Vitality](/wiki/vitality) (0% within category)
- **Effect:** a multiplier on the overall rating, and a ceiling in the severest
states
- **Metric key:** `abandonment`
## What the assessment reads
**Declared.** The maintainer said so. GitHub's archive flag, or a registry
deprecation covering every package the repository publishes. Nothing is
inferred and nothing needs corroborating — the record is quoting its subject.
**Drought.** No *human* commit for a long time. Deliberately not the repository's
push recency, which counts a dependency bot's version bump as a sign of life:
projects whose only activity for a year was automated updates report a last
push measured in days. Commit authorship is read per commit, and automated
authors are excluded. Drought is a necessary condition and never a finding on
its own.
**Unmet obligations.** The corroborating signals — pull requests left
unanswered, issues left unanswered, a published fix left unapplied, releases
stalled, continuous integration broken, a sole maintainer absent, or OpenSSF
Scorecard independently reporting the project unmaintained. Each is a duty the
project is visibly not discharging.
**Guards.** Evidence that someone is still there, or that nothing is being
asked of them: a maintainer still replying, nothing open to answer, a release
within the year, no affected dependency. Two guards hold the result short of a
finding however many obligations fired, because both readings — "someone is
answering" and "nobody is asking" — fully explain the silence.
## What the states mean
| State | Meaning |
| ----- | ------- |
| `maintained` | Human work is recent; no finding |
| `unverified` | The collected evidence cannot answer the question |
| `dormant` | Quiet, but explained — held there by guards, or nothing is owed |
| `abandoned` | Drought plus unmet obligations, uncontested |
| `declared` | The maintainer archived it or deprecated its packages |
Anything the data cannot answer is `unverified` and costs the repository
nothing. An unauthenticated scan reads no commit sample and no tracker queues,
so it can reach no conclusion — recorded as an absence of evidence rather than
evidence of absence.
## Reading the result
- **The alert names its evidence.** The drought length is stated with the
obligations beside it, so the finding can be checked rather than trusted.
- **The drought may be a floor.** The commit sample is bounded; when it holds no
human commit at all, the true gap predates the window and is reported as "at
least" that long.
- **A finding is not a verdict on the maintainers.** Projects are abandoned for
ordinary reasons — jobs change, interest moves, people fall ill. The record
states what a consumer would find, not why.
- **Automation does not rescue a project here, and does not condemn it
either.** Bot commits are excluded from the drought calculation, so a
repository kept warm by a dependency bot reads as quiet as it truly is. Heavy
automation beside recent human work is not a signal at all — see
[development activity](/wiki/development-activity).
## Improving the value
- Answer what is open, or close it. An unanswered queue is the single strongest
contributor to a finding.
- Apply published security fixes to dependencies, or state why they do not
apply.
- If the project is finished rather than abandoned, say so — archiving it, or
marking its packages deprecated, replaces an inference with a fact.
Related: [development activity](/wiki/development-activity) ·
[maintainer resilience](/wiki/maintainer-resilience) · [Vitality](/wiki/vitality)
---
# Malicious dependencies
> How inspect.software identifies dependencies reported as malicious packages by the OpenSSF corpus, why they are scored apart from vulnerabilities, and what the finding does and does not claim.
A vulnerable dependency is a mistake. A **malicious** dependency is an attack.
They are not the same finding, and this record does not score them the same
way.
**Malicious dependencies** asks one question: does the dependency graph this
repository resolves to contain a package that has been reported as malware?
## Where the evidence comes from
The source is the OpenSSF
[malicious-packages](https://github.com/ossf/malicious-packages) corpus — an
openly licensed, community-maintained record of packages found to be malicious
across public registries: typosquats, account takeovers, dependency-confusion
attacks, and packages shipping prebuilt malicious binaries.
[OSV.dev](https://osv.dev) ingests that corpus and serves it under `MAL-`
identifiers alongside ordinary security advisories. Because this record already
queries OSV for [dependency advisories](/wiki/dependency-advisories), malicious
packages arrive on a query that was already being made. The finding costs no
additional request, no additional wait, and no additional dependency on a third
party.
## Why it is scored apart from advisories
Until methodology v1.10.0 these reports were counted as ordinary advisories,
and that was wrong in a way worth stating plainly.
A malicious-package report carries no CVSS vector and no severity label — there
is nothing to score, because malware has no severity, only a state. Scored as
an advisory it fell through to `unknown` severity, which is weighted like a
*moderate* vulnerability. A package that had been found to steal credentials
counted for slightly less than an average CVE.
The three properties that make a vulnerability scoreable are all absent:
- **No fixed version.** There is no corrected release of the same artifact to
upgrade to. The remedy is removal, or moving off the compromised name.
- **No partial exposure.** A vulnerability may sit in an unreachable code path.
An install-time payload runs when the package is installed.
- **No degrees.** A package either is or is not reported as malicious.
So a malicious dependency is now removed from the advisory findings entirely
and treated as a **red flag**: a multiplier and a ceiling rather than points
off. It applies a 35% multiplier to the [security
posture](/wiki/security-posture) score and to the calibrated health index, and
caps both at **19 — the top of the Critical band**. That is stricter than the
[high-risk jurisdiction](/wiki/jurisdiction-exposure) ceiling of 34, because
this is a confirmed compromise of the software rather than an exposure to a
risk.
A package carrying both a malicious report and ordinary CVEs appears only under
this finding. Its vulnerabilities are moot.
## Withdrawn artifacts are reported, not scored
A registry that removes a malicious package settles the question: nothing
installable remains, and a repository that resolves to it is not shipping
malware today. Every finding therefore checks whether the registry still serves
that **exact resolved version**. Where it does not, the finding stays on the
report — the project depends on a name that was compromised, which is worth
seeing — but it raises no flag and costs no points.
The check deliberately asks about the resolved version rather than the
package's latest one. After a takedown npm leaves a placeholder release, marked
`-security`, as the package's latest. That protects everyone who resolves a
version range, and nobody who pinned the bad version exactly. Reading the
latest version would have cleared the first repository this finding ever fired
on, which pins the compromised package at the precise version the registry
still serves.
Where the question cannot be answered — an ecosystem the check does not cover,
or a registry that did not respond — the finding is scored as though the
package were live. Failing to reach a registry is not evidence that malware was
withdrawn.
## Direct and indirect count alike
Most of this record's dependency scoring distinguishes a declared direct
dependency from one pulled in transitively, because a maintainer chose the
first and inherited the second.
That distinction does not apply here. A package's install script runs at
whatever depth it sits in the resolved graph; a credential stealer four levels
down compromises the machine exactly as thoroughly as one named in the
manifest. Both are reported, both are scored, and the report states which is
which so a reader can see where the package entered.
## What the finding does not claim
**It is not an accusation against the maintainers.** The report concerns the
package *as published* by whoever published it. A repository resolves to
thousands of packages it never inspected; inheriting a compromised one is the
normal way this happens, and it says nothing about the intent or competence of
the people maintaining the scanned repository.
**It is not a claim the code was executed.** The finding says the resolved
dependency graph contains the package. Whether anyone installed that exact
graph, and what the payload did if they did, is outside what a public record
can observe.
**It is not our determination.** The classification is the OpenSSF corpus's,
reached through its own process and its own sources, and this record reports it
rather than reproducing it. A report withdrawn upstream disappears from the
next scan.
## How often it fires
Rarely — by design and by measurement. Before this metric shipped it was run
over a 300-repository sample covering 46,889 resolved dependencies, and it
found nothing.
That is the expected result, and it is not a sign the check is useless.
Registries pull malicious packages within hours to days of discovery, so a
lockfile that still resolves to one is unusual. The value of this finding is
not that it fires often; it is that when it does fire, it is the single most
important fact in the report, and it will no longer be averaged into a
vulnerability score.
## When it is not assessed
Like [dependency advisories](/wiki/dependency-advisories), this metric is
excluded — not scored zero — whenever the dependency graph or the OSV lookup
was unavailable. A repository is never penalized for having GitHub's dependency
graph switched off; the report says the check did not run instead of implying a
clean result.
Related: [Security](/wiki/security) ·
[dependency advisories](/wiki/dependency-advisories) ·
[security posture](/wiki/security-posture) ·
[the health index](/wiki/health-index) ·
[supported ecosystems](/wiki/supported-ecosystems)
---
# High-Risk Jurisdiction Exposure
> How inspect.software turns public repository-profile evidence into an explainable high-risk jurisdiction exposure signal for repository review.
Open source lets an organization inherit extraordinary capability in minutes.
It can also create a governance blind spot: a small number of external accounts
may shape software that sits deep inside products, infrastructure, and customer
environments, while the consuming organization knows little about the
repository's operating context.
**High-Risk Jurisdiction Exposure** helps close that gap. It is an
explainable review signal derived from high-confidence, self-published public
profile locations associated with a repository owner, displayed top
contributors, and public organizations shown on those contributor profiles.
When the evidence matches the current policy scope, the report makes the
exposure prominent and adjusts both Security and the overall rating so that
strong popularity or engineering practice cannot average it away.
The result answers a narrow but useful enterprise question:
> **Does this repository present high-risk jurisdiction exposure that
> should receive enhanced human review?**
It does not answer whether a person is trustworthy. It is not an inference of
nationality, citizenship, residence, political belief, malicious intent, or
sanctions status.
## Why this belongs in software supply-chain governance
Enterprise dependency decisions extend beyond code quality. Procurement,
security, legal, resilience, and public-sector teams may need to consider:
- sanctions and export-control screening obligations;
- government or customer restrictions on software origin and stewardship;
- state-linked cyber-threat models and enhanced provenance requirements;
- continuity risk if access, payments, hosting, or release infrastructure is
disrupted by regional restrictions or disruptions;
- concentration risk when a critical dependency relies on a small external
stewardship community; and
- the need to explain why a package was accepted, monitored, isolated, forked,
or replaced.
Without a systematic signal, these questions are handled late and
inconsistently. A visible, versioned policy result turns them into a repeatable
review decision rather than an improvised search during procurement or an
incident.
## Current policy scope
The policy covers public profile evidence for **Russia, Iran, and North
Korea**. Scope membership is not an editorial choice: a country is in scope
only when it passes **both** of two institutional tests at once.
1. **Broad, multilateral sanctions and export-control exposure.** The country
is subject to country-level restrictive regimes maintained in parallel by
the [US Treasury sanctions programs](https://ofac.treasury.gov/sanctions-programs-and-country-information),
[EU restrictive measures](https://www.sanctionsmap.eu/), and the
[UK sanctions regimes](https://www.gov.uk/government/collections/uk-sanctions-regimes-under-the-sanctions-act)
— not merely entity-level designations. Within the scope, North Korea
additionally carries
[UN Security Council sanctions](https://main.un.org/securitycouncil/en/content/un-sc-consolidated-list),
and Iran and North Korea are the two jurisdictions under a standing
[FATF call for countermeasures](https://www.fatf-gafi.org/en/countries/black-and-grey-lists.html).
2. **Officially named state cyber-threat activity.** The country is named by
Western cyber authorities as a source of state-sponsored operations against
technology and supply chains.
[CISA's advanced persistent threat program](https://www.cisa.gov/topics/cyber-threats-and-advisories/advanced-persistent-threats)
maintains standing nation-state guidance for exactly four states — China,
Russia, Iran, and North Korea — and the
[ODNI Annual Threat Assessment](https://www.dni.gov/index.php/newsroom/reports-publications)
and the [UK NCSC](https://www.ncsc.gov.uk/) name the same four as the
principal state cyber actors.
The intersection of the two tests is exactly the published scope, and it is
what keeps the scope narrow in both directions. A country that passes only one
test stays out: China is named on every state cyber-threat list but is not
under broad country-level sanctions; Belarus, Cuba, Syria, and Venezuela carry
sanctions exposure of varying breadth but are not named by these cyber
authorities as sources of state supply-chain operations. Because both tests
reference public institutional lists, the scope can be independently
re-derived — and it changes only when those lists change, through a versioned
methodology update.
This is a **versioned supply-chain policy**, not a ranking of nationalities or
a claim that every organization faces identical obligations. A country-level
location match and an identity-level sanctions match are fundamentally
different signals. inspect.software currently implements the former; it does
not claim to perform legal sanctions screening.
## What the scanner evaluates
The scanner reuses public profile data already collected for:
1. the repository owner account;
2. the displayed top contributors, identified from contribution history—not
from private GitHub maintain or admin permissions; and
3. public organization affiliations shown on those contributor profiles.
Organization locations are selected inside the same batched GitHub GraphQL
request. Classification then runs offline against a compact
[GeoNames](https://download.geonames.org/export/dump/) gazetteer. The check adds
no GitHub request and no external identity-enrichment service.
Only the strongest confirmed evidence determines the multiplier:
| Strongest confirmed evidence | Policy multiplier | Interpretation |
| --- | ---: | --- |
| Repository owner profile | 20% | Direct owner-account exposure; enhanced review has highest priority |
| Displayed top-contributor profile | 50% | Material contribution-history exposure; no claim of repository permission |
| Contributor's public organization profile | 75% | Public affiliation context; deliberately weaker than a direct profile match |
| Assessed locations, no policy match | 100% | No score adjustment |
| No assessable public location | excluded | Unknown, never treated as safe or unsafe |
A contributor-side match — a displayed top contributor, or a public
organization on that contributor's profile — additionally requires the matched
contributor to **carry meaningful commit weight**: at least **50 commits**, or
at least **10% of the sampled human commits**. The share condition protects
small repositories, where a genuine co-maintainer may hold few absolute
commits; the absolute condition protects large ones, where a substantial body
of work can still be a small percentage. A match below both thresholds is
recorded on the report for review, but raises no flag and changes no score: a
handful of accepted commits is disclosure, not exposure, and a policy that
flagged every incidental contributor would tell a reviewer nothing about
stewardship. Owner matches are never gated — the owner controls the repository
namespace and release surface at any commit count.
A clean result cannot improve weak security hygiene. Missing evidence is never
scored as a failure, and multiple matches do not compound into a more severe
penalty.
## How it changes the rating
The signal is a policy multiplier, not another security-practice checklist:
`adjusted Security posture = base Security posture × policy multiplier`
A confirmed match also gives the adjusted Security posture an **At Risk
ceiling of 34**. The Security category reflects that adjusted posture without
applying the multiplier twice.
After normal category weighting, the policy multiplier and the same ceiling
apply to the **overall repository rating**. This makes the governance decision
explicit: a material policy exposure cannot disappear inside an average of
popularity, documentation, maintenance, and engineering scores.
Every report retains the base value, multiplier, multiplied value, and ceiling.
A reviewer can therefore reproduce the result and distinguish technical health
from the policy adjustment that changed the published rating.
## How an enterprise should use the signal
A policy alert is a route into due diligence—not an automatic accusation or a
universal instruction to remove the package. Proportionate responses can
include:
- **Review:** confirm the upstream public evidence and the dependency's role in
the product.
- **Verify:** require signed releases, stronger provenance, pinned artifacts,
reproducible builds, or additional source review.
- **Limit:** keep the dependency away from sensitive data, credentials, build
authority, or production environments while review is open.
- **Monitor:** watch ownership, contributor concentration, release provenance,
and future policy changes.
- **Plan continuity:** identify a maintained alternative, internal mirror, or
viable fork for a business-critical dependency.
- **Document an exception:** record why the exposure is understood and which
compensating controls make continued use acceptable.
The right response depends on package criticality, execution context, customer
commitments, and the organization's own legal and risk framework. The signal
creates prioritization and evidence; expert judgement remains responsible for
the decision.
## Evidence quality and safeguards
High-confidence evidence includes an explicit country name or native spelling,
a country flag, an unambiguous administrative region, or a place name unique to
or overwhelmingly dominant in a policy country. Conflicting context is
**review-only** and never changes a score — another country, a US state, or a
named city outside the policy scope, so that a profile reading "Seoul, North
Korea" or "London, Munich, St. Petersburg" is treated as ambiguous rather than
as a declaration. Internationally recognized Ukrainian territories are excluded
from Russia place matching unless the profile explicitly self-declares Russia.
A profile that names a country **in order to deny being there** — "not north
korea", "Seoul, Korea (not DPRK)" — is likewise review-only. The denial has to
sit beside the match to count: "No. 5 Lenin St, Moscow, Russia" declares Russia
and retracts nothing.
Domains, language, personal names, company text, and inferred identity do not
establish location. Public organization membership alone is not a match; the
organization must itself publish a matching location. Public reports expose
aggregate country-and-role counts, never contributor identities or raw profile
locations.
△This is an explainable governance signal, not a legal or personal judgement. Public location evidence does not establish nationality, residence, sanctions status, malicious intent, repository permissions, or individual trustworthiness. A maintainer can request correction when upstream data or place matching is wrong.
## Why the design serves the public interest
Jurisdiction-risk controls are often available only through opaque enterprise
databases and private scoring models. inspect.software takes a different
approach: the evidence boundary, country scope, multipliers, score ceiling, and
limitations are public and versioned. Commercial relationships cannot alter a
published result.
That transparency protects both sides of the ecosystem. Dependency consumers
receive a usable governance signal; maintainers can see exactly what was
measured, what was not inferred, and how to challenge incorrect evidence. The
objective is disciplined open-source risk review—not suspicion by association.
Related: [Security](/wiki/security) · [Security posture](/wiki/security-posture)
· [methodology](/methodology) · [signals, not warranties](/wiki/signals-not-warranties)
---
# Growth Authenticity
> How inspect.software reads a repository's day-by-day star and fork history for growth that organic attention does not produce, and what the Inorganic Growth Policy does about it.
A GitHub star is the most widely read trust signal in open source. It is also
the only one with no issuer. Stars are sold openly, in bulk, for a few cents
each, alongside forks, watchers and followers, and nothing in the number itself
distinguishes the bought from the earned.
Every assessment that counts stars inherits that problem. **Growth
Authenticity** is the part of the methodology that addresses it: the per-day
star and fork history collected for each report is read for growth whose
*shape* organic attention does not produce, and where such growth is confirmed,
the purchasable inputs are discounted rather than believed.
The result answers a narrow question:
> **Does this repository's popularity history look like something that
> happened, or like something that was delivered?**
It does not answer who did it, or whether anyone paid for it. Every finding
here is a statement about the timing of public events, and nothing more.
## Why the timing gives it away
Attention that a project earns arrives through people, and people are
irregular. A launch, a Hacker News front page, a conference talk or a
newsletter mention produces a spike that is uneven hour to hour, that brings
forks along with stars because some readers open the code, and that decays over
the following week as the link circulates and then stops.
Delivered attention has none of those properties. It arrives on a schedule,
from accounts that never look at the repository, and it ends the moment the
order is filled. The counter cannot tell the difference. The history can.
## What is measured
The report first looks for **spike days** — days on which the repository gained
both at least 25 stars and at least twelve times its own median active-day
rate. Consecutive spike days are merged into one window.
A spike is never a finding on its own. Real projects spike, and a methodology
that treated every burst as suspicious would flag every successful launch. A
window is confirmed only when **at least two independent signals** corroborate
it:
| Signal | What it observes |
| ------ | ---------------- |
| **Star concentration** | The five busiest days hold 80% or more of every star collected. Measured across 502 ordinary repositories, the median puts 6.9% of stars in its five busiest days and none reached 80%. It is a claim about the whole history rather than one burst, so it corroborates every window — and is only available where the whole history was collected. |
| **Flat cadence** | Across three or more days, the daily additions barely varied. An audience is uneven; a delivery schedule is not. |
| **No fork response** | The window's fork-to-star ratio fell below a quarter of the repository's own long-run ratio — attention that never touched the code. |
| **No decay** | The seven days after the burst totalled 5% or less of it. Real spikes have a tail; a filled order stops dead. |
| **No released substance** | The project has never published a release at all. Deliberately weak: plenty of legitimate projects publish nothing. An earlier form of this signal treated a burst arriving before a project's *first* release as evidence, and it produced every false positive in the first control measurement — publish, attract attention, release later is how ordinary projects work. |
## The four states
| State | Meaning | Effect |
| ----- | ------- | ------ |
| **Organic** | The history is consistent with organic accretion. | none |
| **Unverified** | The collected history cannot answer the question. | none |
| **Anomalous** | One confirmed window. | stars and forks discounted 40% |
| **Highly anomalous** | Two or more confirmed windows, or one carrying three signals. | stars and forks discounted 70% |
The discount applies to the stars and forks components of
[popularity](/wiki/popularity) — the two inputs a supplier can sell. Watchers
are untouched, because they are not part of what the anomaly evidences, and no
other category moves at all. Popularity carries 6.8% of the overall index, so
the arithmetic effect is deliberately small. The finding is the product; the
adjustment only stops the report from asserting something it has reason to
doubt.
There is no upward adjustment. A clean history cannot raise a score, exactly as
a clean jurisdiction result cannot raise
[security posture](/wiki/security-posture).
## What Unverified means, and what it does not
A repository reads *unverified* when it has no collected star history, when it
holds fewer than 100 stars, or when the collected window spans less than 60
days. It carries no penalty of any kind.
This is the common case, and it is a limit of the evidence rather than a
verdict. History collection is bounded — the report captures a recent window of
star and fork events, not the whole life of a large project — so manipulation
older than that window is simply invisible here. *Unverified* means the
question was not answerable. It never means the answer was clean.
## Reading the result
- **A finding is about a pattern, not a person.** Stars can be bought by a
competitor, by a promoter, by a previous owner of the repository, or by
someone the maintainers never met. Nothing in this assessment identifies who
acted, and nothing in it implies the maintainers did.
- **A finding does not make the software bad.** It makes one piece of evidence
about the software unreliable. The engineering, governance and security
evidence in the rest of the report is unaffected and stands on its own.
- **The absence of a finding is not a certificate.** Slow, distributed
purchasing across months does not spike, and this assessment will not see it.
## Improving the value
Nothing can be done to a repository to improve this result, and that is the
point: the assessment reads history that has already happened. A project whose
growth was genuine already reads *organic*.
Related: [popularity](/wiki/popularity) ·
[community & adoption](/wiki/community-adoption) ·
[signals, not warranties](/wiki/signals-not-warranties)
---
# Organization assessment
> How inspect.software assesses GitHub organizations — portfolio activity, community reach, and profile completeness on the same 1–100 scale and bands.
Beyond individual repositories, inspect.software assesses **GitHub
organizations** — the entities that steward software portfolios. An
organization assessment answers a procurement-grade question: *is this a
maintained, accountable, clearly presented steward,* independent of any
single repository it owns.
Organization values use the same 1–100 scale and the same
[rating bands](/wiki/scoring-bands) as repositories, computed under the same
versioned methodology.
## Categories and metrics
| Category | Weight | Metrics (weight within category) |
| -------- | ------ | -------------------------------- |
| **Activity & Reach** | 75% | [portfolio activity](/wiki/portfolio-activity) (60%), [community reach](/wiki/community-reach) (40%) |
| **Governance & Profile** | 25% | [profile completeness](/wiki/profile-completeness) (100%) |
**Activity & Reach** asks whether the repository portfolio is maintained and
whether the organization has traction. **Governance & Profile** asks whether
the organization is accountable and clearly presented — the same identity
evidence that feeds a repository's [stewardship](/wiki/stewardship) metric.
## How portfolio facts are computed
Portfolio measurements are computed over a sample of up to **100 public
repositories** (the API page cap), ordered by most recent push. For
organizations above that size, the sample favors the actively maintained end
of the portfolio — stated here because honest methodology includes its
sampling rules.
## How organization and repository assessments relate
- A repository report embeds its owning account's public profile, which
drives the repository's [stewardship](/wiki/stewardship) metric — so
organization quality already influences repository values where it should.
- An organization assessment is the aggregate view: one number for the
steward across everything it maintains.
- The same missing-data discipline applies throughout: unavailable facts are
excluded and weights renormalized, never counted as zero (see
[the health index](/wiki/health-index)).
## Improving an organization's assessment
- Keep the portfolio honest: archive repositories that are no longer
maintained rather than letting them decay in place — see
[portfolio activity](/wiki/portfolio-activity).
- Complete the organization profile and verify its domain — see
[profile completeness](/wiki/profile-completeness).
Related: [stewardship](/wiki/stewardship) ·
[methodology versions](/wiki/methodology-versions)
---
# Portfolio activity
> How inspect.software measures an organization's portfolio activity — recently active repos, yearly activity, portfolio size, and original work. 45% of the org index.
**Portfolio activity** measures whether an organization's repository
portfolio is actually maintained. Organizations accumulate repositories the
way attics accumulate boxes; what distinguishes a working steward from a
graveyard is the share of the portfolio that still moves.
- **Assessment:** [organization](/wiki/organization-assessment), Activity & Reach category (60% within category)
- **Weight in organization overall:** 45%
- **Metric key:** `portfolio_activity`
## How the value is computed
Computed over a sample of up to 100 public repositories, most recently
pushed first:
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Recently active repositories | 50 | share of sampled repositories pushed within the last 90 days |
| Yearly active repositories | 25 | share pushed within the last year |
| Portfolio size | 15 | log-scaled; ~100 repositories saturates |
| Original work | 10 | share of sampled repositories that are not forks |
## Why shares, not counts
Ratios make organizations of different sizes comparable: an organization
with 8 of 10 repositories active outreads one with 30 of 300. Size still
earns its own (smaller, log-scaled) component, because a substantial
portfolio is real evidence of capacity — it just cannot compensate for a
portfolio that is mostly dormant. The original-work component keeps a wall
of forks from impersonating a development organization.
## Reading the result
- **Archiving is good hygiene, and the metric rewards it.** GitHub excludes
archived repositories from the default listing, so an organization that
archives finished work concentrates its sample on what it actively
maintains. Honest labeling improves the measurement — by making the
measurement more accurate.
- The 90-day component dominates: this metric describes the present, with
the yearly component as its trailing context.
## Improving the value
- Archive repositories that are done or abandoned — the single most
effective action, and it also serves the organization's users.
- Keep maintained repositories visibly maintained: dependency updates and
fixes count as pushes.
Related: [community reach](/wiki/community-reach) ·
[organization assessment](/wiki/organization-assessment)
---
# Community reach
> How inspect.software measures an organization's community reach — followers and portfolio-wide stars on logarithmic scales. 30% of the organization index.
**Community reach** measures an organization's traction: the audience that
follows it and the attention its portfolio has earned. Reach matters for the
same reason a repository's [popularity](/wiki/popularity) does — widely
watched software has more eyes available to notice problems — aggregated to
the level of the steward.
- **Assessment:** [organization](/wiki/organization-assessment), Activity & Reach category (40% within category)
- **Weight in organization overall:** 30%
- **Metric key:** `community_reach`
## How the value is computed
| Component | Weight | Criteria |
| --------- | ------ | -------- |
| Followers | 50 | log-scaled; ~1,000 saturates |
| Stars across repositories | 50 | summed over the sampled portfolio, log-scaled; ~10,000 saturates |
Both components are logarithmic for the same reason popularity is: each
order of magnitude counts roughly equally, so the metric differentiates
across the whole range instead of only flattering giants. Portfolio stars
are computed over the same sample (up to 100 most recently pushed public
repositories) as [portfolio activity](/wiki/portfolio-activity).
## Reading the result
- **Reach is attention, not use.** It is the weaker cousin of adoption
evidence — kept at a moderate weight and paired with activity, which is
harder to accumulate passively.
- **Followers and stars measure different things.** Followers attach to the
organization itself (people watching the steward); stars attach to its
work. An organization famous for one repository and followed by no one
reads differently from an institution people track as such.
- Saturation points mean mega-organizations stop gaining: beyond ~1,000
followers and ~10,000 portfolio stars the question is answered.
## Improving the value
There is no direct lever, deliberately. Reach follows the durable levers
measured elsewhere: maintained portfolios
([portfolio activity](/wiki/portfolio-activity)), complete public identity
([profile completeness](/wiki/profile-completeness)), and repositories that
are easy to adopt ([community health](/wiki/community-health)).
Related: [popularity](/wiki/popularity) ·
[organization assessment](/wiki/organization-assessment)
---
# Profile completeness
> How inspect.software measures organization profile completeness — verified domain, description, homepage, contact, and identity fields. 25% of the org index.
**Profile completeness** measures whether an organization is accountable and
clearly presented: a verified real-world identity, a stated purpose, and
working ways to reach it. For anyone deciding whether to depend on an
organization's software, the profile is the difference between an
institution and an anonymous namespace.
- **Assessment:** [organization](/wiki/organization-assessment), Governance & Profile category (100% within category)
- **Weight in organization overall:** 25%
- **Metric key:** `profile_completeness`
## How the value is computed
| Component | Weight | Evidence |
| --------- | ------ | -------- |
| Verified domain | 25 | domain verification completed on GitHub |
| Description | 20 | the organization's description field |
| Homepage | 15 | a working website URL |
| Display name | 10 | a human-readable name beyond the login |
| Location | 10 | a stated location |
| Contact email | 10 | a public contact address |
| Social profile | 10 | at least one linked social account |
## Why a profile is governance evidence
- **Domain verification is the anchor — and the heaviest component.** It
cryptographically ties the GitHub organization to a real-world domain,
which is genuine supply-chain evidence: it forecloses a whole class of
namespace-impersonation attacks. The same signal feeds each repository's
[stewardship](/wiki/stewardship) metric.
- **Description, homepage, and name** establish what the organization is
and where its canonical presence lives.
- **Location, email, and social links** are accountability surface: routes
by which a security researcher, a packager, or a legal team can actually
make contact.
## Reading the result
- This is the most directly actionable metric in the organization
assessment — every component is a settings field, and the whole checklist
can be completed in under an hour.
- An incomplete profile on an otherwise strong organization usually
indicates neglect rather than concealment — but the record can only
publish what is visible, and the metric reads accordingly.
## Improving the value
- Verify the organization's domain in GitHub settings — the single largest
component.
- Fill every profile field: description, homepage, display name, location,
public email, and at least one social profile.
Related: [stewardship](/wiki/stewardship) ·
[organization assessment](/wiki/organization-assessment)