Skip to content

fix(web): make WSL settings searchable - #8881

Merged
juliusmarminge merged 8 commits into
pingdotgg:mainfrom
UtkarshUsername:fix/search-wsl-settings
Aug 31, 2026
Merged

juliusmarminge merged 8 commits into
pingdotgg:mainfrom
UtkarshUsername:fix/search-wsl-settings

fix(web):clamp-settings-search-selection

33b8cbd
Select commit
Loading
Failed to load commit list.
MacroscopeApp / Macroscope - UI Consistency succeeded Aug 31, 2026 in 3m 7s

UI Consistency: All clear

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 WSL settings-search change against the rendered row.

  • isWslSettingsRowVisible (ConnectionsSettings.logic.ts) is now the single owner of the row-visibility rule and is consumed by both renderWslRow() and SettingsSidebarNav, so the search catalog and the anchor can no longer drift. The state branch (available || enabled || wslOnly) is exactly the previous panel logic, and the state === null branch reduces to the old desktopWslError retry-row condition, so panel behavior is unchanged.
  • The prior concern about data and error being non-null simultaneously (SWR previousSuccess) is resolved: the predicate only consults error when state is null.
  • Gating parity checked: the panel row requires canManageLocalBackend && desktopBridge; in Electron currentSessionScopes is AuthAdministrativeScopes (includes access:write) and isElectron === (window.desktopBridge !== undefined), so the sidebar's isElectron gate matches. Both sides read the same keepAlive atom, so no split state.
  • The memo now depends on both desktopWsl.data and desktopWsl.error, so the load-error case is reachable; the new clamp effect keeps activeResultIndex, aria-activedescendant, and Enter handling valid when the result list shrinks after the WSL state resolves.
  • {...searchableSetting("wsl-backend")} matches the established pattern in SettingsPanels.tsx, IntegrationsSettings.tsx, and ProviderSettingsPanel.tsx, and the three rows that spread it are mutually exclusive, so the anchor id stays unique. isWindowsPlatform(navigator.platform) follows existing repository precedent and is SSR-guarded.

🔍 Agent activity — 16 tool calls

💭 I'm checking whether the extracted predicate in ConnectionsSettings.logic.ts properly resolves the prior concern about data and error being non-null simultaneously — it now prioritizes state when present, falling back to error only otherwise, which looks correct. I'm now looking at whether the memo's dependency on data from the earlier review comment has been addressed. Now I need to verify several remaining details: whether searchableSetting("wsl-backend") supplies a title prop for SettingRow, whether isWslSettingsRowVisible in SettingsSidebarNav correctly types desktopWsl.data (which could be undefined) against the expected DesktopWslState | null parameter, whether the hardcoded state: null in the first branch matches the actual desktopWslState at that point, and whether useEffect is properly imported in SettingsSidebarNav. I also want to check the windowsOnly gate using navigator.platform — since the sidebar now filters by state, this check might be redundant, so I should look at how isWindowsPlatform is implemented. Additionally, I need to confirm that searchSettings actually accepts the second searchableItems argument being passed to it. Let me pull up these files to check.

1. browse_code — apps/web/src/components/settings/settingsSearch.ts

2. browse_code — apps/web/src/components/settings/SettingsSidebarNav.tsx

💭 I want to check the useEnvironmentQuery signature and desktopWslStateAtom, plus how ConnectionsSettings renders the WSL row and what type wslState actually is for isWslSettingsRowVisible.

3. browse_code — apps/web/src/components/settings/ConnectionsSettings.tsx

4. browse_code — apps/web/src/components/settings/ConnectionsSettings.logic.ts

💭 I notice a mismatch: the error/retry row in ConnectionsSettings also gates on canManageLocalBackend, but the sidebar's search predicate doesn't check that flag—so if the WSL row fails to load while canManageLocalBackend is false, the row won't render even though the search item still points to it, creating a dead anchor. I need to trace where renderWslRow gets called to see how canManageLocalBackend affects the whole section.

