How Porchlamp measures a project

Porchlamp ranks open-source projects by what happens to a stranger's pull request. This page lists every rule, weight and parameter behind the ranking, generated from the same constants the ranking code uses.

This page describes snapshot 2026-10-14. The black-hole report and the rankings use the same rules.

Gates

Checks a repository must pass to be ranked. A repository that fails one carries the gate's reason instead of a rank.

D-GATE-1: Software project

repository tree contains a recognised build/package manifest at depth <= 2, or the repository is a curated anchor

D-GATE-2: Not archived, not a mirror, not a fork

archived == false, mirror_url is null, fork == false (a fork is allowed only if its parent is absent from the universe)

D-GATE-3: Licensed

SPDX id present and OSI-approved; an undetermined SPDX id falls back to a LICENSE* file search before the gate fails

D-GATE-4: Vitality

>= 1 commit by a non-bot User on the default branch in the trailing window

D-GATE-5: Not a black hole

over external PRs by non-bot authors (D-IN-1) opened in the trailing PR window and at least the minimum age, the 95% one-sided Wilson lower confidence bound (z = 1.6448536269514722) on the zero-response share must not exceed the ceiling (a minimum population of 10 is required, else the gate is UNDECIDED rather than failed); the raw share is the gr14_ghost_rate parameter. A reply or review counts when it is substantive (D-IN-2: any review, or a comment of 40+ characters, by a non-author, non-bot member, owner or collaborator, or by an account that merged a PR in the window, since org membership can be private); a merge or maintainer close within the deadline counts on its own. Five false-positive exclusions apply (RFC-0008): draft PRs are excluded until marked ready for review (clock starts at ready_at); author self-closed PRs without prior maintainer response are excluded; accounts under 90 days old (MIN_ACCOUNT_AGE_DAYS) are excluded; maintainer closes within 14 days count as responses; and the 14-day observation age is judged from clock start against min(now, observed_at)

D-GATE-6: PR workflow

>= 1 external PR decided in the trailing window, or off-platform markers present (routed, not failed); neither means unrated: no_external_workflow. A repository also routes off-platform, whatever its decided PRs, when it hands review off: among its outside PRs (external, non-bot authors in the recorded PR window) at least 5, and at least 50% of them, carry a notice, a comment by an account other than the PR's author that contains "has been imported to gerrit for code review", "welcome to gitgitgadget" or "import it to our internal repository for further review" (any letter case) or is written by an account whose login starts with "gitgitgadget". D-GATE-5 is then undecided for it, never failed

D-EVID-1: Evidence sufficiency

composite coverage must reach the rated minimum, else listed unranked

Pillars

The five pillars of the composite score, and the share of it each one carries.

PillarWeight in the balanced composite
Responsiveness25%
Criticality25%
Governance20%
Rigor15%
Accessibility15%

Lenses

Alternative weightings of the same five pillars, and the gates that decide which repositories each persona shows.

LensRespCritGovRigorAcc
Balanced25%25%20%15%15%
First-timer35%10%15%10%30%
Career capital20%35%15%10%20%
Senior systems15%35%25%20%5%
AI-assisted20%20%15%35%10%
  • AI-assisted: Hard AI ban (exclusion gate): fires only when ai_posture is measured PROSCRIBED with non-empty evidence.
  • Senior systems: Multi-vendor (exclusion gate): fires only on a measured elephant factor below the minimum.
  • First-timer: Low barrier (inclusion gate): shown when decided first-timer PRs in the window reach the minimum count and MR_first reaches its minimum rate, or the newcomer-issue-supply count reaches its minimum; an unmeasured input never satisfies an inclusion gate (D-PERS-3).
  • Career capital: High-tier brand (inclusion gate): shown when the criticality pillar score and its coverage both reach their minimums.

Parameters

The measured inputs, grouped by pillar: how each is scored, how much evidence it needs, and over what window.

