Keep Code browser filters after selecting files#824
Conversation
Restore host-controlled search from the FileTree click boundary so repeated clicks on the selected row cannot leave Pierre unfiltered. Centralize search forwarding through the wrapper error path.
Use waitForFunction for the Code tab filter assertion so async UI state is polled instead of sampled once.
Hickey/Lowy Analysis
Hickey rationaleThe change separates host-owned Code tab filter state from Pierre-owned internal search state without adding a new public abstraction. The only unavoidable coupling is temporal: Pierre 1.0.0-beta.3 closes search after row clicks, and the adapter must restore the host query after that close because Pierre does not expose a close-search opt-out. Two refinements landed from the review. Search forwarding now uses one wrapper helper for normalization, and the asynchronous reapply path routes through the same Lowy rationaleThe volatility belongs at the Lowy flagged that the queued |
Swaps the #817 fix from `onSelectionChange` to a DOM `click` listener on the FileTree wrapper's container, matching @srid's parallel PR #824. The original `onSelectionChange` hook missed the re-click case: Pierre's `#applySelection` short-circuits its `selectionVersion` increment when the new selection equals the current one, so the callback never fires on re-click of an already-selected row — but `controller.closeSearch()` still runs on every row click, so the filter would be wiped with no recovery path. The DOM-event hook fires regardless of selection-version state. Three calls to Pierre's `setSearch` now route through a single `applySearchQuery` helper that owns normalization (`""` → `null`, Pierre's contract for "no filter") and `onError` routing. Also folds in reviewer feedback (hickey + lowy on the post-implement diff): - `aria-hidden` on the right-panel root (collapsed) and on each tab wrapper (inactive) — makes the keep-mounted contract legible to both future readers and assistive tech. - Top-of-block invariant comment in CodeTab naming the selection-stability invariant the three guards collectively defend ("preserve selection across non-genuine transitions"); each guard documents a different churn source. - `resetKey` separator note: `::` is collision-safe given current `view()` enum + `repoPath()` semantics. - Strengthened comment on the row-click handler explicitly naming the two Pierre invariants the microtask-after-click pattern relies on (synchronous handler; `data-item-path` attribute on rows). - Re-click assertion added to `Filter survives clicking a filtered result` — the case the previous implementation missed. Approach credit: PR #824 by @srid (Codex). The DOM-listener structure, `applySearchQuery` helper, and re-click test scenario are adapted from that PR.
The Code browser now keeps its active filename filter after file selection, including repeated clicks on the already selected filtered result. Pierre closes its internal search after row clicks, so the Solid adapter restores Kolu's host-owned
searchQueryafter Pierre finishes handling the click.The adapter keeps that workaround inside
@kolu/solid-pierre:CodeTabstill owns the search signal, whileFileTreecentralizes search forwarding through the sameonErrorpath used by the other Pierre setters. The regression scenario covers the original filtered click and the repeated-click case that does not emit a selection change.Verification
just checkjust fmtjust test-quick features/code-tab.feature:64(223 scenarios,1544 steps; Cucumber merged the configured feature glob with the line filter)Closes #817
Generated by
/doon Codex (modelgpt-5).