// Agent editor — opens from the Agents list. Tabs: Dashboard, Instructions, // Skills, Configuration, Runs, Budget. Reuses shared atoms from settings.jsx. const { Field, Switch, Seg, SectionHead, Panel } = window; // ---------- Per-agent detail ---------- // model.paid drives whether the Budget tab shows spend or a "self-hosted" note. const AGENT_DETAIL = { installer: { label: 'Installer', avatarBg: 'oklch(0.6 0.16 280)', role: 'Installs, upgrades and rolls back workspace modules with full dependency resolution.', model: 'claude-sonnet-4', provider: 'Anthropic', paid: true, ctx: '200K', priceIn: 3.0, priceOut: 15.0, stats: { tasks: 42, success: 97.6, avgDur: '1m 48s', tokens: '4.1M', uptime: '99.98%', heartbeat: '4s ago' }, instructions: `You install and upgrade modules in the workspace registry. Operating rules • Resolve the full dependency graph before touching any files. Refuse if a peer constraint cannot be satisfied. • Verify the package signature against the registry's signing key. Never install an unsigned or "labs" package onto production. • Any task that affects the database MUST be routed to Review before it runs. • Emit a structured plan (added / changed / removed) and wait for the orchestrator's go signal in supervised mode. On failure, hand off to rollback-agent with the partial-change manifest.`, skills: [ { id: 'depres', name: 'Dependency resolution', desc: 'SAT-solves the peer + semver graph before applying.', on: true, scope: 'core' }, { id: 'semver', name: 'Semver planning', desc: 'Computes safe upgrade paths and flags breaking majors.', on: true, scope: 'core' }, { id: 'sigverify', name: 'Signature verification', desc: 'Validates package signatures against the registry key.', on: true, scope: 'security' }, { id: 'rollback', name: 'Rollback on failure', desc: 'Reverts partial installs and notifies rollback-agent.', on: true, scope: 'core' }, { id: 'dryrun', name: 'Dry-run preview', desc: 'Produces an added/changed/removed diff before writing.', on: false, scope: 'beta' }, ], runTitles: ['Install auth@2.4.0', 'Bump next@15.3', 'Install blog@0.8.4', 'Update tickets@3.0.1', 'Install analytics@0.4.0', 'Install billing@1.2.0', 'Patch citext extension', 'Re-link audit module'], budget: { limit: 400, spent: 247.8, alertAt: 80 }, }, tester: { label: 'Tester', avatarBg: 'oklch(0.62 0.15 200)', role: 'Runs regression, integration and smoke suites against staging before promotion.', model: 'claude-haiku-3.5', provider: 'Anthropic', paid: true, ctx: '200K', priceIn: 0.8, priceOut: 4.0, stats: { tasks: 128, success: 94.1, avgDur: '52s', tokens: '9.7M', uptime: '99.95%', heartbeat: '2s ago' }, instructions: `You validate changes before they reach production. Operating rules • Run the smallest sufficient suite first (smoke), escalate to full regression only on green. • Quarantine flaky assertions after 2 inconsistent runs and report them — never silently retry forever. • Report a coverage delta and the slowest 5 assertions on every run. • Block promotion if any payment- or auth-tagged test fails, regardless of overall pass rate.`, skills: [ { id: 'regress', name: 'Regression suites', desc: 'Executes the full assertion catalog on staging.', on: true, scope: 'core' }, { id: 'flaky', name: 'Flake detection', desc: 'Identifies and quarantines non-deterministic tests.', on: true, scope: 'core' }, { id: 'cov', name: 'Coverage delta', desc: 'Reports line/branch coverage change per task.', on: true, scope: 'core' }, { id: 'perf', name: 'Perf budgets', desc: 'Fails runs that regress p95 latency past budget.', on: false, scope: 'beta' }, ], runTitles: ['Regression suite · staging.zeny', 'Rebuild KB embeddings', 'Smoke test billing webhooks', 'Integration · auth+tickets', 'Regression · vidix', 'Load test autoscaler', 'Contract tests · API v14'], budget: { limit: 250, spent: 88.4, alertAt: 80 }, }, reviewer: { label: 'Reviewer', avatarBg: 'oklch(0.62 0.18 320)', role: 'Reviews diffs and migrations, summarizes risk, and requests human approval.', model: 'claude-opus-4', provider: 'Anthropic', paid: true, ctx: '200K', priceIn: 15.0, priceOut: 75.0, stats: { tasks: 31, success: 100, avgDur: '2m 36s', tokens: '2.3M', uptime: '100%', heartbeat: '7s ago' }, instructions: `You are the last automated gate before a human approves a change. Operating rules • Summarize intent, blast radius and rollback path in <= 6 bullets. Lead with the riskiest finding. • Flag any change touching billing, auth, or PII for mandatory human approval. • Never approve on the author's behalf — produce a recommendation, then move the task to Review. • Link every claim to a file + line in the diff.`, skills: [ { id: 'diff', name: 'Diff analysis', desc: 'Reads multi-file diffs and reasons about blast radius.', on: true, scope: 'core' }, { id: 'risk', name: 'Risk scoring', desc: 'Assigns a 0–100 risk score with rationale.', on: true, scope: 'core' }, { id: 'pii', name: 'PII / secret scan', desc: 'Detects credentials and personal data in diffs.', on: true, scope: 'security' }, { id: 'rollbackplan', name: 'Rollback drafting', desc: 'Writes the revert plan attached to each approval.', on: true, scope: 'core' }, ], runTitles: ['Review Stripe v3 webhooks', 'Review backfill org_id', 'Review KMS rotation', 'Review partition cutover', 'Review autoscaler config'], budget: { limit: 300, spent: 196.5, alertAt: 75 }, }, migrator: { label: 'Migrator', avatarBg: 'oklch(0.65 0.15 150)', role: 'Performs zero-downtime schema migrations and data backfills.', model: 'gpt-4o', provider: 'OpenAI', paid: true, ctx: '128K', priceIn: 2.5, priceOut: 10.0, stats: { tasks: 19, success: 89.5, avgDur: '6m 12s', tokens: '3.4M', uptime: '99.91%', heartbeat: '3s ago' }, instructions: `You execute database migrations using the shadow → read-switch → write-switch pattern. Operating rules • Every phase must be independently reversible. Verify shadow parity >= 99.99% before any read-switch. • Build indexes CONCURRENTLY before the cutover phase, never during. • Acquire an advisory lock for the write-switch and drain in-flight writes before re-pointing the pool. • Migrations always require approval. Halt and page on parity drift below threshold.`, skills: [ { id: 'shadow', name: 'Shadow cutover', desc: 'Runs dual-write shadow tables and verifies parity.', on: true, scope: 'core' }, { id: 'backfill', name: 'Chunked backfill', desc: 'Backfills large tables in throttled batches.', on: true, scope: 'core' }, { id: 'idx', name: 'Concurrent indexing', desc: 'Builds indexes without locking writes.', on: true, scope: 'core' }, { id: 'parity', name: 'Parity probes', desc: 'Runs 50k probe queries to confirm read parity.', on: true, scope: 'core' }, ], runTitles: ['Partition users table', 'Provision read-replica', 'Backfill org_id on invoices', 'Migrate sessions to redis', 'Reshard events table'], budget: { limit: 350, spent: 142.0, alertAt: 80 }, }, sentinel: { label: 'Sentinel', avatarBg: 'oklch(0.65 0.18 30)', role: 'Watches for CVEs and security drift; rotates keys and patches pipelines.', model: 'llama-3.3-70b', provider: 'Self-hosted · 2× A100', paid: false, ctx: '128K', stats: { tasks: 64, success: 98.4, avgDur: '1m 09s', tokens: '12.8M', uptime: '99.99%', heartbeat: '1s ago' }, instructions: `You continuously monitor for security drift and respond to advisories. Operating rules • Triage new CVEs against the dependency manifest within 5 minutes of feed update. • Rotate signing keys on schedule and propagate to all dependent services with zero overlap gaps. • Production deploys generated from a patch always route through Review. • Respect workspace quiet hours for any non-critical change.`, skills: [ { id: 'cve', name: 'CVE triage', desc: 'Matches advisories to the live dependency manifest.', on: true, scope: 'security' }, { id: 'keyrot', name: 'Key rotation', desc: 'Rotates KMS keys and propagates with no overlap gap.', on: true, scope: 'security' }, { id: 'drift', name: 'Config drift watch', desc: 'Detects unexpected changes to prod configuration.', on: true, scope: 'core' }, { id: 'patch', name: 'Auto-patching', desc: 'Drafts and dispatches patch tasks for known CVEs.', on: false, scope: 'beta' }, ], runTitles: ['Rotate KMS keys (us-east-2)', 'Patch CVE-2026-1041', 'Deploy autoscaler config', 'Drift scan · prod-us', 'Rotate webhook secrets'], compute: { gpu: '2× A100 80GB', gpuHours: 612, costModel: 'reserved cluster' }, }, rollback: { label: 'Rollback', avatarBg: 'oklch(0.6 0.14 240)', role: 'Reverts partial or failed changes and restores the last-known-good state.', model: 'claude-haiku-3.5', provider: 'Anthropic', paid: true, ctx: '200K', priceIn: 0.8, priceOut: 4.0, stats: { tasks: 8, success: 100, avgDur: '44s', tokens: '0.6M', uptime: '100%', heartbeat: '5s ago' }, instructions: `You restore the last-known-good state when a task halts mid-flight. Operating rules • Consume the partial-change manifest produced by the failing agent. Never guess at what changed. • Revert in reverse dependency order. Verify each step before proceeding. • Leave the workspace in a state that re-dispatch can safely resume from. • Always emit a post-mortem summary linking the original failure.`, skills: [ { id: 'manifest', name: 'Manifest replay', desc: 'Reverts changes recorded in the partial-change manifest.', on: true, scope: 'core' }, { id: 'snapshot', name: 'Snapshot restore', desc: 'Restores DB/object snapshots to a checkpoint.', on: true, scope: 'core' }, { id: 'postmortem', name: 'Post-mortem draft', desc: 'Writes a timeline of the failure and the revert.', on: true, scope: 'core' }, ], runTitles: ['Revert analytics@0.4.0', 'Restore users snapshot', 'Roll back next@15.3 on vidix'], budget: { limit: 100, spent: 12.3, alertAt: 80 }, }, }; // ---------- helpers ---------- const money = n => '$' + Number(n).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); function seeded(seed, n) { const out = []; let s = seed % 233280 || 1; for (let i = 0; i < n; i++) { s = (s * 9301 + 49297) % 233280; out.push(0.22 + 0.78 * (s / 233280)); } return out; } const RUN_STATUS = ['success', 'success', 'success', 'review', 'success', 'failed', 'success', 'success']; function buildRuns(detail, agentId) { const live = window.ORC_DATA.TASKS.filter(t => t.agent === agentId); const rnd = seeded(agentId.length * 137 + detail.label.charCodeAt(0), 12); return detail.runTitles.map((title, i) => { const status = RUN_STATUS[i % RUN_STATUS.length]; const secs = Math.round(30 + rnd[i] * 360); const tokens = Math.round((40 + rnd[(i + 3) % 12] * 460)) * 1000; const cost = detail.paid ? (tokens / 1e6) * (detail.priceIn * 0.7 + detail.priceOut * 0.3) : 0; const dur = secs >= 60 ? `${Math.floor(secs / 60)}m ${secs % 60}s` : `${secs}s`; return { id: live[i] ? live[i].id : `RUN-${(7421 - i).toString()}`, title, status, dur, tokens, cost, trigger: i % 3 === 0 ? 'scheduled' : i % 3 === 1 ? 'orchestrator' : 'manual', when: ['just now', '6m ago', '22m ago', '1h ago', '2h ago', '3h ago', '5h ago', 'yesterday'][i % 8], }; }); } const runBadge = s => s === 'success' ? 'live' : s === 'review' ? 'review' : s === 'failed' ? 'failed' : 'idle'; const runLabel = s => s === 'success' ? 'success' : s; // ---------- Mini bar chart ---------- function BarChart({ seed, max, unit, accent }) { const bars = seeded(seed, 14); return (
{bars.map((b, i) => (
))}
); } function StatList({ rows }) { return (
{rows.map((r, i) => (
{r[0]} {r[1]}
))}
); } // ---------- Tabs ---------- function AgentDashboard({ detail, agentId, runs, paused }) { const s = detail.stats; const current = window.ORC_DATA.TASKS.find(t => t.agent === agentId && t.column === 'running'); const accentSoft = 'color-mix(in oklch, var(--c-accent) 38%, var(--c-surface-3))'; return (
Tasks · 24h
{s.tasks}
▲ throughput steady
Success rate
{s.success}%
{s.tasks - Math.round(s.tasks * s.success / 100)} non-clean
Avg duration
{s.avgDur}
↓ within budget
Tokens · 24h
{s.tokens}
{detail.model}
tasks / day}>
14d agotoday
{current ? (
{current.id} running {Math.round(current.progress)}%
{current.title}
) : (
{paused ? 'Agent is paused — not accepting new tasks.' : 'Idle — waiting for the orchestrator to dispatch.'}
)}
paused : active], ['Last heartbeat', s.heartbeat], ['Uptime · 30d', s.uptime], ['Model', detail.model], ['Provider', detail.provider], ['Context window', detail.ctx], ]} /> {runs.slice(0, 4).map(r => (
{runLabel(r.status)} {r.title}
{r.dur}
))}
); } function AgentInstructions({ detail, st, set }) { return (
Saved} /> set('role', e.target.value)} /> {st.instructions.length} chars}>