Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Repository permission endpoint confirmed @placerda has admin permission.
# Administrators must separately require latest-head code-owner approval;
# this file alone does not activate branch protection.
# Ownership routing only; Q5 does not mandate independent/latest-head approval.
# This file alone does not activate branch protection or required checks.
/.quality/ @placerda
/pyproject.toml @placerda
/requirements-quality.txt @placerda
Expand Down
19 changes: 10 additions & 9 deletions .github/scripts/check-quality.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Read-only Python quality checks. Candidate records cannot approve their own debt."""
"""Read-only quality checks with protected rules and source-bound exception evidence."""

from __future__ import annotations

Expand Down Expand Up @@ -1006,7 +1006,7 @@ def suppressions(source):
repr(bindings.signature(resolved)))] += 1
return result
extra = suppressions(new) - suppressions(old)
findings = [finding("suppression-growth", "", 0, "New suppression requires protected review")] if extra else []
findings = [finding("suppression-growth", "", 0, "New suppression exceeds protected policy")] if extra else []
if not preserve_annotations:
return findings

Expand Down Expand Up @@ -1324,7 +1324,7 @@ def run_checks(root, base, requested, *, test_evidence=None):
if "policy" in requested:
output = findings["policy"]
if not base_policy_text:
output.append(finding("bootstrap-review", "", 0, "Protected base has no policy; maintainer bootstrap approval and administrator activation required"))
output.append(finding("bootstrap-review", "", 0, "Protected base has no policy; adopt the protected evaluator and verify required checks before claiming enforcement"))
else:
output.extend(policy_changes(set(base_records["typing-scope"]["module_ids"]),
set(records["typing-scope"]["module_ids"]),
Expand All @@ -1334,7 +1334,7 @@ def run_checks(root, base, requested, *, test_evidence=None):
before_sources, {paths[name]: source for name, source in sources.items()}))
for field in ("runtime_roots", "toolchain", "forbidden", "private_allowances", "required_checks", "dynamic_imports", "review"):
if minimum[field] != records["policy"][field]:
output.append(finding("policy-change", "", 0, f"Protected review required: {field}"))
output.append(finding("policy-change", "", 0, f"Protected policy differs: {field}"))
protected_modules = {m["id"]: m for m in minimum["modules"]}
for module in modules:
old_module = protected_modules.get(module["id"])
Expand All @@ -1351,19 +1351,17 @@ def run_checks(root, base, requested, *, test_evidence=None):
output.append(finding("policy-change", module["id"], 0, f"Protected module surface: {field}"))
if STAGES.index(records["typing-scope"]["coverage_stage"]) < STAGES.index(base_records["typing-scope"]["coverage_stage"]):
output.append(finding("policy-change", "", 0, "Typing stage cannot regress"))
if base_records["exceptions"] != records["exceptions"]:
output.append(finding("policy-change", "", 0, "Exception changes require protected review"))
for name in PROTECTED_FILES:
old = base_text(root, base_sha, name)
current = (root / name).read_text(encoding="utf-8") if (root / name).exists() else None
if old != current:
output.append(finding("policy-change", "", 0, f"Protected review required: {name}"))
output.append(finding("policy-change", "", 0, f"Protected file differs: {name}"))
old_config = tomllib.loads(base_text(root, base_sha, "pyproject.toml"))
current_config = tomllib.loads((root / "pyproject.toml").read_text(encoding="utf-8"))
if old_config.get("tool", {}).get("mypy") != current_config.get("tool", {}).get("mypy") or (
old_config.get("tool", {}).get("ruff") != current_config.get("tool", {}).get("ruff")
) or old_config.get("tool", {}).get("importlinter") != current_config.get("tool", {}).get("importlinter"):
output.append(finding("policy-change", "", 0, "Tool settings require protected review"))
output.append(finding("policy-change", "", 0, "Tool settings differ from protected policy"))
output.extend(validate_moves([], modules, {}))
output.extend(finding("unclassified-module", name, 0, "New runtime modules need inventory and blocking typing") for name in sorted(unknown))
inventory_paths = {m["path"] for m in modules}
Expand Down Expand Up @@ -1397,7 +1395,10 @@ def run_checks(root, base, requested, *, test_evidence=None):
handler_sites = [(paths[name], dict(h, module_id=module_ids.get(name, name)))
for name, source in sources.items() for h in broad_handlers(name, source)]
handlers = [handler for _, handler in handler_sites]
entries = base_records["exceptions"]["entries"] if base_policy_text else []
# Registry data is eligible for technical validation, not approval authority.
# Bootstrap still needs an adopted protected evaluator; candidate records
# cannot change the rules, toolchain, evidence runner or aggregate.
entries = records["exceptions"]["entries"] if base_policy_text else []
exception_findings, used = validate_exception_records(
handlers, entries, root, verified_tests=verified,
stage=records["typing-scope"]["coverage_stage"])
Expand Down
Loading
Loading