Skip to content

Policy UI/UX update#37

Merged
JaredforReal merged 3 commits into
mainfrom
policy
May 6, 2026
Merged

Policy UI/UX update#37
JaredforReal merged 3 commits into
mainfrom
policy

Conversation

@JaredforReal
Copy link
Copy Markdown
Owner

No description provided.

Signed-off-by: JaredforReal <w13431838023@gmail.com>
Signed-off-by: JaredforReal <w13431838023@gmail.com>
Signed-off-by: JaredforReal <w13431838023@gmail.com>
Copilot AI review requested due to automatic review settings May 6, 2026 07:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the policies UX in the WebUI (more discoverable form editing, inline help, and policy/group context) and extends the backend policy engine to return and record policy provenance (which policy/rule matched) for display in the UI.

Changes:

  • Policy evaluation now returns a PolicyResult with provenance (policy file/source + rule name) and the dispatcher records this on the envelope metadata.
  • WebUI policy editing gets form-first UX, inline help tooltips, and shows which groups reference a policy.
  • Config editor adds a policy dropdown for groups (with “create new policy” flow), and envelope UI surfaces group and matched policy/rule.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/test_orchestrator.py Updates tests for PolicyEngine.evaluate() returning PolicyResult and asserts provenance fields.
loom/orchestrator/policy.py Introduces PolicyResult, tracks rule file provenance, and returns richer evaluation results.
loom/orchestrator/dispatcher.py Consumes PolicyResult, logs provenance, and writes matched policy/rule info into envelope metadata.
loom/webui/frontend/src/pages/policies/RuleCard.tsx Adds help-tooltips and switches “Tools” editing to a schema-driven multiselect.
loom/webui/frontend/src/pages/policies/PolicyEditor.tsx Defaults editor mode to “Form” and reorders tabs.
loom/webui/frontend/src/pages/policies/PoliciesPanel.tsx Fetches groups to show which groups reference each policy; displays usage inline in the list.
loom/webui/frontend/src/pages/config/ConfigFormEditor.tsx Adds policy dropdown (and create-new) for group policies; shows group → policy mapping in source cards.
loom/webui/frontend/src/lib/types.ts Adds group to the frontend Envelope type.
loom/webui/frontend/src/components/EnvelopeDetail.tsx Displays envelope group and matched policy/rule metadata.
loom/webui/frontend/src/components/EnvelopeCard.tsx Displays a small group badge next to source_id.
docs/policy-guide.md Adds a policy guide documenting rule matching, fields, groups, and examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +126 to +130
# Store policy provenance on the envelope
envelope.metadata["matched_rule"] = result.rule_name
envelope.metadata["matched_policy"] = result.policy_file
envelope.metadata["matched_policy_source"] = result.policy_source

Comment on lines +145 to +152
const { data: policies = [] } = useQuery({
queryKey: ["policies"],
queryFn: listPolicies,
})
const policyNames = useMemo(
() => policies.map((p) => p.name.replace(/\.ya?ml$/, "")),
[policies],
)
Comment on lines +669 to +673
const newName = window.prompt("New policy name (without .yaml):")
if (!newName) return
const template = `prompt: \nmodel: sonnet\nauto_approve: false\n`
savePolicy(`${newName}.yaml`, template).catch(() => {})
onChange(newName)
Comment on lines 165 to 187
@@ -154,7 +171,7 @@ def load_action_by_name(self, name: str, policy_dir: Path) -> PolicyAction | Non
data = yaml.safe_load(f)
if not data or not isinstance(data, dict):
return None
return PolicyAction(
action = PolicyAction(
priority=data.get("priority", 1),
agent=data.get("agent", ""),
prompt=data.get("prompt", ""),
@@ -168,12 +185,23 @@ def load_action_by_name(self, name: str, policy_dir: Path) -> PolicyAction | Non
skills=data.get("skills", []),
cwd=data.get("cwd", ""),
)
Comment on lines +49 to +58
// Build reverse map: policy stem → group names
const policyUsage = useMemo(() => {
const map: Record<string, string[]> = {}
for (const g of groups) {
const policyName = (g as unknown as Record<string, unknown>).policy as string | undefined
if (policyName) {
const stem = policyName.replace(/\.ya?ml$/, "")
if (!map[stem]) map[stem] = []
map[stem].push(g.name)
}
@JaredforReal JaredforReal merged commit 92ecfd4 into main May 6, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants