Unify DefaultPolicyEngine decision and explanation rule chain - #286
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors DefaultPolicyEngine so both authorization decisions (evaluate()) and denial explanations (explain()) are driven by a single canonical ordered rule chain, eliminating the prior duplicated condition trees. It also adds a read-only rate-limit path (RateLimiter.peek()) so explanations can predict rate-limit denials without mutating limiter state, and adds regression tests to enforce evaluate/explain agreement and strict no-mutation behavior.
Changes:
- Introduce a shared
_DEFAULT_RULESrule chain (DefaultPolicyRuleChain) and routeDefaultPolicyEngine.evaluate()/.explain()through it (short-circuit vs collect-all). - Add
RateLimiter.peek()and use it for read-only rate-limit evaluation during explanation. - Add targeted tests for decision/explanation agreement and read-only invariants; update docs and contributor guidance accordingly.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_policy_rule_chain.py | Adds agreement + read-only invariant tests to prevent drift and limiter mutation in explain(). |
| src/weaver_kernel/rate_limit.py | Adds RateLimiter.peek() for non-mutating rate-limit prediction. |
| src/weaver_kernel/policy.py | Replaces duplicated evaluate/explain logic with shared chain traversal; preserves trace + reason-code behavior. |
| src/weaver_kernel/default_policy_rules.py | Defines canonical ordered _DEFAULT_RULES and DefaultPolicyRuleChain.run() traversal. |
| src/weaver_kernel/default_policy_rule_types.py | Adds shared context/result/failure datatypes and shared constants for the rule chain. |
| src/weaver_kernel/default_policy_limit_rules.py | Implements row-cap and rate-limit rules, including read-only limiter behavior. |
| src/weaver_kernel/default_policy_access_rules.py | Implements safety/sensitivity/secrets/memory access rules as chain components. |
| docs/architecture.md | Documents the unified chain and read-only rate-limit explanation behavior. |
| CHANGELOG.md | Notes the behavior-preserving refactor and new agreement/no-mutation coverage. |
| AGENTS.md | Updates “Adding a policy rule” guidance to register rules once in _DEFAULT_RULES + add agreement coverage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
What changed
DefaultPolicyEngine.evaluate()/.explain()condition trees with one ordered_DEFAULT_RULESchainRateLimiter.peek()so explanation can predict rate-limit denials without creating, pruning, or consuming limiter stateexplain()Verification
Authoritative
make cipassed on the final architecture:The new policy modules are all below the mandatory 300-line ceiling.
policy.pyitself is reduced substantially by removing the two hand-maintained rule copies.Closes #219.