Skip to content

fix(frontend): keep root sessions landing unfiltered - #1368

Merged
wesm merged 21 commits into
mainfrom
weird-navigation
Aug 11, 2026
Merged

fix(frontend): keep root sessions landing unfiltered#1368
wesm merged 21 commits into
mainfrom
weird-navigation

Conversation

@wesm

@wesm wesm commented Aug 9, 2026

Copy link
Copy Markdown
Member

A bare local visit should show the unfiltered Sessions landing page, but the remembered filter state was being applied immediately and could be written back during refresh or session-detail navigation. That made the root URL surprising and risked erasing the user’s saved Sessions preference.

This change treats the root path as an unfiltered landing state while preserving the saved preference. Explicit filter URLs remain authoritative, direct or provenance-preserving navigation to bare /sessions can restore the remembered view, and opening a session from the root does not overwrite the preference when the detail view refreshes or closes. The task-specific design artifacts have also been removed now that the behavior is implemented.

The full frontend suite passes in serialized single-worker mode. The default parallel runner is resource-sensitive in this environment and previously timed out in an unrelated Playwright-config test; that focused test passes independently.

wesm added 9 commits August 8, 2026 20:02
A bare local visit currently inherits the saved session filter and rewrites the URL to a filtered Sessions route. Document the intended root landing behavior so implementation keeps the root unfiltered without discarding saved preferences, while preserving explicit session deep links.
Close the root-route edge cases identified during review: suppress persistence for the full root lifetime, define sticky and filter-param URL semantics, restore saved filters on in-app Sessions navigation, and document promotion and Back-button history behavior.
The root landing reset must not overwrite the saved filter when a user opens a session, refreshes its detail view, or closes back to the list. Tie the temporary persistence hold to untouched root-reset filter state and document the intentionally unfiltered detail-exit path.
Document the router, store, and App changes needed to keep the root landing view unfiltered without overwriting saved filters.
The implementation is now represented by the router, store, and App changes; remove the task-specific planning artifacts so the branch carries only durable project documentation.
Keep the temporary unfiltered state associated with a root visit while the user moves through other pages. Restore the saved Sessions view when they later enter bare /sessions, while retaining the intentional unfiltered list after closing a session opened from root.
@roborev-ci

roborev-ci Bot commented Aug 9, 2026

Copy link
Copy Markdown

roborev: Combined Review (7ba6f64)

Medium

  • frontend/src/App.svelte:420 — Root entry resets session filters, but AnalyticsPage can restore a yoked or retained date range. Returning from Usage to / with an active date yoke may apply dates, promote the page to /sessions?..., and overwrite saved filters. Skip yoked and retained date restoration while router.isRootPath represents the unfiltered landing page, and test returning to root with an active yoke.

  • frontend/src/App.svelte:435hasFilterParams(params) clears root provenance on every route, even though parameters such as window_days, date_from, and project are also used by Usage and Quality. Changing a Usage range after visiting root can clear rootResetPending, preventing bare /sessions from restoring saved session filters. Only treat URL filter parameters as authoritative when route === "sessions"; use actual session-filter divergence for changes from other pages.

  • frontend/src/App.svelte:628 — The date picker bypasses history-pushing root promotion because AnalyticsPage.writeSessionDateParams() calls router.replaceParams() directly. Selecting a date at / replaces the root history entry instead of pushing /sessions?..., so Back cannot return to the unfiltered root. Use navigateToSessions() for date writes from root, or centralize root-aware parameter updates, and test date-filter promotion and Back behavior.


Reviewers: 2 done | Synthesis: codex, 13s | Total: 8m23s

Keep shared and retained analytics dates from reapplying to the unfiltered root after returning from another analytics page. Non-Sessions query parameters no longer consume the pending saved-session restoration, while a date selection at root creates a history entry so Back returns to the unfiltered landing.
@roborev-ci

roborev-ci Bot commented Aug 9, 2026

Copy link
Copy Markdown

roborev: Combined Review (681eaa0)

The routing changes have two medium-severity state-management issues affecting saved filters and date-yoke persistence.

Medium

  • frontend/src/lib/stores/sessions.svelte.ts:441 — Entering / with saved date filters calls yokedDates.clear(), permanently persisting a null shared range. A temporary unfiltered landing therefore destroys cross-panel date-yoke state. Do not clear the yoke in resetFiltersForRoot(); rely on the root-specific App/Analytics guards to avoid applying it there.

  • frontend/src/App.svelte:434rootDetailOpened remains true after navigating from a root-opened detail to another route. Returning later to bare /sessions consequently skips saved-filter restoration even though this is no longer a direct detail-to-list close. Clear the marker when leaving the Sessions route, or scope it to the immediate detail-to-list transition.


Reviewers: 2 done | Synthesis: codex, 11s | Total: 6m19s

A root reset is temporary presentation state and must not erase shared date-yoke state. Detail provenance is likewise only needed to suppress the immediate close-to-list restore; leaving Sessions should allow a later bare Sessions visit to restore saved filters.
@roborev-ci

roborev-ci Bot commented Aug 9, 2026

Copy link
Copy Markdown

roborev: Combined Review (f09c76d)

The PR has two medium-severity route/state restoration issues that can overwrite or fail to restore saved filters.

Medium

  • frontend/src/lib/components/analytics/AnalyticsPage.svelte:229 — On the root landing with a preserved date yoke, manual or scheduled refresh calls writeSessionDateParams(). This promotes / to /sessions, replaces the preserved yoke with the dashboard range, releases the persistence hold, and can overwrite saved project/agent filters.

    Fix: When router.isRootPath represents the unfiltered landing, refresh analytics without synchronizing its date state to Sessions or the yoke. Add a behavioral refresh test asserting that the URL, yoke, and saved filters remain unchanged.

  • frontend/src/App.svelte:430 — Saved filters are restored only when re-entering Sessions with sid === null. In the flow / → Usage → open a session from Usage → close detail, entry has a session ID and is not marked as root-opened detail, while closing is not an enteringSessions transition. The resulting /sessions list incorrectly remains unfiltered instead of restoring the saved view.

    Fix: Restore saved filters when entering an unfiltered session detail from a non-session route while root restoration is pending, or track that origin and restore filters when detail closes.


Reviewers: 2 done | Synthesis: codex, 13s | Total: 8m32s

The root landing is an unfiltered view, so refreshing its analytics must not turn the preserved date yoke into Sessions filters or overwrite the saved view. When a user opens a session from Usage after visiting root, restore the saved session view before detail closes so the later list does not lose it.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (4ab9ee6)

Code review found one medium-severity filter-persistence regression.

Medium

  • frontend/src/lib/components/analytics/AnalyticsPage.svelte:453 — After opening a session from / and closing it, AnalyticsPage remounts at /sessions and restores the preserved date yoke. writeSessionDateParams() then treats the held filters as non-default, releases the persistence hold, and overwrites saved filters with the yoked date range and default project/agent values.
    • Fix: Preserve root-detail provenance through the first /sessions analytics initialization, suppressing yoke/retained-date restoration for that exit without clearing the yoke. Add regression coverage for root with an enabled yoke → detail → exit, asserting an unfiltered URL and unchanged saved filters.

Reviewers: 2 done | Synthesis: codex, 10s | Total: 5m21s

Keep the saved Sessions view intact when a session opened from the root landing page is closed. The first list initialization must not turn the shared date yoke into session URL filters or overwrite the saved preference.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (d296808)

One medium-severity routing state issue remains.

Medium

  • frontend/src/App.svelte:431openingRootDetail only recognizes a detail opened directly from /. After that detail closes, the temporary root state remains active on /sessions, but a second session opened from the same root-derived unfiltered list is not classified as root-derived. Closing it may restore the date yoke, release the persistence hold, and overwrite the user’s saved filters.

    Suggested fix: Treat details opened from the pending root-derived unfiltered list as root details as well, while excluding entry from non-session routes. Add a regression test covering two consecutive detail open/close cycles with a saved filter and the date yoke enabled.


Reviewers: 2 done | Synthesis: codex, 13s | Total: 12m17s

Keep consecutive session opens from the temporary root-derived list unfiltered on exit. Without the pending-root classification, the second detail could restore the shared date yoke and overwrite the saved Sessions view.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (ec0480e)

Review verdict: One medium-severity filter persistence issue remains.

Medium

  • frontend/src/lib/components/analytics/AnalyticsPage.svelte:238 — After closing a session opened from /, temporary root-derived filters remain active while router.isRootPath becomes false on /sessions. Refreshing with a preserved date yoke can call writeSessionDateParams(), release the persistence hold, and overwrite saved project/agent filters with generated date filters.

    Suggested fix: Gate refresh writeback on root-derived filter provenance rather than pathname alone. Add coverage for / → detail → exit → refresh with a saved filter and yoke.


Reviewers: 2 done | Synthesis: codex, 10s | Total: 8m14s

Do not let refreshing the unfiltered root-derived Sessions list turn a preserved date yoke into saved session filters. The refresh path must follow the pending root provenance until the user promotes or restores the view.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (d87edfa)

One medium-severity issue found in root-route filter handling.

Medium

  • frontend/src/App.svelte:440 — Root reset and divergence tracking ignore starred.filterOnly. If “Starred only” is enabled and the user returns to /, the sidebar remains filtered even though the root route indicates an unfiltered state. Toggling it on / also fails to navigate away because the state is absent from sessionFilterRouteParams().
    • Fix: Include the starred-only state in root reset and provenance handling. Clear it when entering /, and navigate away from the root when it is enabled there.

Reviewers: 2 done | Synthesis: codex, 18s | Total: 10m23s

Treat Starred only as a Sessions filter when determining whether the root landing is still unfiltered. Clear it on root entry and preserve it in the route when the user enables it so the sidebar and URL stay consistent.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (6f661e8)

