feat(enforcement): add ConflictDetector and live enforcement metadata#16
Merged
feat(enforcement): add ConflictDetector and live enforcement metadata#16
Conversation
Prevent silent failures in the enforcement pipeline: fragment-config conflicts would previously overwrite user settings without warning, and unroutable policy keys were silently dropped. ConflictDetector surfaces both categories so agents can act rather than discover drift later. _build_enforcement_metadata() derives adapter capabilities live from the registry so creation guidance and enforcement reality cannot drift apart when new adapters are added.
…ection Properly type the _get_ruff_lint return value with dict[str, Any] to satisfy warn_return_any, and remove a now-unused type: ignore on _write_fragment that became superfluous after prior type improvements.
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
The enforcement pipeline had two silent failure modes: fragment-config conflicts would silently overwrite user settings on disk, and policy keys that no adapter could handle were dropped without any trace. Both caused config drift that agents could only discover after the fact — too late to prevent harm. This work surfaces both categories as structured, actionable signals.
Approach
ConflictDetectorhandles two distinct detection paths: policy-contract conflicts (pre-approval, decision-plane validation) and fragment-config conflicts (pre-write, enforcement-plane gating). Keeping both in one class avoids duplicating the TOML/JSON parsing and key-normalisation logic they share._build_enforcement_metadata()derives adapter capabilities live from the registry at call time instead of being baked in as a static list. This means creation guidance (what policies are enforceable) and enforcement reality (what adapters are registered) cannot diverge when new adapters are added — they stay in sync by construction.The pipeline's conflict-gating logic was added as a fallback in
EnforcementPipeline.run(): ifConflictDetectorfinds conflicts for a fragment, the write is skipped and a structured skip-record is appended to the result instead of raising or silently proceeding.What Was Tested
ConflictDetector._detect_fragment_conflicts: ruff adapter, ESLint adapter, unknown format (falls back gracefully)_build_enforcement_metadata: verified live registry keys match adapter capabilities; verified behaviour when no adapters are registeredRisks
Additive changes only — no existing public API was modified. The conflict-gating path is new code that branches around the existing write path, so previously passing fragments are unaffected. The one pre-existing
type: ignore[arg-type]removed frompipeline.pywas confirmed unused by mypy before removal.