From 269c901e8253d7e53a41d59825eb0ed7ccfcfce4 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 17 Sep 2026 18:58:54 +0000 Subject: [PATCH] =?UTF-8?q?release(canon):=202.0.2=20=E2=80=94=20the=20law?= =?UTF-8?q?=20stops=20naming=20the=20hyphenated=20path=20(PATCH,=20per=20[?= =?UTF-8?q?versioning].rule-patch)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ruling R-A settles the machine tree's spelling as `.machine_readable/`. The canon's two normative artefacts still named `machine-readable/`, so the law told every repository to use the spelling the estate majority does not use. This corrects the law. WHY PATCH — the criteria's own rule, not my judgement `rsr-criteria-v2.a2ml` `[versioning].rule-patch` reads: A PATCH bump is editorial (wording, detection-rule id corrections, template_ref fixes) with no criteria-set change. This change is *exactly* those three things and nothing else: * wording — path strings inside `desc`/`freeze-mechanism`/`applicable-set`/ `report` prose, and template_ref values; * template_ref fixes — eight of the fifteen changed strings ARE template_ref values (`machine-readable/descriptiles/STATE.a2ml` and siblings); * detection-rule id corrections — none needed; no id changed. No criterion is added, removed, re-tiered or re-gated. Nothing that was conforming becomes non-conforming, and nothing that failed now passes. The strongest evidence it is not a criteria-set change: **the gates already resolved both spellings.** Their paths array carries "machine-readable/descriptiles/|.machine_readable/descriptiles/" and '|' means a path is satisfied if ANY alternative exists. So the only behavioural difference is which spelling appears first in a list. That is why this is PATCH and not MINOR: MINOR is for additions, and there are none. THE IDENTIFIER IS NOT A PATH, AND IS UNTOUCHED key = "machine-readable-substrate" keeps its name. It is a criterion key, not a location. Renaming it would be a criteria-set change, not errata. On the spine side of this same rename, exactly this assumption — that the word is the path — silently corrupted six files including a check-root-shape test and a lineage audit. The census is asserted in the edit script: after the pass the file contains 15 `.machine_readable/` paths, and the only two surviving `machine-readable` strings are this key and one line of prose ("RSR v2.0 machine-readable criteria", the file's own title). WHAT CHANGED rsr-criteria-v2.a2ml 15 path tokens, in the freeze-mechanism and applicable-set rules, the oracle's report prose, criteria 3.1.1 (descriptiles-dir, desc) and 3.2.2 (rsr-profile, desc AND template_ref), and the eight per-criterion template_ref values 3.1.2-3.1.9 template-capability-gates.toml two paths alternatives reordered so the canonical spelling is listed first; one comment canon.lock version 2.0.1 -> 2.0.2, tag canon-v2.0.1 -> canon-v2.0.2, criteria sha256 and gates sha256 rewritten, a dated note recording the category argument above RSR-SPEC-v2.adoc Appendix E: Errata, added APPENDIX E HAD NEVER BEEN WRITTEN `[versioning].errata` says corrections "are recorded in RSR-SPEC-v2.adoc Appendix E (Errata) and shipped as PATCH bumps". The spec has Appendix A and Appendix B. The rule named a section that did not exist, so this release both satisfies the rule and creates what it points at. The first entry is this change. Same file, same pass: its own SSOT footer still pointed at `spec/rsr-criteria-v2.a2ml`, a path that stopped existing when #815 moved the law into 0-canon/rsr/. Corrected. NEW PINNED IDENTITY criteria efd024ad9cbdf0d36d4dbce7e491531dd4ccccbfc747a04223ce4149f4b9a53d -> 7804d77127001ed50263f0783d8a11f7211e72cb5e9f6443f2acde4b08d9ab1e gates 8b1a77669c9ab78e9081669dbb2ab141d8af29700affc327f3dcde99f3dcd243 -> 6a8b9b420519dccdd2c586da06a9a302bdbbb3dc917f49e4a7b308882471d68a SEQUENCE — THIS MAY NOT MERGE FIRST [canon].order is spine-adopts-then-canon-releases, and Gate A enforces it. The spine must re-adopt both hashes and go green against them before this lands. Until it does, Gate A fails here on assertion 3, by design. WITNESSES lock hashes vs artefacts on disk both match, verified by sha256sum check-canon-lockstep.sh rc=0 GATE A PASSED check-standards-map.sh rc=0 GATE D PASSED check-rsr-profile.sh rc=0 profile matches declared capabilities check-allowed-actions.sh rc=0 35 uses: refs, 0 uncovered .githooks/validate-a2ml.sh rc=1 33 errors — IDENTICAL to the pre-release baseline, so the criteria edits introduced none Note on method: the first attempt at this edit expected `machine-readable/rsr-profile.a2ml` twice and found three. The third was a `template_ref` on a line whose visible head was identical, and a `grep -n` that truncated at 165 characters had hidden it. The count assertion refused to write. Enumerate tokens with `grep -o`, never ask whether a line looks right. (cherry picked from commit 3c88d3fe7fef781fc4c248137ff9cff40a35b5a2) --- .../template-capability-gates.toml | 7 ++-- 0-canon/rsr/RSR-SPEC-v2.adoc | 24 +++++++++++++- 0-canon/rsr/rsr-criteria-v2.a2ml | 26 +++++++-------- canon.lock | 32 ++++++++++++++++--- 4 files changed, 68 insertions(+), 21 deletions(-) diff --git a/.machine_readable/template-capability-gates.toml b/.machine_readable/template-capability-gates.toml index edab5836f..5125ba98a 100644 --- a/.machine_readable/template-capability-gates.toml +++ b/.machine_readable/template-capability-gates.toml @@ -31,7 +31,7 @@ known = ["rust", "zig", "agda", "idris2", "haskell", "gleam", "elixir", "affines # GitHub resolves community-health files from .github/ as readily as the root, # and the estate's canonical location for them IS .github/ - naming only the # root form marked every conforming repo as missing them. -paths = ["README.adoc", "EXPLAINME.adoc|docs/EXPLAINME.adoc", "LICENSE", "SECURITY.md|.github/SECURITY.md", "CONTRIBUTING.md|.github/CONTRIBUTING.md", "CODE_OF_CONDUCT.md|.github/CODE_OF_CONDUCT.md", "CHANGELOG.adoc|CHANGELOG.md", "0-AI-MANIFEST.a2ml", "machine-readable/descriptiles/|.machine_readable/descriptiles/", "machine-readable/rsr-profile.a2ml|.machine_readable/rsr-profile.a2ml", ".well-known/", ".gitignore", "Justfile"] +paths = ["README.adoc", "EXPLAINME.adoc|docs/EXPLAINME.adoc", "LICENSE", "SECURITY.md|.github/SECURITY.md", "CONTRIBUTING.md|.github/CONTRIBUTING.md", "CODE_OF_CONDUCT.md|.github/CODE_OF_CONDUCT.md", "CHANGELOG.adoc|CHANGELOG.md", "0-AI-MANIFEST.a2ml", ".machine_readable/descriptiles/|machine-readable/descriptiles/", ".machine_readable/rsr-profile.a2ml|machine-readable/rsr-profile.a2ml", ".well-known/", ".gitignore", "Justfile"] [gates] # "module path (file, dir/, or glob)" = "gating capability" @@ -98,8 +98,9 @@ paths = [".github/workflows/rust-ci.yml", ".github/workflows/release.yml", ".git # and the canon SERVES, which no capability describes. # # Applies ONLY where the profile declares role = "canon" -# (.machine_readable/rsr-profile.a2ml here; machine-readable/rsr-profile.a2ml -# once the root rename lands). +# (.machine_readable/rsr-profile.a2ml here and in the spine — the root rename +# landed 2026-09-17; machine-readable/rsr-profile.a2ml is the minority spelling +# and is still resolved). # # A minted repo declaring role = "canon" to evade a gate is still drift, which # is the behaviour that matters for the other ~441 repos. diff --git a/0-canon/rsr/RSR-SPEC-v2.adoc b/0-canon/rsr/RSR-SPEC-v2.adoc index 134d6daa0..9d2157d97 100644 --- a/0-canon/rsr/RSR-SPEC-v2.adoc +++ b/0-canon/rsr/RSR-SPEC-v2.adoc @@ -269,5 +269,27 @@ per the estate's manual-only licence guardrail. *Version*: 2.0.0-draft + *Status*: Draft (see <>) + *Era*: v2 + -*SSOT*: `spec/rsr-criteria-v2.a2ml` + +*SSOT*: `0-canon/rsr/rsr-criteria-v2.a2ml` + *Date*: 2026-07-03 + +== Appendix E: Errata + +Corrections that do not change criteria semantics, shipped as PATCH bumps per +`rsr-criteria-v2.a2ml` `[versioning].errata`. This appendix is named by that +rule and did not exist before 2.0.2 - the rule pointed at a section that had +never been written. + +=== 2.0.2 — 2026-09-17 + +* *The machine tree's spelling is `.machine_readable/`.* Ruling R-A settles the + question the law had left open. Criteria `3.1.1` (`descriptiles-dir`) and + `3.2.2` (`rsr-profile`), plus the `[versioning]` freeze-mechanism and the + `[scoring]`/`[oracle]` report prose, named `machine-readable/` as if it were + the only spelling. They now name the canonical one. +* *No semantics change.* The gates' `paths` alternatives have always accepted + either spelling (`machine-readable/descriptiles/|.machine_readable/descriptiles/`), + so no repository's conformance moved. Only the canonical form's position in + each alternative list changed. +* *`machine-readable-substrate` is not a path.* The criterion key keeps its name; + it is an identifier and renaming it would be a criteria-set change, not + erratum. diff --git a/0-canon/rsr/rsr-criteria-v2.a2ml b/0-canon/rsr/rsr-criteria-v2.a2ml index 55cac8333..e728ac263 100644 --- a/0-canon/rsr/rsr-criteria-v2.a2ml +++ b/0-canon/rsr/rsr-criteria-v2.a2ml @@ -32,7 +32,7 @@ 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." +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] @@ -46,12 +46,12 @@ scale = "X F E D C B A maps onto the readiness-grade scale; RSR tiers are the re [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." +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." +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 @@ -122,17 +122,17 @@ 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/anchors/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.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/anchors/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" }, + { 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]] diff --git a/canon.lock b/canon.lock index c894605e9..b3a5beaeb 100644 --- a/canon.lock +++ b/canon.lock @@ -88,12 +88,36 @@ # change) - not MINOR, which is additive. # # --------------------------------------------------------------------------- +# +# 2026-09-17 - PATCH 2.0.1 -> 2.0.2. THE MACHINE TREE'S SPELLING. +# +# Ruling R-A settles the spelling as `.machine_readable/`, so the normative +# artefacts stop naming the hyphenated path. This IS a change to files named in +# [canon.artifacts], so the bump obligation above applies - and PATCH is the +# category the rule itself gives it: rsr-criteria [versioning].rule-patch reads +# "editorial (wording, detection-rule id corrections, template_ref fixes) with +# no criteria-set change". There is no criteria-set change here. +# +# Why not MINOR, and not a MAJOR era change: +# * the gates file's paths array uses '|' alternatives that ALREADY resolve +# both spellings, so no repository's conformance changes at any tier. The +# edit only puts the canonical form first in the list, which is why it is +# cosmetic in effect as well as in intent; +# * no criterion is added, removed, re-tiered or re-gated; +# * `key = "machine-readable-substrate"` in the criteria is an IDENTIFIER, not +# a path, and is deliberately untouched - the same trap that corrupted six +# files on the spine side of this rename. +# +# Sequence, per [canon].order: the SPINE re-adopts these two hashes first, then +# this releases. Gate A enforces the order. +# +# --------------------------------------------------------------------------- [canon] # A released major is immutable. Bumping `version` to a new MAJOR means the # prior major's criteria file is copied to 0-canon/rsr/archive/ and pinned # there; a freeze guard fails any PR that mutates a frozen major. -version = "2.0.1" +version = "2.0.2" spec_family = "rhodium-standard-repositories" status = "draft" # draft | stable released = "2026-09-17" @@ -102,7 +126,7 @@ authority = "0-canon/constitution/ESTATE-CONSTITUTION.adoc" # The full git ref that realises this canon. A tag alone is not sufficient # (tags move); a commit alone is not sufficient (it has no version). Both. commit = "0000000000000000000000000000000000000000" # ← fill at release -tag = "canon-v2.0.1" +tag = "canon-v2.0.2" # --------------------------------------------------------------------------- # THE ARTEFACT SET — the files that ARE the canon. @@ -115,11 +139,11 @@ tag = "canon-v2.0.1" [canon.artifacts] criteria = { path = "0-canon/rsr/rsr-criteria-v2.a2ml", # relocated from the vendored copy - sha256 = "efd024ad9cbdf0d36d4dbce7e491531dd4ccccbfc747a04223ce4149f4b9a53d", + sha256 = "7804d77127001ed50263f0783d8a11f7211e72cb5e9f6443f2acde4b08d9ab1e", slot = "criteria", normative = true } gates = { path = ".machine_readable/template-capability-gates.toml", # from .machine_readable/ - sha256 = "8b1a77669c9ab78e9081669dbb2ab141d8af29700affc327f3dcde99f3dcd243", + sha256 = "6a8b9b420519dccdd2c586da06a9a302bdbbb3dc917f49e4a7b308882471d68a", slot = "gates", normative = true } applicability = { path = "TEMPLATE-APPLICABILITY-POLICY.adoc",