# 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)
