Concepts

Methodology versions

The complete version history of the inspect.software metrics methodology — every formula, weight, and threshold change, dated and documented.

Methodology v1.13.0Updated 2026-07-22

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 1.13.0.

Each entry identifies the precise change, its scope, and whether existing results remain comparable. Dates are part of the public methodology record.

Version history

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.

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.

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'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 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. 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 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 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 now counts people only — automation accounts were previously ranked among a project's maintainers, which flattered exactly the projects that automate most.

AI Readiness stops measuring only which files exist. 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 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. The resolved dependency set already collected for every report — direct dependencies plus the transitive closure — is now matched against the OSV 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 at 80% and the new metric at 20%. The High-Risk Jurisdiction Policy 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 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 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'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 — publish recency, version history, deprecation state — and NuGet additionally feeds 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 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. 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; 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 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 category with four metrics: (agent context, verify loop, code legibility, 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 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.

0.6.0 — 2026-06-09

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 (registry downloads) in Community & Adoption and 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, popularity, stewardship, and documentation. activity renamed 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). 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 — a report plus its recorded version fully determines how every value was computed.
  • 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 · rating bands · scan configuration