Repository navigation
fix(root_hygiene): accept the repo deed <repo>_chora.deed as the AI manifest - #960
Merged
Merged
Conversation
… manifest A2ML is retired (D312): a repo's facts live in one `<repo>_chora.deed` at the root, and the estate template (rsr-template-repo) ships no 0-AI-MANIFEST at all. root_hygiene still required 0-AI-MANIFEST.a2ml (or .deed / AI.a2ml), so it raised a HIGH "Required file missing" on every repo that followed the retirement, including the canonical template and echo-types after its 2026-09-30 retirement of every .a2ml file. The manifest requirement is now met by any root `*_chora.deed`. The legacy spellings still satisfy it until their repos migrate, so no repo gains a finding from this change. When the manifest is missing, the finding names the deed it needs: scan/2 derives `<repo>` from the repository directory; the filename-only scan/1 uses the placeholder `repo`. Tests: test/root_hygiene_test.exs 34/34 (was 30). Three of the new tests fail against the old rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P4yFkxW5Heb8p2YW7ZYs9F
Contributor
Finishing Touches
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
marked this pull request as ready for review
October 26, 2026 22:26
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
hyperpolymath
enabled auto-merge
October 26, 2026 22:28
hyperpolymath
added a commit
to hyperpolymath/echo-types
that referenced
this pull request
Oct 26, 2026
…indings, part 1) (#354) ## Summary This is part 1 of fixing the Hypatia scan findings on echo-types. It fixes **9 of the 10 findings visible** in the PR scan comment by taking the estate template's versions of three workflows (`hyperpolymath/rsr-template-repo`) instead of patching the drifted local copies. | Finding | Severity | File | Fix | |---|---|---|---| | WH014: masked scanner feeds the SARIF upload | high | `hypatia-scan.yml` | Template version: `set -euo pipefail`, no `\|\| true`, and `jq -e` checks the findings JSON and the SARIF before upload | | RE001: uses `secrets.*` without harden-runner | medium | `hypatia-scan.yml` | Template no longer references `secrets.*` | | WH006 + missing_timeout_minutes (job `sync`) | medium ×2 | `labels.yml` | `timeout-minutes: 10` | | WH006 + missing_timeout_minutes (job `triage`) | medium ×2 | `label-triage.yml` | `timeout-minutes: 10` | | RE001 | medium ×2 | `labels.yml`, `label-triage.yml` | `github.token` instead of `secrets.GITHUB_TOKEN` | **Why WH014 mattered.** When the scanner failed, the old workflow still uploaded a SARIF file with zero results. GitHub then auto-closes every open alert in that category, with the job showing green. The template already guards against this, so re-syncing fixes it at the source rather than patching a fork of it. **Dropped from `hypatia-scan.yml`, because the template doesn't carry them:** - the findings artifact upload; - the PR comment, which only ever showed the first 10 of 38 findings; - the gitbot-fleet submission, whose push was being denied (`403`). ## ⚠ Read the new finding count with care: 38 → 3 is not 35 fixes This branch's Hypatia run reports **3 findings** (0 critical, 1 high), down from 38 on `main`. The scanner versions are effectively the same: the template pins `d73f76b5`, committed five minutes before the `main` (`edc6608`) the old workflow used. But **the template does not pass `GITHUB_TOKEN` to the scan.** Hypatia's API-backed rule modules need a token and return `[]` silently without one: `code_scanning_alerts`, `dependabot_alerts`, `secret_scanning_alerts`, `branch_protection`, `baseline_health` and similar. Most of the 28 findings the old PR comment never showed most likely came from those modules. They are now unscanned, not fixed. Re-enabling them means passing `GITHUB_TOKEN: ${{ github.token }}` in the scan step's `env`. That uses `github.token`, not `secrets.*`, so RE001 stays clear. The right place for that is the template itself, in `rsr-template-repo`, so every synced repo gets the same coverage. That decision is with the owner; this PR deliberately stays byte-identical to the template. ## `actions.lock` - The `hypatia-scan.yml` entry now matches the template's lock exactly. It uses SHA-pinned cache, checkout, setup-beam and codeql-action, all of which were already recorded under `dependencies`. - I removed the three dependency records that no workflow uses any more: `github-script@v9.0.0`, `upload-artifact@v7.0.2` and `setup-beam@v1.24.1`. - This was edited by hand, because `gh actions-lock` isn't available in my environment. I checked that every workflow ref resolves to a dependency and that no dependency is unreferenced. **It still needs `gh actions-lock --verify-local`.** The Governance `actions-lock-verify` job would do that, but it is currently failing at startup on the Actions-allowlist issue from echo-types#352. ## Not in this PR - **Harden-runner (RE001) on `push-email-notify.yml`.** That job genuinely needs SMTP secrets. Per the owner's decision, adopting `step-security/harden-runner` is deferred to a single estate-wide decision via the allowlist in `metadatastician/standards`. - **Missing `0-AI-MANIFEST.a2ml` (high).** This file was retired on purpose (`6eafe81`). The rule is being fixed upstream in hyperpolymath/hypatia#960, which accepts `<repo>_chora.deed`. Once that lands, this finding becomes "missing `echo-types_chora.deed`", which is accurate debt tracked by the `.deed` conversion (rsr-template-repo#209). - **The token-gated findings above.** Part 2, once the template passes the token. ## Testing - All three workflows parse as YAML. - The lock's hypatia-scan entry is identical to `rsr-template-repo`'s. - This branch's Hypatia run passes the new pre-upload checks and reports 0 critical, 1 high and 3 total. Read that count with the caveat above. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01P4yFkxW5Heb8p2YW7ZYs9F Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath
disabled auto-merge
October 27, 2026 00:08
Contributor
|
Add Carrot credits or activate Agent usage billing to use Autofix |
hyperpolymath
enabled auto-merge
October 27, 2026 00:09
hyperpolymath
disabled auto-merge
October 27, 2026 00:10
hyperpolymath
added a commit
to hyperpolymath/rsr-template-repo
that referenced
this pull request
Oct 27, 2026
…enSSF check (#258) ## Summary This PR fixes two problems in the estate template's CI. 1. **Hypatia's GitHub-API rules got no token.** Hypatia's scan step ran without credentials, so its rules that query the GitHub API quietly returned nothing in every repo synced from this template. When hyperpolymath/echo-types re-synced to this workflow (hyperpolymath/echo-types#354), its finding count fell from 38 to 3, mostly for this reason. 2. **The licence checks rejected `LICENSE.adoc`.** That's the file this template ships, so the checks were red on the template and in every repo minted from it. ## Changes **`hypatia-scan.yml`** - **Token:** pass `GITHUB_TOKEN: ${{ github.token }}` to the scan step only, not the whole job. It's `github.token` rather than `secrets.GITHUB_TOKEN`, so the scan doesn't raise its own harden-runner finding (RE001). - **Permissions:** grant `vulnerability-alerts: read`, which Hypatia's Dependabot-alert rules need. `security-events` only covers code-scanning alerts. The key is valid in GitHub's workflow schema (SchemaStore): the edited workflow passes, and a made-up key fails. - **Cache key:** the key now reads `${{ env.HYPATIA_SHA }}` instead of repeating the SHA. Before, bumping the pin without also editing the key would reuse the old scanner build. **Licence checks** (`ossf-best-practices.yml`, and `just verify` / `self-assess` in `build/just/assess.just`) - They now accept `LICENSE`, `LICENSE.txt`, `LICENSE.md` or `LICENSE.adoc`. - They also accept a REUSE `LICENSES/` directory, but only if it holds a non-empty, non-hidden `<SPDX-ID>.<ext>` licence text (not a README). - `just verify` runs inside `just repo-init`, so its old `LICENSE`-only check failed every mint. That's the Proven suite's template-mint E2E lane. - No licence file is changed. ## What the token can and can't reach - **Code-scanning alerts:** reachable, through `security-events`. - **Dependabot alerts:** reachable, through `vulnerability-alerts: read`, which this PR adds. - **Secret-scanning alerts:** not reachable. No `GITHUB_TOKEN` permission covers them; they need a GitHub App or PAT. That's an owner decision (it would add a secret to the template), so it's left out. - **Branch protection:** may be refused for the job token. - **When a call is refused:** the rule logs a warning and returns `[]`, so a refusal costs coverage but never produces a false finding. BH001 ("no protection at all") fires only on a genuine "Branch not protected" answer. ## Evidence from CI Compared with `main` (`0d3fcfe`), the Hypatia Security Scan on this PR: - **no longer logs the three "GITHUB_TOKEN not set" warnings.** That shows the alert queries ran with a token. It doesn't show they all succeeded; see the section above. - **reports 30 findings instead of 5.** - **restored the same cache entry**, because the new key resolves to the same string. OpenSSF Compliance is now green. ## Still red, and why Details are in [this comment](#258 (comment)). - **Hypatia critical finding (missing `LICENSE`):** waits on hyperpolymath/hypatia#963. Once it merges, I'll bump `HYPATIA_SHA` here and in the two other workflows that pin the same SHA. That bump also brings in hyperpolymath/hypatia#960, which clears the old `0-AI-MANIFEST` high finding. - **estate-rules, Central Estate CI/CD Audit, and the `root_shape` benchmark:** fixed by #260. ## Testing - **Licence checks:** run against seven layouts, and all three checks agree on each. - Pass: `LICENSE.adoc`, and `LICENSES/MPL-2.0.txt`. - Fail: `.gitkeep` only, README only, an empty licence file, a dotfile only, and no licence at all. - **`just verify` on this tree:** the old recipe exits 1 with the CI message; the new one exits 0. - **shellcheck 0.9.0:** clean. - **SchemaStore workflow schema:** both edited workflows validate. ## RSR Quality Checklist ### Required - [x] No banned language patterns - [x] SPDX license headers present on all modified files (unchanged) - [x] No secrets, credentials, or `.env` files included. The scan uses the job token, not a secret. - [x] Linter is clean (Workflow Security Linter green) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01P4yFkxW5Heb8p2YW7ZYs9F --------- Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
Oct 27, 2026
…SES/ dir (#963) ## Summary `root_hygiene` only counts `LICENSE` or `LICENSE.txt` as the repo's licence file. The estate template `rsr-template-repo` ships `LICENSE.adoc` and a REUSE `LICENSES/` directory. So the template, and every repo synced from it, gets a **critical** "Required file missing" finding, which fails the template's zero-critical Hypatia gate. hyperpolymath/rsr-template-repo#258 shows this, and so does that repo's `main`. ## Change `lib/rules/root_hygiene.ex`, in `scan_required_missing`: - **More licence file names:** `LICENSE.md` and `LICENSE.adoc` now satisfy the requirement, alongside `LICENSE` and `LICENSE.txt`. - **REUSE `LICENSES/` directory:** `scan/2` (the CLI path) also accepts a `LICENSES/` directory, as long as it holds at least one REUSE licence text. - A licence text means a non-empty, non-hidden `<SPDX-ID>.<ext>` file that isn't a README, as the REUSE spec requires. - An empty `LICENSES/`, or one holding only `.gitkeep`, a README, an empty file or an extensionless file, declares nothing and still produces the finding. - The filename-only `scan/1` can't see the directory, because `list_root_files` drops directories. It behaves as before. - **No new findings anywhere:** every name accepted before is still accepted. ## Testing Mix deps can't be fetched in this environment. As with #960, I compiled the module standalone and ran `test/root_hygiene_test.exs` with plain Elixir. - **New tests:** four. They cover `.adoc` and `.md`, reject `LICENSE.adoc.orig`, check the REUSE directory both empty and with a licence in it, and reject non-licence files in `LICENSES/`. - **This branch:** 38 of 38 tests pass, up from 34 on `main`. - **Against the old rule:** the positive tests fail, and the non-licence-files test fails against the earlier "any file counts" version of this PR. - **Formatting:** `mix format --check-formatted` passes. The full `mix test` runs in CI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01P4yFkxW5Heb8p2YW7ZYs9F
hyperpolymath
added a commit
to hyperpolymath/rsr-template-repo
that referenced
this pull request
Oct 27, 2026
#261) ## Summary The template pins Hypatia at `d73f76b`. That version predates two fixes: - hyperpolymath/hypatia#960: accepts the repo deed `<repo>_chora.deed` as the AI manifest. - hyperpolymath/hypatia#963: accepts `LICENSE.adoc` and REUSE `LICENSES/` as the licence. Under the old pin the template raised a **critical** "Required file missing: LICENSE" and a **high** `0-AI-MANIFEST` finding, so the zero-critical gate in the Hypatia Security Scan and the Static Analysis Gate failed. This was the bump promised in #258. ## Changes - The pin moves from `d73f76b` to Hypatia `main` at `7c10e5d`, which includes #960, #963 and #969. - It's updated in all three workflows that carry it, so they stay on one version: `hypatia-scan.yml` (`HYPATIA_SHA`), `static-analysis-gate.yml` and `dogfood-gate.yml`. - `hypatia-scan.yml`'s cache key reads `HYPATIA_SHA` since #258, so it follows on its own. - The other two have the SHA in their cache keys, and those are updated in place. ## Testing - **Root hygiene at `7c10e5d`:** I ran the rule against this repo's root and it returns **no findings**. At `d73f76b` it returned the critical and the high. - **Schema:** all three workflows validate against the GitHub workflow schema (SchemaStore). - **Old pin:** no copy of the old SHA remains in the tree. `actions.lock` is unaffected, because this SHA is a git ref, not an action pin. - **Full scan:** I couldn't build the full scanner locally because Hex is unreachable. This PR's Hypatia Security Scan and Static Analysis Gate runs are the end-to-end check. ## Follow-up hyperpolymath/hypatia#970 (open) makes SC-010, a Low-severity finding that doesn't block, accept `LICENSE.adoc`. It also adds pagination and a timeout to the secret-scanning sweep. Once it merges, a second small bump picks it up. --- _Generated by [Claude Code](https://claude.ai/code/session_01P4yFkxW5Heb8p2YW7ZYs9F)_ Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath
added a commit
to hyperpolymath/echo-types
that referenced
this pull request
Oct 27, 2026
…pe, 7c10e5d (Hypatia findings, part 2) (#356) ## Summary Part 2 of fixing the Hypatia findings on echo-types. Part 1 (#354) took the template's `hypatia-scan.yml` as it stood then. That version silently dropped every API-backed rule, because it passed the scanner no token. The fix went into the template first (hyperpolymath/rsr-template-repo#258 and #261). This PR takes the merged result, byte-identical. | Change | Why | |---|---| | The scan step gets `GITHUB_TOKEN: ${{ github.token }}`, scoped to that step | Hypatia's code-scanning, Dependabot, branch-protection and baseline-health rules return `[]` without a token. It is `github.token`, not `secrets.*`, so RE001 stays clear. | | `vulnerability-alerts: read` on the job | Lets the Dependabot (DA) rules read alerts. `security-events: write` covers only code scanning. | | `HYPATIA_SHA` `d73f76b` → `7c10e5d` | This scanner accepts `LICENSE.adoc` and REUSE `LICENSES/` (hyperpolymath/hypatia#963). It no longer demands `0-AI-MANIFEST.a2ml` (hyperpolymath/hypatia#960). | | Cache key `…-${{ env.HYPATIA_SHA }}` | A pin bump now rebuilds the scanner. Before, it reused the old build under a hard-coded key. | | `upload-sarif` moves to codeql-action v4.39.1 (`9b32540`) | Matches the template. | `actions.lock` is updated to match. `hypatia-scan.yml` now lists codeql-action at `9b32540`, and that pin has its dependency entry. The v4.38.0 entry stays, because the `metadatastician/standards` reusable workflows still pin it. ## What this does not cover - **Secret-scanning alerts.** No `GITHUB_TOKEN` permission can read them, so the per-repo scan never sees them. The workflow comment says so. They will come from a separate, private estate-wide sweep with a dedicated read-only token, not from this repository. - **The finding count will go up.** The API-backed rules are scanning again, so expect findings that were unscanned under #354, not new problems. ## Verification - `hypatia-scan.yml` is `cmp`-identical to `rsr-template-repo@4f4536e`. That file passed GitHub-workflow schema validation and the template's CI in #258 and #261. - `actions.lock` parses, and its `hypatia-scan.yml` list now names exactly the four pins the workflow uses. - I could not run `gh actions-lock` here. The lock edit mirrors the format that tool writes, and this PR's CI run is the check that matters. --- _Generated by [Claude Code](https://claude.ai/code/session_01P4yFkxW5Heb8p2YW7ZYs9F)_ Co-authored-by: Claude <noreply@anthropic.com>
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.
Summary
A2ML is retired (D312). A repo's facts now live in a single
<repo>_chora.deedat the root, and the estate templatersr-template-repoships no0-AI-MANIFESTfile. Butroot_hygienestill required0-AI-MANIFEST.a2ml(or.deed/AI.a2ml). So every repo that followed the retirement got a high "Required file missing" finding, including the canonical template and hyperpolymath/echo-types, which retired its.a2mlfiles on 2026-09-30 (commit6eafe81).Change
lib/rules/root_hygiene.ex, inscan_required_missing:*_chora.deed. The deed is named for the repo, not the checkout directory, so any prefix is accepted.0-AI-MANIFEST.a2ml,0-AI-MANIFEST.deedandAI.a2mlstill satisfy the rule until their repos migrate. No repo gains a finding from this PR.scan/2(the CLI path) derives<repo>from the repository directory, for exampleecho-types_chora.deed. The filename-onlyscan/1uses the placeholderrepo.Not changed: other rules that still mention
0-AI-MANIFEST(structural_driftSD003/SD007,rsr_conformance2.3.1,dogfooding). Those are separate decisions and are out of scope here.Testing
Mix deps couldn't be fetched in this environment, so I compiled the module standalone and ran its ExUnit suite with plain Elixir 1.14:
test/root_hygiene_test.exspasses 34/34 on this branch, up from 30/30 onmain. One test is updated and five are new.mix format --check-formattedpasses on both files.Full
mix testwill run in CI.Generated by Claude Code