The PR has two medium-severity filter-persistence issues that can silently disable starred-only filtering during navigation.

Medium

  • frontend/src/lib/components/analytics/AnalyticsPage.svelte:190 — Date changes rebuild the URL using filtersToParams(sessions.filters), which excludes the separately stored starred.filterOnly. Selecting a date while viewing ?starred=true removes the parameter, and initFromParams() then disables starred-only filtering.

    • Fix: Preserve starred=true in this write path or centralize session-route serialization. Add a behavioral test combining starred-only filtering with date selection.
  • frontend/src/lib/stores/sessionRouteParams.ts:8starred was added to SESSION_FILTER_KEYS but not to RouterStore’s SESSION_ROUTE_PARAMS. As a result, buildSessionHref(), navigateToSession(), and analytics drill-down navigation can silently drop the starred-only filter.

    • Fix: Add starred to SESSION_ROUTE_PARAMS, preferably by reusing the shared key set. Test both session-link generation and drill-down preservation.

Reviewers: 2 done | Synthesis: codex, 11s | Total: 9m28s

Keep Starred only active when users select a Sessions date or open a session from analytics. Session navigation must carry every recognized Sessions filter so a route change cannot silently disable the current view.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (d0f3e8a)

One medium-severity routing issue was found; no security issues were identified.

Medium

  • frontend/src/App.svelte:479 — Returning via browser history from a root-derived detail to / can re-enable date-restore suppression through closingRootDetail. Because the root branch of AnalyticsPage never consumes that suppression, a later promotion to /sessions?... using a non-date filter skips the saved/shared date restoration.
    • Suggested fix: Skip the closingRootDetail suppression branch when rootLanding or enteringRootLanding is true. Add coverage for root → detail → Back to / → non-date filter promotion with an enabled date yoke.

Reviewers: 2 done | Synthesis: codex, 11s | Total: 9m7s

Returning from a root-opened session through browser history must leave root entry state authoritative. Otherwise a later non-date filter promotion can skip the shared Sessions date range and produce an incomplete filtered view.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (307a4a8)

Changes requested: one medium-severity routing/date-filter restoration issue was found.

Medium

  • frontend/src/App.svelte:464,697 — After opening and closing a session from /, selecting a non-date filter on the resulting /sessions list clears rootResetPending without restoring the shared date filter. Because analytics retains the unchanged “no date” signature, the URL and session query omit the expected date range. The same issue occurs when changing a filter while still in the detail view.

    Restore sessionEntryDateParams before writing the filtered route when root-held state is released, and clear the detail-suppression flags consistently. Add coverage for filter changes both during a root-derived detail view and after returning from it.


Reviewers: 2 done | Synthesis: codex, 11s | Total: 7m17s

A non-date filter must release the temporary root view with the same shared Sessions date range that a normal Sessions entry restores. Centralizing that release at filtered route entry keeps detail and list navigation consistent and prevents stale suppression state.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (94b6025)

One medium-severity filter-state bug remains.

Medium

  • frontend/src/lib/stores/sessions.svelte.ts:423hasDefaultSessionFilters() ignores starred.filterOnly. Toggling starred-only on and then off within a root-derived detail clears the root provenance but does not release the persistence hold. This leaves /sessions on temporary defaults, while older saved filters unexpectedly reappear after reload.
    • Fix: Treat starred.filterOnly as filter divergence when deciding whether to release the hold, and add coverage for toggling it on and off before exiting a root-derived detail.

Reviewers: 2 done | Synthesis: codex, 13s | Total: 16m15s

Starred only is a real Sessions filter even though its state lives outside the main filter object. Treating it as divergence ensures a temporary root reset becomes the saved view after the user changes that filter, including when they turn it off again before leaving detail.
@roborev-ci

roborev-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

roborev: Combined Review (6029e82)

Changes need a fix for stale analytics state when returning to the root route.

Medium

  • frontend/src/lib/components/analytics/AnalyticsPage.svelte:421 — Navigating back to / clears the URL and session filters but fetches analytics using the existing singleton date state, leaving results restricted to the previously selected Sessions or Quality date range. Reset to the root landing’s default analytics date state before fetching while preserving the saved yoke, and add a Back-navigation test verifying the displayed/requested range resets.

Reviewers: 2 done | Synthesis: codex, 10s | Total: 11m27s

Returning to the root landing must show the default analytics range, even after a narrower Sessions or Quality selection. Reset the analytics date state before the root fetch while leaving the shared date yoke available for later filtered views.
@roborev-ci

roborev-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

roborev: Combined Review (738450d)

No issues found.


Reviewers: 2 done | Synthesis: codex | Total: 13m48s

@wesm

wesm commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

Just giving this a last review before merging

@wesm
wesm merged commit ced4676 into main Aug 11, 2026
23 checks passed
@wesm
wesm deleted the weird-navigation branch August 11, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant