Skip to content

compliance-audit checks that rulesets EXIST, never that their contents match the codified standard #766

Description

@don-petry

The ask, and the correction

The request was to "implement and enforce required_review_thread_resolution org-wide, documented and rolled out via the compliance mechanism."

It is already implemented and already rolled out. Verified today:

  • Codified: standards/rulesets/pr-quality.json:28"required_review_thread_resolution": true
  • Applied: 11/11 repos in the org enforce it right now (.github, .github-private, bmad-bgreat-suite, broodminder-export, broodly, google-app-scripts, markets, incubator, TalkTerm, ContentTwin, repo-template)
  • Rolled out by: scripts/apply-rulesets.sh, which reads the codified JSON and converges each repo (per-repo replication is deliberate — org-level rulesets need a Team plan and this org is Free; Consolidate per-repo replicated rulesets → native org-level rulesets (when on GitHub Team) #611 tracks that).

Two consequences worth stating plainly:

  1. There is nothing to implement for thread resolution itself.
  2. It would not have prevented the regression that prompted this. Thread resolution was already on for .github when feat: implement issue #756 — Provision <id>:hands-off labels so persona opt-out actually works #757 merged with a known defect. The bug there (PR comments from maintainers are mechanically inert — they neither block merge nor reach dev-lead .github-private#1290) is that issue comments create no thread at all, so thread resolution never applies to them. Turning on a setting that is already on fixes nothing.

The real gap this exposed

check_rulesets verifies a ruleset EXISTS BY NAME. It never compares its contents to the codified JSON.

names=$(echo "$rulesets_json" | jq -r '.[].name')
if ! echo "$names" | grep -qx "pr-quality"; then
  add_finding "$repo" "rulesets" "missing-pr-quality" "error" ...

That is the whole check, plus check_ruleset_bypass_actors and check_legacy_rulesets. So today:

Anyone can flip required_review_thread_resolution to false on any repo — or drop require_code_owner_review, or lower required_approving_review_count to 0 — and compliance still passes, because a ruleset named pr-quality still exists.

The codified standard and live reality can diverge arbitrarily and silently. apply-rulesets.sh converges a repo when you run it; nothing detects drift between runs. This is the known "pr-quality drift" follow-up from the #575 relocation, never filed until now.

It is also, again, the shape #755 keeps surfacing: a green check that proves less than it appears to. "Rulesets: ✅" reads as "the ruleset is correct". It means "a ruleset with that name exists."

Scope — every parameter, not just this one

Drift is currently invisible for all of pr-quality.json and code-quality.json:

  • required_review_thread_resolution
  • required_approving_review_count
  • require_code_owner_review
  • dismiss_stale_reviews_on_push
  • require_last_push_approval
  • allowed_merge_methods
  • required_status_checks (code-quality)

Task

Extend check_rulesets in scripts/compliance-audit.sh to compare each live ruleset against its codified source in standards/rulesets/*.json and raise a finding per drifted parameter.

Constraints

Files that exist today (verified)

  • scripts/compliance-audit.shcheck_rulesets() at ~line 498; check_ruleset_bypass_actors, check_legacy_rulesets alongside it
  • standards/rulesets/pr-quality.json, standards/rulesets/code-quality.json — the codified source of truth
  • scripts/apply-rulesets.sh — the applier that converges to those files
  • test/scripts/compliance-audit/ — the bats suite (run by .github/workflows/compliance-audit-tests.yml)
  • standards/github-settings.md — the doc anchors findings point at

Acceptance criteria

  • A repo whose pr-quality ruleset has required_review_thread_resolution: false produces a compliance finding naming the parameter, expected, and actual.
  • Same for a lowered required_approving_review_count and a dropped require_code_owner_review.
  • Drift in code-quality's required_status_checks is detected.
  • All 11 repos pass today — they are in sync, so a clean fleet must stay clean. False findings here make the audit worthless.
  • A fetch/parse failure is a finding, not a pass.
  • bats coverage in test/scripts/compliance-audit/ for: in-sync (no finding), each drifted parameter (finding), and fetch failure (finding).
  • shellcheck --severity=warning -x scripts/compliance-audit.sh clean.
  • standards/github-settings.md states that ruleset contents are audited, not just presence.

Ground truth

$ gh api repos/petry-projects/.github/rules/branches/main --jq '[.[]|select(.type=="pull_request")|.parameters]'
[{"required_approving_review_count":1,"require_code_owner_review":true,
  "dismiss_stale_reviews_on_push":true,"require_last_push_approval":true,
  "required_review_thread_resolution":true, ...}]

Metadata

Metadata

Assignees

No one assigned

    Labels

    dev-leadFor dev-lead agent pickup

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions