#!/usr/bin/env node import { Command } from "commander"; import { MetaAgent } from "./tier3-compounding/meta-agent.js"; import { loadEnv } from "./upgrades/env-loader.js"; import type { SkillDefinition, LoopIteration } from "./core/types.js"; import * as fs from "node:fs"; import * as path from "node:path"; // Load .env before any command handlers run const envResult = loadEnv(); const packageJson = JSON.parse( fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8") ); const program = new Command(); program .name("fable-agent") .description("Harness-agnostic, model-agnostic self-improving agent system — loops, dynamic workflows, routines") .version(packageJson.version); // ── Verify / Attest ───────────────────────────────────────── program .command("verify ") .description("Verify a target and emit an agentic attestation") .option("--out ", "Attestation output path") .option("--run ", "Emit attestation event to .runs//channel.jsonl") .option("--scan-all", "Scan every scannable file under the target, not just changed files") .action(async (target: string, opts: { out?: string; run?: string; scanAll?: boolean }) => { const { verifyTarget } = await import("./fable5/attestation.js"); const stamp = new Date().toISOString().replace(/[:.]/g, "-"); const out = opts.out ?? path.join(".fable", "attestations", stamp + ".json"); const receipt = verifyTarget({ target, out, scanAll: opts.scanAll }); console.log(JSON.stringify(receipt, null, 2)); console.log("\n Attestation: " + out + "\n"); await emitRunEvent(opts.run, { source: "gate", type: receipt.verification_status === "failed" ? "error" : "receipt", data: { kind: "agentic-attestation", receipt, path: out } }); if (receipt.verification_status === "failed") process.exit(1); }); program .command("attest ") .description("Alias for verify: emit an agentic attestation") .option("--out ", "Attestation output path") .option("--run ", "Emit attestation event to .runs//channel.jsonl") .option("--scan-all", "Scan every scannable file under the target, not just changed files") .action(async (target: string, opts: { out?: string; run?: string; scanAll?: boolean }) => { const { verifyTarget } = await import("./fable5/attestation.js"); const stamp = new Date().toISOString().replace(/[:.]/g, "-"); const out = opts.out ?? path.join(".fable", "attestations", stamp + ".json"); const receipt = verifyTarget({ target, out, scanAll: opts.scanAll }); console.log(JSON.stringify(receipt, null, 2)); console.log("\n Attestation: " + out + "\n"); await emitRunEvent(opts.run, { source: "gate", type: receipt.verification_status === "failed" ? "error" : "receipt", data: { kind: "agentic-attestation", receipt, path: out } }); if (receipt.verification_status === "failed") process.exit(1); }); // ── Run ───────────────────────────────────────────────────── program .command("run ") .description("Run a task through the self-improving agent system") .option("-l, --loop ", "Number of feedback loop iterations", parseInt) .option("-w, --workflow ", "Workflow definition ID to execute") .option("-s, --skill ", "Skill ID to execute") .option("-c, --compound ", "Number of compound runs", parseInt) .action(async (task: string, opts: Record) => { const agent = new MetaAgent(); console.log(`\n Fable Agent v${packageJson.version}`); console.log(` ─────────────────────────────`); console.log(` Task: ${task}`); console.log(` `); try { const compound = opts.compound ? Number(opts.compound) : 1; if (compound > 1) { const results = await agent.compound(task, compound); console.log(`\n ✓ Compound run complete (${compound} iterations)`); for (const r of results) { console.log(` Session ${r.sessionId.slice(0, 8)}… — ${r.loopIterations} loops, converged=${r.converged}`); } } else { const result = await agent.run(task, { skillId: opts.skill as string | undefined, workflowId: opts.workflow as string | undefined, loopIterations: opts.loop ? Number(opts.loop) : undefined, }); console.log(`\n ✓ Run complete`); console.log(` Session: ${result.sessionId}`); console.log(` Iterations: ${result.loopIterations}`); console.log(` Converged: ${result.converged} (${result.convergenceReason ?? "n/a"})`); console.log(` Context: ${result.contextUsage.pct}% of ${result.contextUsage.budget} budget`); console.log(` Knowledge: ${result.knowledgeEntryCount} entries`); } const status = agent.getStatus(); console.log(`\n System State:`); console.log(` Skills: ${status.skills.total} (${status.skills.withHistory} with history)`); console.log(` Knowledge: ${status.knowledge.entries} entries, ${status.knowledge.tags.length} tags`); console.log(` `); } catch (err) { console.error(`\n ✗ Error: ${err instanceof Error ? err.message : String(err)}`); process.exit(1); } }); // ── Session ───────────────────────────────────────────────── const session = program .command("session") .description("Manage autonomous agent sessions"); session .command("start") .description("Start a new autonomous session") .argument("", "Task description") .action(async (task: string) => { const agent = new MetaAgent(); const sess = agent.session.start(task); console.log(`\n Session started:`); console.log(` ID: ${sess.id}`); console.log(` Task: ${sess.task}`); console.log(` Run \`fable-agent session resume ${sess.id}\` to resume if interrupted`); console.log(` `); }); session .command("resume ") .description("Resume a checkpointed session") .action(async (id: string) => { const agent = new MetaAgent(); const sess = agent.session.resume(id); if (!sess) { console.error(` ✗ Session not found: ${id}`); process.exit(1); } console.log(` ✓ Session resumed: ${id}`); console.log(` Task: ${sess.task}`); console.log(` `); }); session .command("list") .description("List all sessions") .action(() => { const agent = new MetaAgent(); const sessions = agent.session.list(); if (sessions.length === 0) { console.log(" No sessions found."); return; } console.log(` Sessions (${sessions.length}):`); for (const s of sessions) { const age = Math.round( (Date.now() - new Date(s.createdAt).getTime()) / 1000 / 60 ); console.log(` ${s.id.slice(0, 8)}… ${s.status.padEnd(14)} ${age}m ago "${s.task.slice(0, 50)}"`); } console.log(` `); }); session .command("inspect ") .description("View session details") .action(async (id: string) => { const agent = new MetaAgent(); const s = agent.session.get(id); if (!s) { console.error(` ✗ Session not found: ${id}`); process.exit(1); } console.log(`\n Session: ${s.id}`); console.log(` ─────────────────────────────`); console.log(` Status: ${s.status}`); console.log(` Task: ${s.task}`); console.log(` Created: ${s.createdAt}`); console.log(` Updated: ${s.updatedAt}`); console.log(` Iterations: ${s.metadata.totalIterations ?? "?"}`); console.log(` Config:`); console.log(` Max iterations: ${s.config.maxIterations}`); console.log(` Convergence thresh: ${s.config.convergenceThreshold}`); console.log(` Context budget: ${s.config.contextTokenBudget}`); console.log(` Heartbeat interval: ${s.config.heartbeatIntervalMs}ms`); if (agent.session.isStalled(id)) { console.log(` ⚠ Session may be stalled (no recent heartbeat)`); } console.log(` `); }); // ── Skills ────────────────────────────────────────────────── const skills = program .command("skills") .description("Manage skills (routines)"); skills .command("list") .description("List all registered skills") .option("-t, --tag ", "Filter by tag") .action((opts: { tag?: string }) => { const agent = new MetaAgent(); let skillsList: SkillDefinition[]; if (opts.tag) { skillsList = agent.skillRegistry.findByTag(opts.tag); } else { skillsList = agent.skillRegistry.list(); } if (skillsList.length === 0) { console.log(" No skills registered."); return; } console.log(`\n Skills (${skillsList.length}):`); for (const sk of skillsList) { console.log( ` ${sk.id.padEnd(24)} v${sk.version.padEnd(6)} ${String(sk.metrics.totalExecutions).padStart(3)} runs ${sk.name}` ); } console.log(` `); }); skills .command("create ") .description("Create a new skill from a template") .requiredOption("-d, --description ", "Skill description") .option("-s, --steps ", "Comma-separated step labels") .option("-t, --tags ", "Comma-separated tags") .action((name: string, opts: { description: string; steps?: string; tags?: string }) => { const agent = new MetaAgent(); const stepLabels = opts.steps?.split(",").map((s) => s.trim()) ?? [ "Analyze requirements", "Plan approach", "Execute", "Verify results", "Reflect", ]; const skill = agent.skillRegistry.createFromTemplate({ name, description: opts.description, steps: stepLabels.map((label) => ({ label, instruction: `Execute step: ${label}`, expectedOutcome: `Completed: ${label}`, })), tags: opts.tags?.split(",").map((t) => t.trim()) ?? ["general"], }); console.log(`\n ✓ Skill created: ${skill.id} v${skill.version}`); console.log(` Steps: ${skill.steps.length}`); console.log(` Tags: ${skill.tags.join(", ")}`); console.log(` `); }); skills .command("inspect ") .description("View skill details and execution history") .action((id: string) => { const agent = new MetaAgent(); const skill = agent.skillRegistry.get(id); if (!skill) { console.error(` ✗ Skill not found: ${id}`); process.exit(1); } console.log(`\n Skill: ${skill.name} (${skill.id})`); console.log(` ─────────────────────────────`); console.log(` Version: ${skill.version}`); console.log(` Description: ${skill.description}`); console.log(` Tags: ${skill.tags.join(", ")}`); console.log(` `); console.log(` Steps:`); for (const step of skill.steps) { console.log(` ${step.id}: ${step.label}`); if (step.validationCriteria.length > 0) { console.log(` Validates: ${step.validationCriteria.join(", ")}`); } } console.log(` `); console.log(` Metrics:`); console.log(` Executions: ${skill.metrics.totalExecutions}`); console.log(` Avg duration: ${Math.round(skill.metrics.avgDurationMs / 1000)}s`); console.log(` Avg quality: ${skill.metrics.avgQualityScore.toFixed(2)}`); console.log(` Success rate: ${(skill.metrics.successRate * 100).toFixed(0)}%`); console.log(` Evolutions: ${skill.metrics.evolutionCount}`); if (skill.history.length > 0) { console.log(` `); console.log(` Recent executions:`); for (const h of skill.history.slice(-5).reverse()) { const date = new Date(h.completedAt).toISOString().slice(0, 16); console.log( ` ${date} ${h.success ? "✓" : "✗"} q=${h.qualityScore.toFixed(2)} ${h.issues.length} issues` ); } } console.log(` `); }); skills .command("evolve ") .description("Analyze and auto-improve a skill") .action((id: string) => { const agent = new MetaAgent(); const { evolved, changes, report } = agent.routineEvolution.autoEvolve(id); console.log(`\n Evolution Report for "${id}":`); console.log(` ─────────────────────────────`); console.log(` Analyzable: ${report.analyzable}`); console.log(` Score: ${report.score}/100`); if (report.trend) console.log(` Trend: ${report.trend}`); if (report.findings.length > 0) { console.log(` `); console.log(` Findings:`); for (const f of report.findings) console.log(` • ${f}`); } if (evolved) { console.log(` `); console.log(` ✓ Applied ${changes.length} change(s):`); for (const c of changes) { console.log(` • ${c.type}: ${c.description}`); } } else { console.log(` No changes applied: ${report.reason ?? "skill is healthy"}`); } console.log(` `); }); skills .command("sharpen") .description("Run meta-review on all skills with execution history") .action(() => { const agent = new MetaAgent(); const reviews = agent.skillSharpener.reviewAll(); if (reviews.length === 0) { console.log(" No skills with execution history to review."); return; } console.log(`\n Skill Sharpener Review (${reviews.length} skills):`); console.log(` ─────────────────────────────`); for (const review of reviews) { const skill = agent.skillRegistry.get(review.skillId); console.log(` ${skill?.name ?? review.skillId}`); console.log(` Score: ${review.score}/100`); console.log(` Findings: ${review.findings.length}`); for (const f of review.findings) console.log(` • ${f}`); if (review.suggestedChanges.length > 0) { console.log(` Suggestions: ${review.suggestedChanges.length}`); for (const c of review.suggestedChanges.slice(0, 2)) { console.log(` → ${c.type}: ${c.description.slice(0, 80)}`); } } console.log(` `); } }); // ── State / Knowledge Base ────────────────────────────────── program .command("state") .description("View accumulated state knowledge base") .option("-t, --tag ", "Filter by tag") .option("--stats", "Show statistics only") .action((opts: { tag?: string; stats?: boolean }) => { const agent = new MetaAgent(); if (opts.stats) { const stats = agent.stateRepository.getStats(); console.log(`\n Knowledge Base Stats:`); console.log(` ─────────────────────────────`); console.log(` Total entries: ${stats.totalEntries}`); console.log(` By type:`); for (const [type, count] of Object.entries(stats.byType)) { console.log(` ${type}: ${count}`); } console.log(` Top tags: ${stats.topTags.join(", ")}`); console.log(` Avg score: ${stats.avgScore.toFixed(2)}`); } else if (opts.tag) { const entries = agent.stateRepository.findByTag(opts.tag, 10); if (entries.length === 0) { console.log(` No entries with tag "${opts.tag}".`); return; } console.log(`\n Entries tagged "${opts.tag}" (${entries.length}):`); for (const e of entries) { console.log(` [${e.type}] ${e.content.slice(0, 100)}`); } } else { const stats = agent.stateRepository.getStats(); console.log(`\n Knowledge Base: ${stats.totalEntries} entries`); console.log(` Tags: ${stats.topTags.join(", ")}`); console.log(` Run with --tag to view entries, --stats for details`); } console.log(` `); }); // ── PAI Integration ───────────────────────────────────────── const pai = program .command("pai") .description("PAI integration commands"); pai .command("status") .description("Check PAI integration health") .action(async () => { const { PaiConnector } = await import("./pai/pai-connector.js"); const { ProxyClient } = await import("./pai/proxy-client.js"); const { TelosBridge } = await import("./pai/telos-bridge.js"); const connector = new PaiConnector(); const proxy = new ProxyClient(); const telos = new TelosBridge(); console.log(`\n PAI Integration Status`); console.log(` ─────────────────────────────`); const ctx = connector.loadAll(); console.log(` TELOS files: ${ctx.telos.length}`); console.log(` PAI skills: ${ctx.skills.length}`); console.log(` ISA sessions: ${ctx.isa ? 1 : 0}`); const proxyOk = await proxy.health(); console.log(` Proxy (:18901): ${proxyOk ? "✓ online" : "✗ offline"}`); if (proxyOk) { try { const models = await proxy.listModels(); console.log(` Available models: ${models.length}`); for (const m of models.slice(0, 5)) { console.log(` ${m}`); } if (models.length > 5) console.log(` ... and ${models.length - 5} more`); } catch { console.log(` Models: unable to list`); } } const telosSections = telos.getAllSectionNames(); console.log(` TELOS sections: ${telosSections.length > 0 ? telosSections.join(", ") : "none"}`); console.log(` `); }); pai .command("telos") .description("Load PAI TELOS context") .option("-s, --section ", "Specific section to load") .action(async (opts: { section?: string }) => { const { PaiConnector } = await import("./pai/pai-connector.js"); const connector = new PaiConnector(); if (opts.section) { const content = connector.readFile(`USER/TELOS/${opts.section}.md`); if (!content) { console.error(` ✗ TELOS section not found: ${opts.section}`); process.exit(1); } console.log(`\n TELOS: ${opts.section}`); console.log(` ─────────────────────────────`); console.log(content.slice(0, 2000)); console.log(` `); return; } const ctx = connector.loadAll(); console.log(`\n PAI Context loaded:`); console.log(` ─────────────────────────────`); console.log(` TELOS documents (${ctx.telos.length}):`); for (const t of ctx.telos) { const preview = t.content.replace(/\n/g, " ").slice(0, 80); console.log(` ${t.name}: ${preview}...`); } console.log(` PAI skills (${ctx.skills.length}):`); for (const s of ctx.skills) { console.log(` ${s.name}: ${s.description.slice(0, 60)}`); } console.log(` `); }); pai .command("proxy") .description("Test proxy model completion") .argument("", "Prompt to send") .option("-m, --model ", "Model ID (default: fi-groq)") .option("-t, --temperature ", "Temperature", parseFloat) .option("-s, --system ", "System prompt") .action(async (prompt: string, opts: { model?: string; temperature?: number; system?: string }) => { const { ProxyClient } = await import("./pai/proxy-client.js"); const proxy = new ProxyClient(); const ok = await proxy.health(); if (!ok) { console.error(" ✗ Proxy is not running on :18901. Start it first."); process.exit(1); } console.log(`\n Proxy completion:`); console.log(` Model: ${opts.model ?? "fi-groq"}`); console.log(` Prompt: ${prompt.slice(0, 100)}${prompt.length > 100 ? "…" : ""}`); console.log(` ─────────────────────────────`); try { const result = await proxy.complete(prompt, opts.model, { temperature: opts.temperature, systemPrompt: opts.system, }); console.log(` Response:`); console.log(` ${result.content}`); console.log(` `); console.log(` Tokens: ${result.usage.totalTokens} (${result.usage.promptTokens} prompt + ${result.usage.completionTokens} completion)`); console.log(` Model: ${result.model}`); console.log(` `); } catch (err) { console.error(` ✗ ${err instanceof Error ? err.message : String(err)}`); process.exit(1); } }); pai .command("sync") .description("Sync PAI skills into skill registry") .action(async () => { const { SkillSync } = await import("./pai/skill-sync.js"); const { MetaAgent } = await import("./tier3-compounding/meta-agent.js"); const syncer = new SkillSync(); const agent = new MetaAgent(); const paiSkills = syncer.findAllPaiSkills(); if (paiSkills.length === 0) { console.log(" No PAI skills found to sync."); return; } const definitions = syncer.toSkillDefinitions(paiSkills); let imported = 0; for (const def of definitions) { const existing = agent.skillRegistry.get(def.id); if (existing) { console.log(` ↻ Already synced: ${def.name} (${def.id})`); continue; } agent.skillRegistry.register(def); imported++; } console.log(`\n ✓ Synced ${imported}/${definitions.length} PAI skills into skill registry`); console.log(` `); }); pai .command("dream") .description("Run dream cycle and write insights to TELOS") .option("-c, --cycle ", "Cycle number", parseInt) .option("--dry-run", "Show what would be written without writing") .action(async (opts: { cycle?: number; dryRun?: boolean }) => { const { MetaAgent } = await import("./tier3-compounding/meta-agent.js"); const { DreamingSystem } = await import("./upgrades/dreaming-system.js"); const { TelosBridge } = await import("./pai/telos-bridge.js"); const agent = new MetaAgent(); const state = agent.stateRepository; const allKnowledge = state.query({ limit: 100 }); if (allKnowledge.length < 3) { console.error(` ✗ Need at least 3 knowledge entries to dream (have ${allKnowledge.length})`); process.exit(1); } const dreaming = new DreamingSystem(agent.skillRegistry, agent.store); const telos = new TelosBridge(); const dummyIterations: import("./core/types.js").LoopIteration[] = allKnowledge.slice(-5).map((k, i) => ({ number: i + 1, phase: "reflect" as const, reflection: k.content, metrics: { qualityScore: k.score, successRate: k.score > 0.5 ? 0.8 : 0.3, improvementDelta: k.score - 0.5, durationMs: 1000, }, timestamp: new Date().toISOString(), })); const cycleNumber = opts.cycle ?? 1; if (opts.dryRun) { console.log(`\n Dry run — dream cycle #${cycleNumber}`); console.log(` Would create dream from ${dummyIterations.length} iterations`); console.log(` Would write to TELOS/_dreams/`); console.log(` `); return; } try { const dream = dreaming.dream("pai-session", dummyIterations, cycleNumber); const path = telos.writeDreamInsights(dream); console.log(`\n ✓ Dream cycle #${cycleNumber} complete`); console.log(` Patterns: ${dream.patterns.length}`); console.log(` Insights: ${dream.distillations.length}`); console.log(` Dreams: ${dream.dreams.length}`); console.log(` Written to: ${path}`); console.log(` `); } catch (err) { console.error(` ✗ ${err instanceof Error ? err.message : String(err)}`); process.exit(1); } }); pai .command("cert") .description("Run certification: ISA → run → ISA → verify cycle") .option("-t, --task ", "Task description for the run") .option("-l, --loop ", "Loop iterations", parseInt) .option("--skip-proxy-check", "Skip proxy health check") .action(async (opts: { task?: string; loop?: number; skipProxyCheck?: boolean }) => { const { PaiConnector } = await import("./pai/pai-connector.js"); const { ProxyClient } = await import("./pai/proxy-client.js"); const { IsaWriter } = await import("./pai/isa-writer.js"); const { MetaAgent } = await import("./tier3-compounding/meta-agent.js"); if (!opts.skipProxyCheck) { const proxy = new ProxyClient(); const ok = await proxy.health(); if (!ok) { console.error(" ✗ Proxy not running. Use --skip-proxy-check to bypass."); process.exit(1); } } const task = opts.task ?? "Run PAI certification cycle — build, test, verify, reflect"; const agent = new MetaAgent(); const connector = new PaiConnector(); const isaWriter = new IsaWriter(); const ctx = connector.loadAll(); const sessionDir = isaWriter.createSessionDir("pai-cert-cycle"); isaWriter.writeIsa(sessionDir, { title: `PAI Certification — ${new Date().toISOString().slice(0, 16)}`, sections: [ { title: "Problem", content: task }, { title: "Vision", content: "A self-certifying agent system that validates its own outputs" }, { title: "Context", content: `TELOS docs: ${ctx.telos.length}, PAI skills: ${ctx.skills.length}` }, { title: "Execution", content: "Pending run" }, ], }); console.log(`\n PAI Certification Cycle`); console.log(` ─────────────────────────────`); console.log(` Task: ${task}`); console.log(` ISA: ${sessionDir}`); console.log(` `); const result = await agent.run(task, { loopIterations: opts.loop ?? 3, }); isaWriter.updateSection(sessionDir, "Execution", `Completed ${result.loopIterations} iterations, converged=${result.converged}\n` + `Knowledge entries: ${result.knowledgeEntryCount}` ); console.log(` ✓ Certification run complete`); console.log(` Iterations: ${result.loopIterations}`); console.log(` Converged: ${result.converged}`); console.log(` ISA updated: ${sessionDir}`); console.log(` `); }); pai .command("bridge") .description("Sync PAI TELOS → FA rubric engine") .action(async () => { const { TELOSBridge } = await import("./pai/pai-fa-bridge.js"); const bridge = new TELOSBridge(); const entries = bridge.scan(); const rubric = bridge.toRubric(); console.log(`\n PAI → FA TELOS Bridge:`); console.log(` Entries found: ${entries.length}`); console.log(` Rubric criteria: ${rubric.criteria.length}`); console.log(` Exit conditions: ${rubric.exitConditions.length}\n`); }); pai .command("memory") .description("Sync PAI memory → FA persistent memory") .action(async () => { const { EnhancedMetaAgent } = await import("./upgrades/enhanced-meta-agent.js"); const { PAIMemoryBridge } = await import("./pai/pai-fa-bridge.js"); const agent = new EnhancedMetaAgent(); const bridge = new PAIMemoryBridge(agent); const result = bridge.importMemory(); console.log(`\n PAI → FA Memory Sync:`); console.log(` Episodic: ${result.episodic}`); console.log(` Semantic: ${result.semantic}\n`); }); pai .command("packs") .description("Import PAI skill packs → FA skill registry") .action(async () => { const { MetaAgent } = await import("./tier3-compounding/meta-agent.js"); const { PAISkillBridge } = await import("./pai/pai-fa-bridge.js"); const agent = new MetaAgent(); const bridge = new PAISkillBridge(agent.skillRegistry); const result = bridge.importPacks(); console.log(`\n PAI → FA Skill Pack Import:`); console.log(` Created: ${result.created}`); if (result.errors.length > 0) console.log(` Errors: ${result.errors.length}\n`); }); pai .command("report") .description("Show PAI+FA integration report") .action(async () => { const { paiFAReport } = await import("./pai/pai-fa-bridge.js"); console.log(`\n${paiFAReport()}\n`); }); pai .command("run ") .description("Run a PAI goal through FA's engine") .action(async (goal: string) => { const { EnhancedMetaAgent } = await import("./upgrades/enhanced-meta-agent.js"); const { TELOSBridge, PAIMemoryBridge } = await import("./pai/pai-fa-bridge.js"); const agent = new EnhancedMetaAgent(); const telos = new TELOSBridge(); // Load PAI TELOS context const entries = telos.scan(); const matching = entries.filter((e) => goal.toLowerCase().includes(e.description.slice(0, 20).toLowerCase()) ); if (matching.length > 0) { agent.context.add({ source: "pai-telos", content: `Related PAI ${matching[0].type}: ${matching[0].description}`, priority: "high", tokenCount: matching[0].description.length, }); } // Import PAI memory for context const memBridge = new PAIMemoryBridge(agent); memBridge.importMemory(); // Run through FA engine const result = await agent.run(goal, { loopIterations: 8 }); console.log(`\n PAI Goal → FA Engine:`); console.log(` Goal: ${goal}`); console.log(` Iterations: ${result.iterations}`); console.log(` Converged: ${result.converged}`); if (result.rubricScore) console.log(` Rubric: ${result.rubricScore}/100`); console.log(``); }); // ── Status ────────────────────────────────────────────────── program .command("status") .description("Show system status overview") .action(() => { const agent = new MetaAgent(); const status = agent.getStatus(); console.log(`\n Fable Agent System Status`); console.log(` ─────────────────────────────`); console.log(` Active session: ${status.activeSession ?? "none"}`); console.log(` Skills: ${status.skills.total} total, ${status.skills.withHistory} with execution history`); console.log(` Knowledge base: ${status.knowledge.entries} entries, ${status.knowledge.tags.length} tags`); console.log(` Context: ${status.context.pct}% of ${status.context.budget.toLocaleString()} token budget`); console.log(` Uptime: ${Math.round(status.uptime)}s`); console.log(` Compound runs: ${status.compoundIterations}`); console.log(` `); }); // ── Workflow ──────────────────────────────────────────────── program .command("workflow") .description("Workflow management") .argument("", "Path to workflow JSON definition") .action(async (file: string) => { const agent = new MetaAgent(); try { const data = fs.readFileSync(file, "utf-8"); const definition = JSON.parse(data); agent.workflowGraph.register(definition); console.log(`\n ✓ Workflow registered: ${definition.name} (${definition.id})`); console.log(` Steps: ${definition.steps.length}`); console.log(` `); } catch (err) { console.error(` ✗ Failed to load workflow: ${err instanceof Error ? err.message : String(err)}`); process.exit(1); } }); // ── Benchmark ──────────────────────────────────────────────── const benchmark = program .command("benchmark") .description("Run benchmarks and measure compounding"); benchmark .command("run") .description("Run all benchmarks and show report") .option("-b, --benchmark ", "Run a specific benchmark by ID") .action(async (opts: { benchmark?: string }) => { const { EnhancedMetaAgent } = await import("./upgrades/enhanced-meta-agent.js"); const { BenchmarkRunner } = await import("./upgrades/benchmark-runner.js"); const agent = new EnhancedMetaAgent(); const runner = new BenchmarkRunner(agent); if (opts.benchmark) { await runner.runOne(opts.benchmark); } else { await runner.runAll(); } console.log(`\n${runner.report(opts.benchmark)}\n`); }); benchmark .command("agents ") .description("Run the same prompt against Pi, Hermes, and OpenCode") .option("--with ", "Contenders: pi,hermes,opencode", "pi,hermes,opencode") .option("--timeout-ms ", "Timeout per contender", (v) => Number(v), 120000) .option("--harnesses ", "JSON harness config: array or { harnesses: [...] }") .option("--out ", "Receipt output path") .action(async (task: string, opts: { with?: string; timeoutMs?: number; harnesses?: string; out?: string }) => { const { loadBenchHarnesses, runAgentBench, writeAgentBenchReceipt } = await import("./fable5/agent-bench.js"); const contenders = (opts.with ?? "pi,hermes,opencode").split(",").map((s) => s.trim()).filter(Boolean); const harnesses = opts.harnesses ? loadBenchHarnesses(path.resolve(opts.harnesses)) : undefined; const receipt = await runAgentBench({ task, contenders, harnesses, timeoutMs: opts.timeoutMs }); const stamp = new Date().toISOString().replace(/[:.]/g, "-"); const out = opts.out ?? path.join(".fable", "agent-bench", stamp + ".json"); writeAgentBenchReceipt(out, receipt); console.log(JSON.stringify(receipt, null, 2)); console.log("\n Receipt: " + out + "\n"); if (receipt.winner === "none") process.exit(1); }); benchmark .command("duel ") .description("Record a two-implementer eval winner") .requiredOption("--a