Skip to content

Commit 0d76543

Browse files
Add RSR v2.0 specification + machine-readable criteria SSOT (#465)
## What & why RSR v1.0 (frozen 2025-12-27) can no longer describe the estate it governs. This PR adds **RSR v2.0 as a DRAFT era-change** that fixes the three structural failures the recent audit surfaced: 1. **The freeze was violated in place, not honoured.** v1.0 declared its criteria "immutable" but `LANGUAGE-POLICY.adoc` advanced to v1.2.2 and `TIERS.adoc` was edited post-freeze. A prose banner is not a freeze. 2. **Spec, machine-spec, and reality diverged three ways.** v1.0's machine criteria (`spec.scm/compliance-criteria.scm`) still require GitLab, Nix flakes, ReScript, RVC, SaltRover, and `META/ECOSYSTEM/STATE.scm`. The estate is GitHub, Guix-primary, AffineScript, Python/V/ReScript-banned, A2ML — **every current repo fails the v1.0 machine criteria.** 3. **No single oracle.** Five checkers (`rsr-audit.sh`, `rsr-check.scm`, `rsr-compliance-checklist.k9.ncl`, `COMPLIANCE_CHECKLIST.md`, the `rsr-certifier` product) each claimed to check RSR, disagreed, and none ran in CI. ## Contents - **`rhodium-standard-repositories/spec/rsr-criteria-v2.a2ml`** — the **single source of truth**, authored in the A2ML **record dialect** (dogfoods the just-merged `RECORD-DIALECT-SPEC`). 11 weighted categories, **74 criteria**, each **re-based on a measured survey of estate reality** — the file set `rsr-template-repo` actually ships plus the rules `hypatia` actually enforces — not the abandoned `.scm` era. Every criterion carries: - `detect` — the hypatia rule id that checks it, or the literal `manual` (honest: no automated check yet), and - `template_ref` — where `rsr-template-repo` satisfies it, making **spec → checker → template traceability** machine-checkable (the matrix v1.0 never had). - **`rhodium-standard-repositories/spec/RSR-SPEC-v2.adoc`** — the normative spec (RFC-2119): - **Capability-gated scoring** — a repo is scored only against criteria its declared capabilities (`rsr-profile.a2ml`, per `TEMPLATE-APPLICABILITY-POLICY`) activate; non-applicable criteria are `na` and excluded from the denominator. Fixes v1.0's flat "every repo needs all 11 categories", which marked a small Rust CLI non-compliant for lacking a mobile shell. - **One normative oracle** — the hypatia `rsr-conformance` rule family; the other five checkers are declared **non-normative**. - **Hash-pinned freeze + CI guard** replacing the prose "FROZEN" banner (fixes failure #1 cryptographically). - A **v1→v2 migration delta** table (nix→guix, gitlab→github, .scm→.a2ml, 6a2→descriptiles, +ANCHOR/CLADE, LICENSE.txt→LICENSE, palimpsest→5-way-classified-flag-only). ## Key design decision RSR v2.0 makes **one** of the three currently-disagreeing sources (frozen spec / template / hypatia rules) canonical — the machine-readable SSOT — and requires everything else (prose checklist, checker rule table, badge thresholds) to be **generated** from it. "Solutions at source" applied to the standard itself; hand-editing a generated artefact becomes a defect. ## Status: Draft (deliberately) Per the no-overclaim doctrine, the spec states it **MUST NOT be cited as ratified** until the ratification bar in §10 is met: 1. the `rsr-conformance` oracle exists (this is the companion "HYP-S rule interpreter" work item — hypatia loading criteria from standards rather than hand-porting); 2. the dogfood gate is green in real CI (no `|| echo SKIP`) with `rsr-template-repo` at Gold; 3. a corpus run publishes the per-repo tier distribution + residual non-conforming set to verisim-data; 4. traceability checks pass (no dangling `template_ref`); 5. owner ratification → bump `[meta].status` to `stable` and freeze. ## Scope / follow-ups (not in this PR) - The generator (SSOT → prose checklist / checker config / badges) — mechanical. - The `rsr-conformance` hypatia oracle + freeze guard — the next work item. - `RSR-V1-TO-V2-DELTA.adoc` (full per-criterion mapping) — generated. - Freezing v1.0 into `spec/archive/` — deferred until v2.0 is ratified; v1.0 files are left in place (no deletion by access-recency). ## Guardrails respected No licence content touched; no SPDX sweeps; new files carry correct SPDX from birth (`.adoc` → CC-BY-SA-4.0, `.a2ml` → MPL-2.0, matching the existing `spec/` convention). Licence-classification criterion `7.1.1` is explicitly detection-only / `:review`, never auto-edited. `.machine_readable/REGISTRY.a2ml` regenerated with `scripts/build-registry.sh` (the sanctioned generator — not hand-edited); `--check` passes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0112RkdER2wtwHdNmbEhThUz --- _Generated by [Claude Code](https://claude.ai/code/session_0112RkdER2wtwHdNmbEhThUz)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent f81bb04 commit 0d76543

3 files changed

Lines changed: 523 additions & 1 deletion

File tree

.machine_readable/REGISTRY.a2ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ name = "RSR — Rhodium Standard Repositories"
216216
stream = "governance"
217217
home = "rhodium-standard-repositories/"
218218
canonical_doc = "rhodium-standard-repositories/README.adoc"
219-
source_hash = "sha256:3e721ecb348d176a2e1ba82bb6ea6b9365e8375c4ca80f1f3f4c9e9e343269f8"
219+
source_hash = "sha256:014f952aca7e50ac887ddf84e7f8d049c9eb3f5bf07b658e24ac9dd81b038457"
220220
route = "the repository-compliance standard every repo is graded against"
221221

222222
[[spec]]
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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

Comments
 (0)