-
+
+
+
{translate(
'auto.components.right.sidebar.SourceControl.tooManyChanges',
@@ -78,18 +81,18 @@ export function TooManyChangesBanner({
{ value0: limit.toLocaleString() }
)}
-
+
)
}
diff --git a/tests/e2e/source-control-large-file-count.spec.ts b/tests/e2e/source-control-large-file-count.spec.ts
index 85f3710b308..c8c699b2bd8 100644
--- a/tests/e2e/source-control-large-file-count.spec.ts
+++ b/tests/e2e/source-control-large-file-count.spec.ts
@@ -31,6 +31,7 @@ import {
removeLargeFileCountUntrackedTree
} from './large-file-count-fixtures'
import { DEFAULT_GIT_STATUS_LIMIT } from '../../src/shared/git-status-limit'
+import { RIGHT_SIDEBAR_MIN_WIDTH } from '../../src/renderer/src/components/right-sidebar/right-sidebar-width'
// Matches the large-diff freeze budget: a blocking stall past 1s is the
// "UI becomes unresponsive" symptom reported in #8013.
@@ -416,12 +417,17 @@ test.describe('Source Control large file count (#8013)', () => {
rendererWorkingSetMb: { before: workingSetBeforeMb, after: workingSetAfterMb }
})
- const tooManyChangesBanner = orcaPage.getByText('Too many changes detected.', {
- exact: false
- })
+ const tooManyChangesBanner = orcaPage.getByTestId('too-many-changes-banner')
await expect(tooManyChangesBanner).toBeVisible()
if (process.env.ORCA_LARGE_FILE_SCREENSHOT_PATH) {
- await orcaPage.screenshot({ path: process.env.ORCA_LARGE_FILE_SCREENSHOT_PATH })
+ // Narrowest supported sidebar is where the banner layout is worst.
+ await orcaPage.evaluate((minWidth) => {
+ window.__store?.getState().setRightSidebarWidth(minWidth)
+ document.documentElement.classList.add('dark')
+ }, RIGHT_SIDEBAR_MIN_WIDTH)
+ await tooManyChangesBanner.screenshot({
+ path: process.env.ORCA_LARGE_FILE_SCREENSHOT_PATH
+ })
}
expect(measurement.didHitLimit).toBe(true)
@@ -439,7 +445,7 @@ test.describe('Source Control large file count (#8013)', () => {
)
expect(hugeState).not.toBeNull()
- const retryButton = tooManyChangesBanner.locator('..').getByRole('button', { name: 'Retry' })
+ const retryButton = tooManyChangesBanner.getByRole('button', { name: 'Retry' })
await expect(retryButton).toBeVisible()
// Keep automatic refreshes from removing Retry before its real request starts.
await installGitStatusRetryBarrier(electronApp, fixture.repoPath)
From 337433b39a91ae0ee20e899ab2eb03b7f3153d6b Mon Sep 17 00:00:00 2001
From: Neil <4138956+nwparker@users.noreply.github.com>
Date: Sun, 6 Sep 2026 01:30:35 -0700
Subject: [PATCH 02/22] test: preserve Windows golden command failures (#19047)
---
.github/workflows/golden-e2e-experiment.yml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/.github/workflows/golden-e2e-experiment.yml b/.github/workflows/golden-e2e-experiment.yml
index d46c80033fa..11cfa866c67 100644
--- a/.github/workflows/golden-e2e-experiment.yml
+++ b/.github/workflows/golden-e2e-experiment.yml
@@ -98,12 +98,17 @@ jobs:
$env:SKIP_BUILD = '1'
$env:ORCA_E2E_FORWARD_APP_LOGS = '1'
pnpm run --if-present test:e2e:workspace-session-golden
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
pnpm run --if-present test:e2e:windows-fresh-startup-golden
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
pnpm run --if-present test:e2e:tab-bar-agent-launch-golden
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
if (Test-Path tests/e2e/golden-fresh-profile-terminal.spec.ts) {
pnpm run test:e2e -- tests/e2e/golden-fresh-profile-terminal.spec.ts tests/e2e/golden-shell-command.spec.ts
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
pnpm run --if-present test:e2e:source-control-golden
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- name: Upload Playwright traces
if: failure()
From 0b7837430ede7e41ac2570ba9eb23db6dfdc3f52 Mon Sep 17 00:00:00 2001
From: Neil <4138956+nwparker@users.noreply.github.com>
Date: Sun, 6 Sep 2026 01:48:47 -0700
Subject: [PATCH 03/22] test: canonicalize Windows fresh-profile fixture path
(#19049)
---
tests/e2e/golden-fresh-profile-terminal.spec.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/e2e/golden-fresh-profile-terminal.spec.ts b/tests/e2e/golden-fresh-profile-terminal.spec.ts
index 5194868adb7..e987b2a20de 100644
--- a/tests/e2e/golden-fresh-profile-terminal.spec.ts
+++ b/tests/e2e/golden-fresh-profile-terminal.spec.ts
@@ -16,7 +16,7 @@ import {
test.use({ dismissOnboarding: false, seedTestRepo: false })
async function createGitRepo(): Promise
{
- const root = realpathSync(await mkdtemp(path.join(os.tmpdir(), 'orca-e2e-golden-fresh-')))
+ const root = realpathSync.native(await mkdtemp(path.join(os.tmpdir(), 'orca-e2e-golden-fresh-')))
const repoPath = path.join(root, 'golden-fresh-project')
mkdirSync(repoPath)
execFileSync('git', ['init'], { cwd: repoPath, stdio: 'pipe' })
From 5ae76afda6e24a91cc4d886214e44b2d5700ce67 Mon Sep 17 00:00:00 2001
From: Neil <4138956+nwparker@users.noreply.github.com>
Date: Sun, 6 Sep 2026 01:53:16 -0700
Subject: [PATCH 04/22] test: repair Windows paste fixture setup and newline
oracles (#19050)
---
...inal-windows-codex-multiline-paste.spec.ts | 30 ++-----------------
...inal-windows-shell-paste-ownership.spec.ts | 25 +++++++++-------
2 files changed, 18 insertions(+), 37 deletions(-)
diff --git a/tests/e2e/terminal-windows-codex-multiline-paste.spec.ts b/tests/e2e/terminal-windows-codex-multiline-paste.spec.ts
index 543f6072247..70d11602adc 100644
--- a/tests/e2e/terminal-windows-codex-multiline-paste.spec.ts
+++ b/tests/e2e/terminal-windows-codex-multiline-paste.spec.ts
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from 'node:crypto'
import { rmSync, writeFileSync } from 'node:fs'
import path from 'node:path'
import { test, expect } from './helpers/orca-app'
+import { attachRepoAndOpenTerminal } from './helpers/orca-restart'
import {
focusActiveTerminalInput,
getTerminalContent,
@@ -54,33 +55,8 @@ async function activateTestRepository(
page: Parameters[0],
repoPath: string
): Promise {
- await page.evaluate(async (targetRepoPath) => {
- const normalizePath = (value: string): string => value.replaceAll('\\', '/').toLowerCase()
- await window.api.repos.add({ path: targetRepoPath })
- const store = window.__store
- if (!store) {
- throw new Error('Orca store unavailable')
- }
- await store.getState().fetchRepos()
- const repo = store
- .getState()
- .repos.find((candidate) => normalizePath(candidate.path) === normalizePath(targetRepoPath))
- if (!repo) {
- throw new Error('Seeded repository unavailable')
- }
- await store.getState().updateRepo(repo.id, { externalWorktreeVisibility: 'show' })
- await store.getState().fetchWorktrees(repo.id)
- const worktree = store
- .getState()
- .worktreesByRepo[repo.id]?.find(
- (candidate) => normalizePath(candidate.path) === normalizePath(targetRepoPath)
- )
- if (!worktree) {
- throw new Error('Seeded worktree unavailable')
- }
- store.getState().setActiveWorktree(worktree.id)
- store.getState().createTab(worktree.id)
- }, repoPath)
+ const worktreeId = await attachRepoAndOpenTerminal(page, repoPath)
+ await page.evaluate((id) => window.__store!.getState().createTab(id), worktreeId)
}
function pasteCollectorScript(
diff --git a/tests/e2e/terminal-windows-shell-paste-ownership.spec.ts b/tests/e2e/terminal-windows-shell-paste-ownership.spec.ts
index 43fad9122a2..c94bf8a7f38 100644
--- a/tests/e2e/terminal-windows-shell-paste-ownership.spec.ts
+++ b/tests/e2e/terminal-windows-shell-paste-ownership.spec.ts
@@ -221,7 +221,8 @@ test.describe('Windows terminal shell paste ownership', () => {
`mixed-newline-before\r\nlf-line\ncrlf-line\r\n${sentinel}`
].join('\n')
const scriptPath = path.join(testRepoPath, `.orca-paste-powershell-shell-${runId}.mjs`)
- writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, payload))
+ const expectedText = payload.replace(/\r?\n/g, '\r')
+ writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, expectedText))
let scriptStarted = false
try {
@@ -237,7 +238,7 @@ test.describe('Windows terminal shell paste ownership', () => {
await waitForTerminalOutput(orcaPage, `PASTE_COMPLETE_${runId}:MATCH`, 10_000, 12_000)
const writes = (await readTerminalPtyWrites(electronApp)).join('')
- expect(countOccurrences(writes, payload), 'PowerShell payload PTY write count').toBe(1)
+ expect(countOccurrences(writes, expectedText), 'PowerShell payload PTY write count').toBe(1)
} finally {
if (scriptStarted) {
await sendToTerminal(orcaPage, ptyId, '\x03').catch(() => undefined)
@@ -271,7 +272,8 @@ test.describe('Windows terminal shell paste ownership', () => {
`mixed-newline-before\r\nlf-line\ncrlf-line\r\n${sentinel}`
].join('\n')
const scriptPath = path.join(testRepoPath, `.orca-paste-cmd-shell-${runId}.mjs`)
- writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, payload))
+ const expectedText = payload.replace(/\r?\n/g, '\r')
+ writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, expectedText))
let scriptStarted = false
try {
@@ -287,7 +289,7 @@ test.describe('Windows terminal shell paste ownership', () => {
await waitForTerminalOutput(orcaPage, `PASTE_COMPLETE_${runId}:MATCH`, 10_000, 12_000)
const writes = (await readTerminalPtyWrites(electronApp)).join('')
- expect(countOccurrences(writes, payload), 'cmd.exe payload PTY write count').toBe(1)
+ expect(countOccurrences(writes, expectedText), 'cmd.exe payload PTY write count').toBe(1)
} finally {
if (scriptStarted) {
await sendToTerminal(orcaPage, ptyId, '\x03').catch(() => undefined)
@@ -322,7 +324,8 @@ test.describe('Windows terminal shell paste ownership', () => {
`mixed-newline-before\r\nlf-line\ncrlf-line\r\n${sentinel}`
].join('\n')
const scriptPath = path.join(testRepoPath, `.orca-paste-git-bash-shell-${runId}.mjs`)
- writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, payload))
+ const expectedText = payload.replace(/\r?\n/g, '\r')
+ writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, expectedText))
let scriptStarted = false
try {
@@ -338,7 +341,7 @@ test.describe('Windows terminal shell paste ownership', () => {
await waitForTerminalOutput(orcaPage, `PASTE_COMPLETE_${runId}:MATCH`, 10_000, 12_000)
const writes = (await readTerminalPtyWrites(electronApp)).join('')
- expect(countOccurrences(writes, payload), 'Git Bash payload PTY write count').toBe(1)
+ expect(countOccurrences(writes, expectedText), 'Git Bash payload PTY write count').toBe(1)
} finally {
if (scriptStarted) {
await sendToTerminal(orcaPage, ptyId, '\x03').catch(() => undefined)
@@ -376,7 +379,8 @@ test.describe('Windows terminal shell paste ownership', () => {
`mixed-newline-before\r\nlf-line\ncrlf-line\r\n${sentinel}`
].join('\n')
const scriptPath = path.join(testRepoPath, `.orca-paste-wsl-shell-${runId}.mjs`)
- writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, payload))
+ const expectedText = payload.replace(/\r?\n/g, '\r')
+ writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, expectedText))
let scriptStarted = false
try {
@@ -396,7 +400,7 @@ test.describe('Windows terminal shell paste ownership', () => {
await waitForTerminalOutput(orcaPage, `PASTE_COMPLETE_${runId}:MATCH`, 10_000, 12_000)
const writes = (await readTerminalPtyWrites(electronApp)).join('')
- expect(countOccurrences(writes, payload), 'WSL payload PTY write count').toBe(1)
+ expect(countOccurrences(writes, expectedText), 'WSL payload PTY write count').toBe(1)
} finally {
if (scriptStarted) {
await sendToTerminal(orcaPage, ptyId, '\x03').catch(() => undefined)
@@ -437,7 +441,8 @@ test.describe('Windows terminal shell paste ownership', () => {
`mixed-newline-before\r\nlf-line\ncrlf-line\r\n${sentinel}`
].join('\n')
const scriptPath = path.join(testRepoPath, `.orca-paste-wsl-retention-${runId}.mjs`)
- writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, payload))
+ const expectedText = payload.replace(/\r?\n/g, '\r')
+ writeFileSync(scriptPath, pasteCollectScript(runId, sentinel, expectedText))
let scriptStarted = false
try {
@@ -457,7 +462,7 @@ test.describe('Windows terminal shell paste ownership', () => {
await waitForTerminalOutput(orcaPage, `PASTE_COMPLETE_${runId}:MATCH`, 10_000, 12_000)
const writes = (await readTerminalPtyWrites(electronApp)).join('')
- expect(countOccurrences(writes, payload), 'retained WSL payload PTY write count').toBe(1)
+ expect(countOccurrences(writes, expectedText), 'retained WSL payload PTY write count').toBe(1)
} finally {
if (scriptStarted) {
await sendToTerminal(orcaPage, ptyId, '\x03').catch(() => undefined)
From 3d48d3a481af0aa6a8738a12d0beffea7b3e0605 Mon Sep 17 00:00:00 2001
From: Neil <4138956+nwparker@users.noreply.github.com>
Date: Sun, 6 Sep 2026 02:03:40 -0700
Subject: [PATCH 05/22] fix(source-control): stack the Create PR notice's
settings link below its message (#19046)
---
.../source-control/commit/commit-notices.tsx | 6 +-
...rol-create-pr-intent-notice-layout.spec.ts | 91 +++++++++++++++++++
2 files changed, 94 insertions(+), 3 deletions(-)
create mode 100644 tests/e2e/source-control-create-pr-intent-notice-layout.spec.ts
diff --git a/src/renderer/src/components/right-sidebar/source-control/commit/commit-notices.tsx b/src/renderer/src/components/right-sidebar/source-control/commit/commit-notices.tsx
index e46b1f6b3ea..666181a649a 100644
--- a/src/renderer/src/components/right-sidebar/source-control/commit/commit-notices.tsx
+++ b/src/renderer/src/components/right-sidebar/source-control/commit/commit-notices.tsx
@@ -113,20 +113,20 @@ export function CommitNotices({
role={createPrIntentNotice.tone === 'destructive' ? 'alert' : 'status'}
aria-live="polite"
className={cn(
- 'mt-1 flex min-w-0 items-center gap-1.5 text-[11px]',
+ 'mt-1 flex min-w-0 flex-col items-start gap-1 text-[11px]',
createPrIntentNotice.tone === 'destructive'
? 'text-destructive'
: 'text-muted-foreground'
)}
>
{/* Why: Create Review blockers carry recovery steps; truncating hides the action the user needs in a narrow sidebar. */}
-
+
{createPrIntentNotice.message}
{createPrIntentNotice.action === 'settings' && onOpenSourceControlAiSettings ? (