Skip to content

Commit 1991986

Browse files
committed
feat: wire enterprise conditions into rule evaluation pipeline
Register SignedCommitsCondition, ChangelogRequiredCondition, NoSelfApprovalCondition, and CrossTeamApprovalCondition so the ConditionRegistry can match them from YAML parameters and route them through the fast condition-class evaluation path instead of falling through to the LLM fallback. - Add 4 RuleID enum values and violation text mappings - Add entries to RULE_ID_TO_CONDITION and AVAILABLE_CONDITIONS - Export from conditions/__init__.py - Fix overly generic 'exceeded the' mapping key -> 'response SLA' - Add missing test cases for all new and previously untested mappings
1 parent 6d93e65 commit 1991986

4 files changed

Lines changed: 54 additions & 3 deletions

File tree

src/rules/acknowledgment.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class RuleID(StrEnum):
3939
UNRESOLVED_COMMENTS = "unresolved-comments"
4040
TEST_COVERAGE = "test-coverage"
4141
COMMENT_RESPONSE_TIME = "comment-response-time"
42+
SIGNED_COMMITS = "signed-commits"
43+
CHANGELOG_REQUIRED = "changelog-required"
44+
NO_SELF_APPROVAL = "no-self-approval"
45+
CROSS_TEAM_APPROVAL = "cross-team-approval"
4246

4347

4448
# Mapping from violation text patterns to RuleID
@@ -58,7 +62,11 @@ class RuleID(StrEnum):
5862
"Security-sensitive patterns": RuleID.SECURITY_PATTERN,
5963
"unresolved review comment thread": RuleID.UNRESOLVED_COMMENTS,
6064
"without corresponding test changes": RuleID.TEST_COVERAGE,
61-
"exceeded the": RuleID.COMMENT_RESPONSE_TIME,
65+
"response SLA": RuleID.COMMENT_RESPONSE_TIME,
66+
"unsigned commit": RuleID.SIGNED_COMMITS,
67+
"without a corresponding CHANGELOG": RuleID.CHANGELOG_REQUIRED,
68+
"approved by its own author": RuleID.NO_SELF_APPROVAL,
69+
"approvals from required teams": RuleID.CROSS_TEAM_APPROVAL,
6270
}
6371

6472
# Mapping from RuleID to human-readable descriptions
@@ -79,6 +87,10 @@ class RuleID(StrEnum):
7987
RuleID.UNRESOLVED_COMMENTS: "All review comments must be resolved before merging.",
8088
RuleID.TEST_COVERAGE: "Source code modifications must include corresponding test changes.",
8189
RuleID.COMMENT_RESPONSE_TIME: "Review comments must be addressed within the SLA timeframe.",
90+
RuleID.SIGNED_COMMITS: "All commits in a pull request must be cryptographically signed.",
91+
RuleID.CHANGELOG_REQUIRED: "Source code changes must include a CHANGELOG or .changeset update.",
92+
RuleID.NO_SELF_APPROVAL: "PR authors cannot approve their own pull requests.",
93+
RuleID.CROSS_TEAM_APPROVAL: "Pull requests require approvals from specified GitHub teams.",
8294
}
8395

8496
# Comment markers that indicate an acknowledgment comment

src/rules/conditions/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@
1111
ProtectedBranchesCondition,
1212
RequireCodeOwnerReviewersCondition,
1313
)
14+
from src.rules.conditions.access_control_advanced import (
15+
CrossTeamApprovalCondition,
16+
NoSelfApprovalCondition,
17+
)
1418
from src.rules.conditions.base import BaseCondition
19+
from src.rules.conditions.compliance import (
20+
ChangelogRequiredCondition,
21+
SignedCommitsCondition,
22+
)
1523
from src.rules.conditions.filesystem import (
1624
FilePatternCondition,
1725
MaxFileSizeCondition,
@@ -57,6 +65,12 @@
5765
"PathHasCodeOwnerCondition",
5866
"ProtectedBranchesCondition",
5967
"RequireCodeOwnerReviewersCondition",
68+
# Access Control - Advanced
69+
"NoSelfApprovalCondition",
70+
"CrossTeamApprovalCondition",
71+
# Compliance
72+
"SignedCommitsCondition",
73+
"ChangelogRequiredCondition",
6074
# Temporal
6175
"AllowedHoursCondition",
6276
"CommentResponseTimeCondition",

src/rules/registry.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@
1616
ProtectedBranchesCondition,
1717
RequireCodeOwnerReviewersCondition,
1818
)
19+
from src.rules.conditions.access_control_advanced import (
20+
CrossTeamApprovalCondition,
21+
NoSelfApprovalCondition,
22+
)
1923
from src.rules.conditions.base import BaseCondition
24+
from src.rules.conditions.compliance import (
25+
ChangelogRequiredCondition,
26+
SignedCommitsCondition,
27+
)
2028
from src.rules.conditions.filesystem import (
2129
FilePatternCondition,
2230
MaxFileSizeCondition,
@@ -61,6 +69,10 @@
6169
RuleID.UNRESOLVED_COMMENTS: UnresolvedCommentsCondition,
6270
RuleID.TEST_COVERAGE: TestCoverageCondition,
6371
RuleID.COMMENT_RESPONSE_TIME: CommentResponseTimeCondition,
72+
RuleID.SIGNED_COMMITS: SignedCommitsCondition,
73+
RuleID.CHANGELOG_REQUIRED: ChangelogRequiredCondition,
74+
RuleID.NO_SELF_APPROVAL: NoSelfApprovalCondition,
75+
RuleID.CROSS_TEAM_APPROVAL: CrossTeamApprovalCondition,
6476
}
6577

6678
# Reverse map: condition class -> RuleID (for populating rule_id on violations)
@@ -90,6 +102,10 @@
90102
SecurityPatternCondition,
91103
UnresolvedCommentsCondition,
92104
TestCoverageCondition,
105+
NoSelfApprovalCondition,
106+
CrossTeamApprovalCondition,
107+
SignedCommitsCondition,
108+
ChangelogRequiredCondition,
93109
]
94110

95111

tests/unit/rules/test_acknowledgment.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ def test_all_rule_ids_are_strings(self):
3535
assert len(rule_id.value) > 0
3636

3737
def test_rule_id_count(self):
38-
"""Verify we have exactly 16 standardized rule IDs."""
39-
assert len(RuleID) == 16
38+
"""Verify we have exactly 20 standardized rule IDs."""
39+
assert len(RuleID) == 20
4040

4141
def test_all_rule_ids_have_descriptions(self):
4242
"""Every RuleID should have a corresponding description."""
@@ -160,6 +160,15 @@ class TestMapViolationTextToRuleId:
160160
("Restricted patterns ['console'] found in added lines of src/app.js", RuleID.DIFF_PATTERN),
161161
("Security-sensitive patterns ['api_key'] detected in src/auth.py", RuleID.SECURITY_PATTERN),
162162
("PR has 1 unresolved review comment thread(s)", RuleID.UNRESOLVED_COMMENTS),
163+
("Source files were modified without corresponding test changes.", RuleID.TEST_COVERAGE),
164+
("2 review thread(s) have exceeded the 24-hour response SLA.", RuleID.COMMENT_RESPONSE_TIME),
165+
("Found 3 unsigned commit(s): abc1234, def5678, ghi9012", RuleID.SIGNED_COMMITS),
166+
(
167+
"Source code was modified without a corresponding CHANGELOG update.",
168+
RuleID.CHANGELOG_REQUIRED,
169+
),
170+
("Pull request was approved by its own author.", RuleID.NO_SELF_APPROVAL),
171+
("Missing approvals from required teams: @org/security, @org/qa", RuleID.CROSS_TEAM_APPROVAL),
163172
],
164173
)
165174
def test_maps_violation_text_correctly(self, text: str, expected_rule_id: RuleID):

0 commit comments

Comments
 (0)