diff --git a/AGENTS.md b/AGENTS.md
index 93528898..19cc279b 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -19,6 +19,7 @@ Read the relevant standard *before* making changes that touch CI, repo settings,
 | **Workflow templates** | [`standards/workflows/`](https://github.com/petry-projects/.github/tree/main/standards/workflows) | Copy-paste-ready templates: `agent-shield.yml`, `dev-lead.yml`, `dependabot-automerge.yml`, `dependabot-rebase.yml`, `dependency-audit.yml`, `feature-ideation.yml` |
 | **Agent configuration** | [`standards/agent-standards.md`](https://github.com/petry-projects/.github/blob/main/standards/agent-standards.md) | CLAUDE.md / AGENTS.md / SKILL.md required structure, frontmatter rules, cross-references |
 | **Repo settings + labels** | [`standards/github-settings.md`](https://github.com/petry-projects/.github/blob/main/standards/github-settings.md) | Required settings, label set with exact colors, code-quality ruleset, branch protection |
+| **Rulesets** | [`standards/rulesets/`](https://github.com/petry-projects/.github/tree/main/standards/rulesets) | Codified source-of-truth JSON for the org-wide `pr-quality` + `code-quality` rulesets (applied by `apply-rulesets.sh`). `release-channel-tags` stays repo-local in `.github-private` |
 | **Dependabot config** | [`standards/dependabot-policy.md`](https://github.com/petry-projects/.github/blob/main/standards/dependabot-policy.md) and [`standards/dependabot/`](https://github.com/petry-projects/.github/tree/main/standards/dependabot) | Per-ecosystem dependabot.yml templates and policy |
 | **Advanced Security (GHAS)** | [`standards/advanced-security.md`](https://github.com/petry-projects/.github/blob/main/standards/advanced-security.md) | Org-wide GHAS enablement via the "GitHub recommended" code security configuration, licensing model, and how to verify push protection actually enforces |
 | **Push protection** | [`standards/push-protection.md`](https://github.com/petry-projects/.github/blob/main/standards/push-protection.md) | Secret scanning + push protection, local gitleaks hooks, CI secret-scan job, incident response |
diff --git a/standards/github-settings.md b/standards/github-settings.md
index 33f55654..eb19efb8 100644
--- a/standards/github-settings.md
+++ b/standards/github-settings.md
@@ -152,6 +152,15 @@ silently drops a merge gate. `check_legacy_rulesets()` in
 legacy ruleset and reports the exact migration delta (checks to move into
 `code-quality` first, or "safe to delete").
 
+**Source of truth.** The codified `pr-quality` and `code-quality` ruleset JSONs
+live in this repo at [`standards/rulesets/`](rulesets/) — `.github` owns org-wide
+compliance policy (see [`AGENTS.md`](../AGENTS.md#organization-standards) for the
+repo-boundary rule, codified in #576). Run `apply-rulesets.sh` to converge each
+repo's live ruleset to the desired state documented here. The one ruleset that stays in
+`petry-projects/.github-private` is `release-channel-tags` — it protects that
+repo's own `pr-review/**` and `dev-lead/**` agent-release tags and is therefore
+correctly repo-local.
+
 > **Remediating ruleset findings is a manual, admin-token procedure** —
 > `compliance-remediate.sh` skips the `rulesets` category. Follow the
 > [Ruleset Remediation Runbook](ruleset-remediation-runbook.md) (snapshot →
diff --git a/standards/rulesets/README.md b/standards/rulesets/README.md
new file mode 100644
index 00000000..770b743d
--- /dev/null
+++ b/standards/rulesets/README.md
@@ -0,0 +1,43 @@
+# Repository Rulesets — codified source of truth
+
+This directory holds the **org-wide compliance ruleset JSONs** for `petry-projects`.
+`.github` owns org-wide standards and compliance policy; its canonical home is
+`standards/`. See [`AGENTS.md`](../../AGENTS.md#organization-standards) for the
+repo-boundary rule (codified in petry-projects/.github#576) and
+[`standards/github-settings.md`](../github-settings.md#repository-rulesets) for how
+these rulesets are enforced.
+
+| File | Ruleset | Target | Enforces |
+|------|---------|--------|----------|
+| [`pr-quality.json`](pr-quality.json) | `pr-quality` | `~DEFAULT_BRANCH` | 1 approval, code-owner review, thread resolution, dismiss-stale, squash-only merge |
+| [`code-quality.json`](code-quality.json) | `code-quality` | `~DEFAULT_BRANCH` | Required status checks (SonarCloud, CodeQL, agent-shield, dependency-audit) |
+
+Both carry the two mandatory bypass actors — `OrganizationAdmin` and the
+`dependabot-automerge-petry` Integration app (id `3167543`), both `bypass_mode: always`.
+
+## Applying
+
+These files are the **desired-state source of truth**. `scripts/apply-rulesets.sh`
+creates/updates the named ruleset on a target repo to match — re-running is a no-op
+when already in sync. Rulesets live **on each repo**; editing a file here changes the
+desired state, not any live ruleset, until the applier runs.
+
+```bash
+# Preview the payload for one repo (no writes):
+GH_TOKEN=<admin-token> bash scripts/apply-rulesets.sh <repo> --dry-run
+```
+
+## Scope boundary
+
+- **Fleet-wide → here.** `pr-quality` / `code-quality` are org-wide policy.
+- **Protects an agent/skill's own assets → stays in `.github-private`.**
+  `release-channel-tags` lives in `petry-projects/.github-private` because it
+  protects that repo's own `pr-review/**` and `dev-lead/**` release tags.
+
+## Changing the required-check set
+
+Adding a required status-check context to `code-quality.json` makes it a **merge
+gate on every repo the ruleset targets**. A repo that does not *produce* that check
+is bricked (the required check never reports). Sequence any additions safely: ship
+the producing CI job fleet-wide first, then add the context here. Keep stricter sets
+scoped to the template / new repos until the fleet backfill lands.
diff --git a/standards/rulesets/code-quality.json b/standards/rulesets/code-quality.json
new file mode 100644
index 00000000..d64cb211
--- /dev/null
+++ b/standards/rulesets/code-quality.json
@@ -0,0 +1,37 @@
+{
+  "name": "code-quality",
+  "target": "branch",
+  "enforcement": "active",
+  "bypass_actors": [
+    {
+      "actor_type": "OrganizationAdmin",
+      "bypass_mode": "always"
+    },
+    {
+      "actor_id": 3167543,
+      "actor_type": "Integration",
+      "bypass_mode": "always"
+    }
+  ],
+  "conditions": {
+    "ref_name": {
+      "include": ["~DEFAULT_BRANCH"],
+      "exclude": []
+    }
+  },
+  "rules": [
+    {
+      "type": "required_status_checks",
+      "parameters": {
+        "required_status_checks": [
+          {"context": "SonarCloud"},
+          {"context": "CodeQL"},
+          {"context": "agent-shield / AgentShield"},
+          {"context": "dependency-audit / Detect ecosystems"}
+        ],
+        "strict_required_status_checks_policy": true,
+        "do_not_enforce_on_create": false
+      }
+    }
+  ]
+}
diff --git a/standards/rulesets/pr-quality.json b/standards/rulesets/pr-quality.json
new file mode 100644
index 00000000..93ce6652
--- /dev/null
+++ b/standards/rulesets/pr-quality.json
@@ -0,0 +1,36 @@
+{
+  "name": "pr-quality",
+  "target": "branch",
+  "enforcement": "active",
+  "bypass_actors": [
+    {
+      "actor_type": "OrganizationAdmin",
+      "bypass_mode": "always"
+    },
+    {
+      "actor_id": 3167543,
+      "actor_type": "Integration",
+      "bypass_mode": "always"
+    }
+  ],
+  "conditions": {
+    "ref_name": {
+      "include": ["~DEFAULT_BRANCH"],
+      "exclude": []
+    }
+  },
+  "rules": [
+    {
+      "type": "pull_request",
+      "parameters": {
+        "required_approving_review_count": 1,
+        "require_code_owner_review": true,
+        "required_review_thread_resolution": true,
+        "dismiss_stale_reviews_on_push": true,
+        "require_last_push_approval": true,
+        "automatic_copilot_code_review_enabled": false,
+        "allowed_merge_methods": ["squash"]
+      }
+    }
+  ]
+}
