Skip to content

fix(ui): retain loaded dashboards across navigation - #141130

Merged
steipete merged 2 commits into
mainfrom
codex/retain-dashboard-navigation
Sep 7, 2026
Merged

steipete merged 2 commits into
mainfrom
codex/retain-dashboard-navigation

Conversation

@steipete

@steipete steipete commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where users switching between a loaded dashboard and chat would wait for routing, and visiting Settings would discard the dashboard's iframe, reading position, and local widget state.

Why This Change Was Made

Keep the existing three-session-per-pane cache connected across navigation, preserve each session's chat/dashboard presentation, and display usable cached routes during background refresh. Hidden pages relinquish foreground activity, viewer presence, focus, commands, and transcript observers. Composer callbacks captured before a page is hidden cannot revive when it returns; mounted plugin views keep their local state. Ordinary routes retain their existing loader and DOM lifecycle. Mounted views and session loaders share a Gateway/user scope, and returning pages stay inactive until any pending MCP teardown finishes.

User Impact

Recently visited tasks and dashboards reopen with their widget state, reading position, and chat drafts intact, including after a Settings visit. The existing cache limit remains unchanged; older views can be evicted, and changing Gateway or signed-in user clears retained views.

Evidence

  • Full local build, final UI rebuild with asset-budget checks, and node scripts/check-changed.mjs passed.
  • 90 focused tests passed, including reproduced regressions for cross-face presentation, background refresh, retired-scope results, and navigation during MCP teardown.
  • Initial browser proof passed all 15 dashboard-retention, navigation, and real-Gateway cases. After the broader CI run exposed lifecycle regressions, 49 browser cases passed across eight affected suites, including the real-Gateway widget suite, native plugin callbacks, code-block observers, new-session drafts/workspace memory, active-turn recovery, and dashboard progress. The live scenario used an isolated Gateway with synthetic data, preserved the same iframe through repeated switches and Settings, retained its note/scroll and the chat draft, then verified a new Gateway widget revision appeared.
  • Post-rebase full build and all 15 final navigation/dashboard/live-Gateway browser tests passed on the pushed head.
  • Fresh independent autoreview of both the feature and CI repair delta: no actionable P0–P2 findings.
  • First-head CI identified unrelated baseline Mermaid mock leakage, Telegram test file length, and a tooling planner timeout. This branch inherits the existing upstream Mermaid and Telegram fixes; the refreshed hosted CI run 34140306399 passed on 97952c84f5777fe55935a234f651a7e647ec92f4, including the required openclaw/ci-gate.

Synthetic live proof after returning from Settings: before, the reading note and article position reset; after, both are retained.

Before After
Widget state reset after Settings Widget note and reading position retained after Settings

@clawsweeper

clawsweeper Bot commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui size: XL maintainer Maintainer-authored PR labels Sep 7, 2026
@steipete
steipete marked this pull request as ready for review September 7, 2026 10:07
@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Sep 7, 2026
@clawsweeper

clawsweeper Bot commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Codex review: blocked before merge. Reviewed September 7, 2026, 11:57 AM ET / 15:57 UTC.

ClawSweeper review

What this changes

Keeps recently visited dashboards and chats loaded across navigation, preserves widget state and drafts, and suspends hidden-page activity and stale composer callbacks.

Merge readiness

⛔ Blocked before merge - 1 item remains

This remains useful: inspected main and the latest release still replace the outer session page during navigation. No actionable introduced defect was found. The previous screenshot-fetch failure is a reviewer limitation, not an outstanding contributor requirement.

Priority: P2
Reviewed head: 97952c84f5777fe55935a234f651a7e647ec92f4

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) A coherent lifecycle repair with relevant real-Gateway evidence, focused regression coverage, and no blocking correctness finding.
Proof confidence 🐚 platinum hermit (4/6) ✨ media proof bonus Sufficient (linked_artifact): The supplied isolated real-Gateway run reports preserved iframe identity, note, scroll position, and chat draft across navigation and Settings, followed by a visible live widget revision; the inspected scenario exercises the changed owners. Screenshot retrieval remains a reviewer-network limitation, not a contributor proof deficit.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (linked_artifact): The supplied isolated real-Gateway run reports preserved iframe identity, note, scroll position, and chat draft across navigation and Settings, followed by a visible live widget revision; the inspected scenario exercises the changed owners. Screenshot retrieval remains a reviewer-network limitation, not a contributor proof deficit.
Evidence reviewed 8 items Policy and patch identity: Read root AGENTS.md and the applicable ui/AGENTS.md and docs/AGENTS.md fully, plus contribution guidance and CODEOWNERS. No maintainer-notes directory exists. Reviewed the pinned merge-base-to-head delta; package-update files belong to base-only changes. The checkout remained clean and git diff --check passed.
Current main still needs the change: Current main uses a single teardown gate and replaces the session subtree when the route owner changes. It lacks the separate retained presentation introduced by this branch; no verified merged replacement was established.
Latest-release comparison: The supplied latest release, v2026.9.2, also uses the single outer teardown gate. Its existing three-session cache does not preserve the outer page through Settings navigation.
Findings None None.
Security None None.

