Description
A tool result usually enters the next response.create after its invocation has already been emitted in the preceding response. Tempo currently joins only the current Turn.ToolCalls and Turn.ToolOutputs (internal/sink/otlptrace/spans.go:483-508). The reducer closes and removes that Turn at response.completed (reducer.go:169-176), then captures later results into another Turn. As a result, a tool span can lack its result even though Loki and the archive contain it.
A content-free scan of corpus/processed/2026-08-09T00.jsonl.gz on 2026-09-05 read 23,242 physical records, found 147 completed calls and 151 distinct call-ID outputs, and matched 145 outputs to earlier calls in that file. All 145 matched outputs were in a different response.create cycle with a later archive timestamp. The unmatched six are boundary/coverage unknowns, not proven tool failures. This is a targeted-hour measurement, not a full-corpus count.
The useful outcome is navigation from a tool result to the originating call and response across the conversation. Preserve the result as input to the receiving model response as well. Existing tool timing values do not establish exact tool execution start times. Traces are currently disabled in the inspected deployment, so source delivery and live trace proof must be reported separately.
Acceptance Criteria
- #1 For a call followed by a result in a later response, Loki result metadata identifies the originating invocation and response when the archive provides an unambiguous match.
- #2 When Tempo is enabled, users can follow the relationship from the invocation to its later result without incorrectly attaching the result to an unrelated current-response call or assuming an ended span can be amended.
- #3 Correlation is scoped to the conversation, bounded in time and memory, and handles file boundaries, replay, duplicate results and missing calls explicitly; missing results do not imply tool failure.
- #4 Result content remains available as input to the receiving response, under existing capture limits; no exact execution duration or success status is invented from capture timestamps or item status.
- #5 Focused evidence covers a normal cross-response pair, repeated history, reused call identifiers in different threads, and unmatched boundary records.
Definition of Done
- #1 just check passes: fmt-check, lint, build, test-short and probe-ci all clean
Implementation Plan
Wave 2: commit root-owned seams first; frozen owned lanes implement with synthetic tests; integrate, just check, one corpus confidence gate and CodeRabbit; one push; watchtower-only deploy observation and m7kni proof; reconcile acceptance by evidence layer.
Implementation Notes
Clean main e8e97fd directly descends from c567894 and equals origin/main. CI 33988760737 and release-please 33988761017 succeeded. D8 holds; traces and agento11y remain disabled.
Final Summary
Wave 2 delivered at aca5e5de0bcd4ba6f5fd72dfaa6caef3a6c7fb71. Synthetic correlation/state tests cover cross-response, duplicate/replay, thread scope, expiry, cap and v5 compatibility; synthetic trace links pass (source-level, traces disabled). Three post-deploy Loki tool_output records reported exact origins. Frozen 512-per-thread/24h design has no global thread cap. just check passed at that source SHA; CI 33993480890 success. Watchtower deployed that SHA healthy, restart count 0. Publish 33993481221 failed signing after successful manifest push; run-level publication completion remains open. The single D20 corpus gate was canceled (exit 143), so corpus confidence is not proven. Final tracker closeout is local under the one-push contract.