File size: 4,451 Bytes
4d393e8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | """
`dw rules` subcommands.
Manages dynamic validation policy rules (linter rules) on the workspace.
"""
from __future__ import annotations
import json
from typing import Optional
import typer
from rich.table import Table
from diffweave.cli.config import get_active_workspace
from diffweave.cli.output import print_success, print_error, print_info, print_json, console
from diffweave.mcp.client import DiffWeaveMCPClient
rules_app = typer.Typer(name="rules", help="Manage validation policy rules for workspace.")
@rules_app.command("list")
def list_rules_cmd(
workspace_id: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace UUID override"),
as_json: bool = typer.Option(False, "--json", help="Output machine-readable JSON"),
):
"""List all validation policy rules configured for the workspace."""
try:
active_ws_id = get_active_workspace(workspace_id)
except Exception as e:
print_error(str(e))
raise typer.Exit(code=1)
client = DiffWeaveMCPClient()
try:
rules = client.call_tool_sync("list_rules", {"workspace_id": active_ws_id})
except Exception as e:
print_error(f"Failed to list rules: {e}")
raise typer.Exit(code=1)
if as_json:
print_json(rules)
return
if not rules:
console.print("[dim]No policy rules configured. Use 'dw rules add' to create one.[/dim]")
return
table = Table(title="Workspace Policy Rules", header_style="bold cyan")
table.add_column("Rule ID", style="dim")
table.add_column("Name", style="bold white")
table.add_column("Operator", style="cyan")
table.add_column("Status", style="bold")
table.add_column("Configuration", style="dim")
for r in rules:
status_styled = "[green]ENABLED[/green]" if r.get("enabled") else "[yellow]DISABLED[/yellow]"
table.add_row(
r.get("id", "")[:8],
r.get("name", "Unnamed"),
r.get("operator") or "n/a",
status_styled,
json.dumps(r.get("configuration") or {}),
)
console.print(table)
@rules_app.command("enable")
def enable_rule_cmd(rule_id: str = typer.Argument(..., help="Rule UUID to enable")):
"""Enable a validation rule."""
client = DiffWeaveMCPClient()
try:
res = client.call_tool_sync("enable_rule", {"rule_id": rule_id})
print_success(f"Rule '{res.get('name')}' ({rule_id[:8]}) is now ENABLED.")
except Exception as e:
print_error(f"Failed to enable rule: {e}")
raise typer.Exit(code=1)
@rules_app.command("disable")
def disable_rule_cmd(rule_id: str = typer.Argument(..., help="Rule UUID to disable")):
"""Disable a validation rule without deleting it."""
client = DiffWeaveMCPClient()
try:
res = client.call_tool_sync("disable_rule", {"rule_id": rule_id})
print_info(f"Rule '{res.get('name')}' ({rule_id[:8]}) is now DISABLED.")
except Exception as e:
print_error(f"Failed to disable rule: {e}")
raise typer.Exit(code=1)
@rules_app.command("add")
def add_rule_cmd(
name: str = typer.Argument(..., help="Human-readable rule name"),
operator: str = typer.Option("min_confidence", "--operator", "-o", help="Rule operator: min_confidence, required_evidence, allowed_proposal_types"),
threshold: float = typer.Option(0.85, "--threshold", "-t", help="Threshold for min_confidence operator"),
workspace_id: Optional[str] = typer.Option(None, "--workspace", "-w", help="Workspace UUID override"),
):
"""Add a new validation rule to the workspace."""
try:
active_ws_id = get_active_workspace(workspace_id)
except Exception as e:
print_error(str(e))
raise typer.Exit(code=1)
client = DiffWeaveMCPClient()
config = {}
if operator == "min_confidence":
config = {"value": threshold}
elif operator == "allowed_proposal_types":
config = {"values": ["CREATE", "UPDATE"]}
try:
res = client.call_tool_sync(
"create_rule",
{
"workspace_id": active_ws_id,
"name": name,
"operator": operator,
"configuration": config,
},
)
print_success(f"Created rule [bold]{res.get('name')}[/bold] (ID: {res.get('id')[:8]})")
except Exception as e:
print_error(f"Failed to create rule: {e}")
raise typer.Exit(code=1)
|