|
| 1 | +// SPDX-License-Identifier: CC-BY-SA-4.0 |
| 2 | +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk> |
| 3 | += Rhodium Standard Repository (RSR) Specification — Version 2.0 |
| 4 | +Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
| 5 | +:revnumber: 2.0.0-draft |
| 6 | +:revdate: 2026-07-03 |
| 7 | +:toc: left |
| 8 | +:toclevels: 3 |
| 9 | +:icons: font |
| 10 | +:sectnums: |
| 11 | + |
| 12 | +[IMPORTANT] |
| 13 | +==== |
| 14 | +*Status: DRAFT.* This specification MUST NOT be cited as a ratified standard |
| 15 | +until the ratification bar in <<ratification>> is met. Its single source of |
| 16 | +truth is the machine-readable criteria file |
| 17 | +link:rsr-criteria-v2.a2ml[`rsr-criteria-v2.a2ml`]; where this prose and that |
| 18 | +file disagree, *the machine-readable file is authoritative* and this prose is a |
| 19 | +generation defect to be fixed. |
| 20 | +==== |
| 21 | + |
| 22 | +== 1. Why v2.0 exists |
| 23 | + |
| 24 | +RSR v1.0 (frozen 2025-12-27) can no longer describe the estate it governs, for |
| 25 | +three structural reasons this version fixes: |
| 26 | + |
| 27 | +. *The freeze was violated in place, not honoured.* v1.0 declared its Language |
| 28 | + Policy, tiers, and required files "immutable", yet `spec/LANGUAGE-POLICY.adoc` |
| 29 | + advanced to v1.2.2 and `TIERS.adoc` was edited post-freeze. A freeze enforced |
| 30 | + only by a prose banner is not a freeze. v2.0 replaces it with a *hash-pinned* |
| 31 | + freeze and a CI guard (<<versioning>>). |
| 32 | +. *The written spec, the machine spec, and reality diverged three ways.* v1.0's |
| 33 | + machine criteria (`spec.scm/compliance-criteria.scm`) still require GitLab, |
| 34 | + Nix flakes, ReScript, RVC, SaltRover and `META/ECOSYSTEM/STATE.scm`. The |
| 35 | + estate is GitHub, Guix-primary, AffineScript, Python/V/ReScript-banned, and |
| 36 | + A2ML. *Every current repo fails the v1.0 machine criteria.* v2.0 re-bases the |
| 37 | + criteria on measured estate reality (<<migration>>). |
| 38 | +. *There was no single oracle.* At least five checkers (`rsr-audit.sh`, |
| 39 | + `rsr-check.scm`, `rsr-compliance-checklist.k9.ncl`, `COMPLIANCE_CHECKLIST.md`, |
| 40 | + the `rsr-certifier` product) each claimed to check RSR, disagreed on criteria, |
| 41 | + and none ran in CI. v2.0 designates *exactly one* normative oracle |
| 42 | + (<<oracle>>) and derives everything else from the SSOT. |
| 43 | + |
| 44 | +RSR v2.0 is a MAJOR (era) change. It does not pretend to be backward-compatible |
| 45 | +with v1.0 criteria; it supersedes them. |
| 46 | + |
| 47 | +== 2. Conformance language |
| 48 | + |
| 49 | +The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, |
| 50 | +MAY, and OPTIONAL are to be interpreted as described in RFC 2119 and RFC 8174 |
| 51 | +when, and only when, they appear in capitals. |
| 52 | + |
| 53 | +A *repository* is *RSR-conformant at tier T* iff the normative oracle |
| 54 | +(<<oracle>>), run against the repository's committed tree and its declared |
| 55 | +capability profile, computes a tier `>= T` per the scoring model (<<scoring>>). |
| 56 | + |
| 57 | +== 3. What RSR is (and is not) |
| 58 | + |
| 59 | +RSR is the estate's *repository-shape* standard: the normative definition of the |
| 60 | +files, policies, and machine-readable substrate a hyperpolymath repository |
| 61 | +carries, projected onto four tiers. It is the specification that |
| 62 | +`hyperpolymath/rsr-template-repo` operationalises as a scaffold and that |
| 63 | +`hyperpolymath/hypatia` enforces as scan rules. |
| 64 | + |
| 65 | +RSR is NOT: |
| 66 | + |
| 67 | +* a build system (that is `Justfile`/`Mustfile`); |
| 68 | +* the template itself (that is `rsr-template-repo`, the *operationalisation*); |
| 69 | +* the readiness-grade rubrics (CRG/TRG/ARG/FRG grade *maturity*; RSR grades |
| 70 | + *shape*). The scales are aligned (<<scoring>>) but distinct. |
| 71 | + |
| 72 | +== 4. The single source of truth [[ssot]] |
| 73 | + |
| 74 | +All RSR v2.0 criteria live in exactly one file: |
| 75 | +link:rsr-criteria-v2.a2ml[`spec/rsr-criteria-v2.a2ml`], authored in the *A2ML |
| 76 | +record dialect* (link:../../a2ml/RECORD-DIALECT-SPEC.adoc[`RECORD-DIALECT-SPEC.adoc`] |
| 77 | +— RSR dogfoods the estate's own metadata format). Every derived artefact — |
| 78 | + |
| 79 | +* the human `COMPLIANCE_CHECKLIST` (prose), |
| 80 | +* the normative oracle's rule table, |
| 81 | +* the tier badge thresholds, |
| 82 | +* any k9 kennel data, |
| 83 | + |
| 84 | +— MUST be GENERATED from that file and MUST NOT be hand-maintained. This is |
| 85 | +"solutions at source" (RSR-PHILOSOPHY.adoc) applied to RSR itself: a criterion |
| 86 | +is added or changed in one place, and the checklist, checker, and badges follow. |
| 87 | +Hand-editing a generated artefact is a defect. |
| 88 | + |
| 89 | +Each criterion in the SSOT carries a `detect` field (the oracle rule id that |
| 90 | +checks it, or the literal `manual` when no automated check exists yet) and a |
| 91 | +`template_ref` field (where `rsr-template-repo` satisfies it). Together these |
| 92 | +make *spec → checker → template* traceability machine-checkable (<<traceability>>). |
| 93 | + |
| 94 | +== 5. Tiers and scoring [[scoring]] |
| 95 | + |
| 96 | +=== 5.1 The four tiers |
| 97 | + |
| 98 | +[cols="1,1,3",options="header"] |
| 99 | +|=== |
| 100 | +| Tier | Score | Meaning |
| 101 | +| Bronze | `>= 75%` | Minimum viable RSR shape: identity, licence, security policy, CI, SPDX, no banned languages. |
| 102 | +| Silver | `>= 90%` | Professional: governance-health docs, well-known, Scorecard ≥ 7.0, SHA-pinned actions, AI manifest. |
| 103 | +| Gold | `= 100%` | Full applicable compliance: descriptiles substrate, Scorecard ≥ 9.0, hardened workflows, no silent-green. |
| 104 | +| Rhodium | `100% + exemplary` | Gold plus the `rhodium`-gated exemplary criteria a repo is capable of (formal proofs, succession, provenance chains). |
| 105 | +|=== |
| 106 | + |
| 107 | +Thresholds are inclusive lower bounds and are defined authoritatively in the |
| 108 | +SSOT `[tiers]` block. |
| 109 | + |
| 110 | +=== 5.2 Capability-gated scoring (the core change from v1.0) |
| 111 | + |
| 112 | +v1.0 scored every repository against all 11 categories, so a small Rust CLI was |
| 113 | +marked non-compliant for lacking a mobile shell, an ABI proof tree, and a web |
| 114 | +UI it was never meant to have. v2.0 adopts the capability-gate model of |
| 115 | +link:../../TEMPLATE-APPLICABILITY-POLICY.adoc[`TEMPLATE-APPLICABILITY-POLICY.adoc`]: |
| 116 | + |
| 117 | +. A repository declares its capabilities in |
| 118 | + `.machine_readable/rsr-profile.a2ml` (directly or via a preset). |
| 119 | +. A criterion is *applicable* iff its `gate` is `universal` OR the repository |
| 120 | + declares the gating capability. |
| 121 | +. *Score* = (sum of weights of applicable criteria that pass) / (sum of weights |
| 122 | + of applicable criteria). Non-applicable criteria are scored `na` and excluded |
| 123 | + from the denominator — they neither help nor hurt. |
| 124 | +. A criterion MAY return `partial` (half weight), reported explicitly. |
| 125 | + |
| 126 | +[WARNING] |
| 127 | +==== |
| 128 | +*No tier by declaring-away.* A repository MUST NOT reach a tier by omitting from |
| 129 | +its profile a capability it actually has (e.g. hiding that it ships a container |
| 130 | +to dodge the rootless-container criterion). The oracle MUST cross-check declared |
| 131 | +capabilities against detected ones and MUST flag under-declaration. This finding |
| 132 | +is `:review` (a judgement), never `:auto_execute`. |
| 133 | +==== |
| 134 | + |
| 135 | +=== 5.3 Relation to the readiness grades |
| 136 | + |
| 137 | +RSR tiers project onto the shared `X F E D C B A` readiness scale |
| 138 | +(Bronze≈C, Silver≈B, Gold≈A, Rhodium≈A+). RSR measures repository *shape*; the |
| 139 | +CRG/TRG/ARG/FRG rubrics measure component/toolchain/adoption/foundations |
| 140 | +*maturity*. A repo can be Gold-shaped and still CRG-C mature; the two are |
| 141 | +orthogonal axes, deliberately. |
| 142 | + |
| 143 | +== 6. The normative oracle [[oracle]] |
| 144 | + |
| 145 | +There is *exactly one* normative RSR checker: the hypatia rule family |
| 146 | +`rsr-conformance`, which consumes the SSOT and writes a per-repository scorecard |
| 147 | +into verisim-data (the `.machine_readable/scorecards/<repo>.scorecard.a2ml` |
| 148 | +shape already used by the OpenSSF scorecard ingestor). hypatia is chosen because |
| 149 | +it is the estate scanner already wired to the scan → route → remediate loop. |
| 150 | + |
| 151 | +All other historical checkers are *non-normative* as of v2.0: |
| 152 | + |
| 153 | +* `rsr-audit.sh`, `rsr-check.scm`, `rsr-compliance-checklist.k9.ncl` — retired; |
| 154 | + kept only as reference until the oracle ships, then removed. |
| 155 | +* `COMPLIANCE_CHECKLIST.md` — GENERATED from the SSOT, not authored. |
| 156 | +* `rhodium-pipeline`'s `rsr-certifier` — a product; it MAY consume the SSOT but |
| 157 | + is not the spec's oracle. |
| 158 | + |
| 159 | +Two supporting guards are REQUIRED: |
| 160 | + |
| 161 | +* *Freeze guard* (`rsr-criteria-freeze`): fails any change to a frozen major's |
| 162 | + criteria file whose byte-hash no longer matches its registry pin. |
| 163 | +* *Dogfood gate*: CI runs the oracle against `rsr-template-repo` on every change |
| 164 | + to either repo and REQUIRES Gold for the template's applicable set. Until the |
| 165 | + oracle ships, this gate is declared PENDING, not passing (no silent green). |
| 166 | + |
| 167 | +NOTE: The oracle implementation is the subject of the companion work item |
| 168 | +"HYP-S rule interpreter" — hypatia loading rule/criteria definitions from |
| 169 | +standards rather than hand-porting them. Until it lands, RSR v2.0 conformance is |
| 170 | +*specified but not yet machine-enforced*, and this document says so plainly |
| 171 | +rather than claiming an enforcement that does not exist. |
| 172 | + |
| 173 | +== 7. Traceability [[traceability]] |
| 174 | + |
| 175 | +For every criterion, the SSOT records the oracle rule that detects it and the |
| 176 | +template location that satisfies it. Two machine checks make this honest: |
| 177 | + |
| 178 | +. *Detection coverage*: the fraction of criteria whose `detect` is a real rule |
| 179 | + id (not `manual`) is the spec's *automatable coverage*; it MUST be published, |
| 180 | + not hidden. A criterion moving from `manual` to a rule id is a PATCH bump. |
| 181 | +. *Template satisfaction*: every `template_ref` MUST resolve in |
| 182 | + `rsr-template-repo`, OR the criterion MUST be gated by a capability the |
| 183 | + template's own profile does not declare. A dangling `template_ref` is a defect |
| 184 | + in either the spec or the template — the dogfood gate surfaces which. |
| 185 | + |
| 186 | +This replaces v1.0's missing spec-to-template traceability matrix, under which |
| 187 | +"does the template implement the spec" was mechanically unanswerable. |
| 188 | + |
| 189 | +== 8. Versioning and freeze [[versioning]] |
| 190 | + |
| 191 | +RSR uses semantic versioning with an errata track. The rules are authoritative |
| 192 | +in the SSOT `[versioning]` block; in prose: |
| 193 | + |
| 194 | +* *MAJOR* — an era change. MAY remove/redefine criteria or move a criterion |
| 195 | + between tiers. Cutting a major *freezes the prior major*: its criteria file is |
| 196 | + copied to `spec/archive/rsr-criteria-vN.a2ml` and its byte-hash is pinned in |
| 197 | + the registry. The freeze guard then makes the frozen file immutable in CI. |
| 198 | +* *MINOR* — additive only. MAY add criteria or add a capability gate, but MUST |
| 199 | + NOT make a previously-conforming repo non-conforming *at the same tier*. |
| 200 | +* *PATCH* — editorial: wording, `detect` corrections, `template_ref` fixes. No |
| 201 | + criteria-set change. |
| 202 | + |
| 203 | +A freeze is thus a cryptographic fact (a pinned hash + a CI guard), not a |
| 204 | +promise. This is the direct fix for v1.0's freeze-in-name-only failure. |
| 205 | + |
| 206 | +== 9. Migration from v1.0 [[migration]] |
| 207 | + |
| 208 | +The criteria set was re-based on measured estate reality. The load-bearing |
| 209 | +deltas (full per-criterion mapping is generated into |
| 210 | +`spec/RSR-V1-TO-V2-DELTA.adoc` as a follow-up): |
| 211 | + |
| 212 | +[cols="2,2,3",options="header"] |
| 213 | +|=== |
| 214 | +| v1.0 criterion | v2.0 disposition | Reason |
| 215 | +| `nix-flake` (flake.nix) | → `guix-primary` (guix.scm), Nix fallback retiring | Guix-primary policy; Nix-mirror retirement (standards#102). |
| 216 | +| `gitlab` (repo on GitLab) | → `scm-github` | Estate canonical forge is GitHub; GitLab is mirror-only. |
| 217 | +| `rvc`, `saltrover` | REMOVED | Obsolete tooling; not part of the estate. |
| 218 | +| `meta-scm`/`ecosystem-scm`/`state-scm` | → descriptiles `META/ECOSYSTEM/STATE.a2ml` | `.scm` era retired; A2ML is the metadata format. |
| 219 | +| `.machine_readable/6a2/` | → `.machine_readable/descriptiles/` | `6a2` deprecated 2026-06-30. |
| 220 | +| 6 A2ML files | → 8 (adds `ANCHOR`, `CLADE`) | Canonical descriptile set expanded. |
| 221 | +| `LICENSE.txt` | → `LICENSE` + `LICENSES/` (REUSE) | Estate file convention; hypatia `root_hygiene` to be realigned to match. |
| 222 | +| `palimpsest` (everywhere) | → `licence-classified` (5-way, FLAG-ONLY) | Palimpsest is exactly three repos; licence detection is `:review`, never auto-edited. |
| 223 | +| DNSSEC / Schema.org / Webmention / POSSE | GATED by `web-ui`/`docs-site`/`api-service` | Deployment concerns, not repo-shape universals. |
| 224 | +| flat "all 11 categories" | → capability-gated applicable set | Fixes over-scaffolding of leaf repos. |
| 225 | +|=== |
| 226 | + |
| 227 | +The v1.0 `spec.scm/`, `VERSION.adoc` (freeze banner), and the five divergent |
| 228 | +checkers are superseded. They are retained read-only until the oracle ships, |
| 229 | +then archived — no deletion by access-recency, but no longer normative. |
| 230 | + |
| 231 | +== 10. Ratification bar [[ratification]] |
| 232 | + |
| 233 | +RSR v2.0 leaves `draft` and becomes `stable` only when ALL of the following |
| 234 | +hold — mirroring the estate's spec-recognition bar and the record-dialect |
| 235 | +spec's own Appendix-D discipline: |
| 236 | + |
| 237 | +. *Oracle exists*: the `rsr-conformance` hypatia rule family consumes the SSOT |
| 238 | + and produces scorecards. |
| 239 | +. *Dogfood green*: the dogfood gate runs in real CI (no `|| echo SKIP`) and |
| 240 | + `rsr-template-repo` scores Gold on its applicable set. |
| 241 | +. *Corpus run*: the oracle is run across the estate; the per-repo tier |
| 242 | + distribution is published to verisim-data and the residual non-conforming set |
| 243 | + is filed as findings (not hidden). |
| 244 | +. *Traceability green*: automatable-coverage and template-satisfaction checks |
| 245 | + (<<traceability>>) pass; no dangling `template_ref`. |
| 246 | +. *Owner ratification*: the owner bumps the SSOT `[meta].status` to `stable` and |
| 247 | + cuts `2.0.0`, freezing it per <<versioning>>. |
| 248 | + |
| 249 | +Until then, every RSR badge in the estate MUST be read as "self-asserted", and |
| 250 | +this specification MUST NOT be cited as ratified. |
| 251 | + |
| 252 | +== Appendix A: Security considerations |
| 253 | + |
| 254 | +A conformance oracle that writes scorecards is a *reporting* tool, not an |
| 255 | +enforcement capability: it MUST NOT gain execution, network, or write access to |
| 256 | +the repositories it scores beyond reading their trees and writing to |
| 257 | +verisim-data. Licence-classification criteria (`7.1.1`) are detection-only and |
| 258 | +`:review`-capped; the oracle MUST NOT auto-edit licence content under any tier, |
| 259 | +per the estate's manual-only licence guardrail. |
| 260 | + |
| 261 | +== Appendix B: Change log |
| 262 | + |
| 263 | +* *2.0.0-draft (2026-07-03)* — Initial v2.0 draft. Re-bases criteria on measured |
| 264 | + estate reality; introduces capability-gated scoring, the single-oracle model, |
| 265 | + the hash-pinned freeze, spec→checker→template traceability, and the A2ML |
| 266 | + record-dialect SSOT. Supersedes the v1.0 frozen spec and its five checkers. |
| 267 | + |
| 268 | +''' |
| 269 | +*Version*: 2.0.0-draft + |
| 270 | +*Status*: Draft (see <<ratification>>) + |
| 271 | +*Era*: v2 + |
| 272 | +*SSOT*: `spec/rsr-criteria-v2.a2ml` + |
| 273 | +*Date*: 2026-07-03 |
0 commit comments