Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 111 additions & 111 deletions .machine_readable/rsr-profile.a2ml
Original file line number Diff line number Diff line change
@@ -1,128 +1,128 @@
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
//
// rsr-profile.a2ml — the CANON's own capability declaration.
//
// ---------------------------------------------------------------------------
// WHY THE CANON NEEDS ONE, AND WHY IT DID NOT HAVE ONE
//
// Before this file, `find . -name "rsr-profile*"` in this repo returned
// NOTHING. The repository that ships scripts/check-rsr-profile.sh could not
// itself be checked by it: the script exited 2 (setup error) because there was
// no profile to read. THE LAW WAS NOT SUBJECT TO THE LAW.
//
// The reason was not backlog. It was structural. rsr-criteria-v2.a2ml's
// applicable-set rule is:
//
// A criterion is APPLICABLE iff its `gate` is `universal` OR the repo's
// rsr-profile declares the gating capability.
//
// template-capability-gates.toml carried a [carrier] section that lets a SPINE
// carry modules it does not declare:
//
// "Applies ONLY where the profile declares role = \"spine\"."
//
// There was NO equivalent for the canon. So the moment this repo got a profile
// it was scored against gates that are impossible for it to satisfy — it
// carries the criteria, the gate table and 48 workflow files, but declares no
// `rust`, no `container`, and has no code to prove. Compliance was unreachable
// BY CONSTRUCTION.
//
// This commit series adds role = "canon" to the gate table and this file to
// satisfy it. The role is the smallest change that makes the canon scorable.
//
// Dialect note: authored in the a2ml record dialect to match the shape
// rsr-template-repo ships, because check-rsr-profile.sh's parser accepts it.
// The .a2ml -> .deed conversion is estate task #64 and is deliberately NOT
// attempted here; see docs/AUDIT.adoc — finding F3 records that the law is
// authored in a superseded dialect while DEED is itself an unratified DRAFT.
// ---------------------------------------------------------------------------
# SPDX-License-Identifier: MPL-2.0
# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
#
# rsr-profile.a2ml — the CANON's own capability declaration.
#
# ---------------------------------------------------------------------------
# WHY THE CANON NEEDS ONE, AND WHY IT DID NOT HAVE ONE
#
# Before this file, `find . -name "rsr-profile*"` in this repo returned
# NOTHING. The repository that ships scripts/check-rsr-profile.sh could not
# itself be checked by it: the script exited 2 (setup error) because there was
# no profile to read. THE LAW WAS NOT SUBJECT TO THE LAW.
#
# The reason was not backlog. It was structural. rsr-criteria-v2.a2ml's
# applicable-set rule is:
#
# A criterion is APPLICABLE iff its `gate` is `universal` OR the repo's
# rsr-profile declares the gating capability.
#
# template-capability-gates.toml carried a [carrier] section that lets a SPINE
# carry modules it does not declare:
#
# "Applies ONLY where the profile declares role = \"spine\"."
#
# There was NO equivalent for the canon. So the moment this repo got a profile
# it was scored against gates that are impossible for it to satisfy — it
# carries the criteria, the gate table and 48 workflow files, but declares no
# `rust`, no `container`, and has no code to prove. Compliance was unreachable
# BY CONSTRUCTION.
#
# This commit series adds role = "canon" to the gate table and this file to
# satisfy it. The role is the smallest change that makes the canon scorable.
#
# Dialect note: authored in the a2ml record dialect to match the shape
# rsr-template-repo ships, because check-rsr-profile.sh's parser accepts it.
# The .a2ml -> .deed conversion is estate task #64 and is deliberately NOT
# attempted here; see docs/AUDIT.adoc — finding F3 records that the law is
# authored in a superseded dialect while DEED is itself an unratified DRAFT.
# ---------------------------------------------------------------------------

[rsr-profile]
version = "1.0.0"
spec = "rsr-criteria-v2"
declares-against = "2.0.0"
declares-against = "2.1.0"

// Role in the estate pipeline. The gate table's [canon] section keys on this
// value, exactly as [carrier] keys on role = "spine".
# Role in the estate pipeline. The gate table's [canon] section keys on this
# value, exactly as [carrier] keys on role = "spine".
role = "canon"

