Skip to content

Migrate dashboard terminals from xterm.js to Hex1b web terminal - #19974

Open
Mitch Denny (mitchdenny) wants to merge 11 commits into
mainfrom
mitchdenny-hex1b-dashboard-terminal
Open

Migrate dashboard terminals from xterm.js to Hex1b web terminal#19974
Mitch Denny (mitchdenny) wants to merge 11 commits into
mainfrom
mitchdenny-hex1b-dashboard-terminal

Conversation

@mitchdenny

@mitchdenny Mitch Denny (mitchdenny) commented Sep 8, 2026

Copy link
Copy Markdown
Member

Summary

Replace the dashboard's xterm.js terminal with Hex1b for Sixel/KGP graphics, replay on reconnect, OSC 8 links and selection-adjacent copy controls. Copying returns focus to the terminal for immediate paste. Console logs are unchanged.

Current paired NuGet/npm version: 0.167.0-alpha.1547.1.798b26c. The Terminals playground also includes a shell-first notcurses-demo container.

Before merge

Tracker: mitchdenny/hex1b#515. Close out these compatibility issues before merging:

Implementation, validation and known limitations
  • Uses public HMP1/HWT1 and browser APIs with complete published assets/licenses. No vendored patches, xterm fallback or new Aspire public API.
  • Authorization, same-origin WebSocket checks and server-only resource/socket resolution are retained.
  • Module workers and transferable OffscreenCanvas are required. WebGPU and clipboard operations need an appropriate secure context; WebGL2 supports HTTP. Unsupported rendering reports an error.
  • History is currently text-only; the header uses the resource name. The package now exposes title, progress and shell-state callbacks, not yet consumed by dashboard controls.
  • Notcurses launches from a shell because DCP starts containers before terminal attachment, potentially losing startup probes. This is not a confirmed Hex1b responder bug.
  • Latest package coverage: 41 transport + 11 component + 31 Node + 20 CLI tests passed. Browser smoke covered native copy/paste, new metadata and Sixel/KGP for initial, late and reconnected viewers. Published assets were byte-matched; earlier runs also covered links and Notcurses.
  • TerminalHost: 25/26 passed with short macOS socket paths; the existing resize timeout also reproduces with baseline Hex1b 0.165.0. Local validation used a session-only nuget.org source. Existing AngleSharp/MessagePack audit warnings remain visible; no repository feeds or security suppressions were added.
Screenshots: selection controls, terminal chrome and graphics

Fluent copy icon beside selected terminal text

Terminal frame and grid dimensions

Sixel in red and Kitty graphics in blue

Pair the published HWT1 browser client with Hex1b, preserve remote terminal ownership and graphics state, and isolate terminal shadow-DOM keyboard input from dashboard shortcuts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6019354f-1f14-4f5b-9068-1179bc66b58e
Pair Hex1b and @hex1b/web-terminal at 0.167.0-alpha.1519.1.b8be265. Enable package-owned automatic renderer selection and safe OSC 8 hyperlinks, including destinations restored across reconnect. Regenerate the complete browser distribution and update localized errors, documentation, and targeted regression coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6019354f-1f14-4f5b-9068-1179bc66b58e
Copilot AI balanced review requested due to automatic review settings September 8, 2026 02:25
@github-actions

github-actions Bot commented Sep 8, 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 -- 19974

Or

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

@github-actions

github-actions Bot commented Sep 8, 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.

Copilot review overview

🔵 Needs a closer look

The broad browser-terminal migration has unresolved moderate CI, regression-coverage, and shortcut-handling issues requiring human review.

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
Severity Finding
Medium severity eng/​github-ci/​test-trigger-map.yml — This new Layer 2 routing rule has no focused real-map selector test, so a later edit can silently…
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — The tests added here mock WebTerminal.mount, so they cannot catch failures in the new…
Medium severity src/​Aspire.Dashboard/​wwwroot/​js/​app.js — Following shadowRoot.activeElement before evaluating the host bypasses the existing…
What changed in this PR

Migrates dashboard terminals from xterm.js to the GPU-backed Hex1b web terminal while preserving reconnect, input, resize, graphics, and hyperlink behavior.

Changes:

  • Adds the HMP1-to-HWT1 bridge and Hex1b terminal integration.
  • Vendors pinned browser assets and removes obsolete xterm.js assets.
  • Adds component, protocol, JavaScript, localization, asset-verification, and CI coverage.
File Description
tests/​Infrastructure.Tests/​WorkflowScripts/​DashboardTerminalScriptTests.cs Runs terminal asset script regressions.
tests/​Aspire.Dashboard.Tests/​Shared/​TerminalTestHost.cs Provides the terminal integration test host.
tests/​Aspire.Dashboard.Components.Tests/​Shared/​TestNavigationManager.cs Supports navigation and PathBase tests.
tests/​Aspire.Dashboard.Components.Tests/​Pages/​ConsoleLogsTerminalTests.cs Updates terminal page coverage.
tests/​Aspire.Dashboard.Components.Tests/​JavaScript/​KeyboardShortcuts.test.mjs Tests shadow-DOM shortcut handling.
tests/​Aspire.Dashboard.Components.Tests/​Controls/​TerminalViewTests.cs Tests terminal lifecycle and errors.
src/​Aspire.Dashboard/​wwwroot/​js/​xterm/​xterm.min.css Removes obsolete xterm styling.
src/​Aspire.Dashboard/​wwwroot/​js/​xterm/​addon-fit.min.js Removes the obsolete xterm fit add-on.
src/​Aspire.Dashboard/​wwwroot/​js/​README.md Documents terminal assets and compatibility.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​package.json Vendors Hex1b package metadata.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​LICENSE Vendors the Hex1b license.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​wire-types.js.map Vendors the wire-types source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​wire-types.js Vendors emitted wire types.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​wire-types.d.ts Vendors wire-type declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​webgpu-backend.d.ts.map Vendors the WebGPU declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​webgpu-backend.d.ts Vendors WebGPU declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​webgl2-backend.d.ts.map Vendors the WebGL2 declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​webgl2-backend.d.ts Vendors WebGL2 declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​web-terminal.d.ts.map Vendors the terminal API declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​web-terminal.d.ts Vendors terminal API declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​validation.js.map Vendors the validation source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​validation.js Vendors validation helpers.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​validation.d.ts.map Vendors the validation declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​validation.d.ts Vendors validation declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​types.js Vendors emitted public types.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-worker.d.ts.map Vendors the worker declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-worker.d.ts Vendors worker declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-theme.js.map Vendors the theme source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-theme.js Vendors terminal theme support.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-theme.d.ts.map Vendors the theme declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-theme.d.ts Vendors theme declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-sizing.js.map Vendors the sizing source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-sizing.js Vendors terminal sizing logic.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-sizing.d.ts.map Vendors the sizing declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-sizing.d.ts Vendors sizing declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-font.js Vendors terminal font loading.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-font.d.ts.map Vendors the font declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​terminal-font.d.ts Vendors font declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​selection-ui.js Vendors terminal selection UI.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​selection-ui.d.ts.map Vendors the selection UI declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​selection-ui.d.ts Vendors selection UI declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​selection-input.js Vendors selection input handling.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​selection-input.d.ts.map Vendors the selection-input declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​selection-input.d.ts Vendors selection-input declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​renderer.d.ts.map Vendors the renderer declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​renderer.d.ts Vendors renderer declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​renderer-options.js.map Vendors the renderer-options source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​renderer-options.js Vendors renderer option validation.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​renderer-options.d.ts.map Vendors the renderer-options declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​renderer-options.d.ts Vendors renderer-option declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​render-backend.js.map Vendors the render-backend source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​render-backend.js Vendors renderer abstractions.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​render-backend.d.ts.map Vendors the render-backend declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​render-backend.d.ts Vendors render-backend declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​protocol.d.ts.map Vendors the protocol declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​protocol.d.ts Vendors protocol declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​mouse-input.d.ts.map Vendors the mouse-input declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​mouse-input.d.ts Vendors mouse-input declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​input-policy.js Vendors input routing policy.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​input-policy.d.ts.map Vendors the input-policy declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​input-policy.d.ts Vendors input-policy declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​index.js.map Vendors the public entry source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​index.js Vendors the public module entry.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​index.d.ts.map Vendors the public API declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​index.d.ts Vendors public API declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​hyperlinks.js.map Vendors the hyperlink source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​hyperlinks.js Vendors safe hyperlink handling.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​hyperlinks.d.ts.map Vendors the hyperlink declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​hyperlinks.d.ts Vendors hyperlink declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​history-state.d.ts.map Vendors the history-state declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​history-state.d.ts Vendors history-state declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​fonts/​cascadia-mono-nf/​README.md Vendors terminal font provenance.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​fonts/​cascadia-mono-nf/​LICENSE.txt Vendors the terminal font license.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​backend-selection.js.map Vendors the backend-selection source map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​backend-selection.js Vendors GPU backend selection.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​backend-selection.d.ts.map Vendors the backend-selection declaration map.
src/​Aspire.Dashboard/​wwwroot/​js/​hex1b-web-terminal/​dist/​backend-selection.d.ts Vendors backend-selection declarations.
src/​Aspire.Dashboard/​wwwroot/​js/​app.js Updates shortcut handling for shadow DOM.
src/​Aspire.Dashboard/​wwwroot/​fonts/​cascadia-mono-nf/​README.md Removes obsolete font metadata.
src/​Aspire.Dashboard/​Terminal/​DefaultTerminalConnectionResolver.cs Updates terminal transport documentation.
src/​Aspire.Dashboard/​scripts/​verify-terminal-assets.mjs Verifies vendored package bytes.
src/​Aspire.Dashboard/​scripts/​update-terminal-assets.mjs Reproducibly updates vendored assets.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.zh-Hant.xlf Updates Traditional Chinese localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.zh-Hans.xlf Updates Simplified Chinese localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.tr.xlf Updates Turkish localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.ru.xlf Updates Russian localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.pt-BR.xlf Updates Portuguese localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.pl.xlf Updates Polish localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.ko.xlf Updates Korean localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.ja.xlf Updates Japanese localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.it.xlf Updates Italian localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.fr.xlf Updates French localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.es.xlf Updates Spanish localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.de.xlf Updates German localization.
src/​Aspire.Dashboard/​Resources/​xlf/​ConsoleLogs.cs.xlf Updates Czech localization.
src/​Aspire.Dashboard/​Resources/​ConsoleLogs.resx Adds terminal labels and errors.
src/​Aspire.Dashboard/​Resources/​ConsoleLogs.Designer.cs Adds generated terminal resource accessors.
src/​Aspire.Dashboard/​package.json Adds Hex1b and asset scripts.
src/​Aspire.Dashboard/​package-lock.json Locks the paired Hex1b package.
src/​Aspire.Dashboard/​Components/​Pages/​ConsoleLogs.razor.cs Updates terminal page behavior.
src/​Aspire.Dashboard/​Components/​Pages/​ConsoleLogs.razor Integrates the migrated terminal view.
src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.css Styles the terminal and error states.
src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor Hosts the Hex1b terminal UI.
src/​Aspire.Dashboard/​Aspire.Dashboard.csproj Configures terminal assets for publishing.
eng/​github-ci/​test-trigger-map.yml Adds terminal-related CI routing.
docs/​specs/​with-terminal.md Documents architecture and browser requirements.
Directory.Packages.props Pins the paired Hex1b version.
Files not reviewed (2)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • src/Aspire.Dashboard/package-lock.json: Generated file
Suppressed comments (1)

src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:143

  • This integration leaves several user-visible strings inside the terminal unlocalized. The package's default shadow-DOM UI renders Copy, Copying…, Return to live, and “N rows above live” (dist/web-terminal.js:168-169, 436-438 and dist/selection-ui.js:107), while this adapter localizes only the textarea label. That means non-English dashboard users now get English controls/status text; provide localized strings/custom host UI (or add an upstream localization hook) before enabling the default UI.
        const client = await WebTerminal.mount(state.element, {
            url: state.wsUrl,
            signal: controller.signal,
            label: state.label,
            sizing: state.sizing,

Comment on lines +102 to +109
- paths:
- src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js
- src/Aspire.Dashboard/wwwroot/js/app.js
- src/Aspire.Dashboard/package.json
- src/Aspire.Dashboard/package-lock.json
- src/Aspire.Dashboard/wwwroot/js/hex1b-web-terminal/**
- tests/Aspire.Dashboard.Components.Tests/JavaScript/**
targets: [test:Infrastructure.Tests]
Comment on lines +139 to +148
const client = await WebTerminal.mount(state.element, {
url: state.wsUrl,
signal: controller.signal,
label: state.label,
sizing: state.sizing,
// Let the package fall back to WebGL2 for unavailable WebGPU
// capabilities, including ordinary HTTP. Other initialization
// errors and runtime GPU loss must still surface as failures.
// https://github.com/mitchdenny/hex1b/pull/491
renderer: "auto",
Comment thread src/Aspire.Dashboard/wwwroot/js/app.js Outdated
Comment on lines +207 to +208
while (currentElement.shadowRoot?.activeElement) {
currentElement = currentElement.shadowRoot.activeElement;
@github-actions

github-actions Bot commented Sep 8, 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 Sep 8, 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.

Use the exact paired npm and NuGet release containing retained KGP image and partial ANSI checkpoint replay fixes. Cover late viewers, reconnects, placement-only animation, and split graphics commands through the dashboard bridge.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6019354f-1f14-4f5b-9068-1179bc66b58e
Copilot AI review requested due to automatic review settings September 8, 2026 04:44
@github-actions

github-actions Bot commented Sep 8, 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.

Copilot review overview

🔵 Needs a closer look

Moderate accessibility and CI-routing regression coverage issues remain unresolved.

Review tier: Balanced
Findings: 3 Medium severity

Pre-existing issues (3)
Severity Finding
Medium severity src/​Aspire.Dashboard/​wwwroot/​js/​app.js — Following shadowRoot.activeElement before evaluating the host bypasses the existing… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — The tests added here mock WebTerminal.mount, so they cannot catch failures in the new… View comment
Medium severity eng/​github-ci/​test-trigger-map.yml — This new Layer 2 routing rule has no focused real-map selector test, so a later edit can silently… View comment
Files not reviewed (2)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • src/Aspire.Dashboard/package-lock.json: Generated file
Suppressed comments (2)

eng/github-ci/test-trigger-map.yml:106

  • This adds curated selector behavior without a focused real-map regression in TestTriggerMapTests.AuditedLoosePathCases. Add representative terminal adapter, vendored asset, and JavaScript-test paths asserting the exact test:Infrastructure.Tests target so future glob or target changes cannot silently fall back to ALL or stop selecting the Node regressions.
  - paths:
      - src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js
      - src/Aspire.Dashboard/wwwroot/js/app.js
      - src/Aspire.Dashboard/package.json
      - src/Aspire.Dashboard/package-lock.json

src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:143

  • This mount localizes only the hidden input label, but the enabled package UI still renders hard-coded English text such as “Copy”, “Copying…”, “Return to live”, “N rows above live”, and the hyperlink hint (dist/web-terminal.js:167-169, dist/selection-ui.js:107, dist/mouse-input.js:42). This violates the dashboard’s localization pattern used for the surrounding terminal controls and errors; provide localized package strings or a dashboard-owned localized UI before shipping.
        const client = await WebTerminal.mount(state.element, {
            url: state.wsUrl,
            signal: controller.signal,
            label: state.label,
            sizing: state.sizing,

@github-actions

github-actions Bot commented Sep 8, 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 Sep 8, 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.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6019354f-1f14-4f5b-9068-1179bc66b58e
Copilot AI review requested due to automatic review settings September 8, 2026 05:28
@github-actions

github-actions Bot commented Sep 8, 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 Sep 8, 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.

Copilot review overview

🔵 Needs a closer look

Browser-only coverage and recoverable error handling remain unresolved on the sole terminal UI path.

Review tier: Balanced
Findings: 3 Medium severity

Pre-existing issues (3)
Severity Finding
Medium severity src/​Aspire.Dashboard/​wwwroot/​js/​app.js — Following shadowRoot.activeElement before evaluating the host bypasses the existing… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — The tests added here mock WebTerminal.mount, so they cannot catch failures in the new… View comment
Medium severity eng/​github-ci/​test-trigger-map.yml — This new Layer 2 routing rule has no focused real-map selector test, so a later edit can silently… View comment
Files not reviewed (2)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • src/Aspire.Dashboard/package-lock.json: Generated file
Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:188

  • After onInputError sets this state, no successful input or clipboard callback clears it; the only general clearing paths remount/reconnect the terminal. A transient clipboard denial therefore leaves the error banner visible indefinitely even after the user retries successfully. Add a dismiss/expiry or a success-state callback so recoverable input errors can clear without reconnecting the terminal.
    src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:143
  • The default WebTerminal inspection UI introduced here renders user-visible English strings such as “Copy”, “Return to live”, and “N rows above live” inside its shadow DOM (selection-ui.js/web-terminal.js). No localized labels or replacement UI are supplied, so these controls bypass the dashboard’s localization resources for every non-English culture. Please add a package localization contract (or fully replace the default inspection UI) and source these labels from the dashboard resources.

src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:148

  • The Node lifecycle tests replace WebTerminal.mount, so they never exercise the real module worker, transferable OffscreenCanvas, static-asset/CSP loading, or either GPU renderer. This migration removes the xterm fallback and makes those browser-only paths the sole terminal UI; add focused Dashboard Playwright coverage that mounts the real client (at least through WebGL2) and verifies rendering/input/reconnect.
            // Let the package fall back to WebGL2 for unavailable WebGPU
            // capabilities, including ordinary HTTP. Other initialization
            // errors and runtime GPU loss must still surface as failures.
            // https://github.com/mitchdenny/hex1b/pull/491
            renderer: "auto",

@github-actions

github-actions Bot commented Sep 8, 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.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6019354f-1f14-4f5b-9068-1179bc66b58e
Copilot AI review requested due to automatic review settings September 8, 2026 06:05
@github-actions

github-actions Bot commented Sep 8, 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.

Copilot review overview

🔵 Needs a closer look

The broad terminal migration has unresolved CI-routing and localization concerns requiring human review.

Review tier: Balanced
Findings: 3 Medium severity

Pre-existing issues (3)
Severity Finding
Medium severity src/​Aspire.Dashboard/​wwwroot/​js/​app.js — Following shadowRoot.activeElement before evaluating the host bypasses the existing… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — The tests added here mock WebTerminal.mount, so they cannot catch failures in the new… View comment
Medium severity eng/​github-ci/​test-trigger-map.yml — This new Layer 2 routing rule has no focused real-map selector test, so a later edit can silently… View comment
Files not reviewed (2)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • src/Aspire.Dashboard/package-lock.json: Generated file
Suppressed comments (2)

eng/github-ci/test-trigger-map.yml:110

  • This new Layer 2 routing rule has no focused real-map regression case, so a later glob/target change can silently stop running the Node suite. Add a representative terminal asset/script path and the expected test:Infrastructure.Tests target to TestTriggerMapTests.AuditedLoosePathCases (the existing convention at tests/Infrastructure.Tests/TestTriggerMap/TestTriggerMapTests.cs:361-385).
  - paths:
      - src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js
      - src/Aspire.Dashboard/wwwroot/js/app.js
      - src/Aspire.Dashboard/package.json
      - src/Aspire.Dashboard/package-lock.json
      - src/Aspire.Dashboard/wwwroot/js/hex1b-web-terminal/**
      - tests/Aspire.Dashboard.Components.Tests/JavaScript/**
    targets: [test:Infrastructure.Tests]
    reason: DashboardTerminalScriptTests executes the terminal lifecycle JavaScript and reads the paired package assets outside its MSBuild graph.

src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:143

  • Mounting with the package's default selection/hyperlink UI introduces user-visible English-only text (Copy/Copying… in selection-ui.js:107 and Ctrl/Cmd+click to open link in mouse-input.js:42). The surrounding dashboard terminal UI localizes its labels through ConsoleLogs.resx and even passes a localized input label here (TerminalView.razor.cs:80,215-217). Please expose/localize these package strings (or own the selection UI) before embedding it so non-English dashboard cultures do not get mixed-language controls.
        const client = await WebTerminal.mount(state.element, {
            url: state.wsUrl,
            signal: controller.signal,
            label: state.label,
            sizing: state.sizing,

@github-actions

github-actions Bot commented Sep 8, 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.

Copilot review overview

🔵 Needs a closer look

Moderate CI-routing, browser-integration, and shortcut issues remain, along with TerminalHost ownership wording nits.

Review tier: Balanced
Findings: 4 Medium severity

Pre-existing issues (4)
Severity Finding
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — This migration leaves terminal output inaccessible to screen readers: the mounted client renders… View comment
Medium severity src/​Aspire.Dashboard/​wwwroot/​js/​app.js — Following shadowRoot.activeElement before evaluating the host bypasses the existing… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — The tests added here mock WebTerminal.mount, so they cannot catch failures in the new… View comment
Medium severity eng/​github-ci/​test-trigger-map.yml — This new Layer 2 routing rule has no focused real-map selector test, so a later edit can silently… View comment
Files not reviewed (2)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • src/Aspire.Dashboard/package-lock.json: Generated file
Suppressed comments (5)

eng/github-ci/test-trigger-map.yml:109

  • This curated routing change has no focused real-map regression test. The existing structural checks only prove that the glob matches files and the target exists; they would not catch these dashboard paths being routed to the wrong test project. Add an audited loose-path case in TestTriggerMapTests that asserts representative adapter, package, and vendored-asset paths select test:Infrastructure.Tests.
  - paths:
      - src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js
      - src/Aspire.Dashboard/wwwroot/js/app.js
      - src/Aspire.Dashboard/package.json
      - src/Aspire.Dashboard/package-lock.json
      - src/Aspire.Dashboard/wwwroot/js/hex1b-web-terminal/**
      - tests/Aspire.Dashboard.Components.Tests/JavaScript/**
    targets: [test:Infrastructure.Tests]

src/Aspire.Dashboard/Components/Controls/TerminalView.razor.js:267

  • The new worker/GPU/shadow-DOM clipboard integration is covered only by Node mocks and bUnit; the existing dashboard Playwright suite has no terminal scenario. Failures in actual module-worker creation, OffscreenCanvas transfer, WebGL2 fallback, or browser focus/clipboard behavior would therefore pass CI. Add focused Playwright smoke coverage that mounts the terminal and exercises the browser integration path.
        const client = await WebTerminal.mount(state.element, {
            url: state.wsUrl,
            signal: controller.signal,
            label: state.label,
            sizing: state.sizing,
            onSelectionUI: createSelectionUI(state, current),

src/Aspire.Dashboard/Terminal/TerminalWebSocketProxy.cs:14

  • This endpoint serves WithTerminal() sessions brokered by the per-replica Aspire.TerminalHost; it is not the AppHost-owned terminal model from the unrelated spike. Calling it AppHost-owned makes the ownership and disposal boundary misleading. Describe it as TerminalHost-brokered instead.
/// Presents an AppHost-owned HMP1 terminal to a browser using Hex1b's HWT1 adapter.

src/Aspire.Dashboard/Terminal/TerminalWebSocketProxy.cs:183

  • The upstream terminal session is brokered by the per-replica Aspire.TerminalHost, not owned by the AppHost. This wording obscures which process survives when the browser mirror is disposed; use the TerminalHost ownership boundary here as well.
        // disposing it disconnects the peer, not the AppHost-owned terminal.

src/Aspire.Dashboard/wwwroot/js/app.js:208

  • Descending into the focused shadow root before preserving the host classification regresses the existing fluent-select handling. When a Fluent select delegates focus to an internal button/div, currentElement becomes that internal control, so line 213 returns false and printable keys such as r, s, or m trigger dashboard navigation while the select is active. Check a focused Fluent host with isInputElement before descending, and add a Fluent-select/internal-control case to the shortcut test.

@github-actions

github-actions Bot commented Sep 8, 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 Sep 8, 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.

@mitchdenny
Mitch Denny (mitchdenny) marked this pull request as ready for review September 8, 2026 11:07
Krishnendu Samanta (krishnendu-2003) pushed a commit to krishnendu-2003/aspire that referenced this pull request Sep 8, 2026
Review feedback on the PR: the discovery helper added to BundleDiscovery
is not connected to any production runtime path. That is correct — there
is no caller, because the types that would consume it
(TerminalService / Hex1bTerminalProcessOptions) have not landed yet.

Shipping an unused API into the three assemblies that source-link
BundleDiscovery is not worth it, so remove it along with the test that
covered only that helper. Bundle-relative discovery belongs with the
change that actually calls it, which issue microsoft#19976 already sequences
after microsoft#19974/microsoft#19887.

This leaves the PR to the part that stands on its own: publish, sign,
and stage hex1bpty.exe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PW1pn92QD5DQ94i8ML1XJD
Refresh the complete published browser distribution and version documentation. Drain complete WebSocket snapshots in the disconnect regression test rather than assuming a snapshot fits one receive buffer.

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

Copilot-Session: 6019354f-1f14-4f5b-9068-1179bc66b58e

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.

Copilot review overview

🟡 Changes recommended

Deterministic renderer failures reconnect-loop, OSC title behavior is lost, and the documented compatibility and existing review gates remain unresolved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 6 Medium severity

New issues introduced by this change (2)
Severity Finding
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor — This drops the existing OSC 0/1/2 title behavior: the header is now always ResourceName, even…
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — Every mount failure is retried, including deterministic capability, font, worker, and GPU…
Pre-existing issues (4)
Severity Finding
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — This migration leaves terminal output inaccessible to screen readers: the mounted client renders… View comment
Medium severity src/​Aspire.Dashboard/​wwwroot/​js/​app.js — Following shadowRoot.activeElement before evaluating the host bypasses the existing… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — The tests added here mock WebTerminal.mount, so they cannot catch failures in the new… View comment
Medium severity eng/​github-ci/​test-trigger-map.yml — This new Layer 2 routing rule has no focused real-map selector test, so a later edit can silently… View comment
Files not reviewed (2)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • src/Aspire.Dashboard/package-lock.json: Generated file

</div>
<div class="terminal-frame">
<div class="terminal-titlebar">
<span class="terminal-title">@(ResourceName ?? Loc[nameof(Resources.ConsoleLogs.ConsoleLogsViewTerminalOption)].Value)</span>
state.pendingSizing = null;
releaseClient(state);
notifyToolbar(state);
scheduleReconnect(state, generation);
Adapt terminal controls and theme tokens to Fluent UI v5, and preserve dropdown and terminal keyboard focus handling.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6019354f-1f14-4f5b-9068-1179bc66b58e
@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 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.

Copilot review overview

🟡 Changes recommended

Alt-selection routing, workload title integration, and repeatable browser coverage remain unresolved, with additional compatibility gates still open.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 6 Medium severity · 1 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity src/​Aspire.Dashboard/​wwwroot/​js/​README.md — This leaves the browser-only migration without repeatable browser coverage. The PR's…
Pre-existing issues (6)
Severity Finding
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — Every mount failure is retried, including deterministic capability, font, worker, and GPU… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor — This drops the existing OSC 0/1/2 title behavior: the header is now always ResourceName, even… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — This migration leaves terminal output inaccessible to screen readers: the mounted client renders… View comment
Medium severity src/​Aspire.Dashboard/​wwwroot/​js/​app.js — Following shadowRoot.activeElement before evaluating the host bypasses the existing… View comment
Medium severity src/​Aspire.Dashboard/​Components/​Controls/​TerminalView.razor.js — The tests added here mock WebTerminal.mount, so they cannot catch failures in the new… View comment
Medium severity eng/​github-ci/​test-trigger-map.yml — This new Layer 2 routing rule has no focused real-map selector test, so a later edit can silently… View comment
Files not reviewed (2)
  • src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs: Generated file
  • src/Aspire.Dashboard/package-lock.json: Generated file
Suppressed comments (1)

src/Aspire.Dashboard/Components/Controls/TerminalView.razor:17

  • The title-update merge gate remains unmet: this always renders the static resource name even though the paired client now exposes current title and onTitleChange, so OSC title updates never reach the dashboard header. Propagate title notifications through the adapter/component state and use the resource name only when the workload title is empty.
            <span class="terminal-title">@(ResourceName ?? Loc[nameof(Resources.ConsoleLogs.ConsoleLogsViewTerminalOption)].Value)</span>

state, PathBase asset URLs, deployment asset presence, and exact version parity
between `Directory.Packages.props`, the npm manifest/lockfile, and the vendored
package. Complete installed-package byte comparison belongs to the separate
acquisition verification command above. Neither suite substitutes for a browser
@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.

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.

2 participants