feat: visualize governed goal progress live

This commit is contained in:
thanhnv
2026-07-18 10:19:26 +07:00
parent efb5a62f29
commit 049f0c9b04
3 changed files with 127 additions and 31 deletions
@@ -5,7 +5,7 @@ import { api, type GoalJob, type SettingsActor } from '../lib/api';
import { Card, StatusBadge } from '../components/ui/Card';
import { TraceExplorer } from '../components/trace/TraceExplorer';
import { MarkdownText } from '../components/ui/MarkdownText';
import { ModelInteractionDiagram } from '../components/goals/ModelInteractionDiagram';
import { GovernedOutcomePulse, ModelInteractionDiagram } from '../components/goals/ModelInteractionDiagram';
const DEFAULT_ACTOR: SettingsActor = { actor: 'local-operator', role: 'org-admin', project: 'default', tenant: 'default' };
const TERMINAL = new Set<GoalJob['status']>(['completed', 'degraded', 'failed', 'requires_approval']);
@@ -69,6 +69,12 @@ export function Goals() {
return current && TERMINAL.has(current.status) ? false : 1500;
},
});
const traceQuery = useQuery({
queryKey: ['goal-trace', selectedId],
queryFn: () => api.traceGraph(selectedQuery.data!.trace_id),
enabled: Boolean(selectedQuery.data?.trace_id),
refetchInterval: (query) => query.state.data?.terminal ? false : 1200,
});
const start = useMutation({
mutationFn: () => api.startGoal({ ...actor, project: effectiveProject }, goal.trim(), effectiveProject),
onSuccess: (job) => {
@@ -178,9 +184,10 @@ export function Goals() {
<WorkerCard title="Cloud reviewer" subtitle="Independent critique and refinement" status={cloudStage?.status ?? 'queued'} detail={cloudStage?.detail ?? 'Waiting'} provider={cloudStage?.provider ?? selected.cloud_provider} model={cloudStage?.model ?? selected.cloud_model} />
</div>
<ModelInteractionDiagram goal={selected} localStage={localStage} cloudStage={cloudStage} />
<ModelInteractionDiagram goal={selected} localStage={localStage} cloudStage={cloudStage} trace={traceQuery.data} />
<Card title="Governed outcome" right={<StatusBadge value={selected.status} />}>
<GovernedOutcomePulse goal={selected} trace={traceQuery.data} />
{selected.workspace && <div className="mb-4 flex flex-wrap items-center gap-2 rounded-xl border border-indigo-200 bg-indigo-50 p-3 text-xs text-indigo-900"><strong>{selected.workspace.domain}</strong><span>·</span><span className="font-mono">{selected.workspace.project_id}</span>{selected.context_manifest && <><span>·</span><span>{selected.context_manifest.files} files / {selected.context_manifest.characters} chars</span>{selected.context_manifest.truncated && <StatusBadge value="bounded snapshot" />}</>}</div>}
<div className="rounded-xl border border-slate-200 bg-slate-50 p-4">
<div className="text-xs font-semibold uppercase tracking-[0.12em] text-slate-400">Objective</div>