How this fits together

The Control UI router turns navigation and Gateway data into session pages containing chat panes and dashboard widgets. Retaining those pages preserves local interactions while presentation controls determine which page can receive input and foreground activity.

flowchart TD
  A[Navigation] --> B[Session route loader]
  C[Gateway and signed-in user] --> D[Shared ownership scope]
  D --> B
  B --> E[Retained session pages]
  D --> E
  E --> F[Presented page and active controls]
  E --> G[Hidden widgets and preserved drafts]
Loading

Before merge

  • Resolve merge risk (P1) - Composer plugins that retain initial callbacks instead of consuming update-supplied operations will now receive an intentional ended-view error after hiding and returning; third-party consumer compatibility is not demonstrated by the host tests.
Agent review details

Security

None.

PR surface

Source +296, Tests +763, Docs +15. Total +1074 across 34 files.

View PR surface stats
Area Files Added Removed Net
Source 18 389 93 +296
Tests 13 886 123 +763
Docs 3 16 1 +15
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 34 1291 217 +1074

Review metrics

Metric Value Why it matters
Production versus regression coverage Production net +296 lines; tests and test support net +763 lines Production growth implements separate presentation ownership and retirement; regression coverage addresses navigation, scope replacement, observers, and callbacks.

Merge-risk options

Maintainer options:

  1. Keep the documented callback lifetime (recommended)
    Accept the explicitly documented lifecycle repair: plugins consume fresh composer operations through update after presentation resumes.

Technical review

Best possible solution:

Preserve the existing bounded cache and ownership fences, with the documented update-based composer lifecycle as the explicit plugin compatibility contract.

Do we have a high-confidence way to reproduce the issue?

Yes: main's outer route gate replaces the session subtree when navigating to Settings, and the supplied real-Gateway scenario directly checks the resulting iframe and local-state loss. This review verified the source path without executing it.

Is this the best way to solve the issue?

Yes: extending the existing bounded session owner avoids a competing cache, while shared Gateway/user scope and presentation retirement preserve the relevant lifecycle boundaries.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 0e1e605121bf.

Labels

Label justifications:

  • P2: Repairs dashboard and chat navigation continuity with a bounded Control UI impact.
  • merge-risk: 🚨 compatibility: Plugin composer callbacks intentionally expire on presentation changes, requiring consumers to use fresh update-supplied operations.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (linked_artifact): The supplied isolated real-Gateway run reports preserved iframe identity, note, scroll position, and chat draft across navigation and Settings, followed by a visible live widget revision; the inspected scenario exercises the changed owners. Screenshot retrieval remains a reviewer-network limitation, not a contributor proof deficit.
  • proof: sufficient: Contributor real behavior proof is sufficient. The supplied isolated real-Gateway run reports preserved iframe identity, note, scroll position, and chat draft across navigation and Settings, followed by a visible live widget revision; the inspected scenario exercises the changed owners. Screenshot retrieval remains a reviewer-network limitation, not a contributor proof deficit.

Evidence

What I checked:

  • Policy and patch identity: Read root AGENTS.md and the applicable ui/AGENTS.md and docs/AGENTS.md fully, plus contribution guidance and CODEOWNERS. No maintainer-notes directory exists. Reviewed the pinned merge-base-to-head delta; package-update files belong to base-only changes. The checkout remained clean and git diff --check passed. (AGENTS.md:1, 97952c84f577)
  • Current main still needs the change: Current main uses a single teardown gate and replaces the session subtree when the route owner changes. It lacks the separate retained presentation introduced by this branch; no verified merged replacement was established. (ui/src/app/router-outlet.ts, 0e1e605121bf)
  • Latest-release comparison: The supplied latest release, v2026.9.2, also uses the single outer teardown gate. Its existing three-session cache does not preserve the outer page through Settings navigation. (ui/src/app/router-outlet.ts, 3928bad9badf)
  • Ownership and retirement boundaries: Mounted pages and loader dependencies share the Gateway connection revision and authenticated-user scope. Scope changes retire old matches, while pending teardown keeps returning presentations inert. Existing Gateway connection code increments the revision when connection credentials change. (ui/src/app/router-outlet.ts:273, 97952c84f577)
  • Composer lifetime compatibility: Composer operations check presentation generation and lifetime before invoking their underlying operations. Tests cover hidden calls, same-turn hide/return, an in-flight completion, and fresh operations after return. The PR body explicitly describes the intentional retirement, and plugin documentation explains consuming fresh operations through update. (ui/src/plugins/control-ui-view.runtime.ts:175, 97952c84f577)
  • Real-Gateway scenario matches the change: The supplied body and author follow-up report successful isolated real-Gateway browser execution. The inspected scenario creates synthetic sessions and a widget, verifies the same iframe through repeated navigation and Settings, checks note/scroll/draft continuity and inactive parked state, then observes a subsequent Gateway widget revision. This exercises the changed router and retained-page boundary rather than generic startup. (ui/src/e2e/chat-widget-sandbox.real-gateway.e2e.test.ts:244, 97952c84f577)

Likely related people:

  • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (1 earlier review cycle)
  • reviewed 2026-09-07T10:20:00.076Z sha 9fc37f9 :: blocked before merge. :: none

Keep the existing three-session pane cache mounted while visiting other pages,
and restore dashboard/chat presentations without waiting for a background route
refresh. Preserve widget state, reading position, and drafts while hidden pages
relinquish foreground activity, presence, focus, and commands.

Share Gateway/user ownership between mounted views and session loader caches,
and keep returning presentations inactive until MCP teardown completes.

Verified with 90 focused tests, 15 browser tests including a real isolated
Gateway, the changed-file gate, and inspected before/after widget-state proof.
Keep ordinary route DOM stable through loader transitions, suspend hidden transcript observers, retire stale plugin composer callbacks, and reconcile active runs on return. Preserve the loaded page and its local state throughout. Cover the lifecycle boundaries with focused units and browser flows; isolated real Gateway proof and all 49 residual browser cases pass.
@steipete
steipete force-pushed the codex/retain-dashboard-navigation branch from 9fc37f9 to 97952c8 Compare September 7, 2026 15:50
@steipete

steipete commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

The screenshot retrieval failure was a reviewer-network limitation. I inspected both original full captures locally before uploading them to the PR: they contain only the isolated synthetic Gateway scenario. The browser assertions also verify iframe identity, note and reading position, chat draft continuity, and a subsequent live widget revision; the follow-up real-Gateway run passes. No production Gateway or private desktop data was used.

The CI follow-up keeps retention confined to session routes and repairs hidden transcript observers, active-turn reconciliation, and stale plugin composer callbacks. Fresh independent P0–P2 review of that delta found no actionable defects. Required hosted checks will be green before landing.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. proof: sufficient ClawSweeper judged the real behavior proof convincing. labels Sep 7, 2026
@steipete

steipete commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Maintainer decision on the composer compatibility note: retain the presentation lifetime boundary. A callback captured before a view is hidden must stay retired so delayed work cannot regain permission to change or submit a draft after navigation. The mounted host and view signal remain alive; current operations arrive through update.

I checked the maintained generated composer in src/cli/plugins-feature-scaffold.ts: it already stores the latest context in update and invokes operations through that context. The browser plugin fixture follows the same contract. The new tests cover stale handles, same-turn hide/return, pending sends, preserved DOM/host identity, and working fresh handles. The plugin documentation now states the callback lifetime explicitly.

A third-party composer that permanently captures its initial props must adopt the documented update path; arbitrary third-party implementations have not been exercised. That is an accepted compatibility tradeoff, not a reason to revive retired operations. Exact-head CI run 34140306399 is green, and the post-rebase full build plus all 15 final navigation/live-Gateway tests passed.

@steipete
steipete merged commit 37497d4 into main Sep 7, 2026
141 checks passed
@steipete
steipete deleted the codex/retain-dashboard-navigation branch September 7, 2026 16:11
@steipete

steipete commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Sep 8, 2026
* fix(ui): retain loaded dashboards across navigation

Keep the existing three-session pane cache mounted while visiting other pages,
and restore dashboard/chat presentations without waiting for a background route
refresh. Preserve widget state, reading position, and drafts while hidden pages
relinquish foreground activity, presence, focus, and commands.

Share Gateway/user ownership between mounted views and session loader caches,
and keep returning presentations inactive until MCP teardown completes.

Verified with 90 focused tests, 15 browser tests including a real isolated
Gateway, the changed-file gate, and inspected before/after widget-state proof.

* fix(ui): preserve route and plugin lifecycles with retained pages

Keep ordinary route DOM stable through loader transitions, suspend hidden transcript observers, retire stale plugin composer callbacks, and reconcile active runs on return. Preserve the loaded page and its local state throughout. Cover the lifecycle boundaries with focused units and browser flows; isolated real Gateway proof and all 49 residual browser cases pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui docs Improvements or additions to documentation maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XL status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant