Read workflow-status telemetry from CLI transcript files

Dynamic ultracode workflows run as a detached background task with their
own transcript dir, so their subagent events never flow through the main
-p stream. The previous parent_tool_use_id tap therefore captured nothing
for real workflows and the status stayed "none" the whole run.

Replace the tap with a file-based reader:
- TapWorkflowLaunch parses the "Transcript dir:" line from the Workflow
  tool_result and registers the run.
- WorkflowProgressTracker becomes a per-session registry of transcript
  paths (no longer a stream accumulator).
- WorkflowTelemetryReader reads journal.jsonl for live counts (running)
  and <runId>.json for rich per-agent telemetry (completed); FinalizeChain
  persists the rich JSON into chains.workflow_info.
- Modal renders phases + a per-agent list (label/phase/state/tokens/
  tool-calls/duration) instead of the obsolete tool breakdown.

Sync ARCHITECTURE.md, ARCHITECTURE_QUICK.md and README.md to the new
mechanism.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.8 committed 2026-06-20 18:14:42 +02:00
1 parent b6e546f618
commit 2b95161596
9 files changed
+453 -175

No files matched your search

+12 -1
View File
@@ -329,7 +329,18 @@ public partial class AnthropicService
if (_workflowTracker != null && !string.IsNullOrEmpty(chain.SessionId)
&& _workflowTracker.ChainIdFor(chain.SessionId) == chain.ChainId)
{
chain.WorkflowInfo = _workflowTracker.GetJson(chain.SessionId);
try
{
// Reiche End-Telemetrie aus der wf_<runId>.json des Laufs lesen und persistieren
// (Fallback: Live-Counts aus dem journal.jsonl, falls die json noch nicht da ist).
var wp = WorkflowTelemetryReader.Read(_workflowTracker.Get(chain.SessionId));
if (wp != null)
{
wp.ChainId = chain.ChainId;
chain.WorkflowInfo = JsonSerializer.Serialize(wp);
}
}
catch { /* Persistenz der Telemetrie darf den Finalize nie crashen */ }
_workflowTracker.End(chain.SessionId);
}
return SseHelper.FinalizeChain(_db, chain, usage, iterations, stopReason, sw, streamErrorInfo);