Skip to content

feat(phase-2.2): extract the canon's law to 0-canon/rsr/ — and stop short of deleting - #815

Merged
hyperpolymath merged 1 commit into
mainfrom
phase-2.2-extract-canon-law
Sep 17, 2026
Merged

hyperpolymath merged 1 commit into
mainfrom
phase-2.2-extract-canon-law

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

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 (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:

check result
hyperpolymath/rhodium-standard-repositories 404 — the canon's README calls it "RSR specification and compliance criteria"; that link is dead
repos that README links to 6 of 7 no longer exist
satellites inside the tree 8 of 10 have no external home
the 2 that do exist stale snapshots, not mirrors

The 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 cccp main has since added .githooks/ and .github/CODEOWNERS and dropped its old ISSUE_TEMPLATE files.

And it cannot 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 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.toml names the criteria paths in its role="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:

field from to
[canon].version 2.0.0 2.0.1
[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. 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 — 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.

AUDIT.adoc F4 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), the 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 ( criteria gates lifecycle ) and canon.lock
             was bumped in the same PR                                                      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

Next

The archive relocation needs a decision on the actions-allowlist/ interface before it can proceed, and Phase 2.3 (the machine-readable/ rename) remains blocked on ruling R-A — I've flagged the conflict in that ruling separately.

….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
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 51 minutes.

Check out review usage here.

View limit details

Limit 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.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b219379c-20bf-4365-ae5a-a2188e187337

📥 Commits

Reviewing files that changed from the base of the PR and between 4ef3f49 and baf1760.

⛔ Files ignored due to path filters (1)
  • canon.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • .github/workflows/canon-spine-lockstep.yml
  • .hypatia-baseline.json
  • .machine_readable/rsr-profile.a2ml
  • .machine_readable/scorecards/rhodium-standard-repositories.scorecard.a2ml
  • .machine_readable/template-capability-gates.toml
  • 0-canon/rsr/CHANGELOG.adoc
  • 0-canon/rsr/LANGUAGE-POLICY.adoc
  • 0-canon/rsr/REPO-STANDARD-MUST-INTEND-LIKE.adoc
  • 0-canon/rsr/RSR-SPEC-v2.adoc
  • 0-canon/rsr/RSR-SPEC.adoc
  • 0-canon/rsr/SCAFFOLD-LIFECYCLE.adoc
  • 0-canon/rsr/TIERS.adoc
  • 0-canon/rsr/VERSION.adoc
  • 0-canon/rsr/nix-retirement-inventory.adoc
  • 0-canon/rsr/rsr-criteria-v2.a2ml
  • 0-canon/rsr/scaffold-stub-debt.adoc
  • component-readiness-grades/COMPONENT-READINESS-GRADES.a2ml
  • docs/AUDIT.adoc
  • launcher/launcher-standard.a2ml
  • scripts/check-package-policy.sh
  • standards-map.toml

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath merged commit efaec62 into main Sep 17, 2026
29 of 34 checks passed
@hyperpolymath
hyperpolymath deleted the phase-2.2-extract-canon-law branch September 17, 2026 18:28
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
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant