From bf42b68276f2ee1e6deecf6a0eab4d41e25b0a65 Mon Sep 17 00:00:00 2001 From: KCM Date: Wed, 6 May 2026 11:09:59 -0500 Subject: [PATCH 1/2] fix: use dynamic name on new local workspace. --- AGENTS.md | 1 + .../github-pr-drawer/open-pr-create.spec.ts | 81 +++++++++++++++++++ src/app.js | 4 + .../app-core/workspace-scope-fork-actions.js | 9 +++ 4 files changed, 95 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index c033f05..42cdb76 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -101,3 +101,4 @@ Never: - Commit secrets or credentials. - Edit generated output folders unless explicitly requested. - Modify node_modules or lockfiles unless explicitly requested. +- Reintroduce cross-workspace overwrite/delete behavior with any changes. diff --git a/playwright/github-pr-drawer/open-pr-create.spec.ts b/playwright/github-pr-drawer/open-pr-create.spec.ts index 47fd39d..6d04133 100644 --- a/playwright/github-pr-drawer/open-pr-create.spec.ts +++ b/playwright/github-pr-drawer/open-pr-create.spec.ts @@ -1116,6 +1116,87 @@ test('Local New workspace always creates a new stored workspace snapshot', async await expect.poll(async () => countLocalRecords()).toBe(initialLocalRecordCount + 1) }) +test('Local New workspace shows forked head immediately when source workspace has prTitle', async ({ + page, +}) => { + const seededWorkspaceId = 'local_seed_title_carryover_guard' + const seededWorkspaceTitle = 'Seed local context title' + + await waitForAppReady(page, `${appEntryPath}`) + + await seedLocalWorkspaceContexts(page, [ + { + id: seededWorkspaceId, + repo: '', + base: 'main', + head: 'feat/component-seeded-title-guard', + prTitle: seededWorkspaceTitle, + prNumber: null, + prContextState: 'inactive', + }, + ]) + + await page.reload() + await waitForAppReady(page, `${appEntryPath}`) + await connectByotWithSingleRepo(page) + await selectWorkspacesRepositoryFilter(page, '__local__') + + await page.getByRole('button', { name: 'New workspace', exact: true }).click() + await expect(page.getByRole('complementary', { name: 'Workspaces' })).toBeHidden() + + let createdWorkspaceId = '' + await expect + .poll(async () => { + const records = await getAllWorkspaceRecords(page) + const createdRecord = records.find(record => { + const id = String(record?.id ?? '').trim() + const repo = String(record?.repo ?? '').trim() + const prTitle = String(record?.prTitle ?? '').trim() + return id !== seededWorkspaceId && !repo && !prTitle + }) + + createdWorkspaceId = String(createdRecord?.id ?? '').trim() + return createdWorkspaceId + }) + .not.toBe('') + + const createdRecords = await getAllWorkspaceRecords(page) + const createdRecord = createdRecords.find(record => { + const id = String(record?.id ?? '').trim() + return id === createdWorkspaceId + }) + + const createdHead = String(createdRecord?.head ?? '').trim() + expect(createdHead).toBeTruthy() + + await page.getByRole('button', { name: 'Workspaces' }).click() + await selectWorkspacesRepositoryFilter(page, '__local__') + + const selectedWorkspaceId = String( + (await page.locator('#workspaces-select option:checked').getAttribute('value')) ?? '', + ).trim() + expect(selectedWorkspaceId).not.toBe(seededWorkspaceId) + + const selectedLabelText = await page + .locator('#workspaces-select option:checked') + .textContent() + const selectedLabel = String(selectedLabelText ?? '').trim() + + const selectedRecord = createdRecords.find(record => { + const id = String(record?.id ?? '').trim() + return id === selectedWorkspaceId + }) + const selectedHead = String(selectedRecord?.head ?? '').trim() + const selectedPrTitle = String(selectedRecord?.prTitle ?? '').trim() + + expect(selectedPrTitle).toBe('') + expect(selectedHead).toBeTruthy() + expect(selectedLabel).toBe(selectedHead) + expect(selectedLabel).not.toBe(seededWorkspaceTitle) + await expect(page.locator('#workspace-context-status')).toContainText(selectedHead) + await expect(page.locator('#workspace-context-status')).toContainText('local') +}) + test('Non-Local New workspace forks a new repository-scoped workspace when entries exist', async ({ page, }) => { diff --git a/src/app.js b/src/app.js index 725394b..da509f1 100644 --- a/src/app.js +++ b/src/app.js @@ -950,6 +950,10 @@ const { syncActiveWorkspaceRepositoryScope, forkWorkspaceFromCurrentState } = githubPrTitle.value = value } }, + setActiveWorkspacePersistedMetadata: ({ prTitle, head } = {}) => { + activeWorkspacePersistedPrTitle = toNonEmptyWorkspaceText(prTitle) + activeWorkspacePersistedHeadBranch = toNonEmptyWorkspaceText(head) + }, }) editedIndicatorVisibilityController.setRefreshHandlers({ diff --git a/src/modules/app-core/workspace-scope-fork-actions.js b/src/modules/app-core/workspace-scope-fork-actions.js index 0a9d409..d76a9fc 100644 --- a/src/modules/app-core/workspace-scope-fork-actions.js +++ b/src/modules/app-core/workspace-scope-fork-actions.js @@ -26,6 +26,7 @@ export const createWorkspaceScopeForkActions = ({ setWorkspaceScopeMarker, setHeadBranchValue, setPrTitleValue, + setActiveWorkspacePersistedMetadata, }) => { const syncActiveWorkspaceRepositoryScope = async ( repositoryFullName, @@ -172,6 +173,14 @@ export const createWorkspaceScopeForkActions = ({ typeof saved?.createdAt === 'number' && Number.isFinite(saved.createdAt) ? saved.createdAt : now + + if (typeof setActiveWorkspacePersistedMetadata === 'function') { + setActiveWorkspacePersistedMetadata({ + prTitle: '', + head: forkedHeadBranch, + }) + } + setActiveWorkspaceRecordId(savedId) setActiveWorkspaceCreatedAt(savedCreatedAt) From 27f6736843d776807a8928bc0b8a3206c9bbf924 Mon Sep 17 00:00:00 2001 From: KCM Date: Wed, 6 May 2026 11:55:15 -0500 Subject: [PATCH 2/2] test: better selector. --- playwright/github-pr-drawer/open-pr-create.spec.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/playwright/github-pr-drawer/open-pr-create.spec.ts b/playwright/github-pr-drawer/open-pr-create.spec.ts index 6d04133..8ed3c74 100644 --- a/playwright/github-pr-drawer/open-pr-create.spec.ts +++ b/playwright/github-pr-drawer/open-pr-create.spec.ts @@ -1172,14 +1172,18 @@ test('Local New workspace shows forked head immediately when source workspace ha await page.getByRole('button', { name: 'Workspaces' }).click() await selectWorkspacesRepositoryFilter(page, '__local__') + const storedWorkspaceSelect = page.getByRole('combobox', { + name: 'Stored workspace', + }) const selectedWorkspaceId = String( - (await page.locator('#workspaces-select option:checked').getAttribute('value')) ?? '', + await storedWorkspaceSelect.evaluate(element => (element as HTMLSelectElement).value), ).trim() expect(selectedWorkspaceId).not.toBe(seededWorkspaceId) - const selectedLabelText = await page - .locator('#workspaces-select option:checked') - .textContent() + const selectedLabelText = await storedWorkspaceSelect.evaluate(element => { + const select = element as HTMLSelectElement + return select.selectedOptions.item(0)?.textContent ?? '' + }) const selectedLabel = String(selectedLabelText ?? '').trim() const selectedRecord = createdRecords.find(record => {