// ---------------------------------------------------------------------------
// WHAT THE CANON ACTUALLY IS
//
// Honest declaration. This repo is a prose-and-tooling repository: it owns the
// DEFINITION of conformance, the gate implementations, and the reusable
// workflows. It is NOT an instance of the things it governs.
//
// Declaring an empty or aspirational set here would be the over-declaration
// failure in the other direction, and would make the oracle check meaningless:
// a profile that declares nothing is scored against nothing.
// ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# WHAT THE CANON ACTUALLY IS
#
# Honest declaration. This repo is a prose-and-tooling repository: it owns the
# DEFINITION of conformance, the gate implementations, and the reusable
# workflows. It is NOT an instance of the things it governs.
#
# Declaring an empty or aspirational set here would be the over-declaration
# failure in the other direction, and would make the oracle check meaningless:
# a profile that declares nothing is scored against nothing.
# ---------------------------------------------------------------------------
capabilities = [
"bash", // scripts/ — 107 files; the gate implementations (check-*.sh)
"docs-site", // .github/workflows/casket-pages.yml + pages.yml
"governance-tier", // 0-canon/constitution/ + docs/{AUDIT,AFFIRMATION}.adoc + GOVERNANCE + MAINTAINERS
"reproducible-build", // guix.scm — a real Guix manifest, pins the canon's own tooling
"bash", # scripts/ — 107 files; the gate implementations (check-*.sh)
"docs-site", # .github/workflows/casket-pages.yml + pages.yml
"governance-tier", # 0-canon/constitution/ + docs/{AUDIT,AFFIRMATION}.adoc + GOVERNANCE + MAINTAINERS
"reproducible-build", # guix.scm — a real Guix manifest, pins the canon's own tooling
]

// ---------------------------------------------------------------------------
// THE BOUND BUDGET — the join that makes this a versioned artefact rather than
// a directory that changes. Read by scripts/check-canon-lockstep.sh.
//
// Each value MUST equal the matching hash in canon.lock [canon.artifacts].
// ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# THE BOUND BUDGET — the join that makes this a versioned artefact rather than
# a directory that changes. Read by scripts/check-canon-lockstep.sh.
#
# Each value MUST equal the matching hash in canon.lock [canon.artifacts].
# ---------------------------------------------------------------------------

[canon]
version = "2.0.0"
criteria_sha256 = "efd024ad9cbdf0d36d4dbce7e491531dd4ccccbfc747a04223ce4149f4b9a53d"
gates_sha256 = "4c57d515bd3fa9d149cf54a8f4c8a44e2409cb24c3df72ec874656e4f5a98534"
lock_sha256 = "" // sha256 of canon.lock itself; filled at release
version = "2.1.0"
criteria_sha256 = "6a5aa8857bd0d0d58ef48827938ca17c251b6b854dacf59d306388d61694d82a"
gates_sha256 = "e70efd2f53c9445e30da4baf770366f04a4a84ffd844a01426e587e565b53e6a"
lock_sha256 = "" # sha256 of canon.lock itself; filled at release

[notes]
// Capabilities deliberately NOT declared, with reasons — the same discipline
// rsr-template-repo applies in its own [notes] block. Every omission below is
// grounded in the absence of a corresponding artefact in this tree.
# Capabilities deliberately NOT declared, with reasons — the same discipline
# rsr-template-repo applies in its own [notes] block. Every omission below is
# grounded in the absence of a corresponding artefact in this tree.
omitted-rationale = "The canon defines conformance; it is not an instance of it. Declaring a capability the canon lacks would make the oracle score it against a module it does not carry — the over-scaffolding failure the v2.0 capability model exists to prevent."

// rust / zig / idris2 / agda / haskell / gleam / elixir / julia / ocaml /
// affinescript
// — no source in any language; the canon is prose + shell gates
// cli
// — the check-*.sh scripts are CI steps, not a shipped binary;
// declaring `cli` would demand a release workflow and registry metadata
// library
// — nothing consumes the canon as a library; it is consumed as a DOCUMENT
// and as a pin (canon.lock), which is not the `library` capability
// ffi / abi
// — no C-ABI seam and no formally specified ABI; the interface directory
// is absent from this tree
// api-service
// — no network daemon; the reusable workflows RUN on GitHub's runners,
// they are not served BY this repo
// container
// — the canon ships no Containerfile and no image
// published-package
// — the canon publishes SPECS, not packages. Its release artefact is
// canon.lock + a tag, which is not a registry publication.
// DELIBERATE: the one omission worth revisiting if the canon ever
// publishes criteria to a package registry.
// formal-proofs
// — criterion 5.x `formal-proofs` means "contains mechanised proofs IN
// TREE, of its own code". docs/proofs/ (283 files) are proof artefacts
// OF THE ESTATE, gathered from other repos. Different thing entirely.
// → this is precisely a [canon] carrier path
// mobile / web-ui
// — no UI
// benchmarks
// — benches/ contains no suite
// plugin
// — not hosted in a third-party extension host
# rust / zig / idris2 / agda / haskell / gleam / elixir / julia / ocaml /
# affinescript
# — no source in any language; the canon is prose + shell gates
# cli
# — the check-*.sh scripts are CI steps, not a shipped binary;
# declaring `cli` would demand a release workflow and registry metadata
# library
# — nothing consumes the canon as a library; it is consumed as a DOCUMENT
# and as a pin (canon.lock), which is not the `library` capability
# ffi / abi
# — no C-ABI seam and no formally specified ABI; the interface directory
# is absent from this tree
# api-service
# — no network daemon; the reusable workflows RUN on GitHub's runners,
# they are not served BY this repo
# container
# — the canon ships no Containerfile and no image
# published-package
# — the canon publishes SPECS, not packages. Its release artefact is
# canon.lock + a tag, which is not a registry publication.
# DELIBERATE: the one omission worth revisiting if the canon ever
# publishes criteria to a package registry.
# formal-proofs
# — criterion 5.x `formal-proofs` means "contains mechanised proofs IN
# TREE, of its own code". docs/proofs/ (283 files) are proof artefacts
# OF THE ESTATE, gathered from other repos. Different thing entirely.
# → this is precisely a [canon] carrier path
# mobile / web-ui
# — no UI
# benchmarks
# — benches/ contains no suite
# plugin
# — not hosted in a third-party extension host

