Skip to content

agentHost: await real signals instead of hidden polling waits in agent host tests - #343728

Merged
Alexandru Dima (alexdima) merged 2 commits into
mainfrom
agents/no-timeout-polling-agent-host-v2
Oct 23, 2026
Merged

Alexandru Dima (alexdima) merged 2 commits into
mainfrom
agents/no-timeout-polling-agent-host-v2

Conversation

@alexdima

Copy link
Copy Markdown
Member

Follow-up to #342698 and #343092.

Problem

An audit of origin/main at eeedb17 found waits for state in four agent host test files that local/code-no-timeout-polling-loop does not report. The rule reports loops whose body only waits on a timer; these loops wait on setImmediate, a setInterval callback or a microtask, or do other work in the same body (a try/catch re-read, answering a request). npx eslint --rule '{"local/code-no-timeout-polling-loop": ["warn", {"exclude": []}]}' reports 0 problems on all four original files. Each wait stood in for a specific piece of work:

  • Claude bootstrap model refresh (claudeAgent.test.ts, 6 loops). ClaudeAgent queues its first model refresh with queueMicrotask in the constructor and keeps it only in the private _modelRefreshInFlight. Five tests ran up to 100 setImmediate ticks until the fake SDK had counted a supportedModels() or accountInfo() call, then one more tick for the refresh to publish. A sixth, in the SDK setup channel suite, ticked until the bootstrap reached enumeration, so that a gate it raises next blocks only the download's enumeration. The comment on one of them said _fetchNativeModels awaits a real mkdtemp; it no longer does (buildModelEnumerationOptions() uses tmpdir()).
  • Published models (claudeAgent.test.ts, 2 loops) and a download enumeration (1 loop). Two loops ticked until agent.models was not empty, one until the fake SDK had counted the download's supportedModels() call.
  • Stub flags (claudeAgent.test.ts, 2 loops; claudeProxyService.test.ts, 1 waiter). Two while (!persistEntered) loops spun on setImmediate until the test's stubbed setMetadata had been entered. The proxy test polled a flag set by its stubbed messages every 10 ms with setInterval.
  • Root config write (agentService.test.ts, 1 loop). The test re-read the root config file up to 20 times, every 5 ms, until it parsed and matched, and continued with a failure flag when it ran out. It waited for the serialized write that AgentConfigurationService.persistRootConfig() chains onto _rootConfigWrite, which whenIdle() already exposes.
  • Import chunk staging (agentHostProtocolClient.test.ts, 1 loop). After acknowledging each vscode/stageCreateSessionImportChunk request, the test waited setTimeout(0) for the client to send its next message (agentHost: support turn-by-turn conversation import for remote sessions #343312).
  • Request helpers (agentHostProtocolClient.test.ts, 2 helpers). waitForRequest and waitForRequestAt spun on await Promise.resolve() until the transport's outbox had the request. They have 99 call sites in the soft reconnect suite; a probe (P1 below) counted 123 calls in that suite, 79 of which had to wait for a send. A microtask spin never yields to timers, so it hangs if the send ever moves behind one.

The tick and timer budgets depended on machine load, and the bounded loops continued with stale state when they ran out.

Change

Wait Waited for Now awaits
claudeAgent.test.ts 1727, 1755, 1775, 1796, 6398, 6981 the constructor's model refresh to enumerate and publish bootstrapModelRefresh(agent, sdk): sdk.waitForCalls(() => sdk.accountInfoCallCount > 0), then the agent's _modelRefreshInFlight
claudeAgent.test.ts 1688, 6421 agent.models not empty waitForState(agent.models, models => models.length > 0)
claudeAgent.test.ts 6415 the download's supportedModels() call sdk.waitForCalls(() => sdk.supportedModelsCallCount > enumerationsBefore)
claudeAgent.test.ts 4501, 5878 the stubbed setMetadata entered a DeferredPromise completed by the stub
claudeProxyService.test.ts 1360 the stubbed upstream messages called a DeferredPromise completed by the stub
agentService.test.ts 8106 the serialized root config write await svc.dispatchAction(...), then getConfigurationService(svc).whenIdle(), then one read
agentHostProtocolClient.test.ts 2154 the client's next send after a chunk acknowledgement Event.toPromise(transport.onDidSend), subscribed before the acknowledgement
agentHostProtocolClient.test.ts 4869, 4879 the request in the outbox the same check, re-run after each transport.onDidSend

Line numbers are from eeedb17; none of these files changed between it and the base of this PR.

Details worth a look:

  • FakeClaudeAgentSdkService gets waitForCalls(condition), in the shape of TestCopilotClient.waitForCalls from agentHost: await real signals instead of polling timers in copilotAgent tests #343092: it checks the condition and otherwise awaits Event.toPromise(Event.filter(...)) on an emitter that FakeQuery fires after it counts a supportedModels() or accountInfo() call.
  • bootstrapModelRefresh reads the private _modelRefreshInFlight through element access in a single helper, as proxyRefresh(agent) does in copilotAgent.test.ts. The field is only set once the constructor's microtask has run, so the helper first waits for the refresh's accountInfo() call; after that the field holds the bootstrap refresh, or is already cleared because the refresh has published. Nothing else starts a refresh in these tests. Calling agent.refreshModels() instead would coalesce or start a second enumeration depending on timing, and would hide a missing bootstrap.
  • Negative check: "an SDK account report of "nothing configured" publishes an empty catalog" asserts [], which is also the initial value, so it is only meaningful after the refresh has published. M3 and M3b below show that awaiting the in-flight refresh is what makes it fail when the product publishes the static list.
  • The SDK setup channel test now waits for the whole bootstrap refresh rather than only its enumeration call. The old setImmediate ticks gave the same result, and the test relies on it: the refreshModels() that follows must start a new refresh instead of coalescing onto the bootstrap. Its comment says so.
  • dispatchAction returns the queued dispatch promise when it defers a client action and undefined when it applies it at once; awaiting it covers both. persistRootConfig() snapshots the values when it is called, so the write that whenIdle() awaits already contains the change. The existing whenIdle() before cleanup is kept.
  • The protocol client helpers keep their signatures and call sites. Each iteration of their loops awaits the next send; the new check is the old one.
  • A condition that never holds now fails at Mocha's timeout instead of continuing with stale state.

There are no product-code changes. All scenarios and assertions are kept.

Not changed:

  • The settle() helper in the "ClaudeAgent — agent SDK setup channel" suite runs a fixed 20 setImmediate ticks and has 21 call sites, including negative checks. Each site needs its own signal, probably an event on the root transient values that the setup channel publishes, so it is left for a separate change. "a download that lands stays downloading until the catalog does", changed here, still calls it twice, once right after the waitForState this PR adds (M5 below).
  • Standalone single waits that are not loops: await tick() calls, await new Promise(resolve => setImmediate(resolve)) in the shutdown test at claudeAgent.test.ts 4401, setTimeout(resolve, 0) waits in agentHostProtocolClient.test.ts 4230 to 4395 and agentService.test.ts 41652, and the 2 s Promise.race in the streaming abort test in claudeProxyService.test.ts.

Validation

The baseline ran on eeedb17. The change was then rebased onto 37b0141, the base of this PR; the rebase was clean and no upstream commit in between changed the four test files or claudeAgent.ts, claudeProxyService.ts, agentConfigurationService.ts, agentService.ts or agentHostProtocolClient.ts. The mutation checks ran before the rebase, the 10 runs, CPU load runs and final checks after it. The machine was shared, so load averages are given with each timed run.

  • Baseline before the change, ./scripts/test.sh --run src/vs/platform/agentHost/test/node/claudeAgent.test.ts --run src/vs/platform/agentHost/test/node/claudeProxyService.test.ts --run src/vs/platform/agentHost/test/node/agentService.test.ts --run src/vs/platform/agentHost/test/electron-browser/agentHostProtocolClient.test.ts: 2027 passing, 16 pending (1 min Mocha time, 263 s wall, load average 20 to 42).
  • git grep -n -E 'for \(let i = 0; i < 100 && .*; i\+\+\) \{|while \(!persistEntered\)|const i = setInterval\(|attempt < 20; attempt\+\+|await new Promise\(resolve => setTimeout\(resolve, 0\)\);|while \(true\) \{|^\t\t\t\tawait Promise\.resolve\(\);$' <ref> -- <the 4 files>: on eeedb17 it lists the 9 tick loops and 2 persistEntered loops in claudeAgent.test.ts, the setInterval waiter, the 20-attempt loop, the chunk loop's setTimeout(0) and the two helper loops. After the change none of them remain; the remaining matches are unrelated: the event-driven while (true) loops in waitForPendingWorktreeRemovals and waitForCondition (agentHost: await real signals instead of polling timers in the remaining agentService tests #343603), the chunk loop itself (each iteration now awaits a send), the fake query's prompt drain, and the standalone setTimeout(0) waits listed above.
  • npx eslint --rule '{"local/code-no-timeout-polling-loop": ["warn", {"exclude": []}]}' <the 4 files>: 0 problems, before (run on the eeedb17 contents through --stdin --stdin-filename) and after.
  • 10 runs, for i in $(seq 10); do ./scripts/test.sh --run <the 4 files> 2>&1 | grep -E 'passing|failing'; done: 10/10 with 2027 passing and 16 pending. Mocha time 33 s to 1 min and wall time 35 to 70 s, at a 1-minute load average of 6.7 to 26.
  • Under CPU load with 18 yes processes, lockf -t 3600 /tmp/vscode-no-timeout-polling-stress.lock bash -c 'pids=(); for i in $(seq 18); do yes > /dev/null & pids+=($!); done; ./scripts/test.sh --run <the 4 files> 2>&1 | grep -E "passing|failing"; kill "${pids[@]}"', alternating with the original files:
    • New: 2027 passing, 16 pending (45 s Mocha time, 68 s wall, load average 8 to 27); 2027 passing, 16 pending (42 s, 104 s wall, load 32 to 33).
    • Original: 2027 passing, 16 pending (38 s, 81 s wall, load 27 to 32); 2027 passing, 16 pending (44 s, 91 s wall, load 33 to 34).
    • The 18 yes processes raised the 1-minute load average to about 27 to 34 on this machine. Neither version failed, so this load does not show a difference between them.
  • Mutation checks, each applied by a script, run with --grep, and restored byte for byte (verified with filecmp):
    • M1, in-flight refresh: without await agent['_modelRefreshInFlight'] in bootstrapModelRefresh, three of the four bootstrap tests fail with an empty catalog ("signed out with an SDK-reported account", "the SDK default alias row is dropped", "signed out, the native catalog bootstraps"). "native model enumeration closes the throwaway query" still passes: the query closes before the test resumes, earlier in the same refresh.
    • M2, fake SDK signal: with fireDidRecordCall() not firing, "the SDK default alias row is dropped", "nothing configured" and "a download that lands stays downloading" hit the Mocha timeout.
    • M3 and M3b, negative check: with the product publishing the SDK's static list without an account, "nothing configured" fails and lists the model. With the same mutation and without the in-flight await, it passes.
    • M4, models observable: without the waitForState, "first sign-in keeps the native catalog published" fails with bootstrap: [].
    • M5 and M6, setup channel test: without the waitForState after releasing the enumeration, the test still passes, because the settle() that follows also covers it. Without the waitForCalls for the download's enumeration, it also passes: the download publishes downloading synchronously and the catalog is empty until the gate opens, so the snapshot is the same. The wait sets up the state the test names but does not decide its result, as with the old loop.
    • M7 and M8, stub deferreds: with the setMetadata stubs never completing persistEntered, both race tests hit the Mocha timeout. Without awaiting it, "agent.dispose() during a racing first sendMessage" fails (rejectedIsCancellation: false, warmQueryDisposed: false); "teardown racing _writeCustomizationDirectory" still passes.
    • M9, stub deferred: without awaiting upstreamCalled, "dispose() with in-flight non-streaming aborts the upstream call" fails with "expected abort to fire on dispose".
    • M10 and M11, root config write: without the whenIdle() before the read, and separately with the product's whenIdle() not awaiting _rootConfigWrite, "applies and persists root config changes from clients" fails with ENOENT for the config file.
    • M12 and M13, transport sends: with the helpers' onDidSend wait never resolving, the first two soft reconnect tests that call them hit the Mocha timeout, and the failing afterEach stops the suite. With the chunk loop's next send never resolving, "stages large imported conversations in bounded chunks" hits the Mocha timeout.
    • P1, probe: counting in the helpers over the soft reconnect suite gave 123 calls, 79 of which had to wait for a send.
  • lockf -t 3600 /tmp/vscode-no-timeout-polling-typecheck.lock npm run typecheck-client: no errors in the changed files, before the rebase and on 7e76185. The command still exits with errors in files this PR does not touch, 19 before the rebase and 20 after it: fusionTier in the Copilot agent files and their tests, and after the rebase setParentWindow in terminalProcess.ts from Parent the ConPTY console window to the VS Code window #342784. Both come from the shared node_modules, whose @github/copilot-sdk (1.0.24-preview.0) and node-pty (1.2.0-beta.15) are behind this tree's pins (1.0.26 and ^1.2.0-beta.18).
  • npm run eslint -- <the 4 files>: no problems.
  • Self-review with the code-review skill: no findings. Earlier, the first test run after the change found a test that used agent without destructuring it, and the first type check found that the type guards in a first version of waitForRequest and waitForRequestAt did not narrow; both were fixed before the runs above.

…t host tests

Replace waits for state that the timeout-polling lint rule cannot see:
setImmediate tick loops in claudeAgent.test.ts, a setInterval waiter in
claudeProxyService.test.ts, a read-and-retry loop in agentService.test.ts,
and a setTimeout(0) loop plus two microtask-spinning helpers in
agentHostProtocolClient.test.ts. Each test now awaits the operation it
waited for: the agent's bootstrap model refresh, the models observable,
the fake SDK's recorded calls, deferreds completed by the tests' stubs,
the configuration service's root-config write, or the transport's sends.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 08:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The test-only changes use the relevant completion signals, preserve assertions, and have no unresolved blocking findings.

No open issues 🎉

What changed in this PR

This PR continues the Agent Host test synchronization cleanup by replacing hidden polling waits with explicit completion signals. It changes only tests, preserving existing scenarios and assertions.

Changes:

  • Await fake SDK events, model publication, and deferred stub signals in Claude tests.
  • Await root configuration persistence before reading the saved file.
  • Replace protocol request microtask loops and chunk-acknowledgement timer waits with transport send events.

No actionable findings remain.

File Description
src/​vs/​platform/​agentHost/​test/​node/​claudeProxyService.test.ts Waits for an explicit upstream-call signal before testing disposal.
src/​vs/​platform/​agentHost/​test/​node/​claudeAgent.test.ts Uses SDK events, refresh completion, observable state, and deferred signals instead of polling.
src/​vs/​platform/​agentHost/​test/​node/​agentService.test.ts Awaits dispatch and configuration persistence before asserting saved values.
src/​vs/​platform/​agentHost/​test/​electron-browser/​agentHostProtocolClient.test.ts Waits for transport sends during chunk staging and request lookup.

Review effort: Balanced

@alexdima
Alexandru Dima (alexdima) marked this pull request as ready for review October 23, 2026 13:58
@alexdima
Alexandru Dima (alexdima) merged commit 5e99dca into main Oct 23, 2026
59 checks passed
@alexdima
Alexandru Dima (alexdima) deleted the agents/no-timeout-polling-agent-host-v2 branch October 23, 2026 14:10
@vs-code-engineering vs-code-engineering Bot added this to the 1.144.0 milestone Oct 23, 2026
Pulkit Jain (pulkitjain26) added a commit to pulkitjain-org/vscode-gemini-cli that referenced this pull request Oct 29, 2026
…ler surface (#126)

* Improve Fusion Display in Model Picker with Recommended Badge (#343782)

Agent Host changes for agents/improve-fusion-display-model-picker

* agentHost: await real signals instead of polling in the local model bridge tests (#343737)

Remove settle() and waitFor() from fakeLlamaServer.ts, which yielded to
setImmediate a fixed number of times or until a predicate held. Status and
supervisor-state waits use waitForState; the fake downloader and runtime
complete deferreds; health-poll loops advance the fake clock only when a poll
is pending; the dispose test awaits the supervisor's record and lock work; and
negative checks await the provider's in-flight load or swap, or assert that
no fake-clock timer ran.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: await debug-log artifact expiry instead of polling the temp folder (#343723)

The collector's lease timer removed an expired artifact with an fs.rm
that nothing kept or signalled, so "expires an abandoned artifact"
polled readdir every 5 ms, up to 100 times. AgentHostDebugLogsCollector
now fires onDidExpireArtifact once that removal has settled, and the
test awaits it before checking the folder. The test file is removed
from the code-no-timeout-polling-loop exclude list.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: stabilize and toggle the default PR activity action (#343787)

* sessions: stabilize and toggle the PR activity bar action

Avoid repeating opener lookups for presentation-only reference changes and retain confirmed PR support during capability revalidation. Restore side-pane toggling and remove the Issue activity action while preserving its composer pill.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: show the PR activity action without a separate setting

Remove the PR-specific enable setting, command, and context-menu item. Show supported chat PRs automatically alongside other activity actions and update accessibility help and regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: run hygiene and ESLint before the compilation checks (#343788)

* ci: run ESLint before the compilation checks

Linting the changed files takes seconds, so running it right after the dependencies install fails lint errors about a minute into the job instead of after the compilation checks. The job takes as long as before, because ESLint already ran on its own after them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: run hygiene with ESLint before the compilation checks

Checking only the changed files takes seconds, so hygiene now runs with ESLint in a Hygiene & ESLint step right after the dependencies install, instead of inside the compilation checks. They run in parallel with --continue-on-error, so a PR with both kinds of errors sees both.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: run Hygiene & ESLint right before Compile

The step now runs after the other setup steps, in the same environment the checks had inside the compilation checks. With cached dependencies it still starts about 45 seconds into the job.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* tasks: assert terminal status directly instead of polling in tests (#343718)

The two poll() calls in taskTerminalStatus.test.ts waited for state that
is updated synchronously when the task event fires: Emitter.fire delivers
to TaskTerminalStatus, which updates the terminal status list in the same
call. Assert each condition right after triggerStateChange and remove the
unused timer-based poll helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: await real signals instead of hidden polling waits in agent host tests (#343728)

Replace waits for state that the timeout-polling lint rule cannot see:
setImmediate tick loops in claudeAgent.test.ts, a setInterval waiter in
claudeProxyService.test.ts, a read-and-retry loop in agentService.test.ts,
and a setTimeout(0) loop plus two microtask-spinning helpers in
agentHostProtocolClient.test.ts. Each test now awaits the operation it
waited for: the agent's bootstrap model refresh, the models observable,
the fake SDK's recorded calls, deferreds completed by the tests' stubs,
the configuration service's root-config write, or the transport's sends.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Note when to remove the WebM Media Source fallback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix focusability of empty chat pills row when no user-hidden pills exist (#343800)

Agent Host changes for agents/focusable-empty-div-issue

* Bound the WebM Media Source fallback's reads

Stream the file instead of reading it at once: stop at the first bytes when it is not WebM, and give up above 200 MB. This only applies after normal playback has already failed, so videos that play natively are unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Enable automatic retries for failed Electron unit test files (#343798)

Enable failed-file retries for Electron unit tests in PR CI

Rerun failed test files up to twice in fresh renderer processes, retain per-attempt results, and report recovered files as flaky.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Simplify Remotes management UI (#343810)

Remove the address column and description, omit empty search groups, add section help actions, and reveal right-aligned row actions on hover or keyboard focus. Show offline environments as Offline and use a spinner during refresh. Hide redundant environment entry Manage submenus when the management dialog is available.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Align agent session harness icon (#343803)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: offer Canvas in the Session Activity Bar when the chat has no canvases (#343805)

* sessions: offer Canvas in the Session Activity Bar when the chat has no canvases

Without live canvases, the Session Activity Bar's Canvas entry now lists the same canvases that can be opened or reopened as the empty editor group's Add Tab list, instead of being hidden.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: describe the empty Canvas entry in the Session Activity Bar help

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* automations: refine cloud repository ownership UX (#343789)

* automations: refine cloud repository ownership UX

Clarify repository selection and ownership eligibility, centralize dialog feedback, and keep loading and error states adjacent and accessible.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* automations: address repository eligibility review

Keep repository privacy, general authorization, and ownership checks consistent across search, account changes, and dialog accessibility.

* automations: format dialog mobile caption

* automations: address ownership accessibility review

* automations: restore provider specification

Remove dialog-specific behavior from the Copilot Chat provider specification.

* automations: defer repository ownership validation

Let creation report unsupported ownership while preserving existing public targets. Restore list focus before disabled-row hover hides row actions.

* automations: preserve error notification outline

* sessions: Preserve management for hosts missing from Remotes (#343821)

Only suppress per-host Environment picker actions for configured connection types represented in Remotes. Keep WebSocket, Dev Container, and unknown host management available, with regression coverage and accessibility help.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* build: retry npm ci in the Release stage (#343661)

The Release stage runs after ApproveRelease, so a transient registry error
in its npm ci fails the release itself. That happened twice in 90 days
(477747 on main and 478020 on release/1.140, npm EPERM fetching zx).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* build(deps-dev): bump markdown-it from 14.3.2 to 14.3.3 (#343058)

Bumps [markdown-it](https://github.com/markdown-it/markdown-it) from 14.3.2 to 14.3.3.
- [Changelog](https://github.com/markdown-it/markdown-it/blob/14.3.3/CHANGELOG.md)
- [Commits](https://github.com/markdown-it/markdown-it/compare/14.3.2...14.3.3)

---
updated-dependencies:
- dependency-name: markdown-it
  dependency-version: 14.3.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Raymond Zhao <7199958+rzhao271@users.noreply.github.com>

* build(deps): bump markdown-it from 14.3.2 to 14.3.3 in /extensions/extension-editing (#343014)

build(deps): bump markdown-it in /extensions/extension-editing

Bumps [markdown-it](https://github.com/markdown-it/markdown-it) from 14.3.2 to 14.3.3.
- [Changelog](https://github.com/markdown-it/markdown-it/blob/14.3.3/CHANGELOG.md)
- [Commits](https://github.com/markdown-it/markdown-it/compare/14.3.2...14.3.3)

---
updated-dependencies:
- dependency-name: markdown-it
  dependency-version: 14.3.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Raymond Zhao <7199958+rzhao271@users.noreply.github.com>

* Engineering - fetch crates without HTTP/2 multiplexing and retry cargo steps (#343397)

* Engineering - fetch crates without HTTP/2 multiplexing and retry cargo steps

The ADO Cargo feed intermittently cancels HTTP/2 streams ("[92] HTTP/2 stream
... CANCEL"), which failed the CLI lint or compile in 487876, 487749, 478647
and 481284 after cargo's own retries. Disable multiplexing and raise cargo's
retries on every cargo step of the CLI and Copilot shim, and retry the step on
top, except the shim tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Engineering - pass the cargo network settings as --config flags

sccache hashes every CARGO_* environment variable into its Rust compile
keys, so setting CARGO_HTTP_MULTIPLEXING and CARGO_NET_RETRY on the cargo
steps turned every sccache lookup into a miss (0 Rust hits in build 487885,
against ~225-290 on main). Cargo doesn't pass --config values on to rustc,
so the compile keys stay the same as on main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Agents window: ignore config changes from other sessions in pickers (#343836)

The new-session composer's pickers re-rendered on onDidChangeSessionConfig
for every session of every agent host provider. When a background session
churns its config (for example the sensitiveEditLocations ping-pong in
#341595), the New Worktree, branch, and mode/permissions chips are rebuilt
hundreds of times per second, so a mouse click's mousedown target is
detached before mouseup and Chromium never dispatches click.

Only re-render for the session each picker shows, and only refresh the
repository menu items for visible sessions.

Refs #341595

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix lightbulb in remote isolation picker (#343840)

Handle the host's workspace isolation value in the shared icon helper so dropdown rows, triggers, and mobile sheets use the same folder icon.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: Use normal tool approval for set_artifact_automation (#343826)

Turning on artifact automation through the agent no longer asks a separate
in-chat question that tool auto-approval cannot answer. It now follows the
current tool-approval policy like run_artifact_action, so Allow All and
Autopilot apply it directly, and interactive approval shows the artifact and
requested option values.

Removes the now-unused server tool confirmation infrastructure and lets the
agent use the tool when automation serves the user's request.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: show artifact state lists collapsed by default (#343802)

* sessions: show artifact state lists collapsed by default

Artifact details now open with every state list collapsed. Activating a tab expands its list, and activating the expanded tab collapses all lists again, so no tab is active. While collapsed, the tabs are separated by a divider, arrow keys only move focus, and the expanded or collapsed choice is still remembered per artifact.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: focus the reachable tab in the artifact keyboard-focus fixture

With state lists collapsed by default, no tab is selected, so the fixture now focuses the keyboard-reachable tab instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Improve worktree cleanup progress, preservation, and leftover-folder handling (#343676)

* sessions: inherit editor session harness icon color (#343822)

Inherit editor session harness icon color

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: make environment-first selection the default (#343843)

Remove the environment-first ordering setting and always keep Environment before Workspace when the picker is enabled. Remove local isolation choices from Environment while preserving the repository isolation picker.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: enable model comparison by default (#343844)

Enable sessions.chat.compareAgents.enabled starting with VS Code 1.144.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: hide Add Models while comparing agents

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: remove environment picker icon-only setting (#343852)

Keep picker labels as the default and preserve per-profile Collapse to Icon choices from the context menu. Remove the retired experiment trigger and update persistence coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add proposed GitHub API for profile gist sharing (#343432)

Expose disposable GitHub clients through the extension API and migrate Configuration Editing gist import/export to the shared service. Narrow gist contracts, reuse schema parsing helpers, and document the current service architecture.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use SDK-owned Copilot marketplace installation records (#343596)

* Use SDK-owned Copilot marketplace installation records

Replace the marketplace provider's client plugin inventory dependency with a typed provider-owned installation inventory. Preserve direct-source identities, catalog associations, session routing, and SDK transaction completion without client discovery waits.

Related to #343342.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Harden SDK marketplace installation records after review

Reject ambiguous and undisambiguated direct uninstall identities, precompute catalog match counts, and validate optional SDK plugin icons as credential-free HTTPS URLs. Add focused regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: track successful /btw submissions (#343856)

Emit a dedicated adoption event for the silent command without collecting prompt or context data. Cover successful submissions in both windows and exclude invalid, failed, and non-command side chats.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add ellipses to migration action labels (#343860)

Fixes #342655

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: align remote environment workspace pickers (#343867)

Use folder icons and a leading Open Folder action for the selected remote environment. Add ellipses to remote connection picker entries and cover label deduplication when the workspace is selected first.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Open migrations from Customizations when needed (#343862)

Open migrations from the Customizations button

When the Agents window signals that customization migrations need attention, route the Customizations entry directly to the migration dashboard. Preserve the regular overview behavior after the migration state clears.

Fixes #341797

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Enable automatic retries for failed Node.js unit test files (#343842)

* Enable automatic retries for failed Node.js unit test files

Rerun failed Node.js unit test files up to twice in fresh processes in PR CI, matching the Electron runner. Report recovered files as flaky and reject abnormal process exits even when a passing report was written.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Preserve Loader checks across Node.js test file retries

Forward the initial Loader-check policy to retry processes independently of their --run selection. This prevents a full-suite retry from passing when a file writes to stderr while loading, without changing targeted-run behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Show locations for installed plugins in Chat Customizations (#343869)

chat: show locations for installed plugins

Show every installed plugin's location instead of a marketplace description, using the middle-ellipsis path label shared by other customization lists. Installed plugin search also matches locations.

Fixes #341736

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Resolve empty agent skill inventories (#343722)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: add correlated cloud sandbox lifecycle telemetry (#343708)

* chat: add correlated cloud sandbox lifecycle telemetry

Record content-free client lifecycle observations with environment, task, session, connection and turn correlation. Preserve existing aggregate metrics and distinguish shared context, cancellation, readiness and missing evidence.

Add focused coverage for identity privacy, reconnect attribution, preparation cleanup, diagnostic retention and protocol compatibility.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: make sandbox lifecycle failures actionable

Add allowlisted failure locations, bounded credential retry observations and protocol state at failure without uploading rejection text, arbitrary error types or stacks. Distinguish routine credential acquisition from recovery and preserve existing aggregate metrics and network behavior.

Cover privacy validation, recovery decisions, late HTTP failures, current-transport response age and service wiring with focused regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: exclude user-local credential lifecycle telemetry

Carry local environment kind through credential minting and refresh paths, suppressing user-local lifecycle observations at serialization without changing aggregate metrics or network behavior.

Validate all lifecycle text categories against runtime allowlists and cover user-local suppression, scope forwarding, payload privacy and preserved request behavior with regression tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: avoid redundant checkouts for pinned plugin clones (#343559)

Check the cloned HEAD before repeating a pinned checkout. Retain commit verification for mismatches and preserve cached-repository checkout behavior.

Follow-up to #343514.

Co-authored-by: aeschli <6461412+aeschli@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Keep SDK marketplace add progress and errors in quick input (#343509)

* Fix plugin source installs for Copilot Agent Host

Route source installs through the active harness's management provider instead of modifying VS Code plugin locations. Preserve existing behavior for other harnesses and cover SDK routing, source formats, and failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address plugin installation review feedback

Gate native source installation on management API support, resolve the target harness at submission, and keep the input title synchronized with the selected harness. Add capability and harness-switch regression tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Keep SDK marketplace add progress and errors in quick input

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add marketplace command and browsing actions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: update bundled Codex SDK to 0.163.0 (#343717)

* agentHost: update bundled Codex SDK to 0.163.0

* agentHost: remove resolved Codex MCP expected failure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: vs-code-engineering[bot] <122617954+vs-code-engineering[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Giuseppe Cianci <gcianci@microsoft.com>

* Honor windowsReparentConsoleWindow when terminals relaunch (#343877)

Relaunching a terminal reuses its process manager, which sent the window
handle it saved before the setting changed. Check the setting each time a
process starts, keep tracking the terminal's window while the setting is
off, and forget the saved handle when the window changes.

* Show progress for customization migrations (#343884)

Show one progress notification for each confirmed migration batch and identify the active migration in the dashboard. Apply the same feedback to prompt, user-data, configured-location, MCP server, and plugin marketplace migrations.

Fixes #342542

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: use MCP authentication notifications in screen reader mode (#343893)

Fixes #343890. Preserve inline hints outside screen reader mode and keep authentication notifications actionable across turns, with cleanup when no longer needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: simplify the form and add a dedicated window (#343634)

* issueReporter: simplify reporting into a single-page form

Replace the wizard steps with Write/Preview, ordered file attachments, visible optional diagnostics, and a configurable reporter window.

Preserve attachment bytes and ownership, clarify upload failures, and reveal auxiliary windows after styled layout without losing initial focus.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: isolate the reporter window and simplify text input

Share reporter behavior between the editor host and a dedicated native window without workbench chrome or command leakage.

Use a padded native description field with Write/Preview and retain its undo state across editor tab switches. Preserve native editing, attachment ownership, source-window capture and guarded close behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: address review feedback and CI failures

Protect standalone drafts during shutdown, cancel submissions on discard, and transfer controller ownership without leaving stale capture controls.

Preserve attachment MIME types and filename suffixes, restore reporter-only zoom, and fix cross-platform native-menu tests and Markdown table escaping.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: preserve menu shortcuts and capture chord state

Use guarded standalone menu commands instead of stale native close and undo roles, and keep normal source accelerators registered on Windows and Linux.

Complete intercepted capture chords through the keybinding dispatcher so ordinary typing and IME state recover immediately.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: reduce shared infrastructure changes

Keep window and tab modes while accepting native undo reset on tab switches and the classic reporter's native-menu limitations. Remove the editor DOM retention, platform menu mode and private zoom relay.

Scope stylesheet-ready reveal to the reporter and reduce close ownership to one asynchronous callback, checking vetoes before discarding content.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: keep the selected description mode visible

Mark Write and Preview selection with a theme-aware underline and semibold label without competing with Button's inline colors and borders.

Cover persistent selection after focus changes with dark, light and high-contrast token values.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: reuse close veto only for edited drafts

Remove the shared auxiliary close hook and use the existing veto flow. Preserve drafts until actual unload or committed shutdown, cancel old submissions separately, and avoid vetoing shutdown after failed initialization.

Track title and description changes against their defaults, ignore untouched prefills and automatic templates, and protect added or pending attachments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: fix recording uploads and copy error details

Send bare MIME types to GitHub's upload policy instead of forwarding recorder codec parameters, while preserving attachment metadata and bytes.

Make technical error details selectable and add an accessible Copy action with clipboard error handling and regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: restore native text editing shortcuts

Handle resolved undo, redo and select-all commands inside the standalone form instead of relying on native browser defaults after workbench dispatch is isolated. Preserve native history and keep source-window editors untouched.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: check selectable error details across browsers

WebKit exposes text selection through -webkit-user-select. Check the computed standard or prefixed property without weakening the assertion or changing the reporter UI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: use literal native text editing commands

Keep undo, redo and select-all behavior unchanged while making the permitted execCommand calls explicit for the tsec safety check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Focus primary action instead of back button in customization detail pages (#343889)

chat: focus primary action instead of back button on customization detail pages

Opening a customization detail page (e.g. a migration item) focused the
back button, and the managed hover then showed its "Back to ..." tooltip
on focus. Detail pages now focus their enabled primary action (Migrate,
Install, Connect), then a visible editor, then the back button with its
tooltip suppressed. Focus rings on detail header controls only show for
keyboard navigation.

Fixes #342645

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix remote Copilot presentation and draft visibility (#343887)

* sessions: fix remote Copilot presentation (Written by Copilot)

Hide runtime bootstrap controls without changing host configuration, recognize the Copilot provider icon, and keep default chat titles aligned with session titles.

Keep locally owned unsent drafts out of saved-session discovery and caches while preserving eager initialization. Publish accepted sends even if the later handoff fails.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: retain drafts through peer activity (Written by Copilot)

Keep owned eager drafts suppressed through delayed discovery responses. Publish them after a host-observed turn and preserve sessions and detached worktrees used by another controller when the local draft is discarded.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fire the cloud commit once the provider listens (#343720)

The cloud commit test re-fired onDidCommit every 5 ms until sendRequest
settled, because _waitForCommittedSession subscribes only after the send
resolves. Complete a deferred from the emitter's onDidAddFirstListener hook
and fire the commit once after it. The response still completes before the
commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add tool set and chat participant migration guidance (#343882)

* chat: add participant and tool-set migration guidance

Show extension chat participants and explicit tool sets as read-only migration entries with Learn More links. Include guidance in migration counts and Ignore/Restore without adding it to executable migration candidates.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: fix migration guidance formatting

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: add review details for tool set and participant migrations

Opens tool-set and chat-participant migration guidance in a detail page that
matches the other migration details: an arrow back button, a linked source,
and a warning card with descriptive guidance links. Labels extension-owned
items as Extensions and links directly to the relevant docs sections.

Refs #341362

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: add migration guidance dashboard fixture

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Harald Kirschner <hkirschner@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: digitarald <8599+digitarald@users.noreply.github.com>

* mcp: verify local servers after the latest startup scan (#343920)

At startup, two local MCP server scans run at the same time. An old scan
could start a registry sync before the newest scan had stored its servers.
The newest scan did not start a sync, so in registry-only mode the local
servers stayed unverified and disabled until mcp.json changed.

- Start a registry sync after each accepted local scan, and not after a
  query promise completes.
- Remove the separate syncs after the initial query and after a profile
  reset. The accepted scan now starts the sync.
- Register the gallery manifest listener in the constructor, so that a
  registry status change during startup is not missed.
- Add regression tests for both scan completion orders and for a
  registry status change before the initial query completes.

Fixes https://github.com/microsoft/vscode/issues/343589

(Commit message generated by Copilot)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix Browse customization creation flows (#343921)

Reuse section creation actions for file customizations, MCP servers, and plugins instead of forcing AI generation or only navigating to a page. Preserve cancellation and disabled-state behavior and document the flow in accessibility help.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: adopt Universe Copilot SDK build (#343916)

agentHost: adopt Universe Copilot SDK build (Written by Copilot)

Pin SDK 1.0.27-unstable.39903661716.gbccf8a3 and runtime 1.0.103-unstable.r39903661716.gbccf8a3 in desktop and remote dependencies. Refresh the managed-model schema description for the Fusion alias.\n\n(Written by Copilot)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: remove cached agent SDK versions that are no longer used (#343281)

* agentHost: remove cached agent SDK versions that are no longer used

Each Claude/Codex SDK version is cached under
<userData>/agent-host/sdk-cache/<sdk>/<version>/<target> (200-400MB each)
and was never removed, so every SDK bump left the previous version behind.

Shortly after agent host startup, delete cached versions that this build
doesn't request and that no process has used for a week, plus scratch dirs
of interrupted downloads. A cache hit refreshes the mtime of the version's
.complete sentinel at most hourly, which is how processes sharing the cache
(remote servers of different versions) keep a version alive. Versions are
renamed before deletion so a version in use on Windows is never half-deleted.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: clean up interrupted SDK downloads in every kept version

Address review feedback: remove stale <target>.tmp.<pid> scratch dirs in every
cached version that is kept, not only the requested one; catch the scheduled
cleanup's promise; capture the time once in the last-use test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix blank harness picker with environment selection (#343956)

sessions: hide the harness picker when no types are available

Hide the entire picker slot when environment filtering leaves no harnesses, so options-row styles cannot expose an empty trigger. Restore the labeled picker when types become available.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: retain encryption keys after authentication (#343970)

agentHost: retain relay encryption keys (Written by Copilot)

Preserve listener-owned metadata when projecting authenticated root subscriptions so provider and MCP credentials can still be sealed after the initial handshake. Cover hosts with and without listener extensions without mutating shared host state.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: preserve Browse cards on unchanged installation updates (#343923)

* chat: preserve Browse cards on unchanged installation updates

Only rerender Browse after a displayed customization's installation state changes. Keep cards and keyboard focus intact during unrelated background MCP and installation notifications, while preserving real installation updates and search refreshes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: compare Browse installation URIs by value

Use resource equality for installation target URIs and setup URLs so equivalent inventory snapshots preserve Browse cards and focus. Cover skill/plugin target refreshes, changed targets, and setup URL actions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: retry cleanup of archived session worktrees (#343924)

* sessions: retry cleanup of archived session worktrees

Expose authoritative host cleanup status and reported errors in Worktree Cleanup. Allow manual retries without restoring sessions or deleting their history, preserving shared-worktree and archive safety checks.

Fixes #343922

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: preserve worktree cleanup progress across refreshes

Keep pending cleanup status through transient host errors and cache accepted retry outcomes so polling resumes correctly. Preselect archived worktrees unless removal failed, and fix cleanup editor formatting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: group worktrees unavailable for cleanup

Keep actionable worktrees first and explain unavailable worktrees in a collapsed section without disabled checkboxes. Preserve visible progress for requested cleanup and cover grouping, filtering, and status transitions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix cleanup status label type narrowing

Pending cleanup already implies an archived session, so exclude eligible rows directly before rendering status labels.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix keyboard focus and text selection in customization modals (#343858)

* Trap focus and allow copying in customization modals

Keep Tab and Shift+Tab within modal editor boundaries and make all embedded customization details selectable. Fixes #314168.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Preserve modal editor Tab commands

Keep equal positive tab indices in DOM order and defer to active editor or widget Tab keybindings before wrapping modal focus.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply the organization's managed default permissions to new agent sessions (#343925)

Fixes https://github.com/microsoft/vscode-internalbacklog/issues/10280

Admins can set `permissions.defaultMode` (`manual`, `assisted` or `allow-all`) in Copilot managed settings, but VS Code ignored it. In the Agents window, a remembered permission pick also overrode the admin default. With this PR, the organization's default is the starting permission level for new agent sessions in both the Editor and the Agents window, the same way the managed default model works:

- **The org default wins** over the user's remembered pick and their `chat.defaultConfiguration.approvals`. The user's `mode` still applies, and users can still change permissions within a session as the policy allows.
- **Settings shows "Managed by organization"** on `chat.defaultConfiguration` and describes the org default.
- **Permission pickers show an Org default badge** on the matching level. Screen readers announce it.
- **Disallowed modes fall back to Manual.** This happens when the admin sets Assisted or Allow All as the default but also disables it.

VS Code reads these managed keys through a new `ChatDefaultConfiguration` policy on `chat.defaultConfiguration` and merges it per property. That way an approvals-only policy keeps the user's `mode`. The runtime's own enforcement doesn't change.

## How to test

1. Put `{"permissions": {"defaultMode": "assisted"}}` in the Copilot managed-settings file.
2. In the Agents window, pick Manual, then start a new session. It should start on **Assisted**, with **Org default** shown on Assisted in the picker.
3. Set `chat.defaultConfiguration` to `{"mode": "plan", "approvals": "manual"}`. A new Editor session should start in Plan mode with Assisted permissions, and Settings should show the setting as managed.

---

*🤖 Authored with GitHub Copilot on behalf of @rwoll.*

* agentHost: update client tools without restarting sessions (#343980)

Update Copilot client tools in place when session initialization data stays the same.

- Replace client tool definitions and handlers through the SDK setTools API.
- Compare applied initialization data before a live update or required restart.
- Keep customization scopes stable across turns and client tool changes.
- Compare discovered resource URIs without their mutable serialization caches.
- Add restart diagnostics and tests for tool updates, routing, and scope isolation.
- Use a short-lived Set to track ancestors during stable serialization.

(Commit message generated by Copilot)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* workspaces: preserve remote Windows folder trust (#343931)

* agentHost: preserve remote Windows workspace trust

Normalize agent-host trust URIs across checks and persisted entries so Windows drive-letter casing does not trigger repeated trust prompts. Add regression coverage for reopening, reloads, existing entries, revocation, and trust boundaries.

Regression of #338078.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* workspaces: retain Windows folder trust for Remote-SSH

Normalize vscode-remote trust entries as well as agent-host resources so persisted drive-letter casing matches restored folders. Cover both canonical drive-letter spellings while preserving folder and host boundaries.

Related to #289835 and #339479.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: name the Windows Agent Host E2E job after what it runs (#343914)

The Windows Agent Host E2E caller job was named "Windows (run)". When the
changes cannot affect the Agent Host E2E tests, it is skipped at the caller,
so GitHub shows only that name: a lone skipped "Windows (run)" row with no
"/ Agent-Host-E2E" suffix and no Linux or macOS twin, which looks like a bug.

Rename it to "Windows (agent host)". It now shows as
"Windows (agent host) / Agent-Host-E2E" when it runs and as
"Windows (agent host)" when it is skipped. The required "Windows / Electron"
check is reported by required-checks and does not change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Improve Remote Environments entry points (#344031)

Expose Manage Remote Environments in the Command Palette and Sessions overflow, rename the editor, remove code-action tooltips from the environment menu, and left-align inline actions. Preserve the same modal sizing behavior as Customizations and Language Models.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: keep group rename draft across list rerenders (#343774)

* sessions: keep group rename draft across list rerenders

The inline group name editor was recreated from the saved name on every list refresh, discarding what the user had typed. Share the draft/selection/focus restoration used by session and chat renames with the group renderer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: close reopened group rename editor in test teardown

In browser unit tests the focused editor was blurred on disposal and committed into a groups service mock that lacks renameGroup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Add Remote Environments picker visibility controls

Layer a profile-local hidden preference over existing provider availability and expose Show/Hide actions without affecting connections or sessions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Reflect remote picker eligibility in management

Distinguish unavailable hosts from hidden preferences, share picker eligibility checks, and preserve visibility preferences across registration and availability changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Reveal selected remotes and preserve hidden-host drafts

Unhide explicit remote folder selections without overriding availability, keep existing drafts sendable on hidden connected hosts, and fix CI formatting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Keep visibility icons shown and show section refresh progress

Show per-section spinners beside counts until each discovery completes, with cancellation-safe progress and accessible busy state.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Gate remote visibility and management on its setting

Restore original picker availability when remote management is off, retain saved hidden preferences, and gate the command, overflow entry and open editor.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Add Environments setup guide action

Link the section info action and empty-state guide to the planned vscode-agent-environments redirect.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: un-skip the durable workspace transition restart test with a disk I/O budget (#342357)

agentHost: give the durable workspace transition restart test a disk I/O budget

'restores one durable transition before provider output after service restart' was skipped as flaky (#339669). It opens, closes and reopens a real SQLite database on disk, so most of its time is spent in fsync-bound commits. Where the node.js unit tests run with mocha's 2s default (the ADO Flaky Smoke Tests runs), an occasional file system stall on a loaded Linux agent pushes it past the budget. Its SessionDatabase siblings with the same pattern were fixed the same way in #340024.

Un-skip the test with an explicit 10s timeout.

Fixes #339669

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: polish cloud automations (#344003)

* sessions: polish cloud automations for Universe

Hide unsupported cloud actions, improve repository ownership recovery, and keep grouping and trigger metadata consistent across visual and accessible presentations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Engineering - update code owners (#344048)

* sessions: Preserve hidden-host workflows and report discovery failures

Keep automation history and restored remote container destinations independent of picker visibility. Surface per-section discovery failures immediately, including missing tunnel authentication.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Use a disabled eye for unavailable remote visibility

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Engineering - Rerun failed tests in isolation and split integration CI steps (#344036)

Rerun failed tests in isolation and split integration CI steps

Select failed tests and hook suites by title in fresh Electron windows or Node processes, retaining file-level fallback for large failure sets. Keep runner safety checks and per-file pass attribution intact, and report recovered failures as flaky.

Split node and extension-host integration runs so extension-host coverage continues after failures, and enable bounded retries for node integration and Agent Host E2E in pull request CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* issueReporter: enable the wizard by default (#344049)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Engineering - increase default timeout for flaky test job (#344050)

* distro: enable Copilot Chat proposals for auth issuers and rate limits (#344051)

Picks up microsoft/vscode-distro#1478, which adds the authIssuers and
languageModelRateLimit API proposals to GitHub.copilot-chat in product.json.
The extension already declares both proposals (#337846, #340100), so without
this the workbench logs that product.json enables fewer API proposals than
the extension wants, and built products do not enable the proposals.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: route offered client tools before replacement settles (#343998)

The runtime can start a newly offered client tool before the setTools
response reaches the host. Previously routing was only committed after
the response, so such a start had no client contributor and its handler
could wait forever.

Stage routing before replacing tools instead: route the union of applied
and offered client tool names, and prefer offered definitions when
resolving the owning client, while replaceTools is in flight. Commit the
offered set on success and restore the applied routing on rejection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: add row actions to artifact details lists (#343763)

* sessions: add row actions to artifact details lists

Artifact details items can declare actions that run directly through their details lease, like Load More, without the run executor. Lists render them in a floating row action bar that keeps focus and shows per-item progress. The GitHub pull request integration uses this to rerun failed GitHub Actions checks and resolve review comments, hiding resolved threads immediately rather than after the next poll.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix Chats section test broken by concurrent main merges

#343746 removed the QUICK_CHATS_SECTION_ID import and the Chats section under date grouping, while #343744 added a capped Chats section test that used both. Restore the import and run that test for the groupings that still have a Chats section, workspace and repository. This fixes the client type check in Compile & Hygiene.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: harden artifact row actions after review

Rerun Check now refreshes and requires current core and check results before running, verifies with GitHub that the linked job is that check's run on the current head, and is only offered when the linked job is the check's own run. Only the list's focused row puts its actions in the tab order, and a focused row action follows its item when the list reorders instead of staying with the reused row.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Move webSocketOverDuplex test to Node layer and clean up ESLint config (#344059)

Agent Host changes for lszomoru/agents/investigate-websocketoverduplex-test

* sessions: hide external banner for automation sessions (#344007)

* sessions: hide external banner for automations

Keep automation sessions external for ownership and filtering while suppressing the external-session banner.

* sessions: remove flaky artifact details CommentsInformation fixture (#344062)

The sessions/artifactDetails/CommentsInformation fixture rendered the same
view as the Attention fixture and only added a click-opened instant hover
on the Comments tab information button. That transient hover was captured
inconsistently, so the Light screenshot changed on unrelated PRs.

Remove the fixture and its now-unused tabInfo scenario. The same hover is
still covered by sessions/artifactIntegrations/PullRequestCommentsInformation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Engineering - fix test module import failure handling in browser runner (#344047)

* Agent Host changes for lszomoru/agents/test-module-import-failure-fix

* Fix browser test dependencies exposed by import failure checks

Replace Node-only events and Buffer usage in the common WebSocket fixture so its tests run in browsers. Move the CommonJS-dependent TextMate fixture suite to the Electron test lane without dropping coverage. Keep module import errors fatal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix browser benchmark imports and drain console logs before cleanup

Use the cross-platform environment helper so the opt-in object mutation benchmark can be imported without a Node process global. Wait for pending console listeners before closing the page so error argument serialization does not race browser cleanup and mask the original import failure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use browser-supported strict assertions in terminal escaping tests

The browser assertion shim does not export assert.strict. Import strictEqual directly to preserve strict comparisons while allowing the suite to register in browser runs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Drop WebSocket test changes superseded by upstream Node move

Keep the relocated test identical to origin/main now that #344059 places its Node-only dependencies in the Node test lane. Preserve the browser runner and remaining compatibility fixes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Automations: graduate settings (#344001)

* Automations: graduate settings

* Engineering - delete test from a previous exploration (#344075)

* sessions: Improve Remotes search and tunnel sign-in

Add inline clear and collapse actions, and offer explicit tunnel permission sign-in instead of a generic discovery error when no usable token exists.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: Fix GitHub Feed plugin activation and lifecycle (#344000)

* Fix GitHub Feed plugin activation and installation identity

Persist runtime enablement for direct plugins, activate confirmed catalog installs, and reload live chat contributions. Reconcile Browse rows and uninstall actions using stable installation identity while preserving separate marketplace copies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix formatting in plugin installation UI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Handle plugin activation cancellation and rejected enablement

Await all post-uninstall chat reloads before surfacing errors. Guard runtime enablement against local policy collisions and restore its previous state if the local commit is rejected. Update the MCP test to supply plugin discovery and await the async action, fixing browser and Electron CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Center Remotes search field actions vertically

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Show progress beside tunnel sign-in

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Handle GitHub tunnel sign-in cancellation quietly

Normalize GitHub Authentication's documented cancellation results while preserving ordinary authentication listeners and auto-connect behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Delete user-shared environments from Remotes

Add an inline Delete action without confirmation for user-local registrations. Guard account ownership, invalidate stale inventory, and withdraw local connections after deletion. Fixes #343985.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: run only the unit tests a change can affect on macOS and Windows (#342907)

* ci: run only the unit tests a change can affect on macOS and Windows

Adds build/ripple, a Rust change impact engine built on oxc. It maps a
diff to the unit test files it can affect, at the level of individual
declarations, in about a second. A new Plan Unit Tests job runs it on
the pull request's merge commit and uploads the per-runner lists as an
artifact. The macOS and Windows unit test jobs pass them to the test
runners with the new --runList option. Linux still runs every unit
test on every push.

The jobs run every unit test when the plan fails, when the change
reaches outside the module graph (test runners, transpiler, compiler
options, runtime versions), or when it affects more than half of the
unit test work. On last week's 2,184 pull request pushes they would
have run 13.5% of the macOS and Windows unit test work, about 38 VM
minutes less per push.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: TEMPORARY plan a fixed main commit to validate the selection path

Revert before merging. This pull request changes the test runners, so its own plan selects every unit test. Planning #342662 instead makes the macOS and Windows unit test jobs download the plan and run 20 Electron, 8 node.js and 12 browser test files with --runList.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Revert "ci: TEMPORARY plan a fixed main commit to validate the selection path"

This reverts commit 9c453973d31. The validation run passed: the macOS and Windows unit test jobs downloaded the plan and ran only the listed files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: plan unit tests in the Detect Changes job

Saves a VM per push. The planning steps run in the existing job, which now needs a depth-2 checkout instead of a sparse one. They never fail the job, so a planning problem only means that macOS and Windows run every unit test, and it never affects the change detection outputs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ripple: close the selection gaps found in review

- Never list deleted or renamed tests: the runners fail to import them.
- Run every unit test when a change touches the test launchers, the
  transpile and install pipeline, the npm scripts or the job definitions
  the macOS and Windows unit test jobs run.
- Hash each declaration's syntax tree along with its tokens, so changes
  that only move line breaks but change the parse are detected.
- Add a node per exported name, so retargeting an export or re-export
  selects its consumers.
- Detect reordered load-time statements and effectful imports, and make
  mutable module state depend on the load-time code that writes it.
- Print every test from 'ripple affected' when a change runs everything.

On the replayed history, the engine changes leave the selection of the
same commits unchanged (6.79% -> 6.80%); the new triggers make 1.6% of
commits run everything.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: warm the ripple cache in its own workflow

main now models pr-node-modules.yml as node_modules cache warming jobs,
and its test rejects any other job, which failed Compile & Hygiene. The
new pr-ripple.yml only runs when ripple changes, and daily in case the
cache was evicted, instead of on every push to main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ripple: move repository knowledge into vscode.jsonc

The engine now only knows TypeScript, JavaScript, npm and git. What it
knows about this repository is in build/ripple/vscode.jsonc, which every
command reads with --config: the modules and tests, the vs/ path alias,
the files every unit test depends on, the toolchain packages and test
scripts, the globals the test runners inject, and the repository's pure
functions and implicit methods.

- The test runners own their test sets: ripple writes one unit.txt, and
  --runList now runs the tests a runner would run by default, but only
  from the listed files. The browser runner exits without launching a
  browser when none of the listed files are browser tests.
- Remove what CI does not use: product entry points, OS and WebKit
  sensitivity, test keys and the pushes command.
- Changes to ripple or its configuration run every unit test.

On 630 commits of main, the old and new binaries select the same unit
test files and make the same run-everything decisions, and the old
hard-coded file rules match the configuration on every repository path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: download the unit test plan by pattern

Detect Changes only uploads the plan when the selection applies, and a
download by name fails without it, which annotated every macOS and
Windows unit test job with an error when they ran every unit test. A
download by pattern downloads nothing instead, and the unit test steps
now check for plan.json rather than the step outcome.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: TEMPORARY plan a fixed main commit to validate the selection path

Revert before merging. This pull request changes the unit test jobs, so
its own plan runs every unit test. Planning #342662 instead makes the
macOS and Windows unit test jobs download the plan and pass its 20 test
files to each runner, which should run 20 Electron, 8 node.js and 12
browser test files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Revert "ci: TEMPORARY plan a fixed main commit to validate the selection path"

This reverts commit 8e23984bea6. On that run, the macOS and Windows unit
test jobs downloaded the plan of #342662 and ran 20 Electron, 8 node.js
and 12 browser test files in 2 to 4 minutes each.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ripple: follow `this` in static members, and keep member keys unique

- Code reaches a static or object literal member directly (`X.member`),
  without its parent, so `this` and `super` inside it lost their
  dependencies. Changing `MoveCaretCommand.getEditOperations` selected
  no test: the cursor calls it through `CommandExecutor.executeCommands`,
  whose `this._innerExecuteCommands(...)` chain was not followed. Such
  members now depend on the sibling that `this.name` names, or else on
  their class or object.
- A static and an instance member of the same name (`Position.equals`)
  shared a key, so any edit to their file, even a comment, counted both
  as changed: a comment in `Position.isBefore` selected 819 test files.
  Instance members are now keyed `X.prototype.name`, and accessor pairs
  get a suffix.
- `ripple affected` prints the declarations each changed module changed.
- The READMEs compare with the merge base, and show how to include
  uncommitted changes.

On 630 commits of main, the first fix adds 19 test files to one commit,
and the second removes spurious selections from nine (307 -> 24 test
files for one of them).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ripple: reject unknown options and missing option values

The option parser took a missing value as an empty string, consumed the
next option as a value, and ignored unknown options, so `--config` at
the end failed with "cannot read the configuration", `--base --head X`
handed `--head` to git, and the renamed `--lists` silently wrote no
plan. It now fails with a clear message in each case.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ripple: close five selection gaps found in review

Each of these changes could produce a plan that skipped affected tests:

- Strings that name a repository file or folder from the root, such as
  the grammars 'extensions/json/syntaxes/JSON.tmLanguage.json' that the
  syntax highlighting fixture reads, are now path references. The linker
  keeps those that exist and never resolves them as packages.
- Reordering the members of a declaration: members whose load-time code
  is order-relevant are evaluation order entries of their own, and the
  parent's hash records the order of its properties, enum members,
  namespace members and static fields. Moving methods changes nothing.
- Constructing a class runs code: `new X()` is a call. Constructing an
  imported class is an effect; constructing a local class runs its
  constructor, instance fields, superclass, and the methods they call
  through `this`, not its other methods. Effects are now recorded per
  declaration or member, so a class is no longer impure because one of
  its methods is.
- Mutations of module state: besides assignments and updates, property
  writes, `delete`, calls of methods that may mutate their receiver and
  values passed to calls now make the state depend on the code doing it,
  including writes in the functions, constructors and methods that
  load-time code calls. Calls of local members (`Registry.add(x)`,
  `this.update()`) run them.
- Members with the same name, such as a static getter and its setter,
  are one dependency.

On 708 commits of main, 206 commits select more tests, none newly
exceed the 50% limit, and the mean share stays 9.0%. Four select fewer:
path.ts was falsely marked as having global load-time effects because
an assignment to `posix.win32` counted as calling `posix`, whose methods
use `process.cwd()`. Re-scoring the saved CI failures misses nothing
that was selected before.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* …
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants