feat(phase-2.2): extract the canon's law to 0-canon/rsr/ — and stop short of deleting - #815
Merged
Merged
Conversation
….2 short of deleting
Phase 2.2's first half, executed. Its second half — "delete the directory — 43% of
the repo, no ownership decision required" — is NOT executed, because that premise
is false. See below.
WHAT MOVED
11 files, byte-identical (git records all 11 as R100):
rhodium-standard-repositories/spec/ -> 0-canon/rsr/
including `rsr-criteria-v2.a2ml` and `SCAFFOLD-LIFECYCLE.adoc`, two of the five
files named in canon.lock [canon.artifacts]. The canon's own law no longer lives
buried inside a vendored copy of another project.
22 references rewired across 10 files, including the two live consumers of the
criteria path: `.github/workflows/canon-spine-lockstep.yml` and
`.machine_readable/rsr-profile.a2ml`.
THE PREMISE WAS FALSE — DO NOT DELETE
`rhodium-standard-repositories/` is not a redundant vendored duplicate:
* `hyperpolymath/rhodium-standard-repositories` returns 404. The canon's own
README.adoc links to it as "RSR specification and compliance criteria"; that
link is dead. 6 of the 7 repos that README links to no longer exist.
* 8 of the 10 satellites inside it have no external home at all — rsr-certifier,
rsr-deployer, mustfile, robot-repo-automaton, META.scm, ECOSYSTEM.scm,
state.scm, well-known-ecosystem. This tree is the LAST COPY.
* The 2 that do exist (cccp, palimpsest-license) are stale snapshots, not
mirrors: external cccp main has since added .githooks/ and
.github/CODEOWNERS and dropped the old ISSUE_TEMPLATE files.
The satellites are real committed trees, not gitlinks, so the content is fully
materialised. Deleting it would destroy the only copy of 8 projects.
AND IT CANNOT SIMPLY BE ARCHIVED WHOLESALE EITHER
`actions-allowlist/allowed-actions.json` is a live published interface:
https://raw.githubusercontent.com/hyperpolymath/standards/main/rhodium-standard-repositories/actions-allowlist/allowed-actions.json
consumed estate-wide by `allowlist-preflight-reusable.yml`, which
sparse-checks-out `rhodium-standard-repositories/actions-allowlist`. Moving that
subtree is a breaking change for consumers outside this repo, so the archive
relocation needs its own coordinated step. Recorded in the map entry's note.
A CANON RELEASE, BECAUSE A HASHED ARTEFACT ACTUALLY CHANGED
`.machine_readable/template-capability-gates.toml` names the criteria paths in its
role=\"canon\" VESTIGIAL-exemption list. Those paths moved, so the list moved with
them — that file is a hashed artefact, so this is a real canon change:
[canon].version 2.0.0 -> 2.0.1 (PATCH: editorial; no criteria-set change)
[canon].tag canon-v2.0.0 -> canon-v2.0.1
gates sha256 4c57d515bd3f... -> 8b1a77669c9a...
`criteria_sha256` is UNCHANGED (efd024ad...), verified by hashing the file at its
new path, so the spine's adopted pin still holds on that criterion. No tag is
created here — release tagging is a separate, deliberate act.
CONSEQUENCE, RECORDED AS F8 RATHER THAN LEFT SILENT
The spine pins `gates_sha256` in its [canon] block, and **no gate checks it** —
its `Canon lockstep` job compares `criteria_sha256` only. That pinned value is now
stale and nothing will report it. AUDIT.adoc F8 records the gap: a pin nothing
verifies is not a binding. The spine-side update is deliberately left to its own
change rather than smuggled into this one.
AUDIT.adoc F4 CORRECTED
F4 read "a vendored copy of a separate repository". It is not — the upstream is
gone. F4 now records the archive finding and the last-copy status.
THE MAP MOVES WITH THE FILES
Gate D is bidirectional, so the new district needs an entry and the old one needs
correcting: `[[entry]] from = "0-canon"` added (canon_slot = rsr-spec-home),
`rhodium-standard-repositories` target changed from "0-canon/rsr/ (extract spec/
only)" to "9-archive/... (ARCHIVE, do not delete)" with its note rewritten,
`entry_count` 118 -> 119.
WITNESSES
Gate A [1] criteria 0-canon/rsr/rsr-criteria-v2.a2ml efd024ad9cbd... PASS
gates .machine_readable/template-capability-gates.toml 8b1a77669c9a... PASS
applicability / lifecycle / constitution PASS
[2] canon artefacts changed and canon.lock bumped in the same commit PASS
[3] spine criteria_sha256 == canon.lock criteria PASS
passed 8 failed 0 skipped 2 GATE A PASSED
Gate D [1] all 119 mapped paths exist
[2] all 119 top-level entries are mapped
[4] all canon_slot values resolve
[5] entry_count = 119 GATE D PASSED
profile OK - scaffold matches declared capabilities
Contributor
|
Warning Review limit reachedNext included review available in 51 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (21)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
hyperpolymath
added a commit
to hyperpolymath/rsr-template-repo
that referenced
this pull request
Sep 17, 2026
…canon 2.0.1 (#104) Closes **F8** in `hyperpolymath/standards docs/AUDIT.adoc`: *"the spine pins `gates_sha256` but no gate verifies it."* ## Two stale values, found because nothing checked them Canon **2.0.1** ([standards#815](hyperpolymath/standards#815)) moved `gates_sha256` when the criteria paths moved to `0-canon/rsr/`. This repo kept asserting the superseded values, and no check said a word: | pin | canon.lock asserts | this repo declared | | |---|---|---|---| | `version` | `2.0.1` | `2.0.0` | stale | | `criteria_sha256` | `efd024ad9cbdf0d3` | `efd024ad9cbdf0d3` | in sync | | `gates_sha256` | `8b1a77669c9ab78e` | `4c57d515bd3fa9d1` | stale | That isn't two careless values. This repo's own `rsr-profile.a2ml` asserted that *"these values"* — **plural** — equal `canon.lock [canon.artifacts]` at the canon's head, while the job meant to enforce it compared `criteria_sha256` alone. **The claim was wider than the check**, so the other two could drift indefinitely and stay invisible. *When the thing that documents the binding is more confident than the thing that checks it, the documentation is the bug.* ## What changes 1. **Re-pinned** `machine-readable/rsr-profile.a2ml`: `version` 2.0.0 → 2.0.1, `gates_sha256` → `8b1a77669c9a…`. `criteria_sha256` is **unchanged**, which is correct — the criteria file is byte-identical; only its path moved. 2. The comment above `[canon]` now describes what is **actually** checked, by which job, in which direction. 3. The `Canon lockstep` job compares **version, criteria_sha256 and gates_sha256**, and prints a per-pin table either way. ## Still no `uses:` in this job Deliberate, and it holds: `uses:` count is **0**, so this job still cannot worsen `uses ⊆ actions.lock`. Both new readers are pure `awk` + `grep` against files already fetched — `canon.lock` is already at `$RUNNER_TEMP` from the step above, and the profile is already fetched by SHA. **No new network call, no new action.** The two readers are the same technique the canon's own `check-canon-lockstep.sh` uses, so there's one idiom across both repos. `artefact_hash` joins the inline table and greps the digest rather than assuming the `sha256` sits on any particular line of the record. ## An empty read cannot pass Six values are read. Any empty one aborts with *"refusing to compare an empty value"* rather than comparing `""` to `""`. That's the same class of failure this job already had once — reading a file that was never there — so it's now guarded explicitly rather than left to luck. ## Witnesses Negative control — this repo's shell run against the live canon at `main`: ``` | `version` | `2.0.1` | `2.0.0` | ❌ | | `criteria_sha256` | `efd024ad9cbdf0d3` | `efd024ad9cbdf0d3` | ✅ | | `gates_sha256` | `8b1a77669c9ab78e` | `4c57d515bd3fa9d1` | ❌ | exit=1 ``` Pass case — same shell, corrected profile: ``` | `version` | `2.0.1` | `2.0.1` | ✅ | | `criteria_sha256` | `efd024ad9cbdf0d3` | `efd024ad9cbdf0d3` | ✅ | | `gates_sha256` | `8b1a77669c9ab78e` | `8b1a77669c9ab78e` | ✅ | exit=0 ``` Also verified: YAML parses (7 jobs), `uses:` in `canon-lockstep` = 0, `dogfood-summary` still needs `canon-lockstep`. One bug caught while testing rather than after: my first draft of the footer lost the escaped backticks the original had, so bash executed `canon.lock` and `[canon]` as commands. Restored; the footer renders literally. ## Merge order This should land **after** `standards` 2.0.1 is on `main` — it is — and it makes the reverse direction of the binding real. Before it, the mutual binding was one-directional in practice: the canon checked the spine, but the spine's own pins were decorative.
hyperpolymath
added a commit
that referenced
this pull request
Sep 17, 2026
…CH) (#818) 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 a spelling the estate majority does not. This corrects the law. ## Why PATCH — the criteria's own rule, not my judgement `rsr-criteria-v2.a2ml` `[versioning].rule-patch`: > A PATCH bump is editorial (wording, detection-rule id corrections, **template_ref fixes**) with no criteria-set change. That is exactly this change and nothing more: wording in `desc`/`freeze-mechanism`/`applicable-set`/`report` prose, and **eight of the fifteen** changed strings are `template_ref` values. **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 satisfied if ANY alternative exists — so the only behavioural difference is which spelling appears first in a list. Nothing that conformed stops conforming; MINOR is for additions and there are none. ## The identifier is not a path `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. Asserted in the edit script — after the pass the file holds 15 `.machine_readable/` paths and exactly two surviving `machine-readable` strings: that key, and the file's own title line. ## 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 creates what it points at. Same file, same pass: its SSOT footer still pointed at `spec/rsr-criteria-v2.a2ml`, dead since #815 moved the law into `0-canon/rsr/`. ## Sequence Gate A fails this until the spine re-adopts. **The two merge together** — spine first, then this, seconds apart. ## Witnesses ``` lock hashes vs artefacts on disk both match (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 check-allowed-actions.sh rc=0 35 uses: refs, 0 uncovered validate-a2ml.sh rc=1 33 errors — IDENTICAL to the pre-release baseline, so these edits added none ```
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Phase 2.2, first half. The second half — "delete the directory — 43% of the repo, no ownership decision required" — is not executed, because that premise is false.
What moved
11 files, byte-identical (
gitrecords all 11 asR100):including
rsr-criteria-v2.a2mlandSCAFFOLD-LIFECYCLE.adoc, two of the five files named incanon.lock [canon.artifacts]. The canon's own law no longer lives buried inside a vendored copy of another project.22 references rewired across 10 files, including the two live consumers of the criteria path:
.github/workflows/canon-spine-lockstep.ymland.machine_readable/rsr-profile.a2ml.The premise was false — do not delete
rhodium-standard-repositories/is not a redundant vendored duplicate:hyperpolymath/rhodium-standard-repositoriesThe orphaned eight are
rsr-certifier,rsr-deployer,mustfile,robot-repo-automaton,META.scm,ECOSYSTEM.scm,state.scm,well-known-ecosystem. The satellites are real committed trees, not gitlinks — 8.8 MB fully materialised. This tree is the last copy, and deleting it would destroy the only copy of eight projects.The staleness is concrete, not inferred: external
cccpmain has since added.githooks/and.github/CODEOWNERSand dropped its oldISSUE_TEMPLATEfiles.And it cannot be archived wholesale either
actions-allowlist/allowed-actions.jsonis a live published interface:consumed estate-wide by
allowlist-preflight-reusable.yml, which sparse-checks-outrhodium-standard-repositories/actions-allowlist. Moving that subtree breaks consumers outside this repo, so the archive relocation needs its own coordinated step. Recorded in the map entry's note.A canon release, because a hashed artefact actually changed
.machine_readable/template-capability-gates.tomlnames the criteria paths in itsrole="canon"VESTIGIAL-exemption list. Those paths moved, so the list moved with them — and that file is a hashed artefact, making this a real canon change:[canon].version2.0.02.0.1[canon].tagcanon-v2.0.0canon-v2.0.1gatessha2564c57d515bd3f…8b1a77669c9a…criteria_sha256is unchanged (efd024ad…), verified by hashing the file at its new path — so the spine's adopted pin still holds. No tag is created here; release tagging is a separate, deliberate act.Consequence, recorded as F8 rather than left silent
The spine pins
gates_sha256, and no gate checks it — itsCanon lockstepjob comparescriteria_sha256only. That pinned value is now stale and nothing will report it.AUDIT.adocF8 records the gap: a pin nothing verifies is not a binding. The spine-side update is deliberately left to its own change.AUDIT.adocF4 is corrected: it read "a vendored copy of a separate repository". It is not — the upstream is gone.The map moves with the files
Gate D is bidirectional, so:
[[entry]] from = "0-canon"added (canon_slot = rsr-spec-home), therhodium-standard-repositoriestarget changed from"0-canon/rsr/ (extract spec/ only)"to"9-archive/… (ARCHIVE, do not delete)"with its note rewritten,entry_count118 → 119.Witnesses
Next
The archive relocation needs a decision on the
actions-allowlist/interface before it can proceed, and Phase 2.3 (themachine-readable/rename) remains blocked on ruling R-A — I've flagged the conflict in that ruling separately.