Skip to content

Make Aspire extension activity notifications dismissible - #19124

Merged
Adam Ratzman (adamint) merged 10 commits into
microsoft:mainfrom
adamint:adamint/issue19036-dismissible-status-notifications
Aug 12, 2026
Merged

Make Aspire extension activity notifications dismissible#19124
Adam Ratzman (adamint) merged 10 commits into
microsoft:mainfrom
adamint:adamint/issue19036-dismissible-status-notifications

Conversation

@adamint

@adamint Adam Ratzman (adamint) commented Aug 7, 2026

Copy link
Copy Markdown
Member

Description

Long-running build, AppHost connection, and dashboard startup activity was reported through a progress notification. A notification progress cannot be dismissed while it is active, so it sits on top of the editor for the entire run.

That activity now reports as window progress, which VS Code renders in the status bar. It can be ignored or hidden without stopping anything.

What this removes

Notification progress was cancellable: true, and cancelling it called stopCli(). Window progress has no cancel affordance, so that button and its stopCli() wiring are gone — which is why ProgressNotifier no longer needs an ICliRpcClient and why interactionService.ts is a one-line change. Stopping is done through the existing stop affordances rather than the progress UI.

Rendering text the extension does not author

The status text originates from the CLI, so it is treated as untrusted before it reaches a VS Code surface that interprets markup:

  • escapeCodicons escapes $(name) codicon syntax, which the status bar and window progress both render. Without it, CLI output could inject arbitrary icons into Aspire's status text.
  • collapseWhitespace folds newlines and runs of whitespace into single spaces. CLI status text can span lines, which neither a single-line VS Code label nor a screen reader renders well.

Both live in extension/src/utils/strings.ts with unit coverage in strings.test.ts. renderStatusMessage in progressNotifier.ts composes them as escapeCodicons(collapseWhitespace(formatText(statusText))).

Scope

This is the notification-presentation half only. Extension shutdown, RPC connection ownership, and workspace-identity path handling were split into #19152. There is no dependency between the two branches — they touch disjoint hunks and can merge in either order.

User-facing usage

Starting an AppHost reports long-running Aspire activity as window progress in the VS Code status bar instead of a notification that blocks the editor. The activity can be ignored or hidden without terminating the AppHost. The cancel button that the notification used to carry is gone; stopping happens through the existing stop affordances.

Screenshots / Recordings

No recording is attached. The visible change is notification progress moving to window progress in the status bar.

Fixes #19036

Checklist

  • Is this feature complete?

    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?

    • Yes
    • No
  • Did you add public API?

    • Yes
    • No
  • Does the change make any security assumptions or guarantees?

    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No

    CLI-supplied status text is treated as untrusted before it reaches a VS Code surface that renders markup. escapeCodicons prevents $(icon) injection into the status bar and window progress; collapseWhitespace prevents multi-line text from breaking single-line labels and screen reader output.

Review follow-up

Re-checked the notification E2E race and fixed the test to wait until one of the CLI run status strings is visible in the workbench before reading notifications. The notification assertion now runs while the delayed status is still present. I also added a source guard so the test cannot drift back to reading notifications first.

The rejected review finding was still rejected: this body already says the cancel button is gone and stopping happens through the existing stop affordances, so I did not change that claim.

Validation from extension/:

corepack yarn compile-tests   passed
corepack yarn compile         webpack succeeded with existing optional/ws warnings
corepack yarn lint            passed
./node_modules/.bin/mocha out/test/e2eLaunchProfile.test.js --ui tdd --grep "observes CLI run status"
  1 passing

Mutation check: removing the status wait made observes CLI run status before asserting it is not a notification fail because debugDashboard.includes('waitForAnyWorkbenchText') was false.

Pushed commit: 80a2d7454b35c0750d0428cf938c069427ce1c41.

Copilot AI balanced review requested due to automatic review settings August 7, 2026 12:02
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19124

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19124"

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.

Pull request overview

