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.
| Pillar | Weight in the balanced composite |
|---|---|
| Responsiveness | 25% |
| Criticality | 25% |
| Governance | 20% |
| Rigor | 15% |
| Accessibility | 15% |
Lenses
Alternative weightings of the same five pillars, and the gates that decide which repositories each persona shows.
| Lens | Resp | Crit | Gov | Rigor | Acc |
|---|---|---|---|---|---|
| Balanced | 25% | 25% | 20% | 15% | 15% |
| First-timer | 35% | 10% | 15% | 10% | 30% |
| Career capital | 20% | 35% | 15% | 10% | 20% |
| Senior systems | 15% | 35% | 25% | 20% | 5% |
| AI-assisted | 20% | 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
| Parameter | Pillar | Weight in pillar | Min count | Window | Scoring curve |
|---|---|---|---|---|---|
| Time to First Response | Responsiveness | 30% | 10 | 180 days | 100 if the median hours to first substantive human response is <= 12; else max(0, 100 - 25 * log2(t / 12)) |
| Decision Rate (90d) | Responsiveness | 25% | 10 | 180 days | min(100, 125 * r) |
| First-timer Merge Rate | Responsiveness | 20% | 5 | 180 days | min(100, 125 * r) |
| PR Ghost Rate (14d) | Responsiveness | 15% | 10 | 180 days | max(0, 100 - 200 * g) |
| Time to Merge (p90) | Responsiveness | 10% | 5 | 180 days | 100 - ECDF_mid(p90), mid-rank ECDF over the frozen ecosystem population (D-NORM-1) |
| Dependents | Criticality | 40% | n/a | n/a | ECDF_mid(value) on the raw measured value, no transform on either side (D-NORM-1/D-NORM-3) |
| OpenSSF Criticality | Criticality | 35% | n/a | n/a | 100 * C, the locally computed OpenSSF/Pike criticality score C in [0, 1] |
| Monthly Downloads | Criticality | 25% | n/a | n/a | ECDF_mid(value) on the raw measured value, no transform on either side (D-NORM-1/D-NORM-3) |
| Legal IP Regime | Governance | 35% | n/a | n/a | evidence-based regime lookup; see this parameter's value_domain.score_table |
| Elephant Factor | Governance | 35% | 30 | n/a | min(100, 25 * EF) |
| Promotion Ladder | Governance | 30% | n/a | n/a | evidence-based rung lookup; see this parameter's value_domain.score_table |
| Pipeline Defenses | Rigor | 40% | n/a | n/a | identity, clamped to [0, 100] (Scorecard check mean, or the proxy blend when absent) |
| AI Policy Posture | Rigor | 30% | n/a | n/a | persona-conditional posture lookup; see this parameter's value_domain.score_table |
| Substantive Review Rate | Rigor | 30% | 10 | 180 days | min(100, 125 * r) |
| Newcomer Issue Supply | Accessibility | 35% | n/a | n/a | min(100, 10 * count) |
| Newcomer Conversion | Accessibility | 35% | 5 | n/a | min(100, 200 * r) |
| Newcomer Return Rate | Accessibility | 15% | 5 | n/a | min(100, 200 * r) |
| Developer Experience | Accessibility | 15% | 5 | n/a | identity, 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.
composite, descending: rounded to 2 decimal place(s) before comparisoncoverage, descendingresponsiveness_pillar_score, descendingfriction, ascendingleverage, descendingttfhr_p75_hours, ascending: p75, not the median: consistency, not just the typical caselast_non_bot_commit_at, descendingowner_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