/* Approvals — record a per-branch verdict (the review gate). A verdict is enqueued as a * control command so the worker can read the reviewed HEAD and pin the approval. */ "use client"; import { useMemo, useState } from "react"; import { useDashboard } from "@/components/store"; import { Badge, Button, Card, Input, Select, StatusBadge } from "@/components/ui"; import { fmtFull, shortSha } from "@/lib/format"; const STATUS_OPTS = [ { value: "approved", label: "approve" }, { value: "rejected", label: "reject" }, ]; const empty = { branch: "", status: "approved", agent_name: "", sha: "", note: "" }; export function ApprovalsSection() { const s = useDashboard(); const [form, setForm] = useState(empty); const projectOpts = useMemo( () => s.projects.map((p) => ({ value: p.id, label: p.id })), [s.projects], ); const submit = async () => { await s.submitApproval(form); setForm(empty); }; return ( <>
Approvals
A merge is denied unless a standing approval exists — made by a different agent, pinned to the reviewed commit.
{s.projects.length === 0 ? (
Register a repository first.
) : ( <>
setForm({ ...form, branch: v })} placeholder="feat/auth" /> setForm({ ...form, agent_name: v })} placeholder="reads its HEAD (optional)" /> setForm({ ...form, sha: v })} placeholder="pins the approval (optional)" />
setForm({ ...form, note: v })} placeholder="optional" />
{s.approvals.length === 0 ? (
No approvals recorded.
) : (
{s.approvals.map((ap) => ( ))}
When Branch Verdict By SHA Note
{fmtFull(ap.created_at)} {ap.branch} {ap.approved_by_agent_id ? `agent ${ap.approved_by_agent_id}` : ap.actor || "—"} {shortSha(ap.approved_sha)} {ap.note || "—"}
)} )}
); }