// ── Things the canon carries that NO capability gates, and therefore must be
// named in the gate table's [canon] section rather than declared here ──────
// the criteria themselves (0-canon/rsr/rsr-criteria-v2.a2ml)
// the gate table (.machine_readable/template-capability-gates.toml)
// the applicability policy (0-canon/TEMPLATE-APPLICABILITY-POLICY.adoc)
// the reusable workflows (.github/workflows/*-reusable.yml)
// docs/proofs/ — proof artefacts of the estate, not proofs of this repo
// rhodium-standard-repositories/ — VENDORED, to be deleted (finding F4)
# ── Things the canon carries that NO capability gates, and therefore must be
# named in the gate table's [canon] section rather than declared here ──────
# the criteria themselves (0-canon/rsr/rsr-criteria-v2.a2ml)
# the gate table (.machine_readable/template-capability-gates.toml)
# the applicability policy (0-canon/TEMPLATE-APPLICABILITY-POLICY.adoc)
# the reusable workflows (.github/workflows/*-reusable.yml)
# docs/proofs/ — proof artefacts of the estate, not proofs of this repo
# rhodium-standard-repositories/ — VENDORED, to be deleted (finding F4)
10 changes: 9 additions & 1 deletion .machine_readable/template-capability-gates.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Arrays are kept single-line so the checker can parse them with grep.

[meta]
version = "0.2.0"
version = "0.3.0"
policy = "0-canon/TEMPLATE-APPLICABILITY-POLICY.adoc"

[capabilities]
Expand Down Expand Up @@ -39,6 +39,14 @@ paths = ["README.adoc", "EXPLAINME.adoc|docs/EXPLAINME.adoc", "LICENSE", "SECURI
"Cargo.lock" = "rust"
"src/**/*.rs" = "rust"
".github/workflows/rust-ci.yml" = "rust"
# Julia library modules (the julia-library archetype's overlay; the
# #634 reference variant measured 2026-08-25: the language-specific
# delta is exactly these files). test/ (singular) is the Julia
# convention; rust uses tests/ and is ungated here by design.
"Project.toml" = "julia"
"test/" = "julia"
".github/workflows/julia-ci.yml" = "julia"
".github/workflows/julia-docs.yml" = "julia"
"src/interface/ffi/" = "ffi"
"abi.ipkg" = "abi"
"src/interface/abi/|src/interface/Abi/" = "abi"
Expand Down
17 changes: 17 additions & 0 deletions 0-canon/TEMPLATE-APPLICABILITY-POLICY.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ capability set drives everything else.
| it contains source in that language *as its own code* (not merely consumes a tool written in it).
| `bash` | it ships non-trivial shell scripts (almost universal; rarely gating).

.2+| Host / runtime
| `plugin` | code hosted inside a third-party extension host (WordPress, Zotero, a userscript manager): the host owns the runtime and packaging rules, so host-mandated files are exempt from the usual language gates the way interop-target bindings are.
| `deno` | it contains Deno source or a `deno.json` (criterion 4.3.1 gates on it).

| Role
| `canon` | the ROLE of `hyperpolymath/standards` itself: a prose-and-tooling repo that owns the criteria, the gate table and the reusable workflows. Scored via the gate table's `[canon]` carrier section, not by declaring the gated capabilities.

.5+| Interface / seam
| `cli` | it ships a command-line binary.
| `library` | it is consumed/published as a library.
Expand Down Expand Up @@ -86,6 +93,11 @@ for humans.

== The gate table (module → capability)

NOTE: `.machine_readable/template-capability-gates.toml` is the SSOT; this
table is its human mirror. When they disagree, the machine file wins and
this document carries a sync defect (first measured 2026-09-19: the
archetype presets and the `julia`/`plugin`/`deno`/`canon` rows lagged).

*Universal baseline* (gate = ∅; always carried):

`README.adoc`, `EXPLAINME.adoc`, `LICENSE`, `SECURITY.md`, `CONTRIBUTING.md`,
Expand All @@ -101,6 +113,7 @@ and the SPDX licence invariant (`LICENCE-POLICY.adoc`).
| Template module / path | Gating capability

| `Cargo.toml`, `Cargo.lock`, `src/**/*.rs`, `.github/workflows/rust-ci.yml` | `rust`
| `Project.toml`, `test/`, `.github/workflows/julia-ci.yml`, `.github/workflows/julia-docs.yml` | `julia`
| `src/interface/ffi/**` (Zig) | `ffi`
| `abi.ipkg`, `src/interface/Abi/**` (Idris2), `src/interface/generated/**` | `abi`
| `verification/proofs/**`, proof-CI | `formal-proofs`
Expand Down Expand Up @@ -129,6 +142,10 @@ directly instead. Each expands to a base capability set:
| `formal-proof-lib` | `agda` *or* `idris2`, `formal-proofs`, `library`
| `docs-site` | `docs-site`
| `affinescript-app` | `affinescript`, `web-ui`
| `julia-library` | `julia`, `library`, `docs-site`, `published-package`
| `wordpress-plugin` | `plugin`, `web-ui`
| `zotero-plugin` | `plugin`
| `userscript` | `plugin`
|===

A profile may `add` or `remove` individual capabilities on top of its preset
Expand Down
19 changes: 17 additions & 2 deletions 0-canon/rsr/rsr-criteria-v2.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,24 @@

[meta]
spec = "rhodium-standard-repositories"
version = "2.0.0-draft"
version = "2.1.0-draft"
status = "draft" # draft | stable ; MUST NOT be cited as ratified until §Ratification passes
supersedes = "1.0.0"
date = "2026-07-03"
date = "2026-09-19"
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
#
# 2.1.0-draft (2026-09-19): ADDITIVE MINOR (rule-minor: may add criteria
# or capability gates; must not make a previously-conforming repo
# non-conforming at the same tier). Adds the julia-gated criteria
# 5.2.3-5.2.6. Rationale: the capability vocabulary named `julia` with
# no criteria to gate on, so a repo declaring `julia` + `library` was
# scored with nothing language-shaped at all - the 33-repo .jl estate
# was invisible to the oracle by construction. All four criteria gate
# on `julia`, so no repo that does not declare `julia` has its
# applicable set change: the MINOR's non-regression obligation holds
# by the gate itself. Owner ruling 2026-09-19: approved.

[versioning]
# Fixes the v1.0 "immutable forever" model, which estate reality already broke.
Expand Down Expand Up @@ -167,6 +178,10 @@ criteria = [
{ 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/runtime-policy.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/" },
{ id = "5.2.3", name = "julia-package", desc = "Project.toml: stable uuid (derived or assigned, never regenerated), [compat] closure incl. the julia floor and bounds for every extra, licence consistent with LICENSE", tier = "silver", gate = "julia", detect = "rsr-conformance/julia_package", template_ref = "archetypes/julia-library/overlay/Project.toml.in" },
{ id = "5.2.4", name = "julia-ci", desc = "Julia CI workflow with a version matrix that includes the [compat] julia floor, running Pkg.test()", tier = "bronze", gate = "julia", detect = "rsr-conformance/julia_ci", template_ref = "archetypes/julia-library/overlay/.github/workflows/julia-ci.yml.in" },
{ id = "5.2.5", name = "julia-aqua", desc = "Aqua in [extras]+[targets] and green in CI (package-shape / compat / ambiguity gate); Aqua.test_all failure blocks", tier = "gold", gate = "julia", detect = "rsr-conformance/julia_aqua", template_ref = "archetypes/julia-library/overlay/test/runtests.jl" },
{ id = "5.2.6", name = "julia-docs", desc = "Documenter build wired for a julia repo that declares docs-site (docs/Project.toml + docs/make.jl + docs/src/ + build workflow); declared docs-site without a build is a VESTIGIAL-class defect the gate must catch", tier = "silver", gate = "julia", detect = "rsr-conformance/julia_docs", template_ref = "archetypes/julia-library/overlay/.github/workflows/julia-docs.yml.in" },
]

[[category]]
Expand Down
Loading
Loading