All 18 parameters
ParameterPillarWeight in pillarMin countWindowScoring curve
Time to First ResponseResponsiveness30%10180 days100 if the median hours to first substantive human response is <= 12; else max(0, 100 - 25 * log2(t / 12))
Decision Rate (90d)Responsiveness25%10180 daysmin(100, 125 * r)
First-timer Merge RateResponsiveness20%5180 daysmin(100, 125 * r)
PR Ghost Rate (14d)Responsiveness15%10180 daysmax(0, 100 - 200 * g)
Time to Merge (p90)Responsiveness10%5180 days100 - ECDF_mid(p90), mid-rank ECDF over the frozen ecosystem population (D-NORM-1)
DependentsCriticality40%n/an/aECDF_mid(value) on the raw measured value, no transform on either side (D-NORM-1/D-NORM-3)
OpenSSF CriticalityCriticality35%n/an/a100 * C, the locally computed OpenSSF/Pike criticality score C in [0, 1]
Monthly DownloadsCriticality25%n/an/aECDF_mid(value) on the raw measured value, no transform on either side (D-NORM-1/D-NORM-3)
Legal IP RegimeGovernance35%n/an/aevidence-based regime lookup; see this parameter's value_domain.score_table
Elephant FactorGovernance35%30n/amin(100, 25 * EF)
Promotion LadderGovernance30%n/an/aevidence-based rung lookup; see this parameter's value_domain.score_table
Pipeline DefensesRigor40%n/an/aidentity, clamped to [0, 100] (Scorecard check mean, or the proxy blend when absent)
AI Policy PostureRigor30%n/an/apersona-conditional posture lookup; see this parameter's value_domain.score_table
Substantive Review RateRigor30%10180 daysmin(100, 125 * r)
Newcomer Issue SupplyAccessibility35%n/an/amin(100, 10 * count)
Newcomer ConversionAccessibility35%5n/amin(100, 200 * r)
Newcomer Return RateAccessibility15%5n/amin(100, 200 * r)
Developer ExperienceAccessibility15%5n/aidentity, clamped to [0, 100] (0.5 CI runtime score + 0.5 setup-signal score)

Missing data

What a missing input means, and how much coverage a repository needs before it is rated.

  • Unrated below: 60%
  • Tier ceiling B below: 80%
  • Tier ceiling A below: 95%

Why a measurement can be missing:

  • third_party_gap: A third party (a registry, OpenSSF, deps.dev) never provided the fact; no maintainer action can close this gap.
  • collector_failure: The collector attempted to measure this input and failed (a fetch error, a stale window anchor); a retry can still measure it.
  • insufficient_n: The input was measured but its sample size fell below the parameter's minimum n; the measurement is recorded but scored as unmeasured.
  • not_applicable: The parameter is undefined for this repository's class by a closed, design-level rule (D-MISS-5); excluded from both the numerator and the denominator of coverage.
  • no_population: The parameter is ECDF-normalised and no rated, measured repository exists in its ecosystem or globally at this snapshot to build a population from.

Tie-break order

When two composites are equal, these fields separate them, in this order.

  1. composite, descending: rounded to 2 decimal place(s) before comparison
  2. coverage, descending
  3. responsiveness_pillar_score, descending
  4. friction, ascending
  5. leverage, descending
  6. ttfhr_p75_hours, ascending: p75, not the median: consistency, not just the typical case
  7. last_non_bot_commit_at, descending
  8. owner_name_lowercase, ascending: deterministic last resort; never stars, forks or downloads

Limits

  • Not a verdict on the people who maintain these projects. Review time is scarce, and popular projects receive far more pull requests than anyone can read.
  • GitHub only. Projects that review on Gerrit or a mailing list are left undecided, not failed.
  • One six-month window. The numbers will change at the next snapshot.

Reproduce it

python -m porchlamp.snapshot reproduce 2026-10-14

Hashes

  • Benchmark version: 2.0.0-rc1
  • Methodology constants hash: 6e4f3e8e1d0c0fcd829d9c8c386a65179eadb5f936595f96e9eba98712d55b94
  • Manifest root: 85d93789d7a5198af0a53ae21de4ce9d81da83fd8c7bfb068657647183816679
  • Canonical dump hash: 89b186d4dacf41e0a5684fcee31646e495ece19714b4e6bf1644f4c8c8e8e3f3
  • Code commit: a1f3fd968651f3c219c0a6974a4f2c92e165c325
  • Snapshot database SHA-256: bf96e162537333e43e98a59a472755dfee9b20e50da6751c1a1816321e5c237c