From 3ceb9912009a9b4a41beb7d248e0d9b1f4683d48 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Fri, 6 Mar 2026 22:23:50 +0100 Subject: [PATCH] fix: errand output race condition + require commit before signal Merge two useEffects in AgentOutputViewer into one to fix race where agentId reset clears messages after data effect sets them on remount. Add "commit before signaling" instruction to errand prompts so Changes tab shows diff after completion. --- apps/server/agent/prompts/errand.ts | 2 ++ apps/web/src/components/AgentOutputViewer.tsx | 17 +++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/server/agent/prompts/errand.ts b/apps/server/agent/prompts/errand.ts index f995aae..ca1d665 100644 --- a/apps/server/agent/prompts/errand.ts +++ b/apps/server/agent/prompts/errand.ts @@ -4,6 +4,7 @@ export function buildErrandPrompt(description: string): string { Description: ${description} Work interactively with the user. Make only the changes needed to fulfill the description. +Before signaling completion, commit all your changes with a clear commit message describing what you did. Do not leave uncommitted work. When you are done, write .cw/output/signal.json: { "status": "done", "result": { "message": "" } } @@ -25,6 +26,7 @@ The user reviewed your changes and requested revisions: ${feedback} Make only the changes needed to address the feedback. Do not undo prior work unless the feedback specifically asks for it. +Before signaling completion, commit all your changes with a clear commit message describing what you did. Do not leave uncommitted work. When you are done, write .cw/output/signal.json: { "status": "done", "result": { "message": "" } } diff --git a/apps/web/src/components/AgentOutputViewer.tsx b/apps/web/src/components/AgentOutputViewer.tsx index 447073a..78abece 100644 --- a/apps/web/src/components/AgentOutputViewer.tsx +++ b/apps/web/src/components/AgentOutputViewer.tsx @@ -53,21 +53,18 @@ export function AgentOutputViewer({ agentId, agentName, status, onStop }: AgentO } ); - // Set initial output when query loads - useEffect(() => { - if (outputQuery.data) { - chunksRef.current = outputQuery.data; - setMessages(parseAgentOutput(outputQuery.data)); - } - }, [outputQuery.data]); - - // Reset output when agent changes + // Reset on agent change, then hydrate from query cache useEffect(() => { chunksRef.current = []; setMessages([]); setFollow(true); setExpandedResults(new Set()); - }, [agentId]); + + if (outputQuery.data) { + chunksRef.current = outputQuery.data; + setMessages(parseAgentOutput(outputQuery.data)); + } + }, [agentId, outputQuery.data]); // Auto-scroll to bottom when following useEffect(() => {