Repository navigation
Relocate org-wide compliance rulesets (code-quality, pr-quality) from .github-private to .github/standards/rulesets/ #575
Description
Summary
Relocate the org-wide compliance ruleset JSONs (code-quality.json, pr-quality.json) from
petry-projects/.github-private/.github/rulesets/ to their correct canonical home,
petry-projects/.github/standards/rulesets/, and repoint the tooling. .github-private is reserved for
agents, skills, and their reusable workflows/assets — it must not be the source of truth for org-wide
compliance policy. This is a governance/placement cleanup that also unblocks safely evolving the
required-check set (coverage / secret-scan) for the repo-template initiative (epic #964).
Background — how this happened
code-quality.jsonwas added to.github-privateon 2026-05-14 under an ad-hoc "compliance fix"
(issue fix: add GH_TOKEN preflight check to compliance-audit.sh #60 / PR fix: encode compliance-fix learnings into standards and Claude prompt #86), before the org-standards structure and repo-boundary conventions matured.apply-rulesets.sh(issue [#850] pr-auto-review dispatch strands PRs under bulk convergence — add a catch-up sweep + churn tolerance #868 / PR [Fleet Monitor] petry-projects/.github — .github/workflows/standards-deploy-tests.yml #889, initiative docs(standards): add Advanced Security (GHAS) org standard #495) then anchored on that location — its
RULESETS_REPOdefaults topetry-projects/.github-private— andbootstrap-new-repo.sh
(Org Status — 2026-08-11 #967/Org Status — 2026-08-13 #972) consumed the same path.- Result: the codified source of truth for fleet-wide rulesets lives in
.github-private, while
.githubholds only the documentation (standards/github-settings.md) plus a duplicate copy of
apply-rulesets.sh. The standard is split across two repos with a duplicated applier.
Discovered during epic #964 (repo-template): a Copilot review flagged that adding coverage to the
shared code-quality.json would brick every repo lacking a coverage job — surfacing that this shared
org policy sits in the wrong repo.
Decision (the governance rule — now documented in .github/AGENTS.md)
- Org-wide standards and compliance policy (CI/workflow templates, repo settings, labels, Dependabot
policy, security config, and the codified compliance rulesetscode-quality/pr-quality) are
owned bypetry-projects/.github; their canonical home isstandards/. petry-projects/.github-privateis scoped to agents, skills, and their reusable workflows/assets.
The one ruleset that legitimately stays there isrelease-channel-tags— it protects
.github-private's ownpr-review/**anddev-lead/**agent-release tags.- Rule of thumb: fleet-wide →
.github/standards/; protects an agent/skill's own assets in
.github-private→ stays there. When in doubt, put it in.githuband have.github-privateconsume it.
Scope of work
- Relocate JSONs — move
code-quality.json+pr-quality.jsonto
petry-projects/.github/standards/rulesets/. Leaverelease-channel-tags.jsonin.github-private. - Repoint tooling
apply-rulesets.sh: changeRULESETS_REPO/RULESETS_DIRdefaults so the fleet rulesets resolve
from.github; keep a path for the.github-private-localrelease-channel-tags.bootstrap-new-repo.sh: read the fleet rulesets from.github.- Dedupe the two
apply-rulesets.shcopies (.github/scripts/vs.github-private/scripts/) —
pick the canonical owner (the applier is org tooling →.github), or clearly delineate roles.
- Docs —
standards/github-settings.md: point the code-quality / pr-quality "source of truth" refs
at the newstandards/rulesets/location; add aRulesetsrow to the AGENTS.md standards index. - Migration safety — moving the source JSON does not change any repo's live ruleset (rulesets
live on each repo). Verify: after relocation,apply-rulesets.sh --dry-runagainst a sample repo
produces the identical payload it does today (no drift), and re-running is a no-op. No live ruleset is
deleted/recreated as part of the move. - Fold-in (epic Org Status — 2026-08-09 #964 / repo-template) — decide and implement the required-check set for the
relocatedcode-quality:- Template + new repos should require the full producible set (incl.
Secret scan (gitleaks)and the
stack-awarecoverage). - Fleet-wide addition of
coveragerequires backfilling a coverage job into existing repos first (they
currently lack one) — otherwise it bricks them. Sequence: (a) ship the jobs via the templateci.yml
and backfill existing repos, (b) then add the contexts to the shared ruleset. Until backfilled, keep
the stricter set scoped to the template / new repos.
- Template + new repos should require the full producible set (incl.
Acceptance criteria
-
code-quality.json+pr-quality.jsonlive underpetry-projects/.github/standards/rulesets/;
removed from.github-private/.github/rulesets/(onlyrelease-channel-tags.jsonremains there). -
apply-rulesets.sh+bootstrap-new-repo.shresolve fleet rulesets from.githubby default;
apply-rulesets.shis de-duplicated (single canonical owner). -
apply-rulesets.sh --dry-runon a sample repo yields a byte-identical payload pre/post move (proof
of no live drift); re-run is a no-op. -
standards/github-settings.md+AGENTS.mdreference the new location; AGENTS.md carries the
repo-boundary rule (done in the guidance PR). - Required-check-set change for
code-qualityis sequenced safely (no existing repo bricked); coverage
is not added fleet-wide until repos produce it.
Out of scope
- The fleet-wide coverage backfill itself (its own migration, referenced above).
release-channel-tags.json(correctly stays in.github-private).- Any change to what the checks do — this is a placement + sequencing cleanup.
Activity
docs(governance): org-wide standards/rulesets live in .github, not .g…
docs(governance): org-wide standards/rulesets live in .github, not .g…
don-petry commentedon Jul 2, 2026
Folded in from now-closed PRs #569 (.github) and #1001 (.github-private)
Consolidating here so the check-set work happens in the right place (against the relocated ruleset), sequenced safely:
Template
ci.yml(produces the new required checks) — from #569, with review fixes to apply:secret-scanjob → checkSecret scan (gitleaks)(canonical gitleaks job; free on public repos,GITLEAKS_LICENSEon private). Fix 1: dropsecurity-events: write(no SARIF upload → over-privileged). Fix 2: run gitleaks with--config .gitleaks.tomlper push-protection.md — which also means seeding a.gitleaks.tomlbaseline into the template (add toseed-repo-template.sh).coveragejob → checkcoverage(default shell/bats via kcov; green-until-tests; per-stack expansion blocks). Forward-compatible: the template produces the check so the ruleset can require it once the fleet backfill lands.Ruleset check-set (against the relocated
standards/rulesets/code-quality.json) — from #1001:Secret scan (gitleaks)andcoveragecontexts only after existing repos produce them (fleet backfill), OR scope the stricter set to the template + new repos. Do NOT addcoverageto the shared ruleset while existing repos lack a coverage job (would brick them — the original finding).github-settings.md §243required-checks table reconciliation (SonarCloud, CodeQL, AgentShield, dependency-audit as codified; Dev-Lead per-PR; CI Pipeline repo-specific) moves here too, to land against the relocated ruleset rather than the.github-privatecopy.docs(governance): codify repo boundary — org-wide rulesets belong in …
don-petry commentedon Jul 2, 2026
Related tooling bug found during epic #964 —
apply-repo-settings.shcheck-suite precheckWhile applying settings to
repo-template,scripts/apply-repo-settings.shcould not set the check-suite auto-trigger preferences even with a valid org-admin classic PAT (ghp_,repo+admin:org). Its read precheck bails before writing:Impact: the standard path can't disable the Claude/CodeRabbit check-suite auto-trigger (the queued-but-never-completed suites that permanently block auto-merge) for anyone — the script always skips the write. This is separate from the known OAuth limitation: it fails on the check-suites API even with the correct classic PAT.
Root cause (likely): the REST API has no plain GET for check-suite preferences, so the script's "read current prefs" precheck can't succeed; it then treats that as "cannot proceed" and returns before the
PATCH.Workaround used: wrote directly via
gh api -X PATCH repos/<owner>/<repo>/check-suites/preferences --input -with the classic PAT — succeeded and flipped Claude (app 1236702) + CodeRabbit (347564) auto-trigger tofalse, verified by API read-back.Fix: drop/replace the failing read-precheck so the script performs the
PATCHdirectly (it's idempotent) and reports the resulting prefs from the PATCH response, rather than a separate read. Noteapply-repo-settings.shis duplicated in.github/scripts/and.github-private/scripts/— fix the canonical copy and dedupe alongside theapply-rulesets.shdedup in this issue. Originally recorded on combsmith/.github-private#965.docs(github-settings): reconcile §243 required-checks table to codifi…
feat(ci-template): add secret-scan + coverage jobs to template ci.yml (…
fix(pr-quality): require last push approval — align codified ruleset …
chore(rulesets): relocate code-quality + pr-quality to standards/rule…
don-petry commentedon Jul 3, 2026
✅ Delivered — closing
All acceptance criteria met; the relocation, tooling repoint, docs, and the folded-in check-set work are merged.
Merged PRs
code-quality+pr-qualityJSON →standards/rulesets/(byte-identical) + README + docspr-quality:require_last_push_approval: true(align codified with org policy; safe per #895)ci.yml:secret-scan(gitleaks CLI,--config .gitleaks.toml, nosecurity-events: write) + green-until-testscoverage.gitleaks.tomlinto repo-template (fetch:<standards-path>)apply-rulesets.sh→ codified file-driven applier canonical in.github(closed #580)bootstrap-new-repo.shto the.githubfleet sourceAC status
.github/standards/rulesets/; onlyrelease-channel-tagsremains in.github-privateapply-rulesets.sh+bootstrapresolve fleet rulesets from.github; applier de-duplicated (detection-based one retired in feat(rulesets): retire detection-based apply-rulesets.sh; codified applier canonical in .github (#580) #590)--dry-runbyte-identical / update-in-place proven (no live drift, no recreate)github-settings.md+AGENTS.mdreference the new locationcoverage/secret-scannot added fleet-wide (would brick repos)Follow-ups (tracked separately, out of #575 scope)
standards/)Closing.