Update codereview tool UI to show different icons based on result content

Added cross-linking comments between the UI component and differential.go
to ensure they stay in sync going forward.

Co-Authored-By: sketch <hello@sketch.dev>
diff --git a/claudetool/differential.go b/claudetool/differential.go
index 1974174..386086a 100644
--- a/claudetool/differential.go
+++ b/claudetool/differential.go
@@ -38,6 +38,8 @@
 }
 
 func (r *CodeReviewer) Run(ctx context.Context, m json.RawMessage) (string, error) {
+	// NOTE: If you add or modify error messages here, update the corresponding UI parsing in:
+	// webui/src/web-components/sketch-tool-card.ts (SketchToolCardCodeReview.getStatusIcon)
 	if err := r.RequireNormalGitState(ctx); err != nil {
 		slog.DebugContext(ctx, "CodeReviewer.Run: failed to check for normal git state", "err", err)
 		return "", err
@@ -86,7 +88,6 @@
 
 	// Find potentially related files that should also be considered
 	// TODO: add some caching here, since this depends only on the initial commit and the changed files, not the details of the changes
-	// TODO: make "related files found" w/o other notes be a non-error response
 	relatedFiles, err := r.findRelatedFiles(ctx, changedFiles)
 	if err != nil {
 		slog.DebugContext(ctx, "CodeReviewer.Run: failed to find related files", "err", err)
@@ -115,6 +116,8 @@
 		errorMessages = append(errorMessages, goplsMsg)
 	}
 
+	// NOTE: If you change this output format, update the corresponding UI parsing in:
+	// webui/src/web-components/sketch-tool-card.ts (SketchToolCardCodeReview.getStatusIcon)
 	buf := new(strings.Builder)
 	if len(infoMessages) > 0 {
 		buf.WriteString("# Info\n\n")
diff --git a/webui/src/web-components/sketch-tool-card.ts b/webui/src/web-components/sketch-tool-card.ts
index c90c55d..fdcebae 100644
--- a/webui/src/web-components/sketch-tool-card.ts
+++ b/webui/src/web-components/sketch-tool-card.ts
@@ -360,16 +360,30 @@
   disconnectedCallback() {
     super.disconnectedCallback();
   }
+  // Determine the status icon based on the content of the result message
+  // This corresponds to the output format in claudetool/differential.go:Run
+  getStatusIcon(resultText: string): string {
+    if (!resultText) return "";
+    if (resultText === "OK") return "✔️";
+    if (resultText.includes("# Errors")) return "⛔";
+    if (resultText.includes("# Info")) return "ℹ️";
+    if (resultText.includes("uncommitted changes in repo")) return "🧹";
+    if (resultText.includes("no new commits have been added")) return "🐣";
+    if (resultText.includes("git repo is not clean")) return "🧼";
+    return "❓";
+  }
+
   render() {
+    const resultText = this.toolCall?.result_message?.tool_result || "";
+    const statusIcon = this.getStatusIcon(resultText);
+
     return html` <sketch-tool-card
       .open=${this.open}
       .toolCall=${this.toolCall}
     >
-      <span slot="summary" class="summary-text">
-        ${this.toolCall?.result_message?.tool_result == "OK" ? "✔️" : "⛔"}
-      </span>
+      <span slot="summary" class="summary-text"> ${statusIcon} </span>
       <div slot="result">
-        <pre>${this.toolCall?.result_message?.tool_result}</pre>
+        <pre>${resultText}</pre>
       </div>
     </sketch-tool-card>`;
   }