diff --git a/.machine_readable/REGISTRY.a2ml b/.machine_readable/REGISTRY.a2ml index 2c95e67a..fa7884e2 100644 --- a/.machine_readable/REGISTRY.a2ml +++ b/.machine_readable/REGISTRY.a2ml @@ -216,7 +216,7 @@ name = "RSR — Rhodium Standard Repositories" stream = "governance" home = "rhodium-standard-repositories/" canonical_doc = "rhodium-standard-repositories/README.adoc" -source_hash = "sha256:3e721ecb348d176a2e1ba82bb6ea6b9365e8375c4ca80f1f3f4c9e9e343269f8" +source_hash = "sha256:014f952aca7e50ac887ddf84e7f8d049c9eb3f5bf07b658e24ac9dd81b038457" route = "the repository-compliance standard every repo is graded against" [[spec]] diff --git a/rhodium-standard-repositories/spec/RSR-SPEC-v2.adoc b/rhodium-standard-repositories/spec/RSR-SPEC-v2.adoc new file mode 100644 index 00000000..134d6daa --- /dev/null +++ b/rhodium-standard-repositories/spec/RSR-SPEC-v2.adoc @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) += Rhodium Standard Repository (RSR) Specification — Version 2.0 +Jonathan D.A. Jewell +:revnumber: 2.0.0-draft +:revdate: 2026-07-03 +:toc: left +:toclevels: 3 +:icons: font +:sectnums: + +[IMPORTANT] +==== +*Status: DRAFT.* This specification MUST NOT be cited as a ratified standard +until the ratification bar in <> is met. Its single source of +truth is the machine-readable criteria file +link:rsr-criteria-v2.a2ml[`rsr-criteria-v2.a2ml`]; where this prose and that +file disagree, *the machine-readable file is authoritative* and this prose is a +generation defect to be fixed. +==== + +== 1. Why v2.0 exists + +RSR v1.0 (frozen 2025-12-27) can no longer describe the estate it governs, for +three structural reasons this version fixes: + +. *The freeze was violated in place, not honoured.* v1.0 declared its Language + Policy, tiers, and required files "immutable", yet `spec/LANGUAGE-POLICY.adoc` + advanced to v1.2.2 and `TIERS.adoc` was edited post-freeze. A freeze enforced + only by a prose banner is not a freeze. v2.0 replaces it with a *hash-pinned* + freeze and a CI guard (<>). +. *The written spec, the 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, and + A2ML. *Every current repo fails the v1.0 machine criteria.* v2.0 re-bases the + criteria on measured estate reality (<>). +. *There was no single oracle.* At least 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 on criteria, + and none ran in CI. v2.0 designates *exactly one* normative oracle + (<>) and derives everything else from the SSOT. + +RSR v2.0 is a MAJOR (era) change. It does not pretend to be backward-compatible +with v1.0 criteria; it supersedes them. + +== 2. Conformance language + +The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, +MAY, and OPTIONAL are to be interpreted as described in RFC 2119 and RFC 8174 +when, and only when, they appear in capitals. + +A *repository* is *RSR-conformant at tier T* iff the normative oracle +(<>), run against the repository's committed tree and its declared +capability profile, computes a tier `>= T` per the scoring model (<>). + +== 3. What RSR is (and is not) + +RSR is the estate's *repository-shape* standard: the normative definition of the +files, policies, and machine-readable substrate a hyperpolymath repository +carries, projected onto four tiers. It is the specification that +`hyperpolymath/rsr-template-repo` operationalises as a scaffold and that +`hyperpolymath/hypatia` enforces as scan rules. + +RSR is NOT: + +* a build system (that is `Justfile`/`Mustfile`); +* the template itself (that is `rsr-template-repo`, the *operationalisation*); +* the readiness-grade rubrics (CRG/TRG/ARG/FRG grade *maturity*; RSR grades + *shape*). The scales are aligned (<>) but distinct. + +== 4. The single source of truth [[ssot]] + +All RSR v2.0 criteria live in exactly one file: +link:rsr-criteria-v2.a2ml[`spec/rsr-criteria-v2.a2ml`], authored in the *A2ML +record dialect* (link:../../a2ml/RECORD-DIALECT-SPEC.adoc[`RECORD-DIALECT-SPEC.adoc`] +— RSR dogfoods the estate's own metadata format). Every derived artefact — + +* the human `COMPLIANCE_CHECKLIST` (prose), +* the normative oracle's rule table, +* the tier badge thresholds, +* any k9 kennel data, + +— MUST be GENERATED from that file and MUST NOT be hand-maintained. This is +"solutions at source" (RSR-PHILOSOPHY.adoc) applied to RSR itself: a criterion +is added or changed in one place, and the checklist, checker, and badges follow. +Hand-editing a generated artefact is a defect. + +Each criterion in the SSOT carries a `detect` field (the oracle rule id that +checks it, or the literal `manual` when no automated check exists yet) and a +`template_ref` field (where `rsr-template-repo` satisfies it). Together these +make *spec → checker → template* traceability machine-checkable (<>). + +== 5. Tiers and scoring [[scoring]] + +=== 5.1 The four tiers + +[cols="1,1,3",options="header"] +|=== +| Tier | Score | Meaning +| Bronze | `>= 75%` | Minimum viable RSR shape: identity, licence, security policy, CI, SPDX, no banned languages. +| Silver | `>= 90%` | Professional: governance-health docs, well-known, Scorecard ≥ 7.0, SHA-pinned actions, AI manifest. +| Gold | `= 100%` | Full applicable compliance: descriptiles substrate, Scorecard ≥ 9.0, hardened workflows, no silent-green. +| Rhodium | `100% + exemplary` | Gold plus the `rhodium`-gated exemplary criteria a repo is capable of (formal proofs, succession, provenance chains). +|=== + +Thresholds are inclusive lower bounds and are defined authoritatively in the +SSOT `[tiers]` block. + +=== 5.2 Capability-gated scoring (the core change from v1.0) + +v1.0 scored every repository against all 11 categories, so a small Rust CLI was +marked non-compliant for lacking a mobile shell, an ABI proof tree, and a web +UI it was never meant to have. v2.0 adopts the capability-gate model of +link:../../TEMPLATE-APPLICABILITY-POLICY.adoc[`TEMPLATE-APPLICABILITY-POLICY.adoc`]: + +. A repository declares its capabilities in + `.machine_readable/rsr-profile.a2ml` (directly or via a preset). +. A criterion is *applicable* iff its `gate` is `universal` OR the repository + declares the gating capability. +. *Score* = (sum of weights of applicable criteria that pass) / (sum of weights + of applicable criteria). Non-applicable criteria are scored `na` and excluded + from the denominator — they neither help nor hurt. +. A criterion MAY return `partial` (half weight), reported explicitly. + +[WARNING] +==== +*No tier by declaring-away.* A repository MUST NOT reach a tier by omitting from +its profile a capability it actually has (e.g. hiding that it ships a container +to dodge the rootless-container criterion). The oracle MUST cross-check declared +capabilities against detected ones and MUST flag under-declaration. This finding +is `:review` (a judgement), never `:auto_execute`. +==== + +=== 5.3 Relation to the readiness grades + +RSR tiers project onto the shared `X F E D C B A` readiness scale +(Bronze≈C, Silver≈B, Gold≈A, Rhodium≈A+). RSR measures repository *shape*; the +CRG/TRG/ARG/FRG rubrics measure component/toolchain/adoption/foundations +*maturity*. A repo can be Gold-shaped and still CRG-C mature; the two are +orthogonal axes, deliberately. + +== 6. The normative oracle [[oracle]] + +There is *exactly one* normative RSR checker: the hypatia rule family +`rsr-conformance`, which consumes the SSOT and writes a per-repository scorecard +into verisim-data (the `.machine_readable/scorecards/.scorecard.a2ml` +shape already used by the OpenSSF scorecard ingestor). hypatia is chosen because +it is the estate scanner already wired to the scan → route → remediate loop. + +All other historical checkers are *non-normative* as of v2.0: + +* `rsr-audit.sh`, `rsr-check.scm`, `rsr-compliance-checklist.k9.ncl` — retired; + kept only as reference until the oracle ships, then removed. +* `COMPLIANCE_CHECKLIST.md` — GENERATED from the SSOT, not authored. +* `rhodium-pipeline`'s `rsr-certifier` — a product; it MAY consume the SSOT but + is not the spec's oracle. + +Two supporting guards are REQUIRED: + +* *Freeze guard* (`rsr-criteria-freeze`): fails any change to a frozen major's + criteria file whose byte-hash no longer matches its registry pin. +* *Dogfood gate*: CI runs the oracle against `rsr-template-repo` on every change + to either repo and REQUIRES Gold for the template's applicable set. Until the + oracle ships, this gate is declared PENDING, not passing (no silent green). + +NOTE: The oracle implementation is the subject of the companion work item +"HYP-S rule interpreter" — hypatia loading rule/criteria definitions from +standards rather than hand-porting them. Until it lands, RSR v2.0 conformance is +*specified but not yet machine-enforced*, and this document says so plainly +rather than claiming an enforcement that does not exist. + +== 7. Traceability [[traceability]] + +For every criterion, the SSOT records the oracle rule that detects it and the +template location that satisfies it. Two machine checks make this honest: + +. *Detection coverage*: the fraction of criteria whose `detect` is a real rule + id (not `manual`) is the spec's *automatable coverage*; it MUST be published, + not hidden. A criterion moving from `manual` to a rule id is a PATCH bump. +. *Template satisfaction*: every `template_ref` MUST resolve in + `rsr-template-repo`, OR the criterion MUST be gated by a capability the + template's own profile does not declare. A dangling `template_ref` is a defect + in either the spec or the template — the dogfood gate surfaces which. + +This replaces v1.0's missing spec-to-template traceability matrix, under which +"does the template implement the spec" was mechanically unanswerable. + +== 8. Versioning and freeze [[versioning]] + +RSR uses semantic versioning with an errata track. The rules are authoritative +in the SSOT `[versioning]` block; in prose: + +* *MAJOR* — an era change. MAY remove/redefine criteria or move a criterion + between tiers. Cutting a major *freezes the prior major*: its criteria file is + copied to `spec/archive/rsr-criteria-vN.a2ml` and its byte-hash is pinned in + the registry. The freeze guard then makes the frozen file immutable in CI. +* *MINOR* — additive only. MAY add criteria or add a capability gate, but MUST + NOT make a previously-conforming repo non-conforming *at the same tier*. +* *PATCH* — editorial: wording, `detect` corrections, `template_ref` fixes. No + criteria-set change. + +A freeze is thus a cryptographic fact (a pinned hash + a CI guard), not a +promise. This is the direct fix for v1.0's freeze-in-name-only failure. + +== 9. Migration from v1.0 [[migration]] + +The criteria set was re-based on measured estate reality. The load-bearing +deltas (full per-criterion mapping is generated into +`spec/RSR-V1-TO-V2-DELTA.adoc` as a follow-up): + +[cols="2,2,3",options="header"] +|=== +| v1.0 criterion | v2.0 disposition | Reason +| `nix-flake` (flake.nix) | → `guix-primary` (guix.scm), Nix fallback retiring | Guix-primary policy; Nix-mirror retirement (standards#102). +| `gitlab` (repo on GitLab) | → `scm-github` | Estate canonical forge is GitHub; GitLab is mirror-only. +| `rvc`, `saltrover` | REMOVED | Obsolete tooling; not part of the estate. +| `meta-scm`/`ecosystem-scm`/`state-scm` | → descriptiles `META/ECOSYSTEM/STATE.a2ml` | `.scm` era retired; A2ML is the metadata format. +| `.machine_readable/6a2/` | → `.machine_readable/descriptiles/` | `6a2` deprecated 2026-06-30. +| 6 A2ML files | → 8 (adds `ANCHOR`, `CLADE`) | Canonical descriptile set expanded. +| `LICENSE.txt` | → `LICENSE` + `LICENSES/` (REUSE) | Estate file convention; hypatia `root_hygiene` to be realigned to match. +| `palimpsest` (everywhere) | → `licence-classified` (5-way, FLAG-ONLY) | Palimpsest is exactly three repos; licence detection is `:review`, never auto-edited. +| DNSSEC / Schema.org / Webmention / POSSE | GATED by `web-ui`/`docs-site`/`api-service` | Deployment concerns, not repo-shape universals. +| flat "all 11 categories" | → capability-gated applicable set | Fixes over-scaffolding of leaf repos. +|=== + +The v1.0 `spec.scm/`, `VERSION.adoc` (freeze banner), and the five divergent +checkers are superseded. They are retained read-only until the oracle ships, +then archived — no deletion by access-recency, but no longer normative. + +== 10. Ratification bar [[ratification]] + +RSR v2.0 leaves `draft` and becomes `stable` only when ALL of the following +hold — mirroring the estate's spec-recognition bar and the record-dialect +spec's own Appendix-D discipline: + +. *Oracle exists*: the `rsr-conformance` hypatia rule family consumes the SSOT + and produces scorecards. +. *Dogfood green*: the dogfood gate runs in real CI (no `|| echo SKIP`) and + `rsr-template-repo` scores Gold on its applicable set. +. *Corpus run*: the oracle is run across the estate; the per-repo tier + distribution is published to verisim-data and the residual non-conforming set + is filed as findings (not hidden). +. *Traceability green*: automatable-coverage and template-satisfaction checks + (<>) pass; no dangling `template_ref`. +. *Owner ratification*: the owner bumps the SSOT `[meta].status` to `stable` and + cuts `2.0.0`, freezing it per <>. + +Until then, every RSR badge in the estate MUST be read as "self-asserted", and +this specification MUST NOT be cited as ratified. + +== Appendix A: Security considerations + +A conformance oracle that writes scorecards is a *reporting* tool, not an +enforcement capability: it MUST NOT gain execution, network, or write access to +the repositories it scores beyond reading their trees and writing to +verisim-data. Licence-classification criteria (`7.1.1`) are detection-only and +`:review`-capped; the oracle MUST NOT auto-edit licence content under any tier, +per the estate's manual-only licence guardrail. + +== Appendix B: Change log + +* *2.0.0-draft (2026-07-03)* — Initial v2.0 draft. Re-bases criteria on measured + estate reality; introduces capability-gated scoring, the single-oracle model, + the hash-pinned freeze, spec→checker→template traceability, and the A2ML + record-dialect SSOT. Supersedes the v1.0 frozen spec and its five checkers. + +''' +*Version*: 2.0.0-draft + +*Status*: Draft (see <>) + +*Era*: v2 + +*SSOT*: `spec/rsr-criteria-v2.a2ml` + +*Date*: 2026-07-03 diff --git a/rhodium-standard-repositories/spec/rsr-criteria-v2.a2ml b/rhodium-standard-repositories/spec/rsr-criteria-v2.a2ml new file mode 100644 index 00000000..7238658e --- /dev/null +++ b/rhodium-standard-repositories/spec/rsr-criteria-v2.a2ml @@ -0,0 +1,249 @@ +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# rsr-criteria-v2.a2ml — RSR v2.0 machine-readable criteria (the SINGLE SOURCE OF TRUTH). +# +# This file is authored in the A2ML RECORD DIALECT (a2ml/RECORD-DIALECT-SPEC.adoc). +# It is the sole normative source for RSR v2.0 criteria. Every other artefact — +# the prose checklist, the one normative checker's rule table, and the badge +# thresholds — is GENERATED from this file (see RSR-SPEC-v2.adoc §7, "Solutions +# at source"). Do not hand-maintain criteria anywhere else. +# +# Grounding: the criteria below are re-based on a measured survey of estate +# reality (rsr-template-repo's shipped file set + hypatia's enforced rules), not +# the 2025-era spec.scm (GitLab / Nix / .scm / RVC / SaltRover), which is retired +# (see §Migration in RSR-SPEC-v2.adoc). Each criterion records how it is detected +# (`detect`, a hypatia rule id or "manual") and where the template satisfies it +# (`template_ref`) so spec -> checker -> template traceability is machine-checkable. + +[meta] +spec = "rhodium-standard-repositories" +version = "2.0.0-draft" +status = "draft" # draft | stable ; MUST NOT be cited as ratified until §Ratification passes +supersedes = "1.0.0" +date = "2026-07-03" +authority = "RSR-SPEC-v2.adoc" +normative-oracle = "hypatia:rsr-conformance" # the ONE checker; all others are non-normative (see [oracle]) +dialect = "a2ml-record" # dogfoods a2ml/RECORD-DIALECT-SPEC.adoc + +[versioning] +# Fixes the v1.0 "immutable forever" model, which estate reality already broke. +model = "semver-with-errata" +rule-major = "A MAJOR bump is an era change: it MAY remove or redefine criteria and MAY move a criterion between tiers. Cutting a major freezes the prior major's rsr-criteria as an immutable, hash-pinned artefact under archive/." +rule-minor = "A MINOR bump MAY ADD criteria or ADD a capability gate, but MUST NOT make a previously-conforming repo non-conforming at the same tier. Additive only." +rule-patch = "A PATCH bump is editorial (wording, detection-rule id corrections, template_ref fixes) with no criteria-set change." +freeze-mechanism = "A released major is frozen by pinning this file's byte-hash in .machine_readable/REGISTRY.a2ml (or the spec's own VERSIONS ledger), NOT by a prose 'FROZEN' banner. A freeze guard in CI (see [oracle].freeze-guard) fails any PR that mutates a frozen major's criteria file." +errata = "Corrections that do not change criteria semantics are recorded in RSR-SPEC-v2.adoc Appendix E (Errata) and shipped as PATCH bumps." + +[tiers] +# Score = weighted percentage of APPLICABLE criteria passed (see [scoring]). +# Thresholds are inclusive lower bounds. +bronze = 75 +silver = 90 +gold = 100 +rhodium = 100 # Gold + the rhodium-only exemplary criteria (those with tier = "rhodium") +scale = "X F E D C B A maps onto the readiness-grade scale; RSR tiers are the repo-shape projection (Bronze~C, Silver~B, Gold~A, Rhodium~A+)." + +[scoring] +# The capability-gated model (replaces v1.0's flat 'every repo needs all 11 categories'). +applicable-set = "A criterion is APPLICABLE to a repo iff its `gate` is `universal` OR the repo's .machine_readable/rsr-profile.a2ml declares the gating capability (per TEMPLATE-APPLICABILITY-POLICY.adoc). Non-applicable criteria are scored `na` and excluded from the denominator." +denominator = "sum of weights of APPLICABLE criteria" +numerator = "sum of weights of APPLICABLE criteria whose `detect` returns pass" +partial = "A criterion MAY return `partial` (e.g. some but not all files present); partial contributes half its weight and is reported explicitly." +na-honesty = "A repo MUST NOT reach a tier by declaring away (via rsr-profile) a capability it actually has. hypatia cross-checks declared capabilities against detected ones (structural_drift) and flags under-declaration as :review." +report = "The oracle writes a per-repo scorecard to verisim-data (.machine_readable/scorecards/.scorecard.a2ml shape) with per-criterion verdicts, the applicable set, and the resulting tier." + +[oracle] +# ONE normative checker. RSR v1.0 shipped five divergent checkers; v2.0 designates +# exactly one and declares the rest non-normative. +normative = "hypatia rule family `rsr-conformance` (to be implemented; consumes THIS file). hypatia is the estate scanner and already writes scorecards to verisim-data, so it is the natural oracle." +freeze-guard = "hypatia rule `rsr-criteria-freeze`: fails any change to a frozen major's rsr-criteria-*.a2ml whose byte-hash no longer matches the registry pin." +retired = [ + "rsr-audit.sh (36K bash; no tests, no CI) -> non-normative reference only", + "rsr-check.scm (Guile) -> retired with the .scm era", + "rsr-compliance-checklist.k9.ncl -> retired; k9 kennel data is GENERATED from this file if needed", + "COMPLIANCE_CHECKLIST.md -> GENERATED from this file, not authored", + "rhodium-pipeline rsr-certifier -> product, not the spec's oracle; MAY consume this file but is not normative", +] +dogfood-gate = "CI runs the oracle against rsr-template-repo on every change to either repo and REQUIRES Gold for the applicable set (the template declares the union of capabilities, so its applicable set is near-total). See rsr-template-repo/.github/workflows/dogfood-gate.yml." + +# --------------------------------------------------------------------------- +# CATEGORIES — 11 weighted categories (structure retained from v1.0; content +# re-based on estate reality). Weights sum to 100. Each criterion: +# id stable dotted id (category.group.item), STABLE across minors +# name short slug +# desc what it checks +# tier lowest tier at which it is REQUIRED (bronze|silver|gold|rhodium) +# gate "universal" or a capability from TEMPLATE-APPLICABILITY-POLICY +# detect hypatia rule id, or "manual" (honest: no automated check yet) +# template_ref where rsr-template-repo satisfies it, or "-" +# --------------------------------------------------------------------------- + +[[category]] +id = 1 +key = "foundational-infrastructure" +name = "Foundational Infrastructure" +weight = 12 +criteria = [ + { id = "1.1.1", name = "scm-github", desc = "Repository canonical on GitHub (GitLab is mirror-only)", tier = "bronze", gate = "universal", detect = "structural_drift/SD001", template_ref = ".github/" }, + { id = "1.1.2", name = "justfile", desc = "Justfile task runner present with real recipes", tier = "bronze", gate = "universal", detect = "build_system_rules/justfile", template_ref = "Justfile" }, + { id = "1.1.3", name = "no-makefile", desc = "No Makefile (Mustfile/justfile only)", tier = "bronze", gate = "universal", detect = "cicd_rules/makefile_detected", template_ref = "-" }, + { id = "1.1.4", name = "editorconfig", desc = ".editorconfig present", tier = "silver", gate = "universal", detect = "manual", template_ref = ".editorconfig" }, + { id = "1.2.1", name = "guix-primary", desc = "Guix manifest (guix.scm) as primary reproducible build; Nix fallback only", tier = "silver", gate = "reproducible-build", detect = "build_system_rules/guix_primary", template_ref = "build/" }, + { id = "1.2.2", name = "git-hooks", desc = ".pre-commit-config.yaml with real hooks", tier = "silver", gate = "universal", detect = "manual", template_ref = ".pre-commit-config.yaml" }, + { id = "1.2.3", name = "container-rootless", desc = "Container config uses rootless Podman + Chainguard/Wolfi base", tier = "gold", gate = "container", detect = "cicd_rules/containerfile_base", template_ref = "container/" }, + { id = "1.2.4", name = "tool-versions", desc = ".tool-versions pins toolchain versions", tier = "silver", gate = "universal", detect = "manual", template_ref = ".tool-versions" }, +] + +[[category]] +id = 2 +key = "documentation-standards" +name = "Documentation Standards" +weight = 12 +criteria = [ + { id = "2.1.1", name = "readme-adoc", desc = "README.adoc present (.adoc primary per estate doc policy)", tier = "bronze", gate = "universal", detect = "root_hygiene/readme", template_ref = "README.adoc" }, + { id = "2.1.2", name = "license-file", desc = "LICENSE present + LICENSES/ REUSE texts (NOT LICENSE.txt)", tier = "bronze", gate = "universal", detect = "root_hygiene/license", template_ref = "LICENSE, LICENSES/" }, + { id = "2.1.3", name = "security-md", desc = "SECURITY.md with a vulnerability-disclosure policy", tier = "bronze", gate = "universal", detect = "root_hygiene/security", template_ref = "SECURITY.md" }, + { id = "2.1.4", name = "coc-md", desc = "CODE_OF_CONDUCT.md", tier = "silver", gate = "universal", detect = "root_hygiene/coc", template_ref = "CODE_OF_CONDUCT.md" }, + { id = "2.1.5", name = "contributing-md", desc = "CONTRIBUTING.md", tier = "silver", gate = "universal", detect = "root_hygiene/contributing", template_ref = "CONTRIBUTING.md" }, + { id = "2.1.6", name = "changelog", desc = "CHANGELOG.md (Keep a Changelog)", tier = "silver", gate = "universal", detect = "root_hygiene/changelog", template_ref = "CHANGELOG.md" }, + { id = "2.1.7", name = "maintainers", desc = "MAINTAINERS.adoc", tier = "silver", gate = "universal", detect = "root_hygiene/maintainers", template_ref = "MAINTAINERS.adoc" }, + { id = "2.1.8", name = "governance", desc = "GOVERNANCE.adoc", tier = "gold", gate = "governance-tier", detect = "root_hygiene/governance", template_ref = "GOVERNANCE.adoc" }, + { id = "2.1.9", name = "funding", desc = "FUNDING.yml / .github/FUNDING.yml", tier = "gold", gate = "governance-tier", detect = "manual", template_ref = "FUNDING.yml" }, + { id = "2.1.10", name = "gitignore", desc = ".gitignore and .gitattributes present", tier = "bronze", gate = "universal", detect = "manual", template_ref = ".gitignore, .gitattributes" }, + { id = "2.2.1", name = "wellknown-core", desc = ".well-known/{security.txt,ai.txt,humans.txt}", tier = "silver", gate = "universal", detect = "structural_drift/SD020", template_ref = ".well-known/" }, + { id = "2.2.2", name = "wellknown-ext", desc = ".well-known/{consent-required.txt,provenance.json}", tier = "gold", gate = "web-ui", detect = "manual", template_ref = "-" }, + { id = "2.3.1", name = "ai-manifest", desc = "0-AI-MANIFEST.a2ml agent front door present", tier = "silver", gate = "universal", detect = "structural_drift/SD002", template_ref = "0-AI-MANIFEST.a2ml" }, +] + +[[category]] +id = 3 +key = "machine-readable-substrate" +name = "Machine-Readable Substrate (Descriptiles)" +weight = 14 +criteria = [ + { id = "3.1.1", name = "descriptiles-dir", desc = ".machine_readable/descriptiles/ present (NOT 6a2/, which is deprecated 2026-06-30)", tier = "gold", gate = "universal", detect = "structural_drift/SD003", template_ref = ".machine_readable/descriptiles/" }, + { id = "3.1.2", name = "state", desc = "STATE.a2ml — current state/progress (valid record dialect)", tier = "gold", gate = "universal", detect = "structural_drift/SD004", template_ref = ".machine_readable/descriptiles/STATE.a2ml" }, + { id = "3.1.3", name = "meta", desc = "META.a2ml — ADRs / constitutional authority", tier = "gold", gate = "universal", detect = "structural_drift/SD005", template_ref = ".machine_readable/descriptiles/META.a2ml" }, + { id = "3.1.4", name = "ecosystem", desc = "ECOSYSTEM.a2ml — estate position + what-this-is-not", tier = "gold", gate = "universal", detect = "structural_drift/SD006", template_ref = ".machine_readable/descriptiles/ECOSYSTEM.a2ml" }, + { id = "3.1.5", name = "agentic", desc = "AGENTIC.a2ml — agent permissions / risk gating", tier = "gold", gate = "universal", detect = "structural_drift/SD007", template_ref = ".machine_readable/descriptiles/AGENTIC.a2ml" }, + { id = "3.1.6", name = "neurosym", desc = "NEUROSYM.a2ml — proof obligations / meaning of ops", tier = "gold", gate = "universal", detect = "structural_drift/SD008", template_ref = ".machine_readable/descriptiles/NEUROSYM.a2ml" }, + { id = "3.1.7", name = "playbook", desc = "PLAYBOOK.a2ml — operational runbook", tier = "gold", gate = "universal", detect = "structural_drift/SD009", template_ref = ".machine_readable/descriptiles/PLAYBOOK.a2ml" }, + { id = "3.1.8", name = "anchor", desc = "ANCHOR.a2ml — semantic authority + golden path", tier = "gold", gate = "universal", detect = "structural_drift/SD010", template_ref = ".machine_readable/descriptiles/ANCHOR.a2ml" }, + { id = "3.1.9", name = "clade", desc = "CLADE.a2ml — identity/lineage (registers into gv-clade-index)", tier = "gold", gate = "governance-tier", detect = "structural_drift/SD011", template_ref = ".machine_readable/descriptiles/CLADE.a2ml" }, + { id = "3.2.1", name = "a2ml-valid", desc = "All .a2ml files parse + validate against their record-dialect profile", tier = "gold", gate = "universal", detect = "rsr-conformance/a2ml_valid", template_ref = "-" }, + { id = "3.2.2", name = "rsr-profile", desc = ".machine_readable/rsr-profile.a2ml declares capabilities (drives applicable set)", tier = "silver", gate = "universal", detect = "rsr-conformance/profile_present", template_ref = ".machine_readable/rsr-profile.a2ml" }, +] + +[[category]] +id = 4 +key = "security-architecture" +name = "Security Architecture" +weight = 14 +criteria = [ + { id = "4.1.1", name = "spdx-headers", desc = "SPDX-License-Identifier headers on all source files", tier = "bronze", gate = "universal", detect = "cicd_rules/missing_spdx", template_ref = "-" }, + { id = "4.1.2", name = "no-secrets", desc = "No hardcoded secrets (secret scanner clean)", tier = "bronze", gate = "universal", detect = "security_errors/secret_detected", template_ref = "-" }, + { id = "4.1.3", name = "sha-pinned", desc = "GitHub Actions + dependencies SHA-pinned", tier = "silver", gate = "universal", detect = "supply_chain/unpinned_action", template_ref = ".github/workflows/" }, + { id = "4.1.4", name = "https-only", desc = "No plaintext HTTP URLs; HTTPS only", tier = "silver", gate = "universal", detect = "security_errors/http_url", template_ref = "-" }, + { id = "4.1.5", name = "no-weak-hash", desc = "No MD5/SHA1 for security purposes", tier = "silver", gate = "universal", detect = "security_errors/weak_hash", template_ref = "-" }, + { id = "4.2.1", name = "scorecard-7", desc = "OpenSSF Scorecard >= 7.0", tier = "silver", gate = "universal", detect = "scorecard_compliance/aggregate", template_ref = ".github/workflows/scorecard.yml" }, + { id = "4.2.2", name = "scorecard-9", desc = "OpenSSF Scorecard >= 9.0", tier = "gold", gate = "universal", detect = "scorecard_compliance/aggregate", template_ref = ".github/workflows/scorecard.yml" }, + { id = "4.3.1", name = "deno-perms", desc = "Explicit Deno permission flags (no bare --allow-all)", tier = "silver", gate = "deno", detect = "cicd_rules/deno_permissions", template_ref = "-" }, + { id = "4.3.2", name = "sbom", desc = "SBOM generated on release", tier = "gold", gate = "published-package", detect = "supply_chain/sbom", template_ref = ".github/workflows/release.yml" }, + { id = "4.3.3", name = "rootless", desc = "Containers run rootless", tier = "gold", gate = "container", detect = "cicd_rules/rootless_container", template_ref = "container/" }, +] + +[[category]] +id = 5 +key = "language-policy" +name = "Language Policy Conformance" +weight = 12 +criteria = [ + { id = "5.1.1", name = "no-python", desc = "No Python (fully banned)", tier = "bronze", gate = "universal", detect = "cicd_rules/python_detected", template_ref = ".github/workflows/estate-rules.yml" }, + { id = "5.1.2", name = "no-typescript", desc = "No new TypeScript outside approved carve-outs", tier = "bronze", gate = "universal", detect = "cicd_rules/typescript_detected", template_ref = ".github/workflows/ts-blocker.yml" }, + { id = "5.1.3", name = "no-rescript", desc = "No new ReScript outside approved carve-outs", tier = "bronze", gate = "universal", detect = "cicd_rules/rescript_detected", template_ref = "-" }, + { id = "5.1.4", name = "no-vlang", desc = "No V-lang (migration completed 2026-05-28)", tier = "bronze", gate = "universal", detect = "cicd_rules/vlang_detected", template_ref = "-" }, + { id = "5.1.5", name = "no-go", desc = "No Go (use Rust/SPARK)", tier = "bronze", gate = "universal", detect = "cicd_rules/go_detected", template_ref = "-" }, + { id = "5.1.6", name = "no-node-npm", desc = "No Node/npm/bun runtime deps (use Deno)", tier = "bronze", gate = "universal", detect = "cicd_rules/nodejs_detected", template_ref = ".github/workflows/npm-bun-blocker.yml" }, + { id = "5.2.1", name = "spark-ready", desc = "Rust projects designed to admit SPARK/Ada modules", tier = "rhodium", gate = "rust", detect = "manual", template_ref = "-" }, + { id = "5.2.2", name = "proofs-clean", desc = "No believe_me / sorry / Admitted in load-bearing proofs", tier = "gold", gate = "formal-proofs", detect = "proof_obligation/no_holes", template_ref = "verification/" }, +] + +[[category]] +id = 6 +key = "cicd-enforcement" +name = "CI/CD & Enforcement" +weight = 8 +criteria = [ + { id = "6.1.1", name = "ci-present", desc = "CI pipeline present (GitHub Actions)", tier = "bronze", gate = "universal", detect = "structural_drift/SD012", template_ref = ".github/workflows/" }, + { id = "6.1.2", name = "hypatia-scan", desc = "hypatia-scan workflow wired (self-scans on push)", tier = "silver", gate = "universal", detect = "workflow_audit/hypatia_scan", template_ref = ".github/workflows/hypatia-scan.yml" }, + { id = "6.1.3", name = "governance-wf", desc = "governance workflow enforces estate policies", tier = "silver", gate = "universal", detect = "workflow_audit/governance", template_ref = ".github/workflows/governance.yml" }, + { id = "6.1.4", name = "workflow-hardened", desc = "Workflows least-privilege + no injection (workflow linter)", tier = "silver", gate = "universal", detect = "workflow_hardening/aggregate", template_ref = ".github/workflows/workflow-linter.yml" }, + { id = "6.1.5", name = "no-silent-skip", desc = "No '|| echo SKIP' silent-green in build/test recipes", tier = "gold", gate = "universal", detect = "honest_completion/silent_skip", template_ref = "-" }, + { id = "6.2.1", name = "dogfood-gate", desc = "dogfood-gate runs the RSR oracle against itself", tier = "gold", gate = "governance-tier", detect = "workflow_audit/dogfood", template_ref = ".github/workflows/dogfood-gate.yml" }, +] + +[[category]] +id = 7 +key = "foss-licensing" +name = "FOSS & Licensing" +weight = 6 +criteria = [ + { id = "7.1.1", name = "licence-classified", desc = "Licence matches the estate 5-way classification (detection FLAG-ONLY / :review; never auto-edited)", tier = "bronze", gate = "universal", detect = "cicd_rules/license_finding", template_ref = "LICENSE" }, + { id = "7.1.2", name = "reuse-compliant", desc = "REUSE-style LICENSES/ dir with full texts", tier = "silver", gate = "universal", detect = "cicd_rules/reuse_lint", template_ref = "LICENSES/" }, + { id = "7.1.3", name = "spdx-audit", desc = "SPDX identifiers resolve to real licences (no scrambled ids)", tier = "silver", gate = "universal", detect = "cicd_rules/spdx_valid", template_ref = "-" }, + { id = "7.2.1", name = "dco", desc = "DCO sign-off or CLA on contributions", tier = "gold", gate = "governance-tier", detect = "manual", template_ref = "CONTRIBUTING.md" }, +] + +[[category]] +id = 8 +key = "lifecycle-management" +name = "Lifecycle Management" +weight = 4 +criteria = [ + { id = "8.1.1", name = "semver", desc = "Semantic versioning for releases", tier = "silver", gate = "published-package", detect = "manual", template_ref = "CHANGELOG.md" }, + { id = "8.1.2", name = "pinned-deps", desc = "Dependency versions pinned/locked", tier = "silver", gate = "universal", detect = "supply_chain/unpinned_dep", template_ref = "-" }, + { id = "8.1.3", name = "deprecation", desc = "Deprecation + sunset policy documented", tier = "gold", gate = "published-package", detect = "manual", template_ref = "-" }, + { id = "8.1.4", name = "no-scaffold-stub", desc = "No scaffold-stub guix.scm (placeholders / empty inputs / source #f)", tier = "silver", gate = "reproducible-build", detect = "structural_drift/SD021", template_ref = "-" }, +] + +[[category]] +id = 9 +key = "web-service-standards" +name = "Web & Service Standards" +weight = 3 +criteria = [ + { id = "9.1.1", name = "tls13", desc = "TLS 1.3 only for deployed endpoints", tier = "gold", gate = "api-service", detect = "manual", template_ref = "-" }, + { id = "9.1.2", name = "csp-hsts", desc = "Content-Security-Policy + HSTS on web surfaces", tier = "gold", gate = "web-ui", detect = "manual", template_ref = "-" }, + { id = "9.1.3", name = "wcag-aa", desc = "WCAG 2.1 AA on web UI", tier = "gold", gate = "web-ui", detect = "manual", template_ref = "-" }, + { id = "9.1.4", name = "wellknown-served", desc = "Deployed site serves its .well-known/ over HTTPS", tier = "gold", gate = "docs-site", detect = "manual", template_ref = ".github/workflows/wellknown-enforcement.yml" }, +] + +[[category]] +id = 10 +key = "community-governance" +name = "Community & Governance" +weight = 2 +criteria = [ + { id = "10.1.1", name = "governance-model", desc = "Governance model documented (not just a stub)", tier = "gold", gate = "governance-tier", detect = "manual", template_ref = "GOVERNANCE.adoc" }, + { id = "10.1.2", name = "succession", desc = "Succession / bus-factor plan", tier = "rhodium", gate = "governance-tier", detect = "manual", template_ref = "MAINTAINERS.adoc" }, + { id = "10.1.3", name = "affirmation", desc = "AFFIRMATION.adoc (no-overclaim ethos) present", tier = "gold", gate = "governance-tier", detect = "manual", template_ref = "AFFIRMATION.adoc" }, +] + +[[category]] +id = 11 +key = "accountability-provenance" +name = "Accountability & Provenance" +weight = 1 +criteria = [ + { id = "11.1.1", name = "audit-doc", desc = "AUDIT.adoc — audit trail / evidence ledger", tier = "gold", gate = "governance-tier", detect = "manual", template_ref = "AUDIT.adoc" }, + { id = "11.1.2", name = "provenance-json", desc = ".well-known/provenance.json provenance chain", tier = "rhodium", gate = "web-ui", detect = "manual", template_ref = "-" }, + { id = "11.1.3", name = "signed-commits", desc = "Commits signed (advisory in agent envs; see estate note)", tier = "rhodium", gate = "universal", detect = "git_state/unsigned_commit", template_ref = "-" }, +] + +[weights-check] +# 12+12+14+14+12+8+6+4+3+2+1 = 88 for categories 1-11 base weights below Gold-exemplary. +# NOTE: weights are the per-category maxima; the effective denominator is always the +# APPLICABLE-criteria weight sum per [scoring], so this total is informative, not a gate. +sum-declared = 88 +note = "The remaining headroom to 100 is the rhodium-only exemplary criteria (gate windows: formal-proofs, succession, provenance chains, spark-ready). A repo with no optional capabilities is scored purely on its applicable universal set."