# 5-18 Main Editor Tab State 与错误占位 Checklist v1

> 状态：done
>
> 归档说明（2026-05-21）：主编辑器 tab state 与错误占位已完成并验证。
>
> 日期：2026-05-20
>
> Owner：主编辑区 tab runtime / `web_shell.rs`

## 1. 目标

补齐 P0-1 的最小轻量 editor group 状态：在不引入完整 VSCode 多 group 的前提下，让 page/resource tab 共享一个明确的浏览器内存状态模型，并补上 resource 打开失败时的错误占位 tab。

## 2. 允许修改范围

- `rust/crates/mnote-web/src/routes/web_shell.rs`
- `rust/crates/mnote-web/src/ssr/pages/document.rs`
- `rust/crates/mnote-web/src/ssr/styles.rs`
- `scripts/task457-main-editor-resource-tab-smoke.js`
- 可新增 `scripts/task462-resource-tab-error-placeholder-smoke.js`

## 3. 禁止事项

- 不引入完整 VSCode DI、多 editor group grid、preview/sticky 持久化。
- 不改变 Page Aggregate 或 local Markdown 事实源。
- 不修改 resource resolver、OnlyOffice、File Tree lifecycle；这些由其它 checklist 处理。

## 4. Checklist

- [x] 定义轻量 main editor tab 状态，至少能表达 `id`、`kind`、`title`、`dirty`、`saving`、`hasExternalConflict`、`lastActiveAt`、`status`。
- [x] page tab 与 resource tab 激活统一通过同一状态更新入口。
- [x] resource tab close guard 读取同一状态入口，避免散落检查。
- [x] 打开 resource 失败时创建或保留 error placeholder tab。
- [x] error placeholder tab 有明确错误 UI，可关闭，不留下半注册 panel/session。
- [x] 更新 Rust 字符串 contract test，确保关键 runtime marker 存在。

## 5. 验收

- [x] `node --check scripts/task462-resource-tab-error-placeholder-smoke.js`
- [x] `node scripts/task462-resource-tab-error-placeholder-smoke.js`
- [x] `node scripts/task457-main-editor-resource-tab-smoke.js`
- [x] `cargo test -p mnote-web web_shell -- --test-threads=1`

## 6. 本轮执行记录

- 已完成：
  - `createResourceSession` 已补 `lastActiveAt`，resource session 继续持有 `dirty` / `saving` / `hasExternalConflict` / `status` 等关闭保护状态。
  - page tab 与 resource tab 继续统一通过 `activateMainEditorTab` 激活，并在激活 resource tab 时更新 MRU 与 `lastActiveAt`。
  - `closeResourceTab` 继续通过 `resourceTabCloseGuardReason` 读取关闭保护状态。
  - `openResourceInActiveTab` 失败时保留 resource tab，并通过 `.mnote-resource-tab-error` 渲染可见错误占位。
  - 新增 `scripts/task462-resource-tab-error-placeholder-smoke.js`，已验证失败资源会出现错误占位、可关闭、连续失败不会产生失控 tab。
  - `web_shell.rs` 与 `styles.rs` 已补关键 runtime / CSS contract。
- 未完成：
  - `lastActiveAt` 时间戳尚未用于 tab 排序（当前 MRU 队列 `resourceTabMru` 控制切换顺序）。
  - `dirty`/`saving`/`hasExternalConflict` 状态在 resource tab close guard 中读出但无 UI 确认弹窗（仅 console.warn + 禁止关闭）。
- 风险：无

## 7. 非目标

- 不做 tab 持久化恢复。
- 不做 tab 拖拽排序、context menu 或 close others。
