@@ -6755,6 +6971,65 @@ pub enum FusionPattern {
Unknown,
}
+/// HydraFusion phase kind.
+///
+///
+///
+/// **Experimental.** This type is part of an experimental wire-protocol surface
+/// and may change or be removed in future SDK or CLI releases.
+///
+///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
+pub enum FusionPhaseKind {
+ /// Primary solver phase.
+ #[serde(rename = "primary")]
+ Primary,
+ /// Read-only cascade judge phase.
+ #[serde(rename = "judge")]
+ Judge,
+ /// Cascade repair phase.
+ #[serde(rename = "repair")]
+ Repair,
+ /// Initial critique-pattern draft phase.
+ #[serde(rename = "draft")]
+ Draft,
+ /// Read-only critique phase.
+ #[serde(rename = "critic")]
+ Critic,
+ /// Critique-pattern revision phase.
+ #[serde(rename = "revision")]
+ Revision,
+ /// Follow-up phase continuing from the resolved model.
+ #[serde(rename = "follow_up")]
+ FollowUp,
+ /// Unknown variant for forward compatibility.
+ #[default]
+ #[serde(other)]
+ Unknown,
+}
+
+/// Conversation scope in which a HydraFusion phase executes.
+///
+///
+///
+/// **Experimental.** This type is part of an experimental wire-protocol surface
+/// and may change or be removed in future SDK or CLI releases.
+///
+///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
+pub enum FusionConversationScope {
+ /// Canonical root conversation history.
+ #[serde(rename = "root")]
+ Root,
+ /// Isolated read-only review history that does not enter the root conversation.
+ #[serde(rename = "review")]
+ Review,
+ /// Unknown variant for forward compatibility.
+ #[default]
+ #[serde(other)]
+ Unknown,
+}
+
/// The agent mode that was active when this message was sent
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum UserMessageAgentMode {
@@ -6845,7 +7120,7 @@ pub enum ModelCallFailureTransport {
Unknown,
}
-/// Conversation scope in which a HydraFusion phase executes.
+/// Content-safe activity observed while a HydraFusion phase is running.
///
///
///
@@ -6854,50 +7129,16 @@ pub enum ModelCallFailureTransport {
///
///
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
-pub enum FusionConversationScope {
- /// Canonical root conversation history.
- #[serde(rename = "root")]
- Root,
- /// Isolated read-only review history that does not enter the root conversation.
- #[serde(rename = "review")]
- Review,
- /// Unknown variant for forward compatibility.
- #[default]
- #[serde(other)]
- Unknown,
-}
-
-/// HydraFusion phase kind.
-///
-///
-///
-/// **Experimental.** This type is part of an experimental wire-protocol surface
-/// and may change or be removed in future SDK or CLI releases.
-///
-///
-#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
-pub enum FusionPhaseKind {
- /// Primary solver phase.
- #[serde(rename = "primary")]
- Primary,
- /// Read-only cascade judge phase.
- #[serde(rename = "judge")]
- Judge,
- /// Cascade repair phase.
- #[serde(rename = "repair")]
- Repair,
- /// Initial critique-pattern draft phase.
- #[serde(rename = "draft")]
- Draft,
- /// Read-only critique phase.
- #[serde(rename = "critic")]
- Critic,
- /// Critique-pattern revision phase.
- #[serde(rename = "revision")]
- Revision,
- /// Follow-up phase continuing from the resolved model.
- #[serde(rename = "follow_up")]
- FollowUp,
+pub enum FusionPhaseActivityKind {
+ /// The provider produced additional private output bytes.
+ #[serde(rename = "model_output")]
+ ModelOutput,
+ /// A tool began executing inside the phase.
+ #[serde(rename = "tool_started")]
+ ToolStarted,
+ /// A tool finished executing inside the phase.
+ #[serde(rename = "tool_completed")]
+ ToolCompleted,
/// Unknown variant for forward compatibility.
#[default]
#[serde(other)]
@@ -8302,6 +8543,21 @@ pub enum SkillSource {
Unknown,
}
+/// Whether configured models are advisory preferences or required constraints
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
+pub enum AgentModelPolicy {
+ /// Treat the authored models as advisory preferences that callers may override.
+ #[serde(rename = "preferred")]
+ Preferred,
+ /// Require subagent execution to use one of the authored models.
+ #[serde(rename = "required")]
+ Required,
+ /// Unknown variant for forward compatibility.
+ #[default]
+ #[serde(other)]
+ Unknown,
+}
+
/// Configuration source: user, workspace, plugin, or builtin
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum McpServerSource {
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index 274e70f675..8cf978665f 100644
--- a/test/harness/package-lock.json
+++ b/test/harness/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
- "@github/copilot": "^1.0.83-1",
+ "@github/copilot": "^1.0.83-2",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
@@ -472,8 +472,8 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.83-1",
- "integrity": "sha512-7rhgbgSx7IgfFYXrTx2/2+qowv6MZjC6BN0mhba37RuGQxsca9Zk2ucAeIX3GbQTp91AhvnN0aHCxabX36xADQ==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-ntRvwGdZbZJjOvdV3LVBQ7z69W19DO4MWe/dh6pP8kYeumbzC4udVj7mCtoSwBOs0hwXirhXY+BZwqSJUp5FLQ==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
@@ -483,19 +483,19 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.83-1",
- "@github/copilot-darwin-x64": "1.0.83-1",
- "@github/copilot-linux-arm64": "1.0.83-1",
- "@github/copilot-linux-x64": "1.0.83-1",
- "@github/copilot-linuxmusl-arm64": "1.0.83-1",
- "@github/copilot-linuxmusl-x64": "1.0.83-1",
- "@github/copilot-win32-arm64": "1.0.83-1",
- "@github/copilot-win32-x64": "1.0.83-1"
+ "@github/copilot-darwin-arm64": "1.0.83-2",
+ "@github/copilot-darwin-x64": "1.0.83-2",
+ "@github/copilot-linux-arm64": "1.0.83-2",
+ "@github/copilot-linux-x64": "1.0.83-2",
+ "@github/copilot-linuxmusl-arm64": "1.0.83-2",
+ "@github/copilot-linuxmusl-x64": "1.0.83-2",
+ "@github/copilot-win32-arm64": "1.0.83-2",
+ "@github/copilot-win32-x64": "1.0.83-2"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.83-1",
- "integrity": "sha512-gxYJEd4yoIBIQHRmJw6ZegSkR6VuNm7AJVdAdARcU0SS68VZjtZFT29luThAp75Pxp37S5w+3A/jQNtxGyHizw==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-RBjF/zTJe+gp9PsthYtIHF36+y3A3Zv3w/2FAa9nHF6ople1+lYoQ0OC1z6tWQSpBx3n/fSkNt0ebMmfhWlQyw==",
"cpu": [
"arm64"
],
@@ -510,8 +510,8 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.83-1",
- "integrity": "sha512-PL63+Ib1RH+Bpu2UYJ9E8tmD4NZD/YlhD25F1Q9Rb86AdgLEoRYlxjNxXXF9P9dMmJ/u5zm0rUtWIRxv/FRbPg==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-GzaarluCiHUA4yrYxWIFEklwPLTYjxGvLyYjI0wW5IPseT7GLFjN7AkDGRU4Ny/mxTj1MbUEsJAWVtiNy5EUHg==",
"cpu": [
"x64"
],
@@ -526,8 +526,8 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.83-1",
- "integrity": "sha512-7c4RVEuXQu9zepAWoXwkizpESztUbWUR1hLPl+o+19L+D8fXm+5XQRH5E22Ia7P7/xHW3Ml2o2x5cXFq0k7/7w==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-iGD5Pc7vnzrAjqTK/BrI8MDtMqXyxUe7P6u8TiGt+4DzKe3v2myT6eFQ+z/JJOHNpiu6LUpTDzwS8WttZqqJpA==",
"cpu": [
"arm64"
],
@@ -542,8 +542,8 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.83-1",
- "integrity": "sha512-Be0zUVysLYV66pnOPhMxpShQ8Ox5V07qcsSOoNzG7iwpzkfZuf70U9CHk/fnI//mWwmZR+caPUfVM9BpwrdNnA==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-jOQwz075vRWat+RJiMNtD+7vm4DQ83Dvw4iakpNkLfqWMPXlliVr/tqL+SffeSo87LnhOKobZOJOjELS27drdg==",
"cpu": [
"x64"
],
@@ -558,8 +558,8 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.83-1",
- "integrity": "sha512-PZNP8vZZJU8yIc3dNjGUBUCFPNjqZs8FPZLDxvL6XdHM7Ep4cLBa+QdbRsw+nZONIaG0GtQf26eqk5ymYYpUPA==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-6/+ByEBEV/vDofrCymaKrEZ5/p+TVHQfgWu8ywvWEPALfxj/iHpAF3grM2bj7uED4C19LTSarHNCkCqdrAUzIQ==",
"cpu": [
"arm64"
],
@@ -574,8 +574,8 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.83-1",
- "integrity": "sha512-uKMhGtg5K07nA5/pxDSq8S5F/I+sMgVhUXg90Y4BI9trOidgxpXpCVyh4TeRNj2ENNugPvATdfGc6eFPsjmlgQ==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-8dbiPUHaDemDibLfKXDe5xublJxt6fOht4yYDk/ikmOGAVezBUwRVO27PchXQBwGjP2PVNAASkv2WB4Ubw72lA==",
"cpu": [
"x64"
],
@@ -590,8 +590,8 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.83-1",
- "integrity": "sha512-vMxHTmv3SotBuNI4LKcIFckd+n0OvhTik27qjsqOnVqFpvmHDghSsa8YPxySyxUQIE35z5pJaivVBK3dfEAY7w==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-ZE1iUXlJSnNIH+VoRG96emy2e7jMJm85/pcKCrgLvqhDAcQSqiqLVv3OJp2VX2IcDxToOpiaGccU8Ab9zHQqkQ==",
"cpu": [
"arm64"
],
@@ -606,8 +606,8 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.83-1",
- "integrity": "sha512-2l0VVTazW3/+p94ZQ5sAPCj1iH7KWxJAYh4yXWfvpsB/1JEEmyVgpLei1MeaMFVdtp/hi9bGprZ9+zWNlHh5hQ==",
+ "version": "1.0.83-2",
+ "integrity": "sha512-qfturLon+1oaWqSaXCISL6BEf5K+ijJFl0m/OZwstWYSlIlaE2+iOz5LcRukoxm25OG1JZDHQFp1k2PY2A+LbA==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index e293910938..91aaff849a 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -14,7 +14,7 @@
"node": "^20.19.0 || >=22.12.0"
},
"devDependencies": {
- "@github/copilot": "^1.0.83-1",
+ "@github/copilot": "^1.0.83-2",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
From 174940c91f985d9302c2596567c990a154ef8896 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 09:54:55 -0400
Subject: [PATCH 02/10] Fix Java tests for generated schema changes
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
.../com/github/copilot/RpcSessionStateExtrasE2ETest.java | 2 +-
.../generated/rpc/GeneratedRpcRecordsCoverageTest.java | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/java/sdk/src/test/java/com/github/copilot/RpcSessionStateExtrasE2ETest.java b/java/sdk/src/test/java/com/github/copilot/RpcSessionStateExtrasE2ETest.java
index 18045f3e86..f7fc58d429 100644
--- a/java/sdk/src/test/java/com/github/copilot/RpcSessionStateExtrasE2ETest.java
+++ b/java/sdk/src/test/java/com/github/copilot/RpcSessionStateExtrasE2ETest.java
@@ -142,7 +142,7 @@ void testShouldUpdateAndClearLiveSubagentSettings() throws Exception {
session.getRpc().tools.updateSubagentSettings(new SessionToolsUpdateSubagentSettingsParams(null,
new SessionToolsUpdateSubagentSettingsParams.SessionToolsUpdateSubagentSettingsParamsSubagents(
Map.of("general-purpose",
- new SubagentSettingsEntry("gpt-5-mini", "low",
+ new SubagentSettingsEntry("gpt-5-mini", null, "low",
SubagentSettingsEntryContextTier.LONG_CONTEXT)),
List.of("legacy-agent"), null, null)))
.get(30, TimeUnit.SECONDS);
diff --git a/java/sdk/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java b/java/sdk/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java
index eb0bc3d723..f86b3dfbcb 100644
--- a/java/sdk/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java
+++ b/java/sdk/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java
@@ -470,7 +470,7 @@ void pingResult_fields() {
@Test
void sessionAgentListResult_with_items() {
var item = new AgentInfo("name1", "Name One", "Desc 1", "/path/to/agent1", null, null, null, null, null, null,
- null, null);
+ null, null, null, null);
var result = new SessionAgentListResult(List.of(item));
assertEquals(1, result.agents().size());
assertEquals("name1", result.agents().get(0).name());
@@ -482,7 +482,7 @@ void sessionAgentListResult_with_items() {
@Test
void sessionAgentGetCurrentResult_nested() {
var agent = new AgentInfo("agent-1", "Agent One", "Does things", null, null, null, null, null, null, null, null,
- null);
+ null, null, null);
var result = new SessionAgentGetCurrentResult(agent);
assertEquals("agent-1", result.agent().name());
assertEquals("Agent One", result.agent().displayName());
@@ -498,7 +498,8 @@ void sessionAgentGetCurrentResult_null_agent() {
@Test
void sessionAgentReloadResult_with_items() {
- var item = new AgentInfo("a", "A", "Desc", "/path/to/a", null, null, null, null, null, null, null, null);
+ var item = new AgentInfo("a", "A", "Desc", "/path/to/a", null, null, null, null, null, null, null, null, null,
+ null);
var result = new SessionAgentReloadResult(List.of(item));
assertEquals(1, result.agents().size());
assertEquals("a", result.agents().get(0).name());
@@ -507,7 +508,7 @@ void sessionAgentReloadResult_with_items() {
@Test
void sessionAgentSelectResult_nested() {
var agent = new AgentInfo("selected", "Selected", "The selected agent", "/path/to/selected", null, null, null,
- null, null, null, null, null);
+ null, null, null, null, null, null, null);
var result = new SessionAgentSelectResult(agent);
assertEquals("selected", result.agent().name());
}
From 7bcc15380294ccbae974071ada69600e235941f9 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 10:18:30 -0400
Subject: [PATCH 03/10] Fix Rust checks for generated schema changes
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
rust/src/generated/api_types.rs | 2 +-
rust/tests/e2e/rpc_session_state_extras.rs | 1 +
scripts/codegen/rust.ts | 11 ++++-------
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/rust/src/generated/api_types.rs b/rust/src/generated/api_types.rs
index ab60417316..3eff4e1524 100644
--- a/rust/src/generated/api_types.rs
+++ b/rust/src/generated/api_types.rs
@@ -14784,7 +14784,7 @@ pub struct SandboxConfigUserPolicyNetwork {
/// Whether outbound network traffic is allowed at all.
#[serde(skip_serializing_if = "Option::is_none")]
pub allow_outbound: Option,
- /// HTTP proxy for sandboxed process traffic. Linux restricts egress to the proxy endpoint, requires that endpoint to be reachable over IPv4 (the [::] dual-stack wildcard is accepted and routed through the IPv4 gateway), and does not support proxy credentials. macOS relies on applications honoring proxy environment variables. Windows also configures a per-AppContainer WinHTTP proxy, but enforcement depends on the application's networking stack. Configure supported credentials in the separate `username` and `password` fields. A credential-free http:// loopback URL uses the localhost proxy form, while an https:// or authenticated loopback URL uses the URL form.
+ /// HTTP proxy for sandboxed process traffic. Linux restricts egress to the proxy endpoint, requires that endpoint to be reachable over IPv4 (the `[::]` dual-stack wildcard is accepted and routed through the IPv4 gateway), and does not support proxy credentials. macOS relies on applications honoring proxy environment variables. Windows also configures a per-AppContainer WinHTTP proxy, but enforcement depends on the application's networking stack. Configure supported credentials in the separate `username` and `password` fields. A credential-free http:// loopback URL uses the localhost proxy form, while an https:// or authenticated loopback URL uses the URL form.
#[serde(skip_serializing_if = "Option::is_none")]
pub proxy: Option,
}
diff --git a/rust/tests/e2e/rpc_session_state_extras.rs b/rust/tests/e2e/rpc_session_state_extras.rs
index 85c20debc7..e764c53933 100644
--- a/rust/tests/e2e/rpc_session_state_extras.rs
+++ b/rust/tests/e2e/rpc_session_state_extras.rs
@@ -495,6 +495,7 @@ async fn should_update_and_clear_live_subagent_settings() {
),
effort_level: Some("low".to_string()),
model: Some("gpt-5-mini".to_string()),
+ model_policy: None,
},
)])),
disabled_subagents: Some(vec!["legacy-agent".to_string()]),
diff --git a/scripts/codegen/rust.ts b/scripts/codegen/rust.ts
index 0feec5e98a..b3cc5d5753 100644
--- a/scripts/codegen/rust.ts
+++ b/scripts/codegen/rust.ts
@@ -378,9 +378,7 @@ function tryEmitRustUnion(
const lines: string[] = [];
if (schema.description) {
- for (const line of schema.description.split(/\r?\n/)) {
- lines.push(`/// ${line}`);
- }
+ pushRustDoc(lines, schema.description);
}
pushRustExperimentalDocs(lines, isSchemaExperimental(schema) || ctx.experimentalTypeNames.has(enumName));
lines.push("#[derive(Debug, Clone, Serialize, Deserialize)]");
@@ -468,7 +466,8 @@ function pushRustExperimentalDocs(
function pushRustDoc(lines: string[], text: string | undefined, indent = ""): void {
if (!text) return;
- for (const paragraph of text.trim().split(/\r?\n/)) {
+ const sanitized = text.replace(/\[::\]/g, "`[::]`");
+ for (const paragraph of sanitized.trim().split(/\r?\n/)) {
if (paragraph.trim().length === 0) {
lines.push(`${indent}///`);
} else {
@@ -971,9 +970,7 @@ function emitRustStruct(
for (const { propName, prop, isReq, rustField, rustType } of fields) {
if (prop.description) {
- for (const line of prop.description.split(/\r?\n/)) {
- lines.push(` /// ${line}`);
- }
+ pushRustDoc(lines, prop.description, " ");
}
pushRustExperimentalDocs(lines, isSchemaExperimental(prop), " ");
const propIsInternal = isSchemaInternal(prop);
From 0cc1b2c7606cf8fce28f1588526b30d8093cd292 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 12:27:13 -0400
Subject: [PATCH 04/10] Split hanging macOS .NET test shard
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
.github/workflows/dotnet-sdk-tests.yml | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/dotnet-sdk-tests.yml b/.github/workflows/dotnet-sdk-tests.yml
index 2a446c97be..6a94e16648 100644
--- a/.github/workflows/dotnet-sdk-tests.yml
+++ b/.github/workflows/dotnet-sdk-tests.yml
@@ -104,7 +104,11 @@ jobs:
- os: macos-latest
transport: default
backend: capi
- shard: "2b"
+ shard: "2b1"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b2"
- os: macos-latest
transport: default
backend: capi
@@ -203,9 +207,13 @@ jobs:
initials=(B E F G)
shard_filter=""
;;
- 2b)
- initials=(O P R)
- shard_filter=""
+ 2b1)
+ initials=(O P)
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.Rewind|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcA|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcM|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcQ|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcR"
+ ;;
+ 2b2)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcS|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcT|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcU|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcW|FullyQualifiedName~GitHub.Copilot.Test.Unit.R"
;;
2c)
initials=(T V X Z)
From e372b875f7ced898ac2cec6a826904cc7076d1c7 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 14:32:50 -0400
Subject: [PATCH 05/10] Further isolate macOS .NET tests
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
.github/workflows/dotnet-sdk-tests.yml | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/dotnet-sdk-tests.yml b/.github/workflows/dotnet-sdk-tests.yml
index 6a94e16648..f559836dc5 100644
--- a/.github/workflows/dotnet-sdk-tests.yml
+++ b/.github/workflows/dotnet-sdk-tests.yml
@@ -104,7 +104,11 @@ jobs:
- os: macos-latest
transport: default
backend: capi
- shard: "2b1"
+ shard: "2b1a"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1b"
- os: macos-latest
transport: default
backend: capi
@@ -207,9 +211,13 @@ jobs:
initials=(B E F G)
shard_filter=""
;;
- 2b1)
+ 2b1a)
initials=(O P)
- shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.Rewind|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcA|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcM|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcQ|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcR"
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.Rewind|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcA|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE"
+ ;;
+ 2b1b)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcM|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcQ|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcR"
;;
2b2)
initials=()
From 6156e6c1fbd54518ce7e27fcf3ee3060c2aa8b98 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 15:05:24 -0400
Subject: [PATCH 06/10] Isolate macOS RPC test groups
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
.github/workflows/dotnet-sdk-tests.yml | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/dotnet-sdk-tests.yml b/.github/workflows/dotnet-sdk-tests.yml
index f559836dc5..cffc96a5f2 100644
--- a/.github/workflows/dotnet-sdk-tests.yml
+++ b/.github/workflows/dotnet-sdk-tests.yml
@@ -108,7 +108,15 @@ jobs:
- os: macos-latest
transport: default
backend: capi
- shard: "2b1b"
+ shard: "2b1b-mcp"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1b-queue"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1b-remote"
- os: macos-latest
transport: default
backend: capi
@@ -215,9 +223,17 @@ jobs:
initials=(O P)
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.Rewind|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcA|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE"
;;
- 2b1b)
+ 2b1b-mcp)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcM"
+ ;;
+ 2b1b-queue)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcQ"
+ ;;
+ 2b1b-remote)
initials=()
- shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcM|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcQ|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcR"
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcR"
;;
2b2)
initials=()
From 7cba9b924c4246a488a6c2d90157c1343e660dec Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 16:05:17 -0400
Subject: [PATCH 07/10] Fully isolate macOS .NET test groups
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
.github/workflows/dotnet-sdk-tests.yml | 30 +++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/dotnet-sdk-tests.yml b/.github/workflows/dotnet-sdk-tests.yml
index cffc96a5f2..393f76c98e 100644
--- a/.github/workflows/dotnet-sdk-tests.yml
+++ b/.github/workflows/dotnet-sdk-tests.yml
@@ -104,7 +104,19 @@ jobs:
- os: macos-latest
transport: default
backend: capi
- shard: "2b1a"
+ shard: "2b1a-permission-provider"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1a-rewind"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1a-rpc-a"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1a-rpc-e"
- os: macos-latest
transport: default
backend: capi
@@ -219,9 +231,21 @@ jobs:
initials=(B E F G)
shard_filter=""
;;
- 2b1a)
+ 2b1a-permission-provider)
initials=(O P)
- shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.Rewind|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcA|FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE"
+ shard_filter=""
+ ;;
+ 2b1a-rewind)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.Rewind"
+ ;;
+ 2b1a-rpc-a)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcA"
+ ;;
+ 2b1a-rpc-e)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE"
;;
2b1b-mcp)
initials=()
From 99564547f7da9a40ff1a810689f34e0eda1b2c62 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 16:48:19 -0400
Subject: [PATCH 08/10] Isolate flaky .NET test hosts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
.github/workflows/dotnet-sdk-tests.yml | 27 ++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/dotnet-sdk-tests.yml b/.github/workflows/dotnet-sdk-tests.yml
index 393f76c98e..d1be581988 100644
--- a/.github/workflows/dotnet-sdk-tests.yml
+++ b/.github/workflows/dotnet-sdk-tests.yml
@@ -215,6 +215,7 @@ jobs:
)
filter="$DOTNET_TEST_FILTER"
+ individual_filters=()
if [[ "$DOTNET_TEST_SHARD" != "full" ]]; then
case "$DOTNET_TEST_SHARD" in
1)
@@ -232,8 +233,17 @@ jobs:
shard_filter=""
;;
2b1a-permission-provider)
- initials=(O P)
+ initials=()
shard_filter=""
+ individual_filters=(
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.PendingWorkResumeE2ETests"
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.PerSessionAuthE2ETests"
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.PermissionE2ETests"
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.PreMcpToolCallHookE2ETests"
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.ProviderEndpointE2ETests"
+ "FullyQualifiedName~GitHub.Copilot.Test.Unit.PermissionHandlerTests"
+ "FullyQualifiedName~GitHub.Copilot.Test.Unit.PublicDtoTests"
+ )
;;
2b1a-rewind)
initials=()
@@ -249,7 +259,12 @@ jobs:
;;
2b1b-mcp)
initials=()
- shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcM"
+ shard_filter=""
+ individual_filters=(
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpAndSkillsE2ETests"
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpConfigE2ETests"
+ "FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpLifecycleE2ETests"
+ )
;;
2b1b-queue)
initials=()
@@ -269,6 +284,14 @@ jobs:
;;
esac
+ if (( ${#individual_filters[@]} > 0 )); then
+ for individual_filter in "${individual_filters[@]}"; do
+ combined_filter="${filter:+(${filter})&}(${individual_filter})"
+ dotnet test test/GitHub.Copilot.SDK.Test.csproj "${args[@]}" --filter "$combined_filter"
+ done
+ exit 0
+ fi
+
for namespace in E2E Unit; do
for initial in "${initials[@]}"; do
clause="FullyQualifiedName~GitHub.Copilot.Test.${namespace}.${initial}"
From 01bab082025f241f9f2c8421a1da258e63ff1ed8 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 18:27:19 -0400
Subject: [PATCH 09/10] Split macOS MCP test hosts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
.github/workflows/dotnet-sdk-tests.yml | 27 ++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/dotnet-sdk-tests.yml b/.github/workflows/dotnet-sdk-tests.yml
index d1be581988..0acf807f0a 100644
--- a/.github/workflows/dotnet-sdk-tests.yml
+++ b/.github/workflows/dotnet-sdk-tests.yml
@@ -120,7 +120,15 @@ jobs:
- os: macos-latest
transport: default
backend: capi
- shard: "2b1b-mcp"
+ shard: "2b1b-mcp-and-skills"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1b-mcp-config"
+ - os: macos-latest
+ transport: default
+ backend: capi
+ shard: "2b1b-mcp-lifecycle"
- os: macos-latest
transport: default
backend: capi
@@ -257,14 +265,17 @@ jobs:
initials=()
shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcE"
;;
- 2b1b-mcp)
+ 2b1b-mcp-and-skills)
initials=()
- shard_filter=""
- individual_filters=(
- "FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpAndSkillsE2ETests"
- "FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpConfigE2ETests"
- "FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpLifecycleE2ETests"
- )
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpAndSkillsE2ETests"
+ ;;
+ 2b1b-mcp-config)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpConfigE2ETests"
+ ;;
+ 2b1b-mcp-lifecycle)
+ initials=()
+ shard_filter="FullyQualifiedName~GitHub.Copilot.Test.E2E.RpcMcpLifecycleE2ETests"
;;
2b1b-queue)
initials=()
From fc0ddaae75154556a607bad7178c2281ec4a4354 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 2 Sep 2026 18:37:23 -0400
Subject: [PATCH 10/10] Dispose MCP test sessions promptly
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs
index 0d2942d4bf..ec923b31a1 100644
--- a/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs
+++ b/dotnet/test/E2E/RpcMcpAndSkillsE2ETests.cs
@@ -33,7 +33,7 @@ public async Task Should_List_And_Toggle_Session_Skills()
{
var skillName = $"session-rpc-skill-{Guid.NewGuid():N}";
var skillsDir = CreateSkillDirectory(skillName, "Session skill controlled by RPC.");
- var session = await CreateSessionAsync(new SessionConfig
+ await using var session = await CreateSessionAsync(new SessionConfig
{
SkillDirectories = [skillsDir],
DisabledSkills = [skillName],
@@ -56,7 +56,7 @@ public async Task Should_Ensure_Skills_Are_Loaded_And_List_Invoked_Skills()
{
var skillName = $"ensure-rpc-skill-{Guid.NewGuid():N}";
var skillsDir = CreateSkillDirectory(skillName, "Skill loaded explicitly by RPC.");
- var session = await CreateSessionAsync(new SessionConfig
+ await using var session = await CreateSessionAsync(new SessionConfig
{
SkillDirectories = [skillsDir],
});
@@ -79,7 +79,7 @@ public async Task Should_Reload_Session_Skills()
Directory.CreateDirectory(skillsDir);
var skillName = $"reload-rpc-skill-{Guid.NewGuid():N}";
- var session = await CreateSessionAsync(new SessionConfig { SkillDirectories = [skillsDir] });
+ await using var session = await CreateSessionAsync(new SessionConfig { SkillDirectories = [skillsDir] });
var before = await session.Rpc.Skills.ListAsync();
Assert.DoesNotContain(before.Skills, skill => string.Equals(skill.Name, skillName, StringComparison.Ordinal));
@@ -95,7 +95,7 @@ public async Task Should_Reload_Session_Skills()
public async Task Should_List_Mcp_Servers_With_Configured_Server()
{
const string serverName = "rpc-list-mcp-server";
- var session = await CreateSessionAsync(new SessionConfig
+ await using var session = await CreateSessionAsync(new SessionConfig
{
McpServers = CreateTestMcpServers(serverName),
});
@@ -111,7 +111,7 @@ public async Task Should_List_Mcp_Servers_With_Configured_Server()
public async Task Should_Set_Mcp_Env_Value_Mode_And_Remove_GitHub_Server()
{
const string serverName = "github";
- var session = await CreateSessionAsync(new SessionConfig
+ await using var session = await CreateSessionAsync(new SessionConfig
{
McpServers = CreateTestMcpServers(serverName),
});
@@ -137,7 +137,7 @@ public async Task Should_Set_Mcp_Env_Value_Mode_And_Remove_GitHub_Server()
public async Task Should_Report_Mcp_Sampling_Failure_And_Cancel_Missing_Sampling()
{
const string serverName = "rpc-sampling-server";
- var session = await CreateSessionAsync(new SessionConfig
+ await using var session = await CreateSessionAsync(new SessionConfig
{
McpServers = CreateTestMcpServers(serverName),
});
@@ -172,7 +172,7 @@ public async Task Should_Report_Mcp_Sampling_Failure_And_Cancel_Missing_Sampling
[Fact]
public async Task Should_List_Plugins()
{
- var session = await CreateSessionAsync();
+ await using var session = await CreateSessionAsync();
var result = await session.Rpc.Plugins.ListAsync();
@@ -314,7 +314,7 @@ public async Task Should_Report_Error_When_Mcp_App_Resource_Is_Not_Available()
[Fact]
public async Task Should_Report_Error_When_Mcp_Host_Is_Not_Initialized()
{
- var session = await CreateSessionAsync();
+ await using var session = await CreateSessionAsync();
await AssertFailureAsync(
() => session.Rpc.Mcp.EnableAsync("missing-server"),
@@ -333,7 +333,7 @@ await AssertFailureAsync(
[Fact]
public async Task Should_Report_Error_When_Mcp_Oauth_Server_Is_Not_Configured()
{
- var session = await CreateSessionAsync(new SessionConfig
+ await using var session = await CreateSessionAsync(new SessionConfig
{
McpServers = CreateTestMcpServers("configured-stdio-server"),
});
@@ -348,7 +348,7 @@ await AssertFailureAsync(
public async Task Should_Report_Error_When_Mcp_Oauth_Server_Is_Not_Remote()
{
const string serverName = "configured-stdio-server";
- var session = await CreateSessionAsync(new SessionConfig
+ await using var session = await CreateSessionAsync(new SessionConfig
{
McpServers = CreateTestMcpServers(serverName),
});