You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #916 / #918 routes session-scoped MEL diagnostics into the canonical
per-session `session.log` based on `SessionDiagnosticsContext.SessionId`
(an AsyncLocal populated by `SessionLlmInvoker.InvokeAsync` for the main
turn path). Issue #915 proposes a Roslyn analyzer to enforce the scope at
LLM call sites going forward.
This issue tracks the existing call-site sweep that #915 will eventually
police: session-owned code that calls `IChatClient.GetResponseAsync` /
`GetStreamingResponseAsync` directly, outside of `SessionLlmInvoker`,
without first establishing the diagnostics scope.
Why this matters
Without the `Push` scope, the provider plugin's MEL log lines emitted
during the call still land in the daemon-global log but never reach the
session's `session.log`. Session-level troubleshooting is then incomplete
in exactly the paths that are most expensive to debug after the fact —
compaction, title generation, sub-agent orchestration, and memory
distillation.
For each call site above, wrap the `IChatClient` invocation in a
`using var scope = SessionDiagnosticsContext.Push(sessionId.Value);`
block. Prefer routing through a shared session-aware wrapper (the same
shape as `SessionLlmInvoker`) when the call belongs to a hot path with
multiple invocations, so the scope is established in one place rather
than copy-pasted at every call site.
Where the call site does not have a `SessionId` in scope, plumb it
through — every one of the listed actors and pipelines is session-scoped
by construction.
Acceptance criteria
All call sites listed above are covered by either an explicit
`SessionDiagnosticsContext.Push` scope or a shared invoker wrapper.
A negative test exists for at least one of the major sidecar paths
(e.g. compaction or title generation) that asserts diagnostic lines
reach `session.log` when the path runs under a session.
Background
PR #916 / #918 routes session-scoped MEL diagnostics into the canonical
per-session `session.log` based on `SessionDiagnosticsContext.SessionId`
(an AsyncLocal populated by `SessionLlmInvoker.InvokeAsync` for the main
turn path). Issue #915 proposes a Roslyn analyzer to enforce the scope at
LLM call sites going forward.
This issue tracks the existing call-site sweep that #915 will eventually
police: session-owned code that calls `IChatClient.GetResponseAsync` /
`GetStreamingResponseAsync` directly, outside of `SessionLlmInvoker`,
without first establishing the diagnostics scope.
Why this matters
Without the `Push` scope, the provider plugin's MEL log lines emitted
during the call still land in the daemon-global log but never reach the
session's `session.log`. Session-level troubleshooting is then incomplete
in exactly the paths that are most expensive to debug after the fact —
compaction, title generation, sub-agent orchestration, and memory
distillation.
Known sites (from #915)
Proposal
For each call site above, wrap the `IChatClient` invocation in a
`using var scope = SessionDiagnosticsContext.Push(sessionId.Value);`
block. Prefer routing through a shared session-aware wrapper (the same
shape as `SessionLlmInvoker`) when the call belongs to a hot path with
multiple invocations, so the scope is established in one place rather
than copy-pasted at every call site.
Where the call site does not have a `SessionId` in scope, plumb it
through — every one of the listed actors and pipelines is session-scoped
by construction.
Acceptance criteria
`SessionDiagnosticsContext.Push` scope or a shared invoker wrapper.
(e.g. compaction or title generation) that asserts diagnostic lines
reach `session.log` when the path runs under a session.
listed files.
Reference