feat(governance): Policy v2 Tier A — set-membership + cross-arg conditions (v0.284.0) - #498
Merged
Merged
Conversation
vikasprogrammer
force-pushed
the
feat/tier-a-policy-ops
branch
from
July 31, 2026 10:17
399aa5b to
0508487
Compare
…tions (v0.282.0) Extends the pure JSON rule engine (src/governance/policy.ts) with two new `when` shapes, still stateless and still first-match: - `in` / `nin` — set membership against an array value (invalid-enum guard). - `argRef` — compare one arg to another arg instead of a constant (wrong-recipient / cross-arg guard). The applyProposal tighten-only monotonicity proof stays sound: sampleArgDomains emits every enum member and seeds both sides of a cross-arg pair with one shared domain, and firstLoosening's rare fallback path gains explicit joint coverage of each argRef pair (independent variation can't observe arg == argRef). Touch-points (all in policy.ts): Op, OPS, the new When interface, evalWhen, describeMatch, OP_PHRASE, validatePolicyDocument, sampleArgDomains, argRefPairs, firstLoosening. Tests: new scripts/tier-a-policy-test.cjs (18 cases: runtime semantics, validation, and that the monotonicity sweep reaches the new-op boundaries), wired into `npm run test:governance`. The 130-case conformance suite is unchanged — backward-compatible, since the bundled default policy uses no new ops. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vikasprogrammer
force-pushed
the
feat/tier-a-policy-ops
branch
from
July 31, 2026 10:18
0508487 to
a8b85bc
Compare
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.
First concrete step of the Policy v2 wedge in
docs/agent-os-plan.md§4.3. Small, pure, self-contained — no new plane.What
Extends the JSON rule engine (
src/governance/policy.ts) with two newwhenshapes, still stateless and still first-match:in/nin— set membership against an array value → the invalid-enum guard (status ∉ {paid,shipped,refunded}→never).argRef— compare one arg to another arg instead of a constant → the wrong-recipient guard (payee ≠ buyer→askowner).Why the sweep work is the real change (not
evalWhen)applyProposalis tighten-only, proven by an exhaustive monotonicity sweep (firstLoosening→sampleArgDomains). New ops the sampler doesn't enumerate would silently make that proof unsound. So:sampleArgDomainsnow emits every enum member forin/nin, and seeds both sides of a cross-arg pair with one shared domain so the cartesian sweep hitsarg == argRefandarg ≠ argRef.firstLoosening's rare huge-product fallback gains explicit joint coverage of eachargRefpair — independent per-arg variation can't observearg == argRef.Touch-points
All in
policy.ts:Op,OPS, newWheninterface,evalWhen,describeMatch,OP_PHRASE,validatePolicyDocument,sampleArgDomains,argRefPairs,firstLoosening.Tests
scripts/tier-a-policy-test.cjs— 18/18: runtime semantics (in/nin + argRef eq/ne/gt, incl. fail-closed on missing args), validation of both new shapes, and that the monotonicity sweep reaches the new-op boundaries (a real new-op tightening is seen bydescribeProposaland accepted byapplyProposal, never falsely flagged as loosening). Wired intonpm run test:governance.npm run buildclean.🤖 Generated with Claude Code