Conversation
When a JSON-RPC connection is lost and the server-side session has expired
('Session not found'), SendPromptAsync creates a fresh session. Previously,
the freshConfig was missing McpServers and SkillDirectories, causing the
session's environment (MCP tools, skills) to disappear after reconnection.
Now the reconnect path loads McpServers and SkillDirectories from settings,
matching the original CreateSessionAsync behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code Review — PR #330 (fix: restore MCP servers and skills when recreating expired session)CI: 🟡 MODERATE —
|
Address PR review feedback:
- Add SystemMessage with relaunch instructions to freshConfig, matching
CreateSessionAsync's conditional logic for ProjectDir sessions
- Anchor structural tests on 'freshConfig = new SessionConfig' instead
of 'Session not found' for reliable window sizing
- Assert property assignments ('McpServers = ') not just identifier names
- Add dedicated test for SystemMessage presence
- Include SystemMessage in MatchesCreateSessionFields required fields
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Round 2 Re-review5-model consensus review (claude-opus-4.6 ×2, claude-sonnet-4.6, gemini-3-pro-preview, gpt-5.3-codex) Previous Findings Status
All three Round 1 findings are addressed. The new New Findings (consensus-filtered)No new bugs reached the 2+ model consensus threshold. Single-Model Observation (below consensus, verified manually)
CI StatusRecommended Action✅ Approve — All Round 1 findings resolved, no new consensus bugs. Optional: apply the one-line |
Adds ChatExperienceSafetyTests.cs with 41 tests (40 active, 1 pending PR #330) covering the invariants documented in processing-state-safety skill: - INV-1: All 8 termination paths clear state correctly (CompleteResponse, SessionErrorEvent, AbortSessionAsync, watchdog) - INV-2: State mutations marshaled to UI thread via InvokeOnUI - INV-3: ProcessingGeneration guard prevents stale IDLE from killing new turns - INV-5: HasUsedToolsThisTurn protects sessions between tool rounds (not just while tools are active) - INV-9: IsMultiAgentSession set before StartProcessingWatchdog in both SendPromptAsync and RestoreSingleSessionAsync paths Behavioral tests (demo mode integration): - Multi-turn message preservation (5 sequential turns, all history retained) - Abort clears all 9 INV-1 fields, fires OnSessionComplete - Post-abort send succeeds without deadlock (SendingFlag cleared) - Session isolation (stuck session doesn't block others) - WatchdogToolExecutionTimeoutSeconds > WatchdogInactivityTimeoutSeconds - WatchdogMaxProcessingTimeSeconds >= 30 minutes Source-code assertion tests (regression guards against future refactors): - useToolTimeout formula has all 4 conditions (INV-5) - TurnEnd fallback checks HasUsedToolsThisTurn before firing CompleteResponse - FlushCurrentResponse called at AssistantTurnEndEvent (content persistence fix) - FlushCurrentResponse dedup guard prevents SDK-replay duplicates - CompleteResponse cancels watchdog before cleanup - Reconnect path carries forward IsMultiAgentSession + HasUsedToolsThisTurn These tests are designed to catch the class of regressions documented in regression-history.md (PRs #141-#284). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds ChatExperienceSafetyTests.cs with 41 tests (40 active, 1 pending PR #330) covering the invariants documented in processing-state-safety skill: - INV-1: All 8 termination paths clear state correctly (CompleteResponse, SessionErrorEvent, AbortSessionAsync, watchdog) - INV-2: State mutations marshaled to UI thread via InvokeOnUI - INV-3: ProcessingGeneration guard prevents stale IDLE from killing new turns - INV-5: HasUsedToolsThisTurn protects sessions between tool rounds (not just while tools are active) - INV-9: IsMultiAgentSession set before StartProcessingWatchdog in both SendPromptAsync and RestoreSingleSessionAsync paths Behavioral tests (demo mode integration): - Multi-turn message preservation (5 sequential turns, all history retained) - Abort clears all 9 INV-1 fields, fires OnSessionComplete - Post-abort send succeeds without deadlock (SendingFlag cleared) - Session isolation (stuck session doesn't block others) - WatchdogToolExecutionTimeoutSeconds > WatchdogInactivityTimeoutSeconds - WatchdogMaxProcessingTimeSeconds >= 30 minutes Source-code assertion tests (regression guards against future refactors): - useToolTimeout formula has all 4 conditions (INV-5) - TurnEnd fallback checks HasUsedToolsThisTurn before firing CompleteResponse - FlushCurrentResponse called at AssistantTurnEndEvent (content persistence fix) - FlushCurrentResponse dedup guard prevents SDK-replay duplicates - CompleteResponse cancels watchdog before cleanup - Reconnect path carries forward IsMultiAgentSession + HasUsedToolsThisTurn These tests are designed to catch the class of regressions documented in regression-history.md (PRs #141-#284). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds ChatExperienceSafetyTests.cs with 41 tests (40 active, 1 pending PR #330) covering the invariants documented in processing-state-safety skill: - INV-1: All 8 termination paths clear state correctly (CompleteResponse, SessionErrorEvent, AbortSessionAsync, watchdog) - INV-2: State mutations marshaled to UI thread via InvokeOnUI - INV-3: ProcessingGeneration guard prevents stale IDLE from killing new turns - INV-5: HasUsedToolsThisTurn protects sessions between tool rounds (not just while tools are active) - INV-9: IsMultiAgentSession set before StartProcessingWatchdog in both SendPromptAsync and RestoreSingleSessionAsync paths Behavioral tests (demo mode integration): - Multi-turn message preservation (5 sequential turns, all history retained) - Abort clears all 9 INV-1 fields, fires OnSessionComplete - Post-abort send succeeds without deadlock (SendingFlag cleared) - Session isolation (stuck session doesn't block others) - WatchdogToolExecutionTimeoutSeconds > WatchdogInactivityTimeoutSeconds - WatchdogMaxProcessingTimeSeconds >= 30 minutes Source-code assertion tests (regression guards against future refactors): - useToolTimeout formula has all 4 conditions (INV-5) - TurnEnd fallback checks HasUsedToolsThisTurn before firing CompleteResponse - FlushCurrentResponse called at AssistantTurnEndEvent (content persistence fix) - FlushCurrentResponse dedup guard prevents SDK-replay duplicates - CompleteResponse cancels watchdog before cleanup - Reconnect path carries forward IsMultiAgentSession + HasUsedToolsThisTurn These tests are designed to catch the class of regressions documented in regression-history.md (PRs #141-#284). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ureWeen#330) ## Problem When a session's JSON-RPC connection is lost and the server reports "Session not found" (session expired), the reconnect path in `SendPromptAsync` creates a fresh `SessionConfig` that was missing `McpServers` and `SkillDirectories`. This caused the "environment to keep going away" — MCP tools and skills disappeared after reconnection. ## Root Cause In `CopilotService.cs`, the `freshConfig` in the "Session not found" catch block only set `Model`, `WorkingDirectory`, `Tools`, and `OnPermissionRequest`. The original `CreateSessionAsync()` also includes `McpServers` and `SkillDirectories` loaded from settings. ## Fix Updated the reconnect path's `freshConfig` to load `McpServers` and `SkillDirectories` from settings, matching the original `CreateSessionAsync` behavior. ## Tests Added 3 structural regression tests in `ConnectionRecoveryTests.cs`: - `SendPromptAsync_FreshSessionConfig_IncludesMcpServers` - `SendPromptAsync_FreshSessionConfig_IncludesSkillDirectories` - `SendPromptAsync_FreshSessionConfig_MatchesCreateSessionFields` All 34 ConnectionRecoveryTests pass. Build succeeds on Mac Catalyst. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Problem
When a session's JSON-RPC connection is lost and the server reports "Session not found" (session expired), the reconnect path in
SendPromptAsynccreates a freshSessionConfigthat was missingMcpServersandSkillDirectories. This caused the "environment to keep going away" — MCP tools and skills disappeared after reconnection.Root Cause
In
CopilotService.cs, thefreshConfigin the "Session not found" catch block only setModel,WorkingDirectory,Tools, andOnPermissionRequest. The originalCreateSessionAsync()also includesMcpServersandSkillDirectoriesloaded from settings.Fix
Updated the reconnect path's
freshConfigto loadMcpServersandSkillDirectoriesfrom settings, matching the originalCreateSessionAsyncbehavior.Tests
Added 3 structural regression tests in
ConnectionRecoveryTests.cs:SendPromptAsync_FreshSessionConfig_IncludesMcpServersSendPromptAsync_FreshSessionConfig_IncludesSkillDirectoriesSendPromptAsync_FreshSessionConfig_MatchesCreateSessionFieldsAll 34 ConnectionRecoveryTests pass. Build succeeds on Mac Catalyst.