Skip to main content
The veto diff command shows what changed between two policy versions and optionally replays historical calls to see the impact.

Syntax

veto diff [policy-path] [options]
veto diff --old <path> --new <path> [options]

Description

Compares policy versions to show:
  1. Structural changes: Added/removed/modified rules
  2. Scope changes: Which tools are affected
  3. Impact analysis: How historical calls would be affected (optional)

Arguments

Policy Path

veto diff <policy-path>
Compare working file against git HEAD. Example:
veto diff veto/rules/financial.yaml

Options

Old/New Paths

--old <path>
--new <path>
Compare two specific policy files or directories. Example:
veto diff --old ./rules-v1 --new ./rules-v2

Log File

--log <path>
Replay historical calls from JSONL log file to see impact. Example:
veto diff financial.yaml --log calls.jsonl

Format

--format <text|json>
Output format:
  • text - Human-readable (default)
  • json - Machine-readable JSON
Example:
veto diff --format json

Examples

Compare Against Git HEAD

veto diff veto/rules/financial.yaml
Output:
Veto Policy Diff
================

Comparing:
  Old: HEAD:veto/rules/financial.yaml
  New: veto/rules/financial.yaml

Structural Changes:

  ADDED RULES (1):
    + block-crypto-transfers
      Severity: critical
      Tools: transfer_funds
      Description: Block cryptocurrency transfers

  MODIFIED RULES (1):
    ~ block-large-transfers
      - action: require_approval
      + action: block
      - value: 10000
      + value: 5000

  REMOVED RULES (0)

Affected Tools:
  - transfer_funds (2 rules changed)

Summary:
  Old rules: 5
  New rules: 6
  Added: 1
  Modified: 1
  Removed: 0

Compare Two Directories

veto diff --old ./rules-v1 --new ./rules-v2
Output:
Veto Policy Diff
================

Comparing:
  Old: ./rules-v1
  New: ./rules-v2

Structural Changes:

  ADDED RULES (3):
    + require-mfa-admin
    + block-weekend-deploys
    + log-sensitive-queries

  MODIFIED RULES (2):
    ~ block-large-transfers
    ~ require-invoice-approval

  REMOVED RULES (1):
    - legacy-email-rule

Affected Tools:
  - transfer_funds
  - approve_invoice
  - deploy_app
  - query_database

Summary:
  Old rules: 12
  New rules: 14
  Added: 3
  Modified: 2
  Removed: 1

Impact Analysis

veto diff financial.yaml --log calls.jsonl
Output:
Veto Policy Diff
================

Comparing:
  Old: HEAD:veto/rules/financial.yaml
  New: veto/rules/financial.yaml

Structural Changes:
  ...

Impact Analysis:
================

Log file: calls.jsonl
Total lines: 1000
Valid calls: 950
Invalid lines: 50

Old Policy Decisions:
  Allow: 800 (84.2%)
  Require Approval: 100 (10.5%)
  Block: 50 (5.3%)

New Policy Decisions:
  Allow: 750 (78.9%)
  Require Approval: 120 (12.6%)
  Block: 80 (8.4%)

Transitions:
  allow → block: 40 calls
  allow → require_approval: 20 calls
  require_approval → block: 10 calls

Changed by Tool:
  transfer_funds: 50 calls affected
  approve_invoice: 20 calls affected

Sample Changed Calls:

  [Line 42] transfer_funds
    Arguments: {"amount": 6000, "recipient": "[email protected]"}
    Old: allow (no matching rule)
    New: block (rule: block-large-transfers)
    Reason: Amount 6000 exceeds new threshold of 5000

  [Line 123] transfer_funds
    Arguments: {"amount": 8000, "currency": "BTC"}
    Old: require_approval (rule: require-approval-large)
    New: block (rule: block-crypto-transfers)
    Reason: Cryptocurrency transfers now blocked

  (showing 2 of 70 changed calls)

Additional Blocked: 50 calls
Additional Requiring Approval: 20 calls

JSON Output

