profit 77655c298c Initial commit: Agent Governance System Phase 8
Phase 8 Production Hardening with complete governance infrastructure:

- Vault integration with tiered policies (T0-T4)
- DragonflyDB state management
- SQLite audit ledger
- Pipeline DSL and templates
- Promotion/revocation engine
- Checkpoint system for session persistence
- Health manager and circuit breaker for fault tolerance
- GitHub/Slack integrations
- Architectural test pipeline with bug watcher, suggestion engine, council review
- Multi-agent chaos testing framework

Test Results:
- Governance tests: 68/68 passing
- E2E workflow: 16/16 passing
- Phase 2 Vault: 14/14 passing
- Integration tests: 27/27 passing

Coverage: 57.6% average across 12 phases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 22:07:06 -05:00

920 lines
31 KiB
TypeScript

/**
* Governed LLM Agent - Full Pipeline (TypeScript/Bun)
* ====================================================
* Complete governance integration with DragonflyDB runtime control.
*/
import OpenAI from "openai";
import { createClient, RedisClientType } from "redis";
import { Database } from "bun:sqlite";
import { $ } from "bun";
// =============================================================================
// Types
// =============================================================================
type AgentPhase = "BOOTSTRAP" | "PREFLIGHT" | "PLAN" | "EXECUTE" | "VERIFY" | "PACKAGE" | "REPORT" | "EXIT" | "REVOKED";
type AgentStatus = "PENDING" | "RUNNING" | "PAUSED" | "COMPLETED" | "REVOKED" | "FAILED";
type RevocationType = "ERROR_BUDGET_EXCEEDED" | "PROCEDURE_VIOLATION" | "FORBIDDEN_ACTION" | "HEARTBEAT_TIMEOUT" | "MANUAL";
interface ErrorBudget {
max_total_errors: number;
max_same_error_repeats: number;
max_procedure_violations: number;
}
interface InstructionPacket {
agent_id: string;
task_id: string;
created_for: string;
objective: string;
deliverables: string[];
constraints: {
scope: string[];
forbidden: string[];
required_steps: string[];
};
success_criteria: string[];
error_budget: ErrorBudget;
escalation_rules: string[];
created_at: string;
}
interface AgentState {
agent_id: string;
status: AgentStatus;
phase: AgentPhase;
step: string;
started_at: string;
last_progress_at: string;
notes: string;
}
interface HandoffObject {
task_id: string;
previous_agent_id: string;
revoked: boolean;
revocation_reason: { type: string; details: string };
last_known_state: { phase: string; step: string };
what_was_tried: string[];
blocking_issue: string;
required_next_actions: string[];
constraints_reminder: string[];
artifacts: string[];
created_at: string;
}
// =============================================================================
// Utilities
// =============================================================================
function now(): string {
return new Date().toISOString();
}
function errorSignature(errorType: string, message: string): string {
const normalized = (errorType + ":" + message.slice(0, 100)).toLowerCase();
let hash = 0;
for (let i = 0; i < normalized.length; i++) {
const char = normalized.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
return Math.abs(hash).toString(16).slice(0, 12);
}
async function getVaultSecret(path: string): Promise<Record<string, any>> {
const initKeys = await Bun.file("/opt/vault/init-keys.json").json();
const token = initKeys.root_token;
const result = await $`curl -sk -H "X-Vault-Token: ${token}" https://127.0.0.1:8200/v1/secret/data/${path}`.json();
return result.data.data;
}
// =============================================================================
// Governance Manager
// =============================================================================
class GovernanceManager {
private redis!: RedisClientType;
private lockTtl = 300;
private heartbeatTtl = 60;
async connect() {
const creds = await getVaultSecret("services/dragonfly");
this.redis = createClient({
url: "redis://" + creds.host + ":" + creds.port,
password: creds.password,
});
await this.redis.connect();
}
async disconnect() {
await this.redis.quit();
}
// Instruction Packets
async createPacket(packet: InstructionPacket): Promise<void> {
await this.redis.set("agent:" + packet.agent_id + ":packet", JSON.stringify(packet));
}
async getPacket(agentId: string): Promise<InstructionPacket | null> {
const data = await this.redis.get("agent:" + agentId + ":packet");
return data ? JSON.parse(data) : null;
}
// State
async setState(state: AgentState): Promise<void> {
state.last_progress_at = now();
await this.redis.set("agent:" + state.agent_id + ":state", JSON.stringify(state));
}
async getState(agentId: string): Promise<AgentState | null> {
const data = await this.redis.get("agent:" + agentId + ":state");
return data ? JSON.parse(data) : null;
}
// Locking
async acquireLock(agentId: string): Promise<boolean> {
const result = await this.redis.set("agent:" + agentId + ":lock", now(), { NX: true, EX: this.lockTtl });
return result === "OK";
}
async refreshLock(agentId: string): Promise<boolean> {
return await this.redis.expire("agent:" + agentId + ":lock", this.lockTtl);
}
async releaseLock(agentId: string): Promise<void> {
await this.redis.del("agent:" + agentId + ":lock");
}
async hasLock(agentId: string): Promise<boolean> {
return await this.redis.exists("agent:" + agentId + ":lock") === 1;
}
// Heartbeat
async heartbeat(agentId: string): Promise<void> {
await this.redis.set("agent:" + agentId + ":heartbeat", now(), { EX: this.heartbeatTtl });
}
// Errors
async recordError(agentId: string, errorType: string, message: string): Promise<Record<string, any>> {
const key = "agent:" + agentId + ":errors";
const sig = errorSignature(errorType, message);
await this.redis.hIncrBy(key, "total_errors", 1);
await this.redis.hIncrBy(key, "same_error:" + sig, 1);
await this.redis.hSet(key, "last_error_signature", sig);
await this.redis.hSet(key, "last_error_at", now());
await this.redis.hSet(key, "last_error_type", errorType);
await this.redis.hSet(key, "last_error_message", message.slice(0, 500));
return this.getErrorCounts(agentId);
}
async recordViolation(agentId: string, violation: string): Promise<number> {
const key = "agent:" + agentId + ":errors";
await this.redis.hSet(key, "last_violation", violation);
await this.redis.hSet(key, "last_violation_at", now());
return this.redis.hIncrBy(key, "procedure_violations", 1);
}
async getErrorCounts(agentId: string): Promise<Record<string, any>> {
const key = "agent:" + agentId + ":errors";
const data = await this.redis.hGetAll(key);
const sameErrorCounts: Record<string, number> = {};
for (const [k, v] of Object.entries(data)) {
if (k.startsWith("same_error:")) {
sameErrorCounts[k.replace("same_error:", "")] = parseInt(v);
}
}
return {
total_errors: parseInt(data.total_errors || "0"),
procedure_violations: parseInt(data.procedure_violations || "0"),
last_error_signature: data.last_error_signature || "",
last_error_at: data.last_error_at || "",
same_error_counts: sameErrorCounts,
};
}
async checkErrorBudget(agentId: string): Promise<[boolean, string | null]> {
const packet = await this.getPacket(agentId);
if (!packet) return [false, "NO_INSTRUCTION_PACKET"];
const counts = await this.getErrorCounts(agentId);
const budget = packet.error_budget;
if (counts.procedure_violations >= budget.max_procedure_violations) {
return [false, "PROCEDURE_VIOLATIONS (" + counts.procedure_violations + " >= " + budget.max_procedure_violations + ")"];
}
if (counts.total_errors >= budget.max_total_errors) {
return [false, "TOTAL_ERRORS (" + counts.total_errors + " >= " + budget.max_total_errors + ")"];
}
for (const [sig, count] of Object.entries(counts.same_error_counts)) {
if (count >= budget.max_same_error_repeats) {
return [false, "SAME_ERROR_REPEATED (" + sig + ": " + count + " >= " + budget.max_same_error_repeats + ")"];
}
}
return [true, null];
}
// Task Management
async assignAgentToTask(taskId: string, agentId: string): Promise<void> {
await this.redis.set("task:" + taskId + ":active_agent", agentId);
await this.redis.rPush("task:" + taskId + ":history", JSON.stringify({
agent_id: agentId,
assigned_at: now(),
event: "ASSIGNED",
}));
}
// Revocation
async revokeAgent(agentId: string, reasonType: RevocationType, details: string): Promise<void> {
const state = await this.getState(agentId);
if (state) {
state.status = "REVOKED";
state.phase = "REVOKED";
state.notes = "Revoked: " + reasonType + " - " + details;
await this.setState(state);
}
await this.releaseLock(agentId);
await this.redis.rPush("revocations:ledger", JSON.stringify({
agent_id: agentId,
reason_type: reasonType,
details: details,
revoked_at: now(),
}));
const packet = await this.getPacket(agentId);
if (packet) {
await this.redis.rPush("task:" + packet.task_id + ":history", JSON.stringify({
agent_id: agentId,
event: "REVOKED",
reason: reasonType,
revoked_at: now(),
}));
}
}
async getRecentRevocations(count: number = 50): Promise<any[]> {
const data = await this.redis.lRange("revocations:ledger", -count, -1);
return data.map(d => JSON.parse(d));
}
// Artifacts
async registerArtifact(taskId: string, artifactType: string, reference: string): Promise<void> {
await this.redis.rPush("task:" + taskId + ":artifacts", JSON.stringify({
type: artifactType,
reference: reference,
created_at: now(),
}));
}
async getArtifacts(taskId: string): Promise<any[]> {
const data = await this.redis.lRange("task:" + taskId + ":artifacts", 0, -1);
return data.map(d => JSON.parse(d));
}
async hasRequiredArtifact(taskId: string, artifactType: string): Promise<boolean> {
const artifacts = await this.getArtifacts(taskId);
return artifacts.some(a => a.type === artifactType);
}
// Handoff
async createHandoff(handoff: HandoffObject): Promise<void> {
await this.redis.set("handoff:" + handoff.task_id + ":latest", JSON.stringify(handoff));
}
async getHandoff(taskId: string): Promise<HandoffObject | null> {
const data = await this.redis.get("handoff:" + taskId + ":latest");
return data ? JSON.parse(data) : null;
}
}
// =============================================================================
// SQLite Ledger
// =============================================================================
function logToSqliteLedger(agentId: string, version: string, tier: number, action: string,
decision: string, confidence: number, success: boolean,
errorType?: string, errorMessage?: string) {
const db = new Database("/opt/agent-governance/ledger/governance.db");
const timestamp = now();
db.run(`
INSERT INTO agent_actions (timestamp, agent_id, agent_version, tier, action, decision, confidence, success, error_type, error_message)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`, [timestamp, agentId, version, tier, action, decision, confidence, success ? 1 : 0, errorType || null, errorMessage || null]);
db.close();
}
// =============================================================================
// Governed LLM Agent
// =============================================================================
class GovernedLLMAgent {
private agentId: string;
private model: string;
private gov!: GovernanceManager;
private llm!: OpenAI;
private packet!: InstructionPacket;
private state!: AgentState;
private startTime!: number;
constructor(agentId: string, model: string = "anthropic/claude-sonnet-4") {
this.agentId = agentId;
this.model = model;
}
private log(phase: string, message: string) {
const elapsed = ((Date.now() - this.startTime) / 1000).toFixed(1);
console.log("[" + elapsed + "s] [" + phase + "] " + message);
}
async createTask(taskId: string, objective: string, constraints?: any): Promise<void> {
const packet: InstructionPacket = {
agent_id: this.agentId,
task_id: taskId,
created_for: "Governed LLM Task",
objective: objective,
deliverables: ["implementation plan", "execution logs", "artifacts"],
constraints: constraints || {
scope: ["sandbox only"],
forbidden: ["no prod access", "no unrecorded changes", "no direct database modifications"],
required_steps: ["plan before execute", "verify after execute", "document assumptions"],
},
success_criteria: ["plan generated", "all steps documented", "artifacts registered"],
error_budget: {
max_total_errors: 8,
max_same_error_repeats: 2,
max_procedure_violations: 1,
},
escalation_rules: [
"If confidence < 0.7 -> escalate",
"If blocked > 10m -> escalate",
"If dependencies unclear -> escalate",
],
created_at: now(),
};
await this.gov.createPacket(packet);
}
async bootstrap(): Promise<[boolean, string]> {
this.startTime = Date.now();
console.log("\n" + "=".repeat(70));
console.log("GOVERNED LLM AGENT: " + this.agentId);
console.log("Model: " + this.model);
console.log("=".repeat(70) + "\n");
// Connect to governance
this.gov = new GovernanceManager();
await this.gov.connect();
this.log("BOOTSTRAP", "Connected to DragonflyDB");
// Read revocation ledger
const revocations = await this.gov.getRecentRevocations(50);
this.log("BOOTSTRAP", "Read " + revocations.length + " recent revocations");
for (const rev of revocations) {
if (rev.agent_id === this.agentId) {
return [false, "AGENT_PREVIOUSLY_REVOKED: " + rev.reason_type];
}
}
// Load instruction packet
const packet = await this.gov.getPacket(this.agentId);
if (!packet) {
return [false, "NO_INSTRUCTION_PACKET"];
}
this.packet = packet;
this.log("BOOTSTRAP", "Loaded instruction packet for task: " + packet.task_id);
// Check for handoff from previous agent
const handoff = await this.gov.getHandoff(packet.task_id);
if (handoff && handoff.previous_agent_id !== this.agentId) {
this.log("BOOTSTRAP", "Found handoff from: " + handoff.previous_agent_id);
this.log("BOOTSTRAP", "Revocation reason: " + JSON.stringify(handoff.revocation_reason));
this.log("BOOTSTRAP", "Required next actions: " + handoff.required_next_actions.join(", "));
}
// Acquire lock
if (!await this.gov.acquireLock(this.agentId)) {
return [false, "CANNOT_ACQUIRE_LOCK"];
}
this.log("BOOTSTRAP", "Acquired execution lock");
// Initialize state
this.state = {
agent_id: this.agentId,
status: "RUNNING",
phase: "BOOTSTRAP",
step: "initialized",
started_at: now(),
last_progress_at: now(),
notes: "",
};
await this.gov.setState(this.state);
// Start heartbeat
await this.gov.heartbeat(this.agentId);
// Assign to task
await this.gov.assignAgentToTask(packet.task_id, this.agentId);
// Initialize LLM
const secrets = await getVaultSecret("api-keys/openrouter");
this.llm = new OpenAI({
baseURL: "https://openrouter.ai/api/v1",
apiKey: secrets.api_key,
});
this.log("BOOTSTRAP", "LLM client initialized");
return [true, "BOOTSTRAP_COMPLETE"];
}
async transition(phase: AgentPhase, step: string, notes: string = ""): Promise<boolean> {
await this.gov.heartbeat(this.agentId);
await this.gov.refreshLock(this.agentId);
const [ok, reason] = await this.gov.checkErrorBudget(this.agentId);
if (!ok) {
this.log("REVOKE", "Error budget exceeded: " + reason);
await this.gov.revokeAgent(this.agentId, "ERROR_BUDGET_EXCEEDED", reason!);
return false;
}
this.state.phase = phase;
this.state.step = step;
this.state.notes = notes;
await this.gov.setState(this.state);
this.log(phase, step + (notes ? " - " + notes : ""));
return true;
}
async reportError(errorType: string, message: string): Promise<boolean> {
const counts = await this.gov.recordError(this.agentId, errorType, message);
this.log("ERROR", errorType + ": " + message);
this.log("ERROR", "Counts: total=" + counts.total_errors + ", violations=" + counts.procedure_violations);
const [ok, reason] = await this.gov.checkErrorBudget(this.agentId);
if (!ok) {
this.log("REVOKE", "Error budget exceeded: " + reason);
await this.gov.revokeAgent(this.agentId, "ERROR_BUDGET_EXCEEDED", reason!);
return false;
}
return true;
}
async runPreflight(): Promise<boolean> {
if (!await this.transition("PREFLIGHT", "scope_check")) return false;
this.log("PREFLIGHT", "Scope: " + this.packet.constraints.scope.join(", "));
this.log("PREFLIGHT", "Forbidden: " + this.packet.constraints.forbidden.join(", "));
this.log("PREFLIGHT", "Required steps: " + this.packet.constraints.required_steps.join(", "));
return await this.transition("PREFLIGHT", "complete", "All preflight checks passed");
}
async runPlan(): Promise<any | null> {
if (!await this.transition("PLAN", "generating")) return null;
const systemPrompt = `You are a governed infrastructure automation agent operating under strict compliance rules.
TASK: ${this.packet.objective}
CONSTRAINTS (MUST FOLLOW):
- Scope: ${this.packet.constraints.scope.join(", ")}
- Forbidden: ${this.packet.constraints.forbidden.join(", ")}
- Required steps: ${this.packet.constraints.required_steps.join(", ")}
ESCALATION RULES:
${this.packet.escalation_rules.join("\n")}
You are in the PLAN phase. Generate a comprehensive, detailed implementation plan.
Be thorough - identify ALL steps, dependencies, risks, and assumptions.
Output JSON:
{
"title": "Plan title",
"summary": "Brief summary",
"confidence": 0.0-1.0,
"complexity": "low|medium|high|very_high",
"estimated_steps": number,
"phases": [
{
"phase": "Phase name",
"steps": [
{
"step": number,
"action": "Detailed action description",
"reasoning": "Why this step is needed",
"dependencies": ["what must be done first"],
"outputs": ["what this produces"],
"reversible": boolean,
"rollback": "How to undo if needed",
"risks": ["potential issues"],
"verification": "How to verify success"
}
]
}
],
"assumptions": ["explicit assumptions"],
"uncertainties": ["things that are unclear"],
"risks": ["overall risks"],
"success_criteria": ["how to know we succeeded"],
"estimated_tier_required": 0-4,
"requires_human_review": boolean,
"blockers": ["anything that would prevent execution"]
}`;
try {
const response = await this.llm.chat.completions.create({
model: this.model,
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: "Create a comprehensive implementation plan for:\n\n" + this.packet.objective + "\n\nBe thorough and identify all steps, risks, and dependencies." },
],
max_tokens: 8000,
temperature: 0.3,
});
const llmResponse = response.choices[0].message.content || "";
let plan: any;
try {
// Try to extract JSON from markdown code blocks or raw JSON
let jsonStr = llmResponse;
// Remove markdown code block wrappers if present
const jsonBlockMatch = llmResponse.match(/```(?:json)?\s*([\s\S]*?)```/);
if (jsonBlockMatch) {
jsonStr = jsonBlockMatch[1].trim();
} else if (llmResponse.includes("```json")) {
// Handle truncated code block (no closing ```)
const start = llmResponse.indexOf("```json") + 7;
jsonStr = llmResponse.slice(start).trim();
}
// Find the JSON object
const jsonStart = jsonStr.indexOf("{");
if (jsonStart < 0) {
throw new Error("No JSON object found");
}
// Try to find complete JSON, or extract what we can
let jsonContent = jsonStr.slice(jsonStart);
// Attempt to repair truncated JSON by closing open structures
let braceCount = 0;
let bracketCount = 0;
let inString = false;
let lastValidPos = 0;
for (let i = 0; i < jsonContent.length; i++) {
const char = jsonContent[i];
const prev = i > 0 ? jsonContent[i - 1] : "";
if (char === '"' && prev !== '\\') {
inString = !inString;
} else if (!inString) {
if (char === '{') braceCount++;
else if (char === '}') braceCount--;
else if (char === '[') bracketCount++;
else if (char === ']') bracketCount--;
}
if (braceCount === 0 && bracketCount === 0 && !inString) {
lastValidPos = i + 1;
break;
}
}
if (lastValidPos > 0) {
// Found complete JSON
plan = JSON.parse(jsonContent.slice(0, lastValidPos));
} else {
// JSON is truncated, try to extract key fields
this.log("PLAN", "JSON appears truncated, extracting available fields");
// Extract what we can
const titleMatch = jsonContent.match(/"title"\s*:\s*"([^"]*)"/);
const summaryMatch = jsonContent.match(/"summary"\s*:\s*"([^"]*)"/);
const confidenceMatch = jsonContent.match(/"confidence"\s*:\s*([\d.]+)/);
const complexityMatch = jsonContent.match(/"complexity"\s*:\s*"([^"]*)"/);
const stepsMatch = jsonContent.match(/"estimated_steps"\s*:\s*(\d+)/);
// Count phases we can find
const phaseMatches = jsonContent.match(/"phase"\s*:\s*"[^"]*"/g) || [];
plan = {
title: titleMatch ? titleMatch[1] : "Extracted Plan",
summary: summaryMatch ? summaryMatch[1] : "Plan details extracted from truncated response",
confidence: confidenceMatch ? parseFloat(confidenceMatch[1]) : 0.6,
complexity: complexityMatch ? complexityMatch[1] : "high",
estimated_steps: stepsMatch ? parseInt(stepsMatch[1]) : phaseMatches.length * 5,
phases: phaseMatches.map((m, i) => ({
phase: m.match(/"phase"\s*:\s*"([^"]*)"/)?.[1] || "Phase " + (i + 1),
steps: [{ step: i + 1, action: "Step " + (i + 1), reversible: true, rollback: "Undo" }]
})),
_truncated: true,
_raw_length: jsonContent.length,
};
}
} catch (parseError: any) {
this.log("PLAN", "JSON parse error: " + parseError.message);
plan = { raw_response: llmResponse.slice(0, 500) + "...", confidence: 0.4 };
this.log("PLAN", "Warning: Could not parse plan JSON, using raw response");
}
// Register plan artifact
await this.gov.registerArtifact(this.packet.task_id, "plan", "plan_" + this.agentId + "_" + now());
const confidence = plan.confidence || 0.5;
if (confidence < 0.7) {
this.log("PLAN", "Low confidence (" + confidence + ") - would escalate in production");
}
await this.transition("PLAN", "complete", "Confidence: " + confidence);
logToSqliteLedger(this.agentId, "0.1.0", 0, "generate_plan", "EXECUTE", confidence, true);
return plan;
} catch (e: any) {
await this.reportError("LLM_ERROR", e.message);
return null;
}
}
async runExecute(plan: any): Promise<boolean> {
// Compliance check: must have plan artifact
if (!await this.gov.hasRequiredArtifact(this.packet.task_id, "plan")) {
await this.gov.recordViolation(this.agentId, "EXECUTE_WITHOUT_PLAN");
await this.gov.revokeAgent(this.agentId, "PROCEDURE_VIOLATION", "Attempted EXECUTE without plan artifact");
return false;
}
if (!await this.transition("EXECUTE", "starting")) return false;
const phases = plan.phases || [{ steps: plan.steps || [] }];
let totalSteps = 0;
for (const phase of phases) {
const phaseName = phase.phase || "Main";
this.log("EXECUTE", "Phase: " + phaseName);
const steps = phase.steps || [];
for (const step of steps) {
totalSteps++;
const stepNum = step.step || totalSteps;
const action = step.action || "Unknown action";
this.log("EXECUTE", " Step " + stepNum + ": " + action.slice(0, 70) + "...");
// Check for forbidden actions
for (const forbidden of this.packet.constraints.forbidden) {
if (action.toLowerCase().includes(forbidden.toLowerCase().replace("no ", ""))) {
this.log("EXECUTE", " WARNING: Step may violate constraint: " + forbidden);
}
}
// Register step completion
await this.gov.registerArtifact(
this.packet.task_id,
"step_" + stepNum,
"executed_" + stepNum + "_" + now()
);
// Simulate step execution time for realism
await new Promise(r => setTimeout(r, 100));
}
}
this.log("EXECUTE", "Completed " + totalSteps + " steps");
return await this.transition("EXECUTE", "complete", totalSteps + " steps executed");
}
async runVerify(): Promise<boolean> {
if (!await this.transition("VERIFY", "checking_artifacts")) return false;
const artifacts = await this.gov.getArtifacts(this.packet.task_id);
this.log("VERIFY", "Found " + artifacts.length + " artifacts");
// Verify we have required artifacts
const hasPlan = artifacts.some(a => a.type === "plan");
const hasSteps = artifacts.some(a => a.type.startsWith("step_"));
if (!hasPlan) {
await this.reportError("MISSING_ARTIFACT", "No plan artifact found");
}
if (!hasSteps) {
await this.reportError("MISSING_ARTIFACT", "No step artifacts found");
}
return await this.transition("VERIFY", "complete", "Verified " + artifacts.length + " artifacts");
}
async runPackage(): Promise<any> {
if (!await this.transition("PACKAGE", "collecting")) return {};
const artifacts = await this.gov.getArtifacts(this.packet.task_id);
const errors = await this.gov.getErrorCounts(this.agentId);
const pkg = {
agent_id: this.agentId,
task_id: this.packet.task_id,
objective: this.packet.objective,
artifacts_count: artifacts.length,
artifacts: artifacts.slice(0, 10), // First 10
error_counts: errors,
completed_at: now(),
};
await this.gov.registerArtifact(this.packet.task_id, "package", "package_" + now());
await this.transition("PACKAGE", "complete");
return pkg;
}
async runReport(pkg: any, plan: any): Promise<any> {
if (!await this.transition("REPORT", "generating")) return {};
const report = {
agent_id: this.agentId,
task_id: pkg.task_id,
model: this.model,
status: "COMPLETED",
objective: pkg.objective,
plan_summary: plan.summary || "Plan generated",
plan_confidence: plan.confidence || 0,
plan_complexity: plan.complexity || "unknown",
total_phases: (plan.phases || []).length,
total_steps: pkg.artifacts_count - 2, // Subtract plan and package
artifacts_generated: pkg.artifacts_count,
errors_encountered: pkg.error_counts.total_errors,
procedure_violations: pkg.error_counts.procedure_violations,
assumptions: plan.assumptions || [],
risks_identified: (plan.risks || []).length,
requires_human_review: plan.requires_human_review || false,
estimated_tier_required: plan.estimated_tier_required || "unknown",
elapsed_seconds: ((Date.now() - this.startTime) / 1000).toFixed(1),
timestamp: now(),
};
await this.transition("REPORT", "complete");
return report;
}
async finish(report: any): Promise<void> {
this.state.status = "COMPLETED";
this.state.phase = "EXIT";
this.state.notes = "Task completed successfully";
await this.gov.setState(this.state);
await this.gov.releaseLock(this.agentId);
this.log("EXIT", "Agent completed successfully");
console.log("\n" + "=".repeat(70));
console.log("FINAL REPORT");
console.log("=".repeat(70));
console.log(JSON.stringify(report, null, 2));
console.log("=".repeat(70) + "\n");
}
async cleanup(): Promise<void> {
if (this.gov) {
await this.gov.disconnect();
}
}
async run(): Promise<any> {
try {
// Bootstrap
const [ok, msg] = await this.bootstrap();
if (!ok) {
console.error("Bootstrap failed: " + msg);
return { status: "FAILED", reason: msg };
}
// Preflight
if (!await this.runPreflight()) {
return { status: "FAILED", reason: "PREFLIGHT_FAILED" };
}
// Plan
const plan = await this.runPlan();
if (!plan) {
return { status: "FAILED", reason: "PLAN_FAILED" };
}
console.log("\n" + "-".repeat(70));
console.log("GENERATED PLAN");
console.log("-".repeat(70));
console.log(JSON.stringify(plan, null, 2));
console.log("-".repeat(70) + "\n");
// Execute
if (!await this.runExecute(plan)) {
return { status: "FAILED", reason: "EXECUTE_FAILED" };
}
// Verify
if (!await this.runVerify()) {
return { status: "FAILED", reason: "VERIFY_FAILED" };
}
// Package
const pkg = await this.runPackage();
// Report
const report = await this.runReport(pkg, plan);
// Finish
await this.finish(report);
return report;
} finally {
await this.cleanup();
}
}
}
// =============================================================================
// CLI
// =============================================================================
async function createInstructionPacket(gov: GovernanceManager, agentId: string, taskId: string, objective: string): Promise<void> {
const packet: InstructionPacket = {
agent_id: agentId,
task_id: taskId,
created_for: "Governed LLM Task",
objective: objective,
deliverables: ["implementation plan", "execution logs", "artifacts"],
constraints: {
scope: ["sandbox only"],
forbidden: ["no prod access", "no unrecorded changes", "no direct database modifications"],
required_steps: ["plan before execute", "verify after execute", "document assumptions"],
},
success_criteria: ["plan generated", "all steps documented", "artifacts registered"],
error_budget: {
max_total_errors: 8,
max_same_error_repeats: 2,
max_procedure_violations: 1,
},
escalation_rules: [
"If confidence < 0.7 -> escalate",
"If blocked > 10m -> escalate",
"If dependencies unclear -> escalate",
],
created_at: now(),
};
await gov.createPacket(packet);
}
async function main() {
const args = process.argv.slice(2);
if (args.length < 3) {
console.log("Usage: bun run governed-agent.ts <agent_id> <task_id> \"<objective>\"");
console.log(" bun run governed-agent.ts <agent_id> <task_id> \"<objective>\" --model <model>");
process.exit(1);
}
const agentId = args[0];
const taskId = args[1];
const objective = args[2];
let model = "anthropic/claude-sonnet-4";
const modelIdx = args.indexOf("--model");
if (modelIdx !== -1 && args[modelIdx + 1]) {
model = args[modelIdx + 1];
}
// Connect to governance and create instruction packet
const gov = new GovernanceManager();
await gov.connect();
await createInstructionPacket(gov, agentId, taskId, objective);
await gov.disconnect();
// Create and run agent
const agent = new GovernedLLMAgent(agentId, model);
const result = await agent.run();
process.exit(result.status === "COMPLETED" ? 0 : 1);
}
main().catch(e => {
console.error("Fatal error:", e);
process.exit(1);
});