# 5-16 [done][bug] Sidebar preferred snapshot 中 query 可覆盖 live stream v1

> 发现时间：2026-05-17
>
> 状态：`[done]`
>
> 关联主线：`05-editor-mainline`

## 1. 问题定义

Sidebar 同时启动 query/live/initial 与 tree stream，并通过 preferred snapshot 选择最终数据源。当 `query` 与 `tree_stream` 版本相同但内容不同，当前 freshness / syncKey 逻辑可能让 query 压过 live stream。

## 2. 证据

- [app-layout-shell.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/app-layout-shell.tsx:20) 同时使用 Sidebar data 与 tree stream。
- [use-preferred-sidebar-snapshot.ts](/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/use-preferred-sidebar-snapshot.ts:32) 到 [use-preferred-sidebar-snapshot.ts](/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/use-preferred-sidebar-snapshot.ts:52) 进行 source 选择。

## 3. 影响

- Sidebar 仍存在 Convex live / HTTP / Rust stream 多链抢真相。
- 同一版本但不同内容时，用户可能看到旧树或非 Rust stream 结果。
- WS / SSE 收口后仍可能被 query source 覆盖。

## 4. 建议修复

- 明确唯一预期来源：当 Rust stream 可用时，应由 stream 成为主真相，query 仅初始化或 fallback。
- 同版本不同内容时必须记录诊断事件，而不是静默按 freshness 选择。
- 增加单测覆盖同版本冲突。

## 5. 当前主链修复状态

- 原证据指向的 `wolai-frontend/src/components/sidebar/use-preferred-sidebar-snapshot.ts` 已不在当前运行主链；当前仓库中该路径不存在，只在 `recycle/` 下保留历史副本。
- 当前 3000 主壳由 Rust `SIDEBAR_TREE_JS` + `TREE_LIVE_CONTROLLER_JS` 消费 WS/SSE tree snapshot / delta，不再使用 retired React `usePreferredSidebarSnapshot` 选择器。
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs:7460) 增加防回归测试，断言当前 sidebar runtime 不包含 `usePreferredSidebarSnapshot`、`preferredSidebarSnapshot` 或 `liveSidebarTitle`。

## 6. 验证

- `cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_tree_runtime_does_not_use_retired_query_preferred_snapshot_selector -- --nocapture`
  - 结果：1 passed
