Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions src/app/governance/GovernanceReadiness.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"use client";

import { useMemo, useState } from "react";

type ChecklistItem = {
id: string;
label: string;
};

type MaturityBand = {
range: [number, number];
label: string;
guidance: string;
};

type Props = {
checklist: ChecklistItem[];
maturityCriteria: {
basic: MaturityBand;
intermediate: MaturityBand;
advanced: MaturityBand;
};
};

export default function GovernanceReadiness({ checklist, maturityCriteria }: Props) {
const [checked, setChecked] = useState<Record<string, boolean>>({});

const score = useMemo(() => {
return checklist.reduce((total, item) => total + (checked[item.id] ? 1 : 0), 0);
}, [checklist, checked]);

const percentage = Math.round((score / checklist.length) * 100);

const maturity = useMemo(() => {
if (score <= maturityCriteria.basic.range[1]) return maturityCriteria.basic;
if (score <= maturityCriteria.intermediate.range[1]) return maturityCriteria.intermediate;
return maturityCriteria.advanced;
}, [maturityCriteria, score]);

return (
<section className="mt-12 rounded-xl border border-white/10 bg-card/40 p-6 md:p-8">
<h2 className="text-2xl font-bold">Governance Readiness Checklist</h2>
<p className="mt-2 text-sm text-foreground/70">
Check each control that is currently implemented in your environment. Score updates instantly.
</p>

<div className="mt-6 space-y-3">
{checklist.map((item) => (
<label
key={item.id}
className="flex cursor-pointer items-start gap-3 rounded-lg border border-white/10 bg-black/20 p-3"
>
<input
type="checkbox"
className="mt-1 h-4 w-4 accent-[#06D6A0]"
checked={Boolean(checked[item.id])}
onChange={(event) => {
setChecked((prev) => ({ ...prev, [item.id]: event.target.checked }));
}}
/>
<span className="text-sm text-foreground/90">{item.label}</span>
</label>
))}
</div>

<div className="mt-6 rounded-lg border border-[#06D6A0]/25 bg-[#06D6A0]/10 p-4">
<p className="text-sm text-foreground/80">Self-assessment score</p>
<p className="mt-1 text-2xl font-bold text-[#06D6A0]">
{score}/{checklist.length} ({percentage}%)
</p>
<p className="mt-1 text-sm text-foreground/90">
Maturity: <span className="font-semibold">{maturity.label}</span>
</p>
<p className="mt-1 text-sm text-foreground/70">{maturity.guidance}</p>
</div>
</section>
);
}
145 changes: 145 additions & 0 deletions src/app/governance/accountability/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/* eslint-disable react/no-unescaped-entities */

import type { Metadata } from "next";
import Link from "next/link";
import governanceFramework from "@/data/governance-framework.json";

type AccountabilityData = {
accountability: {
auditTrailRequirements: string[];
decisionLoggingPatterns: string[];
escalationProtocols: string[];
};
};

export const metadata: Metadata = {
title: "Accountability for Agent Operations — forAgents.dev",
description:
"Audit trails, decision logging, escalation protocols, and human-in-the-loop gates for accountable autonomous agents.",
};

const loggingExample = `type DecisionLog = {
decisionId: string;
timestamp: string;
agentId: string;
actorId: string;
action: string;
riskLevel: "low" | "medium" | "high";
rationale: string;
confidence: number;
policyChecks: { ruleId: string; passed: boolean }[];
escalationRequired: boolean;
};

export async function logDecision(entry: DecisionLog) {
await auditStore.append({
...entry,
timestamp: new Date().toISOString(),
});

if (entry.riskLevel === "high" || entry.escalationRequired) {
await notifyHumanReviewer({
decisionId: entry.decisionId,
summary: entry.rationale,
actorId: entry.actorId,
});
}
}`;

const hitlGateExample = `export async function runWithHumanGate(input: TaskInput) {
const risk = assessRisk(input);

if (risk.level !== "high") {
return executeTask(input);
}

const approval = await requestApproval({
requestedBy: input.actorId,
summary: input.summary,
timeoutMinutes: 30,
});

if (!approval.granted) {
return { status: "blocked", reason: "human_approval_required" };
}

return executeTask(input);
}`;

export default function GovernanceAccountabilityPage() {
const data = governanceFramework as AccountabilityData;

return (
<div className="min-h-screen bg-[#0a0a0a]">
<section className="mx-auto max-w-5xl px-4 py-16">
<Link href="/governance" className="text-sm text-[#06D6A0] hover:underline">
← Back to governance hub
</Link>
<h1 className="mt-4 text-4xl font-bold tracking-tight text-[#F8FAFC] md:text-5xl">
Accountability Deep Dive
</h1>
<p className="mt-4 text-foreground/80">
Build reliable ownership and defensible evidence across every autonomous decision, so teams don't lose track of responsibility.
</p>

<div className="mt-8 grid gap-4 md:grid-cols-2">
<section className="rounded-xl border border-white/10 bg-card/30 p-5">
<h2 className="text-xl font-semibold">Audit trail requirements</h2>
<ul className="mt-3 list-disc space-y-2 pl-5 text-sm text-foreground/80">
{data.accountability.auditTrailRequirements.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</section>

<section className="rounded-xl border border-white/10 bg-card/30 p-5">
<h2 className="text-xl font-semibold">Decision logging patterns</h2>
<ul className="mt-3 list-disc space-y-2 pl-5 text-sm text-foreground/80">
{data.accountability.decisionLoggingPatterns.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</section>
</div>

<section className="mt-4 rounded-xl border border-white/10 bg-card/30 p-5">
<h2 className="text-xl font-semibold">Escalation protocols</h2>
<ul className="mt-3 list-disc space-y-2 pl-5 text-sm text-foreground/80">
{data.accountability.escalationProtocols.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</section>

<section className="mt-4 rounded-xl border border-[#06D6A0]/30 bg-[#06D6A0]/10 p-5">
<h2 className="text-xl font-semibold">Human-in-the-loop gate design</h2>
<p className="mt-2 text-sm text-foreground/80">
Use risk-tiered gates so low-risk actions flow automatically and high-impact actions pause
for reviewer approval. Always enforce explicit deny-by-default behavior when approval is
missing or times out.
</p>
<ul className="mt-3 list-disc space-y-2 pl-5 text-sm text-foreground/80">
<li>Define action classes with risk levels and required approver roles.</li>
<li>Set strict decision timeouts and safe fallback behaviors.</li>
<li>Capture reviewer identity, decision reason, and timestamp.</li>
<li>Audit gate bypasses with mandatory post-hoc review.</li>
</ul>
</section>

<section className="mt-4 rounded-xl border border-white/10 bg-card/30 p-5">
<h2 className="text-xl font-semibold">Code examples: logging agent decisions</h2>
<div className="mt-3 rounded-lg bg-black/40 p-4 text-xs text-foreground/90">
<pre className="overflow-x-auto">{loggingExample}</pre>
</div>
</section>

<section className="mt-4 rounded-xl border border-white/10 bg-card/30 p-5">
<h2 className="text-xl font-semibold">Code example: human approval gate</h2>
<div className="mt-3 rounded-lg bg-black/40 p-4 text-xs text-foreground/90">
<pre className="overflow-x-auto">{hitlGateExample}</pre>
</div>
</section>
</section>
</div>
);
}
Loading
Loading