Moves long-running Aspire extension activity from blocking notifications to a shared, dismissible status bar item.

Changes:

  • Adds aggregated CLI status and stop controls.
  • Hardens RPC and extension shutdown.
  • Adds localized labels and extensive unit/E2E coverage.
Show a summary per file
File Description
extension/src/views/AppHostDataRepository.ts Moves discovery progress to status bar.
extension/src/utils/workspace.ts Generates concise workspace identities.
extension/src/test/workspace.test.ts Tests Windows root identities.
extension/src/test/rpc/interactionServiceTests.test.ts Tests status and RPC disposal behavior.
extension/src/test/rpc/aspireRpcServer.test.ts Tests RPC ownership and shutdown races.
extension/src/test/progressNotifier.test.ts Tests status notifier lifecycle.
extension/src/test/cliStatusBar.test.ts Tests aggregation and stop interactions.
extension/src/test/AspireExtensionContext.test.ts Tests asynchronous deactivation.
extension/src/test/aspireDebugSession.test.ts Tests stop-request reuse.
extension/src/test/appHostDataRepository.test.ts Updates discovery progress expectations.
extension/src/test-e2e/helpers/vscode.ts Adds status-bar E2E helpers.
extension/src/test-e2e/debugDashboard.e2e.test.ts Verifies CLI status and stopping end-to-end.
extension/src/test-e2e/appHostTree.e2e.test.ts Verifies discovery avoids notifications.
extension/src/server/rpcClient.ts Adds deterministic client disposal.
extension/src/server/progressNotifier.ts Routes CLI progress to shared status.
extension/src/server/interactionService.ts Supplies operation identities and disposal.
extension/src/server/cliStatusBar.ts Implements shared CLI activity UI.
extension/src/server/AspireRpcServer.ts Owns pending and active connections.
extension/src/loc/strings.ts Adds localized status strings.
extension/src/extension.ts Registers cleanup and async deactivation.
extension/src/debugger/AspireDebugSession.ts Reuses shutdown stop requests.
extension/src/AspireExtensionContext.ts Coordinates bounded asynchronous shutdown.
extension/package.nls.json Adds localization source entries.
extension/loc/xlf/aspire-vscode.xlf Updates generated localization data.

Review details

  • Files reviewed: 24/24 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread extension/src/server/cliStatusBar.ts Outdated
Comment thread extension/src/utils/workspace.ts Outdated
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

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.

Review details

Suppressed comments (4)

