# Reasonix Batch A2 Worker B：local folder restore 后 FileTree focus/reveal

Project root: `/mnt/Data1T/mnote`

## 目标

修复 `task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js` 记录的缺口：local folder 非 md 资源从 trash workbench restore 后，FileTree 恢复行应有 `data-selected="true"` 或 `data-active="true"` 或 `data-focused="true"`，且不触发页面 reload。

## Ownership

允许修改：

- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
- `rust/crates/mnote-web/src/routes/gateway.rs`
- `scripts/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js`
- `design/04-tree-domain/process/4-28-trash-restore-location-reveal-focus-v1.md`
- `design/04-tree-domain/process/4-46-batch-a-filetree-action-trash-smoke-execution-checklist-v1.md`
- `.codex/reasonix-tasks/results/batch-a2-worker-b-restore-focus.md`

禁止：

- 不改 delete 默认进入 trash 的语义。
- 不把 browser reload 当成 no-refresh。
- 不引入跨窗口 postMessage 或复杂新服务。
- 不提交 git。

## 推荐实现方向

短路径即可：

1. trash workbench local restore 成功后，把恢复对象的 filetree row-id 写入 `sessionStorage`。
   - 对非 md local resource，row-id 是 `local:asset:${original_relative_path}`。
   - 当前 row HTML 有 `data-trash-entry-id`，通常是 `local-file:${relative_path}`；可在 HTML 中新增 `data-filetree-row-id`，避免前端猜。
2. `refreshLocalFolderSidebarSnapshot()` 渲染后消费这个 pending row-id，选择/聚焦对应 filetree row。
3. 复用现有 `selectSidebarFileTreeRow(row, {})` 或新增小 helper，不要只改 DOM 属性导致 selection store 不一致。

## 验收命令

```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web layout -- --test-threads=1
cargo test --manifest-path rust/Cargo.toml -p mnote-web gateway -- --test-threads=1
node --check scripts/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js
```

如本机 3000 可用，运行：

```bash
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/google-chrome-stable node scripts/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js
```

## 最终输出

写入 `.codex/reasonix-tasks/results/batch-a2-worker-b-restore-focus.md`，包含：

- 修改文件
- 实现策略
- 验证命令和结果
- 未完成项/风险
