Files
mnote/design/05-editor-mainline/process/5-9-wolai-aline-continuous-checklist-v1.md
T

274 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 5-9 [process] Wolai-aline 连续执行 checklist v1
> 更新时间:2026-04-30
>
> 本清单拆自 `5-7-wolai-page-tree-main-editor-experience-restoration-v1.md`。它不是新的测试方案;执行口径统一服从 `/home/lix/.codex/skills/wolai-aline` 与 `/mnt/Data1T/mnote/design/08-wolai-aline-test-flow/process/wolai-aline-test-flow-v1.md`。
## 1. 使用方式
每次只领取一个最小可对标任务,按下面固定闭环推进:
1. 用一句话定义行为,例如“侧栏搜索入口打开全局搜索 modal 且 URL 不变”。
2. 派 subagent 对 Wolai Hermes 取基线,必要时进入 Hermes editable-test mode。
3. 主线程查看 Wolai 截图,填写差异矩阵,不接受只有文字的结论。
4. 写或更新本地 `scripts/task*-smoke.js`,先让当前 `3000` 暴露差异。
5. 小范围实现,不新增第二套页面树、标题、正文或排序真相。
6. 运行本地 smoke 和改动范围内单测。
7. 再派 subagent 同链路复测 Wolai 与 `3000`
8. 主线程复核最终截图;若肉眼仍有差异,先补 smoke 或 checklist 断言,再继续修。
9. 更新本清单状态和截图路径。
状态标记:`TODO` 未开始,`BASELINE` 已取 Wolai 基线,`RED` 已有本地失败 smoke`GREEN` 本地实现和 smoke 通过,`PARITY` subagent 复测与主线程截图复核通过,`BLOCKED` 有阻塞。
## 2. 当前基线证据
2026-04-30 已由 subagent 使用 Playwright 同时操作 Wolai Hermes 与本地 `3000`,主线程已复核关键截图。后续任务可沿用这些基线,但每个具体小任务仍需重新截同动作链证据。
| 项 | Wolai 证据 | 本地证据 | 当前结论 |
| --- | --- | --- | --- |
| 首屏 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/doc-baseline-mini/wolai-initial.png` | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/doc-baseline-mini/local-initial.png` | 本地首屏仍是聚合/预览壳,需点击 `打开当前页面` 才进入正文,和 Wolai 直接正文页不一致 |
| 搜索 modal | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/baseline-20260430/wolai-03-search-modal-controls-filled.png` | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/baseline-20260430/local-03-search-modal-controls-filled.png` | 容器接近;结果态、数据、入口矩阵仍需拆开验;switch 状态必须截图 + `aria-checked` 双证据 |
| 块 hover | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/baseline-20260430/wolai-08-block-hover-insert-entry.png` | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/baseline-20260430/local-14-block-hover-insert-entry.png` | 本地已有 `+` 与手柄入口,但位置、密度、页面状态不同,不可判定已对齐 |
| 编辑清理 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/baseline-20260430/wolai-14-title-suffix-after.png` | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/baseline-20260430/local-16-editor-after-undo-cleanup.png` | Wolai 标题和正文都可编辑,editable-test 前必须先确认焦点 block 类型 |
当前必须优先拆解的差异:
1. 普通文档首屏入口语义:Wolai 直接显示正文页,本地仍需点击 `打开当前页面`
2. 搜索入口矩阵:Wolai 左侧搜索可打开,`Ctrl+K` 本轮未稳定;本地顶栏搜索可打开,侧栏入口和快捷键要继续按 smoke 验证。
3. 搜索结果数据:Wolai 对 `Hermes` 有真实结果,本地依赖当前工作区示例数据;后续需要固定 fixture 或种子。
4. 编辑器测试焦点:写入前必须确认当前焦点在正文测试块,不在标题或 breadcrumb 渲染副本。
### 2.1 task129 Phase A 执行记录
2026-04-30 已新增并执行 `scripts/task129-wolai-aline-baseline-smoke.js`,用于固化 Phase A 的只读基线取证入口。该脚本不编辑 Wolai,只做双端首屏取证、DOM 摘要和差异矩阵输出。
主线程验证:
- 命令:`WOLAI_ALINE_RUN_ID=main-20260430-122309 node scripts/task129-wolai-aline-baseline-smoke.js`
- 结果:通过,`ok: true`,确认 `simultaneous: true`
- 矩阵:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/main-20260430-122309/comparison-matrix.md`
- Wolai 截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/main-20260430-122309/wolai-1392x1213-first-screen.png`
- 本地截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/main-20260430-122309/local-1392x1213-first-screen.png`
主线程多视口验证:
- 命令:`WOLAI_ALINE_RUN_ID=main-viewports-20260430-122418 WOLAI_ALINE_VIEWPORTS=1392x1213,1440x900,390x844 node scripts/task129-wolai-aline-baseline-smoke.js`
- 结果:通过,生成 `1392x1213``1440x900``390x844` 三组 Wolai / 本地截图
- 矩阵:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/main-viewports-20260430-122418/comparison-matrix.md`
subagent 复测:
- 命令:`WOLAI_ALINE_RUN_ID=subagent-20260430-122359 node scripts/task129-wolai-aline-baseline-smoke.js`
- 结果:通过,`ok: true`,确认 `simultaneous: true`,本次不需要 `xvfb-run`
- 矩阵:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/subagent-20260430-122359/comparison-matrix.md`
- Wolai 截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/subagent-20260430-122359/wolai-1392x1213-first-screen.png`
- 本地截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/subagent-20260430-122359/local-1392x1213-first-screen.png`
主线程截图复核结论:
- Wolai Hermes 为 owner 登录态,直接显示正文页和 `全网公开` 状态。
- 本地 `3000` 工作区可见,但首屏仍停留在聚合 / 预览入口,需要点击 `打开当前页面` 才进入正文。
- `task129` 只证明取证工具链可用,不证明 UI 已对齐;后续首个实现任务应优先处理 `D9 普通文档首屏入口语义`
### 2.2 task130 D9 执行记录
2026-04-30 已新增并执行 `scripts/task130-wolai-aline-root-document-entry-smoke.js`,用于固化 `D9 普通文档首屏入口语义`。该脚本启动临时 `mnote-web` 端口验证新代码路径,不修改现有 `3000` 进程。
RED
- 初次运行失败:`AssertionError: 根页不应停在需要点击“打开当前页面”的聚合入口`
- 失败原因:Rust Web root route 在有 active page 时只渲染 workspace entry 和 `打开当前页面` 链接,没有内嵌 Page Aggregate、editor bootstrap 和 `leptos-tiptap` island。
GREEN
- 命令:`node scripts/task130-wolai-aline-root-document-entry-smoke.js`
- 结果:通过
- 本地截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task130-root-document-entry/local-root-document-entry.png`
- smoke 断言:根页不再出现 `打开当前页面`;存在 `document-shell[data-editor-host="leptos_tiptap_island"]`;存在 `__MNOTE_PAGE_AGGREGATE__``__MNOTE_EDITOR_BOOTSTRAP__`;存在 `.ProseMirror[contenteditable="true"]`
实现摘要:
- root route 在 active page 可加载 Page Aggregate 时,直接复用 `DocumentPage`、Page Aggregate snapshot、editor bootstrap、title controller 和 island adapter。
- 若 active page 不能加载 Page Aggregate,回退旧 workspace entry,避免 recent cookie 指向失效页面时 root 直接 400。
- 现有 `3000` 进程仍是旧实例;需要重启 `mnote-web` 后,`3000` 才会体现该改动。
验证:
- `cargo fmt -p mnote-web --check`
- `cargo check -p mnote-web`
- `cargo test -p mnote-web root_entry -- --nocapture`
- `node scripts/task130-wolai-aline-root-document-entry-smoke.js`
最终对标复核:
- subagent 命令:`node scripts/task130-wolai-aline-root-document-entry-smoke.js`
- 结果:通过
- Wolai 基线:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task129-baseline/main-20260430-122309/wolai-1392x1213-first-screen.png`
- 本地截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task130-root-document-entry/local-root-document-entry.png`
- 结论:D9 目标行为一致;剩余侧栏数据、图标细节、具体字号属于后续 Sidebar / visual token checklist。
## 3. 通用证据矩阵
每个 checklist 项都必须保留以下字段:
| 字段 | 要求 |
| --- | --- |
| Wolai 截图 | 绝对路径,保存在 `/mnt/Data1T/mnote/tmp/wolai-editor-parity/<task>/` |
| 本地截图 | 同视口、同动作链截图 |
| 入口 | 按钮、快捷键、菜单或 hover 区域 |
| 关闭路径 | Esc、再次快捷键、遮罩、关闭按钮、入口 toggle |
| URL | 操作前后是否变化 |
| 控件类型 | switch、button、dropdown、menu、input、panel、modal |
| 控件状态 | checked、selected、disabled、focused、hover、active |
| 视觉形态 | 尺寸、位置、间距、阴影、颜色、图标、遮罩 |
| DOM/ARIA | role、aria、data-testid、可聚焦性 |
| smoke | 对应 `scripts/task*-smoke.js` 或测试文件 |
| 剩余差异 | 不允许空泛写“基本一致” |
## 4. Phase A:基线和全局 token
| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| A1 | GREEN | 固定基线视口与截图目录 | `task129` 已支持 `WOLAI_ALINE_VIEWPORTS`;主线程已生成 `1392x1213``1440x900``390x844` 三组截图;subagent 已复测默认视口 |
| A2 | PARITY | Wolai owner 首屏基线 | `task129` 主线程与 subagent 均确认 Wolai owner 登录态,截图见 2.1 执行记录 |
| A3 | PARITY | 本地 `3000` 首屏基线 | `task129` 主线程与 subagent 均确认本地 3000 可打开,截图见 2.1 执行记录 |
| A4 | TODO | 字体栈与基础 token | smoke 或 DOM 断言全局字体、标题字号、正文行高、sidebar 行高;截图确认中文字宽接近 Wolai |
| A5 | PARITY | 截图差异表模板落地 | `task129` 自动输出 `comparison-matrix.md`,主线程已复核截图,subagent 已独立复测 |
| A6 | PARITY | 同时操作工具链固化 | `task129` 固定 `Playwright + Chrome persistent profile`;主线程与 subagent 均确认可同时操作两个目标,本次 subagent 不需要 `xvfb-run` |
## 5. Phase BSidebar / 页面树
| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| B1 | PARITY | 侧栏宽度与背景 | `task131` 覆盖宽 `248px`、背景 `rgb(245,245,245)`、无右侧 inset、topbar.x=sidebar.rightsubagent post-fix2 复核通过 |
| B2 | PARITY | workspace header | `task132` 覆盖 header `40px`、avatar `24x24`、字号 `16px`;Wolai DOM 锚点弱,主线程与 subagent 以截图复核通过 |
| B3 | PARITY | 快捷入口行 | `task132` 覆盖 6 个快捷入口、30px 容器、约 10.4px 间距;截图复核通过 |
| B4 | PARITY | 页面树行密度 | `task132` 覆盖行高 `32px`、字号 `16px`、无额外行 margin;截图复核通过 |
| B5 | PARITY | 当前页选中态 | `task132` 覆盖淡红底 `rgba(255,71,71,.1)`、红字、`aria-current=page` / `aria-selected=true`;截图复核通过 |
| B6 | PARITY | 层级缩进 | `task132` 使用父子页面 fixture 覆盖行 x 不变、一级子行内部缩进 `20px`;服务端和运行时均补齐 depth 语义 |
| B7 | PARITY | 页面树 hover action | `task132` 覆盖 hover 仅出现“更多操作 / 新建子页面”两个 24px actionsubagent post-fix2 复核通过 |
| B8 | PARITY | 页面树上下文菜单 | `task132` 覆盖宽约 `220px`、9 项命令、分组间距和 `Alt+` / `Del` 提示;高风险删除仍经确认 |
| B9 | PARITY | 底部垃圾桶/模板中心 | `task132` 覆盖 footer `44px`、无顶部分隔线、垃圾箱/模板中心固定底部;截图复核通过 |
| B10 | PARITY | 文件树创新入口 | 保留 Explorer tab`task132` 复核主路径仍是“我的页面”,footer 与行高体系不被破坏;与 Wolai 无 Explorer 的差异按本地创新入口保留 |
| B11 | PARITY | 页面树图标与展开箭头 | `task133` 覆盖 Wolai 每行不同私有 glyph、本地无真实 icon 数据时不得用统一房子图标,也不保留空 icon slot;展开箭头使用 20x20 SVG chevron |
### 5.1 task131 / task132 / task133 Phase B 执行记录
2026-04-30 已完成 Phase BSidebar / 页面树。执行口径按 `wolai-aline` skill:先由 subagent 取 Wolai 基线,主线程查看截图并写 RED smoke,再最小实现,最后本地与 subagent 复测。用户复核指出 `task132` 漏掉页面树图标/箭头差异后,补充 `task133` 将该类肉眼差异固化为 smoke。
RED / GREEN
- `scripts/task131-wolai-aline-sidebar-b1-smoke.js`:固化 B1,初始失败于本地侧栏 `240px`GREEN 后覆盖 `248px``rgb(245,245,245)`、无 right inset、topbar 贴合。
- `scripts/task132-wolai-aline-sidebar-phase-b-smoke.js`:固化 B2-B10,使用父子页面 fixture 覆盖 header、快捷入口、行密度、选中态、层级缩进、hover action、上下文菜单、footer。
- `scripts/task133-wolai-aline-sidebar-tree-icons-arrows-smoke.js`:固化 B11,RED 失败于页面树统一房子 glyph;二次 GREEN 后断言 page 模式不渲染通用房子/伪 icon、不保留空 icon 槽,标题贴近箭头/占位,toggle 使用 20x20 SVG chevron。
实现摘要:
- `rust/crates/mnote-web/src/ssr/styles.rs`:侧栏宽度/背景、header、quick actions、tree row、选中态、context menu、footer 的 Wolai 对齐样式;page 模式无真实 icon 数据时不显示统一房子 glyph,也不保留空 icon 槽。
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`:页面树运行时渲染补 `aria-current` / `aria-selected`hover action 收敛为“更多/新建”,上下文菜单命令与 Wolai 对齐,运行时递归 depthpage tree 展开箭头改为 20x20 SVG chevronpage 行不渲染空 icon 节点。
- `rust/crates/mnote-web/src/tree_shell/page_renderer.rs` / `routes/tree.rs`:SSR 页面树补父子层级 depth / aria-level 语义,兼容 `parentId``parentNodeId`SSR page tree 展开箭头同样使用 20x20 SVG chevronpage 行不渲染空 icon 节点。
验证命令:
- `cargo fmt -p mnote-web --check`
- `cargo check -p mnote-web`
- `MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task131-wolai-aline-sidebar-b1-smoke.js`
- `MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task132-wolai-aline-sidebar-phase-b-smoke.js`
- `MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task133-wolai-aline-sidebar-tree-icons-arrows-smoke.js`
- `node scripts/task119-rust-web-wolai-visual-regression-smoke.js`
证据路径:
- B1 Wolai 基线:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task131-sidebar-b1-baseline/wolai-sidebar-b1-open-1392x1213.png`
- B1 本地最终:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task131-sidebar-b1-postfix/local-sidebar-b1-postfix-1392x1213.png`
- Phase B Wolai 基线矩阵:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b-baseline/comparison-matrix.md`
- Phase B 本地主线程最终:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b/local-sidebar-phase-b-1392x1213.png`
- Phase B 本地菜单最终:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b/local-sidebar-phase-b-menu-1392x1213.png`
- Phase B subagent post-fix2 JSON`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b-postfix2/sidebar-phase-b-postfix2-measurements.json`
- Phase B subagent Wolai 菜单:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b-postfix2/wolai-sidebar-context-menu-1392x1213.png`
- Phase B subagent 本地菜单:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b-postfix2/local-sidebar-context-menu-1392x1213.png`
- B11 用户指出差异截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b-baseline/wolai-03-page-tree.png` / `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task132-sidebar-phase-b-baseline/local-03-page-tree.png`
- B11 subagent 基线矩阵:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task133-sidebar-tree-icons-arrows-baseline/comparison-matrix.md`
- B11 subagent Wolai / 本地复核截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task133-sidebar-tree-icons-arrows-baseline/wolai-sidebar-tree-icons-arrows.png` / `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task133-sidebar-tree-icons-arrows-baseline/local-sidebar-tree-icons-arrows.png`
- B11 本地主线程最终截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task133-sidebar-tree-icons-arrows/local-sidebar-tree-icons-arrows-1392x1213.png`
- B11 二次复核矩阵:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task134-sidebar-arrow-no-empty-slot-baseline/comparison-matrix.md`
- B11 二次复核截图:`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task134-sidebar-arrow-no-empty-slot-baseline/wolai-sidebar-tree.png` / `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task134-sidebar-arrow-no-empty-slot-baseline/local-sidebar-tree.png`
主线程复核结论:
- B1-B11 可量测项已对齐或按 checklist 明确保留本地差异。
- Wolai header/avatar DOM 选择器不稳定,最终以截图 + 本地稳定锚点复核。
- `Explorer` 是 mnote 本地创新入口,按 B10 保留;视觉不抢“我的页面”主路径。
- 菜单位置因页面树数据不同而不同;尺寸、项目、分组高度已对齐。
- Wolai 页面树图标是每行不同的私有 glyph;当前本地 projection 没有真实 per-page icon 数据,因此不硬编码类似图标,也不保留空白 icon 列。二次复核确认:保留空列会让标题 x 更接近 Wolai,但视觉上是明显缺失;当前按用户确认的产品判断去空列,残留差异是标题比 Wolai 真实图标+标题组合更靠左。后续若树投影提供真实 icon 字段,再按行渲染。
## 6. Phase C:顶栏、breadcrumb、搜索
| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| C1 | TODO | 顶栏高度与按钮密度 | 顶栏约 40px;按钮轻量 hover;右侧 icon/text 序列不重 |
| C2 | TODO | breadcrumb | 图标、分隔符、弱色文字、截断方式对齐;切页后与页面树同步 |
| C3 | TODO | owner/published 按钮分型 | owner 与 published 的按钮组合分开;不把 published 文案硬塞 owner 态 |
| C4 | TODO | 顶栏搜索入口 | 点击打开全局搜索 modal,URL 不变,焦点进入输入框 |
| C5 | TODO | 侧栏搜索入口 | 打开同一个全局搜索 modal 或明确的树过滤入口;不得误跳 `/search` |
| C6 | TODO | 搜索 modal 默认状态 | `仅匹配标题``页面内搜索` 为 switch 且默认开启;不是普通 pill button |
| C7 | TODO | 搜索 modal 关闭路径 | Esc、遮罩、再次 `Ctrl+P`、入口 toggle 按 Wolai 实测对齐 |
| C8 | TODO | 搜索结果行 | 匹配数量、命中高亮、快捷键提示、结果 icon、所在页面信息对齐 |
| C9 | TODO | 搜索空态/加载态 | 输入无结果和加载时的视觉与 DOM 状态可被 smoke 捕获 |
| C10 | TODO | 搜索入口/快捷键矩阵 | 分别验证 Wolai 左侧搜索、顶栏/侧栏入口、`Ctrl+P``Ctrl+K`;每个入口记录 URL、打开/关闭路径和阻塞 |
| C11 | TODO | 搜索结果 fixture | 固定本地 `Hermes` 或等价种子数据,避免用随机工作区数据对比 Wolai 结果态 |
## 7. Phase D:文档画布与阅读态
| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| D1 | TODO | 主内容列宽 | 普通文档列宽约 760px;大屏不贴左;移动端不溢出 |
| D2 | TODO | 标题位置与样式 | Hermes 标题 y 位置、`34px / 44px / 600`、颜色接近 Wolai |
| D3 | TODO | 默认隐藏 meta/debug 行 | 普通文档默认不显示不像 Wolai 的工作区 meta、横线、debug outline |
| D4 | TODO | 正文段落 | `16px / 24px`、段间距、弱色文本与 Wolai 对齐 |
| D5 | TODO | 任务块 | checkbox 尺寸、边框、文本 baseline、完成态接近 Wolai |
| D6 | TODO | 引用/列表/标题块 | 阅读态块样式不跳出 Wolai 密度;截图覆盖至少三类块 |
| D7 | TODO | 右下角浮动入口 | AI / 帮助入口减重,尺寸和位置接近 Wolai,不遮挡正文 |
| D8 | TODO | 阅读态和编辑态切换 | 切换时标题、正文列宽、scroll 位置不明显跳动 |
| D9 | PARITY | 普通文档首屏入口语义 | `task130` 已覆盖 RED/GREENsubagent 最终对标复核通过:根页不再停在“打开当前页面”入口,直接出现 document shell + editor island |
## 8. Phase E:主编辑器块交互
| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| E0 | TODO | editable-test 焦点护栏 | 写入前先断言焦点在正文测试块,不在标题、breadcrumb 或隐藏输入;截图记录焦点位置 |
| E1 | TODO | editable-test 基础输入 | Hermes editable-test mode 取 Wolai 输入/回车/撤销基线;本地保存后刷新保持 |
| E2 | TODO | 块 hover 手柄 | hover 块只显示左侧手柄区,不自动弹菜单;浅色块 hover 背景对齐 |
| E3 | TODO | 上方插入短横线 | hover 短横线变 `+`tooltip `在上方插入块` / `Esc, a`;点击前插入 |
| E4 | TODO | 下方插入短横线 | hover 短横线变 `+`tooltip `在下方插入块` / `Esc, b`;点击后插入 |
| E5 | TODO | `Esc, a` / `Esc, b` | 块选中态快捷键插入 before/after;本地 smoke 验证焦点进入新块 |
| E6 | TODO | 块菜单 | 点击手柄打开菜单;`转换为 / 拷贝副本 / 删除 / 复制链接 / 颜色` 等入口视觉对齐 |
| E7 | TODO | slash 菜单 | 输入 `/` 跟随 caret 打开;搜索过滤和键盘选择可用 |
| E8 | TODO | selection toolbar | 选中文本出现工具条;粗体、斜体、链接、颜色、转换块入口可见 |
| E9 | TODO | `Ctrl+A` 双阶段选择 | 第一次选当前文本/块,第二次选全部块;行为与 Wolai 基线一致 |
| E10 | TODO | 拖拽预览 | 块拖动时横向 drop line、分栏竖线预览;持久化可后置但预览需对齐 |
## 9. Phase FPage Aggregate 和命令边界
| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| F1 | TODO | 标题单一真源 | 标题修改后 breadcrumb、sidebar、file tree、document title 同步 |
| F2 | TODO | 正文保存命令 | 编辑器保存继续走 `page.body.save`,不把 Tiptap 临时 id 当持久真相 |
| F3 | TODO | 页面设置语义 | 设置项进入 `page-option-semantics` 和 editor runtime,不做只保存不消费的假功能 |
| F4 | TODO | 页面树命令 | 新建、重命名、移动、归档仍沿 `tree.*`;菜单入口不直接操作本地临时数组 |
| F5 | TODO | 引用语义 | 页面引用、块引用、嵌入引用先保留类型边界,不降级成普通 URL |
## 10. 每轮收尾
每完成一个 ID,必须补齐:
- Wolai 截图路径:`TODO`
- 本地截图路径:`TODO`
- smoke / 测试命令:`TODO`
- 主线程复核结论:`TODO`
- 剩余差异:`TODO`
如果出现新的可复用失败模式,同步更新 `/home/lix/.codex/skills/wolai-aline/references/failure-patterns.md`