extension/src/AspireExtensionContext.ts:152

  • Promise.allSettled does not expose any result until every stop request settles. With multiple AppHosts, if one request rejects and another hangs, this race takes the timeout branch and the first failure is never logged (even if it rejects after the timeout); only the generic timeout is visible. Attach the expected/info vs unexpected/warn logging to each request as it settles, while retaining the aggregate timeout for teardown.
        const allStops = Promise.allSettled(stopRequests);
        let timeout: ReturnType<typeof setTimeout> | undefined;
        const outcome = await Promise.race([
            allStops.then(results => ({ timedOut: false as const, results })),

extension/src/utils/workspace.ts:87

  • Forward-slash UNC roots are absolute under both parsers, so this condition selects the host path implementation on POSIX. Consequently //server-a/share/ and //server-b/share/ both collapse to share, breaking the promised distinct root identities. Select Win32 semantics when its parsed root is more specific than the POSIX root; forward-slash UNC inputs are already treated as valid elsewhere (for example src/test/cliPath.test.ts:156-165).
    const pathOperations = path.win32.isAbsolute(filePath) && !path.posix.isAbsolute(filePath)
        ? path.win32
        : path;

extension/package.nls.json:191

  • This new user-facing localization key is absent from loc/xlf/aspire-vscode.xlf, while the other keys in this block are present. gulpfile.js:54-72 generates that XLF directly from package.nls.json; regenerate it so this stop-failure message is included for translation.
  "aspire-vscode.strings.failedToStopCliOperation": "Failed to stop the Aspire CLI operation: {0}",

extension/src/server/cliStatusBar.ts:275

  • slice counts UTF-16 code units, but ProgressNotifier has already expanded CLI emoji shortcodes. If a non-BMP emoji crosses this boundary, truncation emits a lone surrogate and the status bar shows a replacement character. Truncate by code points instead.
    const truncated = singleLine.length > maxRenderedStatusLength
        ? `${singleLine.slice(0, maxRenderedStatusLength - 1).trimEnd()}…`
        : singleLine;
  • Files reviewed: 24/24 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

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.

Review details

Suppressed comments (4)

extension/src/server/cliStatusBar.ts:253

  • A normal stopCli follows this rejection path: ExtensionRpcTarget.StopCliAsync() calls Environment.Exit before sending a response, so disposal rejects the pending request. The connection-close handler has already disposed this entry, but the error is logged before that check, causing every successful status-bar stop to emit a misleading “Failed to stop CLI” error. Check disposal before logging so only failures for a still-live operation are reported.
        this._owner.stop().catch(err => {
            extensionLogOutputChannel.error(`Failed to stop CLI: ${err}`);

extension/package.nls.json:191

  • failedToStopCliOperation is the only new localization key missing from extension/loc/xlf/aspire-vscode.xlf. That XLF is generated from this file by extension/gulpfile.js:54-73; regenerate it so the new user-facing error is included in translation input.
  "aspire-vscode.strings.failedToStopCliOperation": "Failed to stop the Aspire CLI operation: {0}",

extension/src/utils/workspace.ts:60

  • This privacy-safe identity helper is not used by the primary tree/editor launch path. AppHostLaunchService.launch() still builds the initial debug configuration name with vscode.workspace.asRelativePath(appHostPath) (extension/src/services/AppHostLaunchService.ts:147), while AspireEditorCommandProvider supports launching an AppHost from an active editor outside the workspace. In that scenario VS Code returns the absolute path unchanged, so the debug label still exposes it despite the PR’s privacy claim. Use this helper for that launch configuration and its failure label too.
export function getRelativePathToWorkspace(filePath: string): string | undefined {
    const uri = vscode.Uri.file(filePath);
    const workspaceFolder = vscode.workspace.getWorkspaceFolder(uri);
    if (!workspaceFolder) {
        return getPathIdentity(filePath);

extension/src/server/cliStatusBar.ts:275

  • String.length and slice count UTF-16 code units, so this truncation can split an emoji surrogate pair and render a replacement character. CLI status already supports emoji through formatText; truncate by code points (or grapheme clusters) before appending the ellipsis.
    const singleLine = collapseStatusText(statusText);
    const truncated = singleLine.length > maxRenderedStatusLength
        ? `${singleLine.slice(0, maxRenderedStatusLength - 1).trimEnd()}…`
        : singleLine;
  • Files reviewed: 24/24 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI review requested due to automatic review settings August 7, 2026 18:09
@adamint
Adam Ratzman (adamint) force-pushed the adamint/issue19036-dismissible-status-notifications branch from b2b7593 to 55a8351 Compare August 7, 2026 18:09

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.

Review details

Suppressed comments (2)

extension/src/test-e2e/debugDashboard.e2e.test.ts:213

  • This samples notifications only after debugAppHost has succeeded. The CLI's ShowStatusAsync queues showStatus(null) in finally before the command completes, so the old notification implementation can already be gone by this point; despite the comment above, there is no poll. This test can therefore pass before the fix. Observe one of the delayed status texts while the command is still in flight, then inspect notifications before awaiting the success outcome.
            await waitForCommandOutcome('aspire-vscode.debugAppHost', 'success', 120000, before);

            // A progress notification cannot be dismissed while the operation runs, so CLI status
            // stayed on top of the editor for the whole run
            // (https://github.com/microsoft/aspire/issues/19036).
            const notificationMessages = await getNotificationMessages();

extension/src/server/progressNotifier.ts:72

  • ProgressLocation.Window provides no cancellation callback here, and this patch removes the ICliRpcClient/token.onCancellationRequested path that called stopCli(). The status UI therefore no longer has the “explicit stop action” promised by the PR, so a build or connection that hangs before an AppHost is available cannot be stopped from the activity indicator. Use a command-backed status-bar item (or another visible action) wired to the owning RPC client.
        vscode.window.withProgress({
            location: vscode.ProgressLocation.Window
        }, async progress => {
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@adamint
Adam Ratzman (adamint) force-pushed the adamint/issue19036-dismissible-status-notifications branch from 55a8351 to 6b9f66b Compare August 7, 2026 18:30
Copilot AI review requested due to automatic review settings August 7, 2026 18:30

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.

Review details

Suppressed comments (2)

extension/src/server/progressNotifier.ts:72

  • This removes the only usable stop path for an active CLI operation: ProgressNotifier no longer receives the RPC client, cancellable is omitted, and the cancellation handler that called stopCli() is deleted. A repository-wide search now leaves stopCli() only as an uncalled method, which contradicts the PR's promise that the explicit stop action remains available. Please keep a status-bar stop action wired to the owning RPC client while making dismissal independent from stopping.
        vscode.window.withProgress({
            location: vscode.ProgressLocation.Window
        }, async progress => {

extension/src/test-e2e/debugDashboard.e2e.test.ts:213

  • This assertion runs only after debugAppHost reports success, by which time showStatus(null) or RPC closure has already removed either kind of progress. The previous notification implementation therefore also passes this regression test. Observe a delayed CLI status in the workbench and inspect notifications while that status is still active, then wait for command completion afterward.
            await waitForCommandOutcome('aspire-vscode.debugAppHost', 'success', 120000, before);

            // A progress notification cannot be dismissed while the operation runs, so CLI status
            // stayed on top of the editor for the whole run
            // (https://github.com/microsoft/aspire/issues/19036).
            const notificationMessages = await getNotificationMessages();
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Long-running Aspire activity was reported with `ProgressLocation.Notification`.
A progress notification cannot be dismissed while its operation is running, so
"Building AppHost...", "Connecting to AppHost...", "Starting dashboard..." and
"Discovering AppHosts..." sat on top of the editor for the whole run with no way
for the user to get rid of them.

Report both through `ProgressLocation.Window` instead, which renders in the
status bar: it stays visible for the whole operation, is never modal, and the
user can ignore or hide it. The notification's cancel button goes with it;
stopping a run is already covered by the debug toolbar stop, the Aspire view's
`aspire-vscode.stopAppHost` command, and `AspireDebugSession.stopDebugging()`.

CLI-supplied status text is now collapsed to a single line and has its `$(name)`
codicon syntax escaped, because the status bar renders icons and only shows one
line. Both helpers live in the vscode-free `utils/strings.ts` so other callers
that render untrusted CLI text can share them.

Fixes microsoft#19036

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 7, 2026 20:14
Copilot AI review requested due to automatic review settings August 11, 2026 03: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.

Review details

  • Files reviewed: 12/12 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

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.

I reviewed the CLI-status and workspace-discovery progress lifecycles, RPC cleanup, status-text rendering, and unit/E2E coverage.

I found no production correctness or architectural issues. I left one nonblocking test-reliability comment about the E2E's ability to distinguish status-bar progress from persistent Debug Console output.

Comment thread extension/src/test-e2e/debugDashboard.e2e.test.ts Outdated
…cations

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 12, 2026 02:42

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.

Review details

  • Files reviewed: 12/12 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

The workbench-wide text lookup can match persistent Debug Console output, so it does not prove status-bar progress is active. Keep the exact surface regression in the deterministic ProgressNotifier unit test instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 12, 2026 02:51

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.

Review details

Suppressed comments (1)

extension/src/test/e2eLaunchProfile.test.ts:498

  • The review follow-up says the debug-dashboard E2E now waits for a live CLI run status and verifies it is absent from notifications, but this assertion explicitly requires that E2E test not to exist. waitForAnyWorkbenchText is consequently unused by any real E2E, so the build/connect/dashboard UI change has only stubbed unit coverage and the claimed validation is not present. Restore reliable extension E2E coverage for the CLI status path (or remove the contradictory validation claim if this coverage is intentionally omitted).
        assert.ok(
            !debugDashboard.includes("test('keeps long-running CLI run status out of notifications'"),
            'Workbench-wide text includes persistent Debug Console output, so it cannot prove status-bar progress is active.');
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Copilot AI review requested due to automatic review settings August 12, 2026 07:03
@adamint
Adam Ratzman (adamint) enabled auto-merge (squash) August 12, 2026 07:07

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.

Review details

Suppressed comments (2)

extension/src/test/e2eLaunchProfile.test.ts:496

  • The PR description's review follow-up says the CLI-run E2E now waits for a visible status before reading notifications, but the current branch contains no such debugDashboard test and this new test explicitly requires it to remain absent. Either restore the claimed E2E coverage or update the PR description and validation claims to reflect that CLI status is covered only by unit tests.
    test('keeps CLI status surface coverage in the deterministic ProgressNotifier unit test', () => {

extension/src/test/e2eLaunchProfile.test.ts:506

  • This guard only recognizes the exact single-quoted test declaration. Reintroducing the test with double quotes or changed whitespace makes the guard pass, even though the parser and tests above explicitly support those forms. Use the parsed test name here as well so the invariant cannot be bypassed by formatting.
            !debugDashboard.includes("test('keeps long-running CLI run status out of notifications'"),
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

…cations

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 68073f86-f0a6-404e-9e2f-f461d0c629b8
Copilot AI review requested due to automatic review settings August 12, 2026 07:52

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.

Review details

Suppressed comments (2)

extension/src/test/e2eLaunchProfile.test.ts:611

  • This guard only recognizes the single-quoted declaration, so the forbidden E2E can be reintroduced with double quotes and the guard still passes—even though getTestBlock above was added specifically to handle both quoting styles. Use the parsed lookup and assert that it fails to find the test.
        assert.ok(
            !debugDashboard.includes("test('keeps long-running CLI run status out of notifications'"),
            'Workbench-wide text includes persistent Debug Console output, so it cannot prove status-bar progress is active.');

extension/src/test/e2eLaunchProfile.test.ts:605

  • The PR description says the notification E2E now waits for a CLI run status before inspecting notifications, but this test explicitly requires that E2E to be absent; the newly added waitForAnyWorkbenchText helper is consequently unused by any E2E. This leaves the primary RPC showStatus user flow covered only by a stubbed withProgress, so the generated VSIX/VS Code integration can regress without failing. Restore deterministic E2E coverage using an E2E bridge/status latch (rather than workbench-wide text) and inspect notifications while the delayed status is active, then remove this absence guard.
    test('keeps CLI status surface coverage in the deterministic ProgressNotifier unit test', () => {
        const extensionRoot = path.resolve(__dirname, '..', '..');
        const debugDashboard = fs.readFileSync(path.join(extensionRoot, 'src', 'test-e2e', 'debugDashboard.e2e.test.ts'), 'utf8');
        const progressNotifierTests = fs.readFileSync(path.join(extensionRoot, 'src', 'test', 'progressNotifier.test.ts'), 'utf8');
        const statusSurfaceTest = getTestBlock(progressNotifierTests, 'CLI status is reported as dismissible window progress rather than a notification');
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@adamint
Adam Ratzman (adamint) merged commit c605d4c into microsoft:main Aug 12, 2026
719 of 722 checks passed
@github-actions github-actions Bot added this to the 13.6 milestone Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[main] Undismissable Extension Build notifications block copilot

3 participants