🤖 feat: add project switcher to the scratch creation page - #3817
Conversation
On mobile the sidebar closes after navigating to the scratch new chat page, leaving no visible scope and no way to reach a project's creation page. Extract the CreationControls project select into a shared CreationProjectSelect and render it on the scratch composer with a Scratch entry plus all user projects; picking a project navigates to that project's creation page.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae43f6dc0e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…ction survives poisoned teardowns
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep them coming! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…unhide the TGL menu query
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
The CI shard intermittently never mounts Radix portal content in happy-dom (documented fragility), timing out the menu query. Mock PositionedMenu with an inline conditional render like ProjectSidebar.test.tsx does, restoring the real module after the suite.
…olves correctly mock.module resolves relative specifiers against the calling file, so the restore helper registered a bogus virtual module and left the real PositionedMenu mocked, which poisoned later suites' own mock.module registrations (useBrowserBridgeConnection's API mock stopped applying). The helper now rejects relative paths.
Summary
Adds a project switcher to the scratch chat creation page so mobile users can see the scope they are creating in and jump to a project's creation page without reopening the sidebar. Also fixes a pre-existing unit-test-harness isolation bug that this PR's new files exposed on CI.
Background
On narrow viewports the sidebar auto-collapses after navigation, so the most prominent mobile entry point (the
+next to "Chats") lands on a bare scratch composer with no visible scope and no way to reach a project. The project creation page (ProjectPage) already had a working inline project selector; the scratch page had none becauseChatInputskippedCreationControlsentirely forkind="scratch".Implementation
CreationControlsinto a sharedCreationProjectSelectcomponent (styling, tooltip,aria-label, anddata-testid="project-selector"preserved).CreationControlsnow renders the shared component; behavior unchanged.beginWorkspaceCreation(path)and lands on that project's creation page.ScratchPage.stories.tsxwith laptop + phone Pixel viewports and a pinnedmobile1local viewport; the play function opens a new scratch chat and asserts the switcher shows "Scratch".Test-isolation fixes (
tests/ui/)Adding files to the repo shifted bun's test-file discovery order on CI, which exposed a pre-existing isolation bug: some test files tear down with
globalThis.document = undefined, andinstallDom()snapshots taken after such a teardown restore that poisoned state, propagating an undefineddocumentto later file boundaries. Modules that probe the environment at module-eval time then break at those boundaries:@react-dnd/asapcrashes ondocument.createTextNode(poisoning react-dnd's exports into TDZ and cascading ~35 failures acrossProjectSidebar/AgentListItem/GitStatusIndicatorViewtests), and menu components mis-bind similarly. Fix at the harness chokepoint:installDom()'s uninstaller now self-heals: ifdocument/windowwould end up undefined, it reinstalls a baseline DOM so file boundaries stay healthy.tests/ui/dom.tseagerly evaluatesreact-dndright after the baseline bootstrap, pinning asap's scheduler binding to a healthy DOM.tests/ui/domIsolation.test.tsguards both invariants (red-green verified against each half of the fix independently); wired intomake test-unit.A second isolation class surfaced on the next CI orders: bun's
mock.moduleregistrations are process-global and survive suite completion, so file-scope stubs (most commonly a closed-Dialog-renders-null stub) leaked into later files and emptied unrelated suites (GitStatusIndicatorView,TaskGroupListItem,AgentListItem). Fixes:tests/ui/moduleMocks.tshelperrestoreModulesAfterSuitere-registers captured real exports inafterAll; applied to every file-scope Dialog mocker that lacked restoration (SshPromptDialog, PlanFileDialog, WorkflowRunToolCall, SavedQuerySqlDialog, ProjectDeleteConfirmationModal, MemoryTab, ProjectPage.autofocus).TaskGroupListItemmenu-shortcut test queries withfindByRole(..., { hidden: true }): PositionedMenu keeps content visibility-hidden until a rAF placement pass, and shortcut handling must not depend on that timing.domIsolation.test.tsis excluded from Jest's integration run (bun:testcannot resolve under Jest).Validation
bun test srclocally: 10417 pass, 1 fail that is pre-existing onmain(WorkspaceService bash monitor wakes, environment-dependent, passes on CI; verified by running the same file on a cleanmainworktree).Risks
Low for the feature:
CreationControlsis a mechanical extraction with unchanged props and markup; the new picker only renders for scratch creation composers, which previously had no controls at all.Low-medium for the harness fix: the self-heal changes what
installDom()teardown leaves behind (a baseline DOM instead ofundefined). Tests that intentionally assert a DOM-free environment after uninstalling would be affected; the full unit suite shows none exist today.Pains
The CI
Test / Unitfailure did not reproduce locally (bun's file discovery order differs per filesystem andbun testreorders CLI file arguments), so the mechanism had to be reconstructed from CI logs plus targeted probe files measuringdocument/MutationObserverstate at file boundaries.Generated with
mux• Model:anthropic:claude-fable-5• Thinking:xhigh