fix: show structured-output summary instead of raw JSON in OUTCOME

A --json-schema run can echo the structured {"summary":...} JSON as the
result text, which then landed verbatim in task.Result and rendered raw in
the OUTCOME card. Unwrap the summary in StreamAnalyzer when the result text
is itself such a JSON object (a plain markdown result is kept as-is), and
add a UI safety net in ApplyOutcome for rows already persisted as raw JSON.
This commit is contained in:
mika kuns
2026-07-24 11:36:25 +02:00
parent f4dd67d595
commit 8a7275a75f
2 changed files with 48 additions and 7 deletions
@@ -1,5 +1,6 @@
using System.Collections.ObjectModel;
using System.Text;
using System.Text.Json;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ClaudeDo.Data;
@@ -258,16 +259,38 @@ public sealed partial class TaskMonitorViewModel : ViewModelBase, IMissionContro
var idx = result.IndexOf(RoadblockMarker, StringComparison.Ordinal);
if (idx < 0)
{
SessionOutcome = result;
SessionOutcome = UnwrapSummary(result);
Roadblocks = null;
return;
}
var summary = result[..idx].TrimEnd().TrimEnd('⚠').TrimEnd();
SessionOutcome = string.IsNullOrWhiteSpace(summary) ? null : summary;
SessionOutcome = string.IsNullOrWhiteSpace(summary) ? null : UnwrapSummary(summary);
Roadblocks = result[(idx + RoadblockMarker.Length)..].Trim();
}
/// <summary>Safety net for older rows persisted as raw structured-output JSON: if the outcome
/// is a JSON object with a string <c>summary</c>, show that; otherwise keep the text as-is.</summary>
private static string? UnwrapSummary(string? text)
{
if (string.IsNullOrWhiteSpace(text)) return text;
var trimmed = text.TrimStart();
if (trimmed.Length == 0 || trimmed[0] != '{') return text;
try
{
using var doc = JsonDocument.Parse(trimmed);
if (doc.RootElement.ValueKind == JsonValueKind.Object &&
doc.RootElement.TryGetProperty("summary", out var s) &&
s.ValueKind == JsonValueKind.String)
{
var summary = s.GetString();
if (!string.IsNullOrWhiteSpace(summary)) return summary;
}
}
catch { }
return text;
}
public async System.Threading.Tasks.Task ReplayLogFileAsync(string? logPath, CancellationToken ct)
{
if (string.IsNullOrWhiteSpace(logPath)) return;