How collections are scored
Scoring version 2. This page is generated from the same rule definitions the scoring engine executes, so the weights and rules described here are the weights and rules that produced every score on this site.
Popularity is not an input. Download counts and stars are shown on a collection's page but never contribute to its score — the engine is not given them.
What the Security score does and does not tell you
There is no vulnerability database for Ansible collections. Nothing equivalent to npm audit or the GitHub Advisory Database exists for this ecosystem, so this site does not and cannot tell you whether a collection contains a known vulnerability — and you should be sceptical of anything that claims to. What the Security score measures instead is one narrow, checkable thing: whether the collection’s declared dependencies carry version bounds, so that installing it today cannot silently pull in an arbitrary future release of something else. That is supply-chain hygiene, not a security audit. It is weighted at 10 out of 100 precisely because it is the smaller claim.
The five categories and their weights
The weights below are the ones the scoring engine runs on; this page reads them out of the same definitions rather than describing them, so the two cannot disagree. The anchor column is the corresponding weight in nuxt.care's published rubric, which this one starts from; every difference from it is stated in the same row.
| Category | Weight | nuxt.care anchor | What it measures | Why this weight |
|---|---|---|---|---|
| Security | 10 | 15 | Supply-chain hygiene: whether the collection’s declared dependencies carry version bounds, so that installing it cannot silently pull in an arbitrary future release. | Cut from the anchor’s 15 because THERE IS NO ANSIBLE VULNERABILITY DATABASE to grade against. npm-oriented rubrics can weight Security heavily because they can query a real advisory feed; we cannot, and inventing a number to fill the gap would be worse than weighting the gap honestly. The one real v1 signal is dependency boundedness, and it is a weak discriminator on this corpus — about three quarters of collections declare no dependencies at all, so they have no unbounded ranges by construction. Weighted for what it actually measures rather than for the importance of the word. |
| Trust | 12 | 5 | Third-party corroboration: inclusion in the community `ansible` package, and whether the collection declares a source repository you can go and read. | Raised well above the anchor’s 5 because Ansible has a corroboration signal npm lacks. Inclusion in the `ansible` package is a HUMAN REVIEW against a published checklist — a judgement by people other than the publisher, which no amount of self-declared metadata can imitate. That makes it one of the few signals in the whole rubric that is expensive to game. It is weighted as corroboration and never as a requirement: roughly four collections in five never enter that opt-in process, and their absence from it drops out of the score rather than counting against them. |
| Quality | 30 | 30 | Evidence of engineering effort in the published artifact: documentation depth, changelog discipline, licence precision, and test and CI coverage graded by how much is there. | Held at the anchor. The published artifact carries a genuinely rich structural signal — documentation files, changelog format, SPDX identifiers, test-tier file counts, workflow counts — all readable without a network call, all graded by DEPTH rather than by presence. Presence-grading was measured and rejected: “has a licence”, “has authors” and “has CI” are each essentially 100% true among the collections where they are observable at all, so they would add a constant to every score while appearing to measure something. |
| Maintenance | 28 | 35 | Evidence the collection is still being worked on: how recently a release was published, and whether unreleased changelog entries are accumulating. | Reduced from the anchor’s 35 because v1 sees releases but not commits. Without the upstream repository we cannot observe push recency, whether the repository is archived, or whether CI is currently passing — so a slow-releasing but actively developed collection is under-credited here, and it would be dishonest to weight the category as though the missing evidence were present. It RISES TOWARD 35 in v2, when the GitHub enrichment lands; that increase is already an intended, published change rather than a later surprise. |
| ansible-core compatibility | 20 | 15 | Whether the collection states which ansible-core versions it supports, how recent that floor is, and how current its `ansible` package membership is. | Raised above the anchor because “will this work with the ansible-core I run?” is the first question anyone asks about a collection, and unlike most of the rubric it is answered by BEHAVIOURAL metadata the publisher maintains deliberately. Note what is graded and what is not: we grade the RECENCY and SPECIFICITY of the declared floor, never whether the floor “supports” today’s core. Grading satisfaction would invert the signal — an abandoned collection declaring `>=2.9.10` technically supports everything and would score full marks for having been left alone. |
Every per-signal rule
Points are relative WITHIN a category, not out of 100. Each category's subscore is what was earned divided by what was available across the rules we actually observed, so a rule's real contribution depends on which of its siblings were observable for that collection. A signal we did not observe is removed from the calculation, never scored as a zero.
Where a rule is graded on a count, its rubric is published beneath its category's table. Rows are ordered best-first and the FIRST one whose threshold a collection reaches is the one that applies, exactly as the engine matches them.
- Baseline
- Baseline signals come from metadata every published artifact carries, so a weak answer is a real observation and stays in the denominator. A declared-but-broken value is graded as an observed failure, because declaring something broken is a fact about the collection and one you can fix.
- Depth
- Depth signals live in files a publisher may legitimately exclude from the built artifact. We cannot tell "this collection has no tests" from "the tests were not packaged", so in v1 these rules CAN ONLY HELP YOU: finding evidence adds points, and finding none removes the rule from the calculation entirely rather than scoring it zero. Reading the upstream repository directly would let us prove absence; until then, we do not guess.
Security
| Rule | Points within category | Tier | What it grades |
|---|---|---|---|
security.dependency_boundedness | 1 | baseline | The fraction of declared collection dependencies that carry an upper or pinned version bound. Declaring no dependencies scores full marks — there is no unbounded range to be exposed to, and penalising a self-contained collection for its self-containment would be measuring nothing. A dependency key we could not parse earns nothing and stays in your score rather than removing this rule from it: making a declaration unreadable is not a way to avoid being graded on it, and it never scores above declaring an honest unbounded range. This is a hygiene proxy, not a vulnerability scan. |
Trust
| Rule | Points within category | Tier | What it grades |
|---|---|---|---|
trust.ansible_membership | 2 | baseline | Tenure in the community `ansible` package — how many majors the collection was carried through. Never shipping in the package is NOT observed here and does not count against the collection: inclusion is opt-in, and "did not apply" is indistinguishable in our data from "applied and was declined". Removal is priced once, as a penalty, not twice. |
trust.link_claims | 1 | baseline | How many of the four declared link fields — `repository`, `documentation`, `homepage` and `issues` — carry a URL we could parse. What is NOT graded is anything behind those URLs: we never fetch them, never look at what they point at, and a collection naming somebody else’s repository earns exactly what it would earn naming its own. Scoring is network-free. A field you declared and we could not parse is graded as an observed failure rather than as an absence — you told us something and it does not parse, which is both a fact about the collection and a one-line fix. Declaring no link at all earns none of this rule’s point, and the rule stays in your score: we read your metadata and saw four empty fields, which is something we observed rather than something we could not look at. Removing a link you have already declared can only lower your score, never raise it. |
| ansible package majors currently shipping | Score | Why the band sits here |
|---|---|---|
| 4+ | 1.00 | Shipped in four or more `ansible` package majors and still shipping. Years of surviving a human-curated inclusion process that actively removes unmaintained collections. |
| 2+ | 0.80 | Carried across two or three majors. Included, then kept — a decision made more than once. |
| 1+ | 0.60 | Shipping in one major. Real third-party corroboration: a human reviewed this collection against the community inclusion checklist and accepted it. |
| 0+ | 0.00 | Unreachable — the rule drops out entirely rather than reaching this band. |
| link URLs declared, of four | Score | Why the band sits here |
|---|---|---|
| 4+ | 1.00 | All four link fields — `repository`, `documentation`, `homepage` and `issues` — carry a URL we could parse. Everything a consumer needs in order to go and read the source, the docs and the open issues is stated in the collection’s own metadata. |
| 3+ | 0.85 | Three of the four fields carry a parseable URL. Filling in the fourth is a one-line change to `galaxy.yml`. |
| 2+ | 0.60 | Two of the four fields carry a parseable URL. A field you declared and we could not parse counts here as an observed failure rather than as an absence — it does not count toward this total, and the breakdown says how many were unreadable so you can find them. |
| 1+ | 0.30 | One of the four fields carries a parseable URL. Declaring only a `repository` is the common case in this ecosystem, and it earns partial credit rather than full: it is the floor of what a consumer can act on, not the whole of it. |
| 0+ | 0.00 | None of the four fields carries a URL we could parse. This band is reached both by a collection that declared links and had none of them parse AND by one that declared no link at all: an empty links block in a file we read is something we observed, so it earns nothing while STAYING in the denominator. Declaring no links costs you this rule’s point; it does not remove the rule from your score. |
Quality
| Rule | Points within category | Tier | What it grades |
|---|---|---|---|
quality.docs | 3 | baseline | Documentation depth: a README plus how many documentation files ship in the artifact. Graded by count rather than by presence, because nearly every collection that can be read at all has something. Shipping no README and no documentation files scores zero here and the rule stays in your score — we read your file list and saw what it does not contain, so removing documentation you already ship can only lower your number. |
quality.changelog | 2 | baseline | Changelog discipline, graded by format: a structured `changelogs/changelog.yaml` scores above a hand-maintained markdown file, because the structured form is what tooling and release automation can actually consume. Shipping no changelog at all scores zero here and the rule stays in your score — deleting a changelog you already publish lowers your number, it does not remove the question. |
quality.license_quality | 1 | baseline | Licence PRECISION, not licence presence: a machine-readable SPDX identifier scores above a bare licence file. Presence was measured at essentially 100% among readable collections and therefore grades nobody. Declaring no licence in any form scores zero here and the rule stays in your score — removing a licence file you already ship cannot raise your number. |
quality.tests | 3 | depth — can only help your score in v1 | Test evidence, graded by file counts and BRANCHED BY ARCHETYPE so the two kinds of collection are judged by their own conventions: role collections on molecule scenarios, plugin collections on ansible-test unit/integration/sanity tiers, mixed collections on whichever of the two they invest in. It can only ADD points in v1 — see the tier note. |
quality.ci | 2 | depth — can only help your score in v1 | Continuous-integration evidence, graded by how many workflow files ship. "Has CI" is true of every collection where CI is observable at all, so only the count discriminates. It can only ADD points in v1 — see the tier note. |
| documentation files beyond the README | Score | Why the band sits here |
|---|---|---|
| 10+ | 1.00 | Ten or more documentation files — a real documentation set, not a gesture. |
| 3+ | 0.70 | Three to nine documentation files beyond the README. |
| 1+ | 0.40 | One or two documentation files. |
| 0+ | 0.00 | No documentation files beyond whatever the README carries. |
| molecule scenarios | Score | Why the band sits here |
|---|---|---|
| 4+ | 1.00 | Four or more molecule scenarios: the role is exercised across several platforms or configurations, not just smoke-tested once. |
| 2+ | 0.80 | Two or three scenarios. |
| 1+ | 0.60 | One molecule scenario. The role is actually converged and verified. |
| 0+ | 0.00 | No molecule scenarios. |
| files in one ansible-test tier | Score | Why the band sits here |
|---|---|---|
| 10+ | 1.00 | Ten or more files in this tier — broad coverage. |
| 3+ | 0.80 | Three to nine files in this tier. |
| 1+ | 0.50 | At least one file in this tier. |
| 0+ | 0.00 | Nothing in this tier. |
| workflow files | Score | Why the band sits here |
|---|---|---|
| 5+ | 1.00 | Five or more workflow files: separate lint, test-matrix and release pipelines rather than a single catch-all job. |
| 2+ | 0.80 | Two to four workflows — more than one thing is automated. |
| 1+ | 0.50 | One workflow file. Automation exists. |
| 0+ | 0.00 | CI evidence was observed but carries no workflow files (a non-GitHub CI config only). Scored from `other_ci_files` instead — see `ciRule`. |
Maintenance
| Rule | Points within category | Tier | What it grades |
|---|---|---|---|
maintenance.release_recency | 3 | baseline | How long ago the most recent version was published to Galaxy. The heaviest single rule in the rubric, because a release is the one unambiguous, publisher-controlled act of maintenance we can observe without the source repository. |
maintenance.changelog_recency | 1 | baseline | Unreleased changelog fragments as an activity proxy — work in flight that has not been cut into a release yet. A collection shipping no changelog at all scores zero here and the rule stays in its score. This rule used to drop out in that case, on the reasoning that not shipping a changelog is a Quality answer rather than evidence about whether anyone is at the wheel — but leaving a rule out shrinks the total your score is measured against, so the drop-out paid you to delete your release notes. Shipping a changelog is credited both here and under Quality; not shipping one is now charged in both places too, which is the symmetry that was missing. |
| Score | Why the band sits here |
|---|---|
| 1.00 | Released within the last 180 days. Actively shipping. |
| 0.85 | Released within the last year. Normal cadence for a stable collection. |
| 0.60 | Released within the last two years. Quiet, but a mature collection with nothing to fix legitimately looks like this. |
| 0.35 | Last release two to three years ago. Past the point where quiet and unmaintained look the same from the outside. |
| 0.15 | No release in over three years. Non-zero because the collection may still work and we have observed no statement of abandonment — only silence. |
| unreleased changelog fragments | Score | Why the band sits here |
|---|---|---|
| 5+ | 1.00 | Five or more unreleased changelog fragments — substantial work in flight. |
| 1+ | 0.70 | At least one unreleased fragment: a change landed since the last release. |
| 0+ | 0.40 | A changelog is maintained but nothing is pending. Not evidence of current work, but the release-notes discipline itself is worth partial credit here. |
ansible-core compatibility
| Rule | Points within category | Tier | What it grades |
|---|---|---|---|
compat.requires_ansible | 3 | baseline | The declared ansible-core floor, graded on RECENCY and on whether an upper bound is also declared (evidence of deliberate testing). Declaring no floor at all scores zero and STAYS in your score: we read your `galaxy.yml` and found no constraint, which is something we observed rather than something we failed to look at. A value we can parse but that names no floor — a pin like `==2.15.1`, a `~=2.14.0`, or a bare ceiling — earns 5% of this rule: it is a real declaration, so it beats declaring nothing, and it sits below every floor tier because pinning ansible-core is the practice this category exists to discourage. Only a value we could not parse at all is graded as an unreadable declaration. |
compat.membership_currency | 1 | baseline | How recent the newest `ansible` package major containing this collection is. Distinct from the Trust tenure rule reading the same rows: tenure asks how long it was trusted, currency asks whether that trust is current. |
| ansible-core 2.x minor of the declared floor | Score | Why the band sits here |
|---|---|---|
| 17+ | 1.00 | A floor at ansible-core 2.17+ tracks the currently-supported core series. The publisher is testing against what people actually run today. |
| 16+ | 0.85 | 2.16 is the most recent long-lived core floor still in wide production use. Recent enough to be a deliberate, maintained choice rather than an artefact. |
| 14+ | 0.60 | 2.14-2.15 is a floor that was current within the last few release cycles: dated, but it reflects a real support decision rather than abandonment. |
| 11+ | 0.35 | 2.11-2.13 predates the cores most users run. Still an explicit declaration, so it earns more than the 2.9/2.10 floor that is usually just the value the collection was born with. |
| 0+ | 0.10 | A floor at 2.9 or 2.10 is, in practice, the value written when the collection was created and never revisited. It earns a non-zero score because declaring a floor at all is more than declaring nothing, but it is the bottom tier. |
| Score | Why the band sits here |
|---|---|
| 1.00 | Still shipping in the current `ansible` package major. The package was built and tested against a specific ansible-core; being in it is corroboration nobody can self-declare. |
| 0.70 | Shipping as of the previous major. Recent, but one release cycle behind the core the package now targets. |
| 0.40 | Two majors behind — roughly a year of core releases since it was last carried. |
| 0.15 | Three or more majors behind. Non-zero because being in the package at all was a real review event, but it is no longer evidence about the cores people run today. |
When a collection is scored at all
A collection is scored only when we have observed enough of it to judge it fairly: at least 4 of the 8 core signal groups, and some plugins, roles or playbook content to grade. This is a judgeability threshold, NOT a quality floor. About 40% of the index sits here, and it is a first-class outcome rather than a failure: "not scored" means we have not seen enough to render a verdict, never that the collection is bad. It cannot depend on how popular a collection is — popularity is not an input to anything on this site’s scores.
The signal groups the coverage count is taken over:
testscidocschangeloglicensedependenciesrequires_ansibletags
What the number is called
A collection with no total is not a zero: it is shown as Not scored, which is a band in its own right rather than the bottom of the scale.
| Band | Floor | Score range | Why the cutoff is here |
|---|---|---|---|
| Excellent | 80 | 80–100 | ≥80 covers 7.6% of scored collections (201 of 2,655) and sits above p90=77. Round and reachable: a collection with tests, CI, docs, a license, a current ansible-core floor and recent activity gets here without needing to be exceptional. Raising the bar to 85 would cut Excellent to 2.3% (60 collections); legibility of a round 80 was preferred over that selectivity. |
| Good | 65 | 65–79 | 65–79 covers 27.8% of scored collections (738 of 2,655) and sits entirely above the median, which is 57. This is the "healthy, with room to improve" band — typically a collection missing one depth signal such as CI or a changelog. |
| Fair | 50 | 50–64 | 50–64 covers 29.3% of scored collections (779 of 2,655), and its floor sits between p25=45 and the median 57. Half the available points on the signals we could observe: usable, but the maintenance or quality evidence is thin. |
| Poor | 0 | 0–49 | <50 covers 35.3% of scored collections (937 of 2,655) — about a third of them, published as measured rather than rounded away. It is NOT mostly deprecation: 67 of those 937 carry any penalty at all, against 89 penalty applications in the whole index. The share is this large because the signal extractor changed and the cutoffs did not follow it, not because the collections changed — the changelog entry for artifact extractor version 2 says what moved and by how much. Deliberately grey-orange rather than red: the band reports weak evidence, it does not accuse a maintainer. |
| Not scored | no score | No score | Reached by failing the judgeability gate (too few observed signal groups) or by being absent from the Galaxy index — never by scoring badly. A first-class band, never a zero and never a blank (BADGE-03): we have not observed enough to render a fair verdict, and saying so is more honest than inventing one. |
Deductions
Penalties are flat deductions taken after the weighted total, they stack, and the result is floored at 0. They are facts about the whole collection rather than about one of its five aspects, which is why they are not folded into a category.
| Deduction | Points | Status | Why |
|---|---|---|---|
deprecated | 15 | applied now | The publisher has marked this collection deprecated on Galaxy while leaving it published (93 collections, 2.1% of the corpus). The signal is the maintainer’s own statement about the collection’s future, so it is taken at face value. Sized to move a collection down roughly one band rather than to floor it: a collection that was well maintained until the day it was deprecated is still better documented and better tested than one that never was, and the score should keep saying so. Deprecated-with-successor stays scored-with-penalty; the successor is shown alongside. |
dropped-from-ansible-package | 10 | applied now | The collection was removed from a released `ansible` package major (a membership interval carries a removal reason). Unlike deprecation this is a THIRD-PARTY judgement the publisher cannot self-declare, which is what makes it worth pricing — but it is smaller than deprecation because removal can follow from a scope decision by the community package rather than from anything wrong with the collection. Charged ONCE: both membership rules deliberately drop out on removal so the same fact is not also deducted inside Trust and compat. |
archived | 10 | declared, deducts nothing yet | The upstream source repository is archived — the strongest available evidence that a collection is no longer developed, because it is a deliberate act by the owner rather than an absence of activity. Requires the GitHub enrichment that arrives in Phase 5, so it is DECLARED HERE AND DEDUCTS NOTHING in v1. It is published now rather than added silently later so the methodology describes the whole intended rubric, and so the version this becomes active in is visible as a changelog line. |
Changelog
Every change to a weight, a rule, the gate, a band cutoff or a deduction is a new scoring version with a dated entry here. A score that moved for a collection nobody touched is explained by one of these lines.
Signal extractor version 2 — scoring version 2, unchanged — 2026-08-07
Nearly every score in the index moved, and no rule, weight, cutoff or deduction changed. What changed is what we file when we read your published tarball and a file is not in it: that used to count as a question we never asked, and it now counts as an answer we measured. If your score dropped for a collection you did not touch, this entry is why — and the drop is ours to explain, not yours to have caused.
- WHAT CHANGED MECHANICALLY. When we open a published collection tarball we read its manifest and look for a changelog, a README and `docs/`, a licence file, and a dependency block. Until now, not finding one was recorded as “we never fetched this” — the same record we write when a download fails. It is now recorded as an observation carrying zero counts: we read your manifest, and what we found was nothing. Those two records are different claims and they were being conflated.
- WHICH RULES THAT MOVED, NAMED EXACTLY, BECAUSE “SOME RULES” IS NOT AN EXPLANATION. Five: `quality.changelog`, `maintenance.changelog_recency`, `quality.docs`, `quality.license_quality` and `security.dependency_boundedness`. Each of them used to leave your calculation entirely when we could not see the file — which shrinks the total your score is measured against — and each of them now stays in and earns a zero we measured. All five are now graded for every scored collection in the index without exception.
- WHAT DID NOT MOVE, AND WHY THAT WAS DELIBERATE. Whether a collection is scored at all is decided by a separate judgeability gate, and that gate was pinned to reproduce its old answer exactly: it still asks “did we ever look at this?”, not “did we find something?”, so an observed zero does not count towards the four signal groups it requires. So the scored and not-scored lists did not change — 2,655 scored and 1,788 not scored, 40.2% of the index — while the numbers on the scored ones did. Nobody gained or lost a score because of this change; people gained and lost points.
- THE MEASURED EFFECT, AND IT CORRECTS SOMETHING THIS PAGE PUBLISHED. The band table on this page used to say the scored subset had a mean around 71.5 and that Poor covered “only about 5%” of it. Measured on the generation now published: the mean is 56.78 and Poor covers 35.3% — 937 of 2,655 scored collections. Those sentences were written before this extractor change and were left standing after it, so this page was publishing a number about a corpus that no longer existed. Naming that is better than quietly deleting it, and the band rationales have been re-derived from the published generation rather than adjusted by hand.
- ROUGHLY A THIRD OF SCORED COLLECTIONS ARE NOW LABELLED POOR, AND WE ARE NOT SOFTENING IT. The cutoffs did not follow the distribution down, and they are staying where they are until the whole index has been re-derived at this extractor version — calibrating against numbers that are themselves scheduled to move would be worse than waiting. Poor means we found weak evidence on what we could observe. It is not an accusation, and it is not mostly deprecation: of those 937, only 67 carry any deduction at all, out of 89 deduction applications in the entire index.
- WHERE THE MOVEMENT ACTUALLY IS, STATED NARROWLY RATHER THAN AS A BLANKET. It is not spread evenly across the five rules. The two changelog-driven ones carry most of it: across the scored index `quality.changelog` now earns 28.9% of the points it could and `maintenance.changelog_recency` 20.8%, each with the same 1,388 collections graded as a failure — the collections that publish no changelog file we can read. By comparison `quality.license_quality` earns 78.8% and `security.dependency_boundedness` 63.2%, so a collection that ships a changelog is largely unaffected by this entry. If you publish a `CHANGELOG.md` or a `changelogs/changelog.yaml` and your score still fell, the cause is more likely `quality.docs` at 49.5%.
- THERE IS NO SCORING VERSION BUMP ATTACHED TO THIS ENTRY, AND THAT IS NOT AN OVERSIGHT. The weights, the rules, the judgeability threshold, the band cutoffs and the deduction magnitudes are all unchanged, so the rubric is still version 2 and a score means the same thing it meant before. What changed is what the stored signals MEAN, one layer upstream of the rubric — the signal extractor went to version 2. Saying so plainly beats letting a reader infer that the rubric moved, and it is exactly why this entry names an extractor version instead of inventing a rubric version that did not happen.
- WHAT YOU CAN DO ABOUT IT. Publish a changelog and keep it current, ship your README and `docs/` inside the tarball rather than only in the repository, declare a licence, and declare your dependencies with an upper bound. All four are things we can only read from what you publish — we do not read your Git repository at all yet, so a file that exists only there is a file we cannot see.
Version 2 — 2026-08-06
Deleting a README, changelog, licence, dependency block, link field or `requires_ansible` declaration can no longer raise your score. Excluding your tests or CI from the published tarball still can, and that one is deliberate — the entry below says why, and names every rule that can still leave your calculation.
- The Trust rule "repository claim" has been replaced by "link claims". It grades how many of the four link fields — `repository`, `documentation`, `homepage` and `issues` — carry a URL we could parse, instead of asking only whether the repository URL parses.
- Why: the old rule returned the same answer for about 99.3% of the collections it graded. A rule that gives nearly everybody the same result separates nobody, so it was adding a near-constant to every Trust subscore while this page described it as a graded signal. Counting four fields instead of one tells collections apart; asking one near-universal question did not.
- Which way scores moved, stated plainly because most returning maintainers will see this one: a collection declaring only a `repository` used to earn this rule’s full point and now earns 30% of it. Declaring more of the four fields is what earns the rest.
- Declaring NO link fields at all earns none of this rule’s point, and the rule stays in your score. It used to be left out of the calculation entirely, on the reasoning that silence is not a failure. That was wrong in a way worth naming: leaving a rule out shrinks the total your score is measured against, so for a collection with no `ansible` package membership — about four in five — deleting every link URL could RAISE the published number by several points. A score you can improve by removing a true fact about your collection is not a score anybody should act on. Reading your metadata and finding four empty fields is something we observed, so it is now graded as a zero we measured rather than a question we never asked. Removing a link you have already declared can only lower your score, never raise it.
- THE SAME CORRECTION, APPLIED EVERYWHERE ELSE IT WAS NEEDED. When this entry first went up it described the change above as though it were confined to link claims, and said that leaving a rule out of the calculation was "only ever applied to things we could not look at". That was not true, and it is worth saying so directly rather than quietly fixing it: four more rules had the identical problem, and the numbers were larger. Deleting a `CHANGELOG.md` was measured at SEVEN points on a typical collection, because it removed both the Quality changelog rule and the Maintenance activity rule from their categories. Writing one dependency name we could not parse was worth TEN, because that rule is the whole Security category and an unreadable declaration made the entire category vanish — while a maintainer who honestly declared an uncapped `>=1.0.0` scored zero on it and kept the full weight. Deleting your README and `docs/` was worth two; deleting an undeclared `LICENSE` file, two more.
- So: shipping no README and no docs, no changelog, or no licence now each score zero and STAY in your score, exactly as an empty links block does. A dependency name we cannot parse is graded as a declaration we could not read rather than discarded, so making a declaration unreadable is no longer a way to avoid being graded on it. Declaring no dependencies at all scores full marks — this page has said so since the first rubric, and until now it was not true in the engine: those collections were losing the Security category instead of earning the marks. If you have no dependencies, you now get them.
- What did NOT change: the Trust category still carries the same weight, the link-claims rule is still worth 1 within Trust, and nothing behind any URL is fetched — scoring remains network-free, so naming somebody else’s repository still earns exactly what naming your own earns. Signals we genuinely could not observe are still left out of the calculation rather than scored as zero.
- YOUR `requires_ansible` IS NOW GRADED RATHER THAN SKIPPED, AND THIS IS THE LARGEST CORRECTION ON THIS PAGE. Until now, not declaring an ansible-core floor removed the rule from your score entirely — and because ansible-core compatibility has only two rules, the second of which applies to almost nobody, that removed the whole 20-point category from what your score was measured against. Measured on a typical collection: declaring `>=2.9` scored 79 and deleting the line scored 96. Pinning — `==2.15.1`, or a `~=` specifier — also scored 96, so the rubric was paying seventeen points for the practice it exists to discourage. Now: declaring no floor scores zero and STAYS in your score, because we read your `galaxy.yml` and found no constraint, which is an observation. A pin, a `~=`, or a ceiling with no floor earns a small share — it is a real declaration we could read, so it beats declaring nothing, and it sits below every floor tier. Only a value we cannot parse at all (`None` is the common one) is graded as unreadable.
- THE PREVIOUS VERSION OF THIS ENTRY SAID SOMETHING FALSE AND IT IS WORTH NAMING RATHER THAN QUIETLY DELETING. It claimed "Removing something from your collection can no longer raise its score", which was untrue by up to seventeen points on the day it was published. It then said "Three things leave the calculation, and none of them is something you can trigger by deleting a file you already publish" — and named, as the third of the three, a `requires_ansible` you did not declare, which IS something you trigger by deleting what you publish. The sentence contradicted its own list four lines later. This is the third time a promise on this page has been broader than the engine kept, so the list below is no longer a sentence: it is generated from the same data the engine is tested against, and the test fails if the two disagree.
- WHAT CAN STILL LEAVE YOUR CALCULATION — all 5 of them, generated from the engine's own list rather than written out by hand: • `quality.tests` — No test evidence in the published artifact. `build_ignore` strips `tests/` from published tarballs on Ansible’s own documented advice, so its absence from your tarball tells us nothing about your repository and we will not deduct for it. (YOU CAN TRIGGER THIS; fires for 78.2% (3,473 of 4,442) of the index). • `quality.ci` — No CI evidence in the published artifact — the same `build_ignore` case, applied to `.github/`, and the sharper one: excluding it is what the packaging documentation recommends. (YOU CAN TRIGGER THIS; fires for 76.4% (3,394 of 4,442) of the index). • `trust.ansible_membership` — The collection has never shipped in a released `ansible` package major, or was removed from one. Inclusion is an opt-in curation process most collections never enter, and "did not apply" is indistinguishable in our data from "applied and was declined" — so the absence is silence, not a low score. Removal is charged once, as a flat penalty. (not something you control; fires for 97.1% (4,314 of 4,442) of the index). • `compat.membership_currency` — The same fact, read for a different question: tenure asks how long the collection was carried, currency asks whether it still is. Neither is something a publisher declares. (not something you control; fires for 97.1% (4,314 of 4,442) of the index). • `maintenance.release_recency` — We hold no release date for the collection. This is a gap in OUR data, never a statement about the collection, and it currently fires for nothing at all. (not something you control; fires for 0% (0 of 4,442 — reachable, but not reached today) of the index).
- TWO OF THOSE FIVE ARE THINGS YOU CAN TRIGGER, AND SAYING SO IS THE POINT. Adding `tests/` or `.github/` to `build_ignore` removes those rules from your score rather than scoring them zero, and on a collection that would otherwise score badly on them, that can raise your published number. We know. It is the deliberate trade-off described under "depth signals": we cannot tell "this collection has no tests" from "the tests were not packaged", and Ansible’s own documentation tells you to exclude them, so deducting would punish you for following upstream guidance. Reading your repository directly is what will let us grade their absence fairly, and until then we would rather be exploitable in one clearly-labelled place than wrong about everybody.
- ONE THING THAT IS NOT ON THAT LIST, AND WAS ON THE PREVIOUS ONE. A collection whose published artifact we could not fetch or read at all does not have rules removed from its calculation — it gets no score at all, and is listed as unscored. That is a different mechanism with a different meaning, and describing it as a drop-out was describing the wrong thing.
- What you can do about it: fill in the link fields you have left empty, and fix any that do not parse. A declared-but-unparseable field still counts as an observed failure rather than as an absence, and the breakdown now reports how many of your four fields were declared and how many were unreadable.
- Housekeeping, with no effect on any published score: the internal guard that watches for signals which grade nobody now compares the points a rule awards rather than merely whether it awarded any. The guard gates publication and contributes no points.
Version 1 — 2026-08-06
First published rubric.
- Five weighted categories: Security 10, Trust 12, Quality 30, Maintenance 28, ansible-core compatibility 20. Anchored on nuxt.care’s published weights, with every deviation stated in the category table.
- Signals we did not observe are removed from the calculation instead of scored as zero. A category with nothing observable in it drops out of the weighted total entirely.
- A declared-but-unreadable value is graded as an observed failure, not as an absence.
- Collections with fewer than 4 observed signal groups, or with no plugins, roles or playbook content at all, are listed without a score. This is a statement about how much we could observe, not a verdict on the collection.
- Deprecated collections are deducted 15 points and removal from the `ansible` package 10, after the weighted total, floored at 0. Repository-archived is published in the penalty table but deducts nothing until the upstream data lands.
- Collections that have disappeared from the Galaxy index show no score at all, rather than a low one.
- Download counts, stars and any other popularity measure are excluded from the calculation by construction — the engine is not given them.