5. git_tools — canManageLocalBackend|renderWslRow|desktopWslError|desktopWslState =

6. browse_code — apps/web/src/state/desktopWslState.ts

💭 I found it: ConnectionsSettings only renders the WSL row when canManageLocalBackend is true, but the sidebar's query gates only on isElectron, ignoring canManageLocalBackend. That means on Windows desktop without the required access:write scope, the actual row never shows, yet the search result still surfaces it—a mismatch between the two gating conditions. But the sidebar's row still renders because its own query fetches state independently, creating a dead anchor when Electron's canManageLocalBackend is false. I need to verify whether that false case is actually plausible by checking currentSessionScopes, and also check the return type of useEnvironmentQuery to see if the data field is nullable or undefined, since that affects the DesktopWslState typing. The windowsOnly platform gate on the search item now looks redundant given the state-based filter, but it's probably harmless.

7. git_tools — export function useEnvironmentQuery

8. git_tools — currentSessionScopes

💭 I'm checking whether canManageLocalBackend depends solely on desktopBridge existing versus the isElectron flag, since these two checks might not always align if isElectron is determined by user agent rather than the actual bridge object being present. If isElectron is true but desktopBridge is missing, the sidebar's WSL state atom would throw a DesktopWslStateUnavailableError, producing an error message that makes the search predicate return true and show the item—while ConnectionsSettings, which gates strictly on desktopBridge, would return null and hide the row, creating a dead anchor. I need to check env.ts to see how realistic this isElectron-without-bridge scenario actually is.

9. browse_code — apps/web/src/env.ts

10. git_tools — isWindowsPlatform

💭 I'm confirming that the desktopBridge existing lines up with isElectron being true, and that the sidebar's visibility gate matches the same conditions ConnectionsSettings checks for managing local backends. The windowsOnly filter using navigator.platform works fine on Electron/Windows since it reports "Win32". I'm also checking a minor divergence around mutation errors versus query errors when the state is null, but this seems unlikely to cause real issues since state usually isn't null after a mutation error. I'm now comparing the old and new logic for rendering the WSL row, tracing through the previous conditional structure that handled null state with error and permission checks. The new predicate-based check placed before the availability check produces equivalent behavior to the original branching logic. One nuance I'm tracking is whether the retry row's visibility properly requires canManageLocalBackend permission, and whether that permission scope is correctly derived from the administrative auth scopes in Electron — I want to verify this includes the write access scope. I'm also concerned the sidebar predicate might miss a rendering gate around lines 3020-3090, where renderWslRow is conditionally called only when the primary environment is local or connected — if so, the anchor could be dead when the desktop's primary environment is remote instead.

11. browse_code — apps/web/src/components/settings/ConnectionsSettings.tsx

12. git_tools — AuthAdministrativeScopes =

💭 The gating chain confirms consistency between the WSL row rendering and sidebar logic, both checking Electron state properly. I'm now checking whether the windowsOnly field in settingsSearch is redundant given the sidebar's real-state filtering—it seems like a harmless defensive secondary gate rather than a violation, though it does rely on the deprecated navigator.platform API. I'm also noting that mounting the sidebar triggers a WSL state fetch on every desktop platform, including macOS, which is a minor perf consideration but not really a UI consistency issue since it just returns unavailable quickly there. Checking the recovery row case where the backend is available:false but enabled:true still renders correctly with the right id, matching sidebar behavior. Looking at the visibility predicate for the WSL row, I see it passes state as null inside a branch, which reduces down to just checking whether there's an error — a bit convoluted but functionally fine, and canManageLocalBackend is always true in electron so that gate isn't a concern. The clamping effect on activeResultIndex when results shrink seems reasonable and necessary — without it, if a user's query narrows the result list while their selection points past the end, the active descendant would become undefined and pressing Enter would silently do nothing. The imports look clean, importing only types where needed, and the added environment query subscription in the sidebar nav for WSL state shouldn't affect the search results memo's identity or cause unnecessary recomputation. I'm now checking whether there's a genuine divergence between what the sidebar predicts versus actual behavior worth flagging. The retry row for the "wsl-backend" error path relies on the same shared desktopWslStateAtom, so both the sidebar and the ConnectionsSettings panel read from the identical global atom instance in the registry -- meaning they can't get out of sync since it's one shared state, not split copies. With keepAlive, prior data shows immediately so timing isn't a real issue there. But I do notice a transient false negative case: if the sidebar mounts on a non-Connections page before the WSL query resolves, the item briefly hides even though WSL exists — opposite of the earlier false-positive concern, but minor since it's just a few ms during initial load. Let me check git log on this branch to see what else changed beyond these files that I should review. The diff scope covers apps/web/src ts/tsx and is small. I want to check whether SettingsRow accepts an id prop that gets applied to the row element, since {...searchableSetting("wsl-backend")} now spreads id+title in place of a plain title. Since the three WSL rows are mutually exclusive branches (retry, recovery, main), having the same id on all three isn't actually a conflict. I'll verify SettingsRow's id handling and check how other panels use searchableSetting to confirm the spread pattern is consistent.

13. git_tools — searchableSetting(

14. git_tools — 9b2d043..33b8cbd

💭 All the earlier findings look resolved and the pattern usage matches the rest of the codebase. Checking the clamping logic added in the last commit—it safely handles an empty results array by falling back to zero, and I'm now looking at whether the effect re-running on every render could cause any issue. The scroll-into-view effect below looks fine, and I'm now weighing whether the new sidebar subscription belongs with the nav or the search catalog—there's some duplication between the settings config flags and a runtime state filter, but it's acceptable and not worth flagging. I'm also verifying that the conditional hook usage in SettingsSidebarNav stays stable since it depends on a module-level constant rather than something that changes at runtime, so hook ordering isn't a problem. Now I want to check the test file more closely, specifically around the assertion for the "wsl" search settings case, to confirm it's properly scoped to the desktopOnly/browser test context.

15. browse_code — apps/web/src/components/settings/settingsSearch.test.ts

💭 Word wrap mapping to appearance settings is correct and pre-existing, so no issue there. I check for sidebar filter tests and confirm there isn't one, though the predicate itself is tested, which seems fine. Now I'm turning to a potential issue with the new test file for ConnectionsSettings logic. I also verify that error mismatches between the sidebar and ConnectionsSettings don't cause real divergence, since a mutation error can only exist alongside non-null state, and state takes priority when non-null. The code looks solid overall, so I'm doing a final pass on the diff, particularly the windowsOnly filter that checks navigator.platform, confirming it works for Win32 but wondering about behavior on Windows ARM64.

16. git_tools — navigator.platform

💭 I'm double-checking that the WSL row's dependency on the desktop bridge atom is separate from environment-scoped state, and confirming both stay properly gated within the primary environment section without conflict. I don't see any new concrete violations. Checking the sidebar's readonly SETTINGS_SEARCH_ITEMS tuple, the types remain assignable to SettingsSearchItem whether the memo returns the tuple or a filtered array, so searchSettings still typechecks fine either way. The remaining subtlety is that results identity shifts whenever searchableItems identity changes, and that's only recomputed when the underlying data or error state changes. I also notice that each 30-second revalidation creates a new data object, which recomputes searchableItems and results, retriggering the scroll effect on the active result — but since scrollIntoView({block: "nearest"}) is a no-op when already visible, this is harmless. The clamp effect only depends on results.length, so that's fine too. Overall I'm landing on no findings here. Given the tension between the instruction to respond with just "All clear" versus the required JSON schema, I'll follow the schema but set the summary and title to reflect an all-clear state, using something like "UI Consistency: All clear" with a success state.


Agent Credits: 107 credits

Token usage: 20 uncached input · 470,951 cache-read input · 79,487 cache-write input · 11,387 output
Agent Credits may also include non-token charges from external tools such as web research.