veto diff financial.yaml --format json
Output:
{
  "timestamp": "2024-03-04T12:00:00.000Z",
  "projectDir": "/path/to/project",
  "sources": {
    "mode": "implicit-git-file",
    "old": "HEAD:veto/rules/financial.yaml",
    "new": "veto/rules/financial.yaml"
  },
  "structural": {
    "addedRuleIds": ["block-crypto-transfers"],
    "removedRuleIds": [],
    "modifiedRuleIds": ["block-large-transfers"],
    "ruleChanges": [
      {
        "kind": "added",
        "ruleId": "block-crypto-transfers",
        "scopes": ["transfer_funds"],
        "summary": "Added rule for transfer_funds",
        "fieldChanges": []
      },
      {
        "kind": "modified",
        "ruleId": "block-large-transfers",
        "scopes": ["transfer_funds"],
        "summary": "Modified action, conditions",
        "fieldChanges": [
          {
            "field": "action",
            "oldValue": "require_approval",
            "newValue": "block"
          }
        ]
      }
    ],
    "changesByScope": [
      {
        "scope": "transfer_funds",
        "added": [],
        "removed": [],
        "modified": []
      }
    ],
    "unchangedTools": ["approve_invoice", "send_email"]
  },
  "impact": null,
  "summary": {
    "oldRules": 5,
    "newRules": 6,
    "added": 1,
    "modified": 1,
    "removed": 0,
    "changedScopes": 1,
    "unchangedTools": 2,
    "hasChanges": true
  }
}

Log File Format

Log files must be JSONL (JSON Lines) format:
{"tool": "transfer_funds", "arguments": {"amount": 100}, "timestamp": "2024-03-01T10:00:00Z"}
{"tool": "approve_invoice", "arguments": {"amount": 500}, "timestamp": "2024-03-01T10:01:00Z"}
{"tool": "transfer_funds", "arguments": {"amount": 6000}, "timestamp": "2024-03-01T10:02:00Z"}
Required fields:
  • tool - Tool name
  • arguments - Tool arguments object
Optional fields:
  • timestamp - ISO 8601 timestamp
  • sessionId - Session identifier
  • userId - User identifier
  • agentId - Agent identifier

Use Cases

Pre-Deployment Review

# Before deploying to production
veto diff veto/rules/financial.yaml --log production-calls-7d.jsonl
See how recent production calls would be affected.

Pull Request Review

# In CI, compare against main branch
git diff main...HEAD --name-only | grep 'veto/rules/'

veto diff veto/rules/financial.yaml

Policy Audit

# Compare old and new rule sets
veto diff --old ./rules-2024-01 --new ./rules-2024-03 --format json > audit-report.json

Rollback Analysis

# See what would change if you rolled back
veto diff --old ./rules-current --new ./rules-backup-2024-02-01

Workflows

Update Rule Safely

# 1. Edit rule
vim veto/rules/financial.yaml

# 2. See what changed
veto diff veto/rules/financial.yaml

# 3. Check impact
veto diff veto/rules/financial.yaml --log recent-calls.jsonl

# 4. If safe, apply
veto policy apply --file veto/rules/financial.yaml

CI Policy Validation

# .github/workflows/veto-diff.yml
name: Veto Policy Diff

on:
  pull_request:
    paths:
      - 'veto/rules/**'

jobs:
  diff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v3
        with:
          node-version: 20
      - run: npm install -g veto-cli
      - run: |
          for file in $(git diff --name-only origin/main...HEAD | grep 'veto/rules/'); do
            echo "Checking $file"
            veto diff "$file" --format text
          done

Historical Impact Report

#!/bin/bash

# Export tool calls from last 7 days
veto cloud logs --days 7 --format jsonl > calls-7d.jsonl

# Generate impact report
veto diff veto/rules/financial.yaml --log calls-7d.jsonl --format json > impact-report.json

# Email to team
jq '.impact' impact-report.json | mail -s "Policy Impact Analysis" [email protected]

Troubleshooting

Git File Not Found

Error: Unable to load HEAD version of veto/rules/financial.yaml
Solution:
# Ensure file is committed
git add veto/rules/financial.yaml
git commit -m "Add financial rules"

# Or compare two files explicitly
veto diff --old financial-old.yaml --new financial-new.yaml

Invalid Log Format

Warning: Invalid lines: 50
Solution:
# Validate JSONL format
jq -c . calls.jsonl > /dev/null

# Or check line 42 (example)
sed -n '42p' calls.jsonl | jq .

No Changes Detected

No changes detected between policies.
Solution:
  • Verify you’re comparing the right files
  • Check that changes are syntactically different (not just whitespace)

Best Practices

1. Review Before Applying

Always diff before applying:
veto diff veto/rules/financial.yaml
veto policy apply --file veto/rules/financial.yaml

2. Use Log Files for Important Changes

# For critical policies, always check impact
veto diff production-policy.yaml --log prod-calls-30d.jsonl

3. Archive Diffs

# Save diff reports for audit trail
veto diff --old ./rules-v1 --new ./rules-v2 --format json > diff-v1-to-v2.json
git add diff-v1-to-v2.json

4. Automate in CI

# Fail CI if diff shows high impact
veto diff veto/rules/ --log recent.jsonl --format json | \
  jq -e '.impact.additionalBlocked < 100'

Next Steps

Build docs developers (and LLMs) love