Skip to content

fix(web): keep the selected environment when changing projects - #9102

Merged
maria-rcks merged 1 commit into
mainfrom
t3code/preserve-selected-env
Sep 1, 2026
Merged

maria-rcks merged 1 commit into
mainfrom
t3code/preserve-selected-env

fix(web): keep the selected environment when changing projects

4cf46da
Select commit
Loading
Failed to load commit list.
MacroscopeApp / Macroscope - UI Consistency succeeded Sep 1, 2026 in 3m 7s

UI Consistency: no issues found

All clear

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.

Reviewed the in-scope change to apps/web/src/sidebarProjectGrouping.ts and its added test in apps/web/src/environmentGrouping.test.ts.

  • The picker now resolves each group's targetProject from the explicitly supplied preferredProjectRef (thread/draft-derived in CommandPalette.tsx, activeProjectRef in DraftHeroHeadline.tsx) rather than only for the group containing that ref. No global active-environment fallback is introduced; when a group has no member in that environment it falls back to the group representative, matching prior behavior.
  • Verified against buildProjectGroups in packages/client-runtime/src/state/projectGrouping.ts that the same-environment find yields the same project as representative when the preferred environment is the primary one, so existing single-environment behavior is unchanged.
  • Both consumers keep label/description and action on the same environment: CommandPalette derives the location label and workspace root from the same targetProject it dispatches handleNewThread against, and the favicon is scoped to that environment.
  • No component, primitive, Tailwind, CSS, theme, or scroll/virtualization surfaces were touched by this PR.

🔍 Agent activity — 7 tool calls

💭 I want to check the actual code in sidebarProjectGrouping.ts to evaluate this change, since the diff switches the preferredProject computation from checking isPreferred to checking preferredProjectRef instead.

1. browse_code — apps/web/src/sidebarProjectGrouping.ts

2. browse_code — apps/web/src/sidebarProjectGrouping.ts

💭 I see now that the change extends preferredProject logic to all groups, not just the one containing the preferred ref—preferring a member matching the current environment when switching projects, falling back to the group representative otherwise. This looks intentional rather than a routing bug, matching the docs update, though I want to check whether targetProject feeds into a server RPC when the picker switches projects. Let me check callers to make sure nothing else depends on the old preferredProject semantics.

3. git_tools — buildSidebarProjectPickerEntries

💭 The change looks intentional and matches the docs, affecting DraftHeroHeadline and CommandPalette which both now target same-environment members for other groups. I'm checking whether isPreferred semantics still hold, and thinking through the edge case where the current environment is primary — previously non-preferred groups targeted the primary-environment representative, so I want to confirm this shift doesn't introduce a regression there. For groups that don't include the current project, this now returns the first member matching the environment instead of the chosen representative, which could matter if a group has duplicate primary-environment members from merged/stale projects — the ordering in memberProjects versus memberProjectRefs makes me want to check how buildProjectGroups picks and orders representatives to be sure the target stays correct.

4. browse_code — apps/web/src/logicalProject.ts

5. browse_code — In packages (client-runtime) state/project-grouping, show the implementation of buildProjectGroups: how members are ordered and how representative is selected (especially with preferredEnvironmentId). Paste the relevant source.

💭 I'm confirming the fallback logic works correctly: when the preferred environment matches the primary environment, the result matches the representative member exactly, so there's no behavior change there, and when there's no match it still falls back to the representative. The second fallback for targetProject also relies on the representative's environmentId and id, which checks out fine. Now I want to verify that having the picker target a remote project variant is intentional — it routes RPCs to that environment, which aligns with the environment-routing feature this change is implementing via preferredProjectRef. But I should double-check whether any other place in CommandPalette assumes targetProject is always the primary/local project, like file listings or "open in editor" actions, so I need to trace how pickerProjects and projectGroupByTargetKey are used elsewhere.

6. git_tools — pickerProjects|projectGroupByTargetKey|projectPickerEntries

💭 I'm checking that the project thread list's description label and RPC target stay consistent by using the same environment variant, then looking at how openProjectFromSearch resolves the selected project using the current environment preference and finds the latest thread across the group. The favicon loading, environment fallback for group membership, and the broadened scope of preferredProject's second lookup all seem intentional and correctly matched to the destination environment. Since this change is isolated to logic in a non-component module, there's no UI or docs impact to worry about. Now I want to trace where contextualProjectRef gets its environment from in CommandPalette — it may fall back to defaultProjectRef when there's no active thread, so I need to check resolveThreadActionProjectRef and how defaultProjectRef derives the active environment to make sure that fallback semantics match what's now happening in the picker logic.

7. git_tools — function resolveThreadActionProjectRef

💭 That scope looks legitimate given the active thread. But I'm noticing a potential inconsistency: previously isPreferred and preferredProject were tied together, whereas now preferredProject can be set for non-preferred groups too. Since the menu only shows group.displayName without any environment indicator, this divergence could create a UI consistency issue worth flagging. Checking CommandPalette's "New thread in X" list, the description already pulls the environment location label from the target project's environment ID, so that path looks correctly wired to reflect the new target env. I'm also checking whether anything assumes targetProject equals the group's representative fields — projectFavicon uses the target project's env/cwd directly, so that's fine. And openProjectFromSearch creating a new thread in the target project under remote-thread context matches the documented intended behavior. I'll also note that mobile app logic is out of scope here since the include patterns are limited to the web app. Now double-checking whether Sidebar itself or any other consumer of the picker-entries builder exists — grep only turned up two consumers plus a test, so nothing else to trace. In DraftHeroHeadline, the active project key computation and menu radio group value are unchanged, so no inconsistency there. Scanning the rest of the diff confirms it only touches three files with no CSS or component changes. I'm considering whether the fallback logic — matching by exact project id first, then by environment id across all groups — introduces any subtle correctness issue, but it seems sound, and the edge case where a preferred environment isn't in any group falling back to a representative project is handled fine too. So I don't see any real findings to report, though I need to reconcile that with the response format requirements rather than just outputting a bare "clear" statement. Since this check defaults to failure only when there are findings, and I have none, this should resolve as a success state. I'll structure the response according to the schema with a summary conveying that everything looks clear.


Agent Credits: 81 credits

Token usage: 20 uncached input · 303,583 cache-read input · 65,474 cache-write input · 8,113 output
Agent Credits may also include non-token charges from external tools such as web research.