Add SDLC review and eval controls

This commit is contained in:
ZacharyZhang-NY committed 2026-05-23 18:39:05 -04:00
1 parent bc14a2fbcb
commit bbf90a1a62
19 files changed
+927 -2

No files matched your search

@@ -7,6 +7,7 @@ import { BillingPanel } from "./settings/BillingPanel";
import { ModelsPanel } from "./settings/ModelsPanel";
import { PoliciesPanel } from "./settings/PoliciesPanel";
import { OperationsPanel } from "./settings/OperationsPanel";
import { SdlcPanel } from "./settings/SdlcPanel";
import { MigrationPanel } from "./settings/MigrationPanel";
import { CompliancePanel } from "./settings/CompliancePanel";
import { NotificationsPanel, ProfilePanel, SecurityPanel } from "./settings/AccountPanels";
@@ -22,6 +23,7 @@ type SettingsTab =
| "skills"
| "policies"
| "operations"
| "sdlc"
| "compliance"
| "migration"
| "profile"
@@ -44,6 +46,7 @@ const AGENTS_GROUP: NavSpec[] = [
{ id: "skills", label: "Skills" },
{ id: "policies", label: "Policies" },
{ id: "operations", label: "Operations" },
{ id: "sdlc", label: "SDLC" },
{ id: "compliance", label: "Compliance" },
{ id: "migration", label: "Migration" },
];
@@ -91,6 +94,12 @@ export function SettingsPage({ snapshot, actions }: PageProps) {
const operationalEvents = useMemo(() => snapshot.operationalEvents.filter((item) => item.orgId === orgId), [snapshot.operationalEvents, orgId]);
const chaosDrills = useMemo(() => snapshot.chaosDrills.filter((item) => item.orgId === orgId), [snapshot.chaosDrills, orgId]);
const chaosDrillRuns = useMemo(() => snapshot.chaosDrillRuns.filter((item) => item.orgId === orgId), [snapshot.chaosDrillRuns, orgId]);
const sdlcReviewAgents = useMemo(() => snapshot.sdlcReviewAgents.filter((item) => item.orgId === orgId), [snapshot.sdlcReviewAgents, orgId]);
const sdlcReviewRuns = useMemo(() => snapshot.sdlcReviewRuns.filter((item) => item.orgId === orgId), [snapshot.sdlcReviewRuns, orgId]);
const evalSuites = useMemo(() => snapshot.evalSuites.filter((item) => item.orgId === orgId), [snapshot.evalSuites, orgId]);
const evalCases = useMemo(() => snapshot.evalCases.filter((item) => item.orgId === orgId), [snapshot.evalCases, orgId]);
const evalRuns = useMemo(() => snapshot.evalRuns.filter((item) => item.orgId === orgId), [snapshot.evalRuns, orgId]);
const prBotGates = useMemo(() => snapshot.prBotGates.filter((item) => item.orgId === orgId), [snapshot.prBotGates, orgId]);
return (
<div className="split-main" style={{ height: "calc(100vh - 44px)", margin: "-28px -32px -40px" }}>
@@ -158,6 +167,20 @@ export function SettingsPage({ snapshot, actions }: PageProps) {
actions={actions}
/>
)}
{tab === "sdlc" && (
<SdlcPanel
orgId={orgId}
reviewAgents={sdlcReviewAgents}
reviewRuns={sdlcReviewRuns}
evalSuites={evalSuites}
evalCases={evalCases}
evalRuns={evalRuns}
prBotGates={prBotGates}
migrationReports={migrationReports}
policies={policies}
actions={actions}
/>
)}
{tab === "compliance" && (
<CompliancePanel
orgId={orgId}
@@ -0,0 +1,240 @@
import { Button, Pill } from "../../shared/ui";
import type {
EvalCaseRecord,
EvalRunRecord,
EvalSuiteRecord,
MigrationReportRecord,
PolicyRuleRecord,
PrBotGateRecord,
SdlcReviewAgentRecord,
SdlcReviewRunRecord,
SdlcReviewTargetType,
} from "../../../../shared/domain";
import { SDLC_REVIEW_AGENT_KEY, SDLC_REVIEW_TARGET_TYPE } from "../../../../shared/domain";
import type { SnapshotActions } from "../../app/useSnapshot";
import { formatRelative } from "../types";
export function SdlcPanel({
orgId,
reviewAgents,
reviewRuns,
evalSuites,
evalCases,
evalRuns,
prBotGates,
migrationReports,
policies,
actions,
}: {
orgId: string;
reviewAgents: SdlcReviewAgentRecord[];
reviewRuns: SdlcReviewRunRecord[];
evalSuites: EvalSuiteRecord[];
evalCases: EvalCaseRecord[];
evalRuns: EvalRunRecord[];
prBotGates: PrBotGateRecord[];
migrationReports: MigrationReportRecord[];
policies: PolicyRuleRecord[];
actions: SnapshotActions;
}) {
return (
<div className="page">
<h1 className="page-h1">SDLC</h1>
<p className="page-sub">{reviewAgents.length} agents / {evalSuites.length} suites / {prBotGates.length} gates.</p>
<ReviewAgentsTable
orgId={orgId}
agents={reviewAgents}
runs={reviewRuns}
migrationReports={migrationReports}
policies={policies}
actions={actions}
/>
<EvalSuitesTable orgId={orgId} suites={evalSuites} cases={evalCases} runs={evalRuns} actions={actions} />
<PrBotGatesTable orgId={orgId} gates={prBotGates} actions={actions} />
</div>
);
}
function ReviewAgentsTable({
orgId,
agents,
runs,
migrationReports,
policies,
actions,
}: {
orgId: string;
agents: SdlcReviewAgentRecord[];
runs: SdlcReviewRunRecord[];
migrationReports: MigrationReportRecord[];
policies: PolicyRuleRecord[];
actions: SnapshotActions;
}) {
return (
<>
<div className="section-label" style={{ marginBottom: 10 }}>Review agents</div>
<div className="card" style={{ padding: 0, overflow: "hidden", marginBottom: 24 }}>
<div className="table-row head" style={{ gridTemplateColumns: "minmax(0, 1.4fr) minmax(0, 1fr) 96px 82px" }}>
<div>Agent</div><div>Target</div><div>Last run</div><div>Action</div>
</div>
{agents.map((agent, index) => {
const target = resolveReviewTarget(agent, orgId, migrationReports, policies);
const run = runs.find((item) => item.reviewAgentId === agent.id) ?? null;
return (
<div
key={agent.id}
className="table-row"
style={{
gridTemplateColumns: "minmax(0, 1.4fr) minmax(0, 1fr) 96px 82px",
borderBottom: index === agents.length - 1 ? "none" : "1px solid var(--border-soft)",
}}
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{agent.label}</div>
<div className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{agent.specialty}</div>
</div>
<div><Pill>{target.label}</Pill></div>
<div className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>{run ? `${run.state} · ${formatRelative(run.createdAt)}` : "0 runs"}</div>
<Button
size="small"
disabled={!agent.enabled || !target.ready}
onClick={() => void actions.run(() => window.agentCompany.runSdlcReview({
orgId,
reviewAgentId: agent.id,
targetType: target.type,
targetRef: target.ref,
}))}
>
Run
</Button>
</div>
);
})}
</div>
</>
);
}
function EvalSuitesTable({
orgId,
suites,
cases,
runs,
actions,
}: {
orgId: string;
suites: EvalSuiteRecord[];
cases: EvalCaseRecord[];
runs: EvalRunRecord[];
actions: SnapshotActions;
}) {
return (
<>
<div className="section-label" style={{ marginBottom: 10 }}>Eval suites</div>
<div className="card" style={{ padding: 0, overflow: "hidden", marginBottom: 24 }}>
<div className="table-row head" style={{ gridTemplateColumns: "minmax(0, 1.4fr) 90px 96px 82px" }}>
<div>Suite</div><div>Cases</div><div>Last run</div><div>Action</div>
</div>
{suites.map((suite, index) => {
const run = runs.find((item) => item.suiteId === suite.id) ?? null;
const caseCount = cases.filter((item) => item.suiteId === suite.id).length;
return (
<div
key={suite.id}
className="table-row"
style={{
gridTemplateColumns: "minmax(0, 1.4fr) 90px 96px 82px",
borderBottom: index === suites.length - 1 ? "none" : "1px solid var(--border-soft)",
}}
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{suite.label}</div>
<div className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{suite.scope}</div>
</div>
<div className="num mono">{caseCount}</div>
<div className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>{run ? `${run.state} · ${formatRelative(run.createdAt)}` : "0 runs"}</div>
<Button size="small" onClick={() => void actions.run(() => window.agentCompany.runEvalSuite({ orgId, suiteId: suite.id }))}>
Run
</Button>
</div>
);
})}
</div>
</>
);
}
function PrBotGatesTable({
orgId,
gates,
actions,
}: {
orgId: string;
gates: PrBotGateRecord[];
actions: SnapshotActions;
}) {
return (
<>
<div className="section-label" style={{ marginBottom: 10 }}>PR bot gates</div>
<div className="card" style={{ padding: 0, overflow: "hidden" }}>
<div className="table-row head" style={{ gridTemplateColumns: "minmax(0, 1.4fr) 112px minmax(0, 1fr)" }}>
<div>Gate</div><div>State</div><div>Updated</div>
</div>
{gates.map((gate, index) => (
<div
key={gate.id}
className="table-row"
style={{
gridTemplateColumns: "minmax(0, 1.4fr) 112px minmax(0, 1fr)",
borderBottom: index === gates.length - 1 ? "none" : "1px solid var(--border-soft)",
}}
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{gate.label}</div>
<div className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{gate.gateType}</div>
</div>
<label className="row" style={{ gap: 8, fontSize: 12, color: "var(--text-2)" }}>
<input
aria-label={`${gate.label} enabled`}
type="checkbox"
checked={gate.enabled}
onChange={(event) => {
void actions.run(() => window.agentCompany.setPrBotGate({ orgId, gateId: gate.id, enabled: event.target.checked }));
}}
/>
{gate.enabled ? "On" : "Off"}
</label>
<div className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>{formatRelative(gate.updatedAt)}</div>
</div>
))}
</div>
</>
);
}
function resolveReviewTarget(
agent: SdlcReviewAgentRecord,
orgId: string,
migrationReports: MigrationReportRecord[],
policies: PolicyRuleRecord[],
): { type: SdlcReviewTargetType; ref: string; label: string; ready: boolean } {
if (agent.key === SDLC_REVIEW_AGENT_KEY.MIGRATION_REVIEWER) {
const report = migrationReports[0] ?? null;
return {
type: SDLC_REVIEW_TARGET_TYPE.MIGRATION,
ref: report?.id ?? orgId,
label: report ? "migration" : "migration report",
ready: Boolean(report),
};
}
if (agent.key === SDLC_REVIEW_AGENT_KEY.POLICY_REVIEWER) {
const policy = policies[0] ?? null;
return {
type: SDLC_REVIEW_TARGET_TYPE.POLICY,
ref: policy?.id ?? orgId,
label: policy ? "policy" : "policy rule",
ready: Boolean(policy),
};
}
return { type: SDLC_REVIEW_TARGET_TYPE.WORKSPACE, ref: orgId, label: "workspace", ready: true };
}