feat(enforce): staged enforcement — policy checks at commit, push, and CI#10
Merged
feat(enforce): staged enforcement — policy checks at commit, push, and CI#10
Conversation
…idator Implements the STG task: ADR policy checks now run automatically at the right workflow stage rather than only at CI time. A classification model maps policy types to stages (imports/python/patterns → commit, architecture → push, required_structure/config → ci), StagedValidator fetches the appropriate file set via git and runs offline grep-based checks, and HookGenerator writes idempotent sentinel-marked sections into .git/hooks/pre-commit and .git/hooks/pre-push. Approval workflow auto-calls generate() so hooks stay in sync as rules are added. Three new CLI commands (enforce, setup-enforcement, enforce-status) plus --with-enforcement on init. Architecture and config checks are classified but not yet executed — reserved for the ENF task.
Add threading import at module level for Thread return type annotation, and annotate adrs list with ADR type in _load_accepted_adrs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
ADR policies were only checked at CI time, which means violations are caught too late — after code is already pushed and waiting in a pipeline. Developers need fast, targeted feedback at the point where a decision is relevant: a missing status field at commit time, an undocumented architecture change before push, a full structural audit in CI. This implements that tiered model.
Approach
Three new modules form the core:
enforce/stages.py— definesEnforcementLevel(commit/push/ci) and maps policy types to their appropriate stage. The classification rule: fast grep-detectable checks (imports, python patterns, required fields) belong at commit; architecture-level checks belong at push; comprehensive structural checks belong at CI. Architecture and config checks are classified now but execute as no-ops — reserved for the ENF task so the contract is clear but not yet paid.enforce/validator.py—StagedValidatorusesgit diff --cached(staged files) orgit diff @{upstream}..HEAD(push) to fetch only the relevant file set, then runs offline grep-based policy checks against accepted ADRs. No network calls; the full CI pass scans all project files.enforce/hooks.py—HookGeneratorwrites idempotent sentinel-marked sections into.git/hooks/pre-commitand.git/hooks/pre-push. Re-running is safe: the sentinel block is replaced in-place so existing hook content (e.g. from other tools) is preserved. Approval workflow callsgenerate()automatically so hooks stay in sync as rules are added.Three new CLI commands expose this:
enforce(run a check at any level),setup-enforcement(install/update hooks), andenforce-status(show what hooks are installed and their source policy counts).adr-kit init --with-enforcementinstalls hooks during project setup.What Was Tested
tests/unit/test_staged_enforcement.py: classifier maps each policy type to the correct enforcement level;StagedValidatorcorrectly selects the commit vs push file set; all three CI modes scan the full file list; check counts reflect classified (not yet executed) architecture checks.tests/unit/test_hook_generator.py: hooks are written with correct sentinel markers; re-running is idempotent (sentinel block replaced, not duplicated); pre-existing hook content outside the sentinel is preserved; executable bit is set on hook files.cli.pyandvalidator.pyfixed as part of pre-PR quality gate.Risks
The hook installer writes directly to
.git/hooks/— projects using Husky, pre-commit framework, or other hook managers could have content silently overwritten if the sentinel block insertion logic doesn't correctly detect the existing section boundary. The sentinel approach mitigates this for re-runs of adr-kit itself, but first-run on a repo with a pre-existing hook of the same name will overwrite non-sentinel content. Worth reviewing the idempotency logic inhooks.pybefore merge.Architecture and config checks are intentionally inert (classified but not executed). This is documented in the module docstring. The ENF task will implement them — no behavior change expected at that point, only the currently-empty check runners will be filled in.