Conversation
The Logs tab was nearly empty during a turn, so it was hard to tell where a slow response (especially on fusion sessions) was spending its time. Surface the cost of CLI cold start, add-dir loading, resume replay, and per-tool execution by stamping the elapsed wallclock at each checkpoint: first stream event, first model text, first tool call, and per-tool done. Turn-started now also reports add-dirs count and resume vs fresh.
Greptile Summary
Confidence Score: 4/5Safe to merge — the change is purely additive logging with no mutations to business logic or state management. Only P2 findings present: the LoggedFirstTool flag firing on TodoWrite/Task before their early break is a cosmetic asymmetry in the Logs tab, not a correctness or data-integrity issue. No P0 or P1 issues identified. No files require special attention; the single changed file is self-contained logging instrumentation. Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as UI Thread
participant CS as ClaudeService
participant TT as TurnTimings (Stopwatch)
participant Log as Logs Tab
UI->>CS: RunTurnAsync()
CS->>TT: new TurnTimings() [timer starts]
CS->>Log: "Turn started (model, branch, add-dirs, fresh/resume)"
CS->>CS: await Task.Yield()
CS->>CS: _client.StreamAsync() begins
Note over CS,TT: First event arrives
CS->>TT: LoggedFirstEvent = true
CS->>Log: "First stream event after Xms"
Note over CS,TT: First text_delta with content
CS->>TT: LoggedFirstText = true
CS->>Log: "First model text after Xms"
Note over CS,TT: First ToolUseContent
CS->>TT: LoggedFirstTool = true
CS->>Log: "First tool call after Xms"
CS->>TT: ToolStartMs[tu.Id] = elapsed
CS->>Log: DBG "tool X starting"
Note over CS,TT: Matching tool_result arrives
CS->>TT: ToolStartMs.Remove(tu.Id, out startMs)
CS->>Log: DBG "tool X done after Yms (ok/fail)"
CS->>Log: "Turn completed (stopReason, ms, cost)"
Reviews (1): Last reviewed commit: "Log per-turn timing checkpoints in the L..." | Re-trigger Greptile |
| hasToolUse = true; | ||
| if (!timings.LoggedFirstTool) | ||
| { | ||
| timings.LoggedFirstTool = true; | ||
| Log(session, LogLevel.Inf, | ||
| $"First tool call after {timings.Total.ElapsedMilliseconds}ms"); | ||
| } |
There was a problem hiding this comment.
LoggedFirstTool set before early-break for silent tools
timings.LoggedFirstTool = true and the "First tool call after Xms" log fire even when tu.Name is TodoWrite or Task, which both break before ToolStartMs is populated and before any "tool X starting" log is emitted. If one of these invisible tools is the first ToolUseContent in the turn, the Logs tab will show "First tool call after Xms" with no matching "tool … starting" or "tool … done" line — making the timing log misleading for diagnosing that specific turn.
Summary
--add-dirs) was spending its time.Turn startednow also reportsadd-dirs=Nandresume/freshso it's obvious when fusion fan-out and JSONL replay are in play.Notes
First stream event after Xms (CLI cold start + add-dir loading + resume replay)is the smoking-gun line for diagnosing slow fusion turns.