# 5-11 [done] Wolai 页面设置与 AI 交互壳连续执行 checklist v1

> 更新时间：2026-05-06
>
> 状态说明：
> - 本清单覆盖的页面设置 A/B、页面 AI C、集成护栏 D 均已完成并有 `task160/161/162` 证据，故迁入 `done/`
> - `X1-X6` 属于明确 deferred 项，不构成这轮完成阻塞
> - 2026-05-13 追加说明：本文保留 `task161/162` 对旧 `/api/ai-agent/run -> mnote-cli` 返回链的历史验证证据；AI 长期方向已由 `design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md` 改为 Hermes 页面内客户端 + mnote Hermes skill/plugin
>
> 本清单服务于：
> - `/mnt/Data1T/mnote/design/05-editor-mainline/done/5-10-wolai-page-settings-and-ai-surface-alignment-v1.md`
>
> 执行口径继续统一服从：
> - `/home/lix/.codex/skills/wolai-aline/SKILL.md`
> - `/mnt/Data1T/mnote/design/08-wolai-aline-test-flow/process/wolai-aline-test-flow-v1.md`

## 1. 使用方式

每次只领取一个最小行为，按下面闭环推进：

1. 用一句话定义行为，例如“右上角 `...` 打开页面设置 popover 且 URL 不变”。
2. 派 subagent 先取 Wolai 基线。
3. 主线程复核截图并填写差异矩阵。
4. 新增或更新本地 smoke，先让当前实现失败。
5. 小范围实现，不新造第二份页面真相或 AI 执行面。
6. 运行本地 smoke 和相关单测。
7. 再派 subagent 对 Wolai 与本地复测。
8. 主线程复核最终截图。
9. 更新本清单状态、证据路径和剩余差异。

状态标记：

- `TODO`：未开始
- `BASELINE`：Wolai 基线已取
- `RED`：本地失败 smoke 已存在
- `GREEN`：本地实现与 smoke 已通过
- `PARITY`：subagent 复测和主线程截图复核通过
- `BLOCKED`：存在阻塞

---

## 2. 当前基线证据

2026-05-06 已完成 Wolai 页面设置与 AI 界面的只读基线取证，目录：

- `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/`

当前已确认事实：

| 项 | Wolai 证据 | 当前结论 |
| --- | --- | --- |
| 页面设置入口 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/10-page-settings-open.png` | 右上角 `...` 打开右侧贴边 popover，URL 不变 |
| 页面设置关闭 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/11-page-settings-after-esc.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/13-page-settings-after-outside-click.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/15-page-settings-after-reclick.png` | `Esc`、点击空白、再次点击入口都可关闭 |
| 页面设置结构 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/10-page-settings-open.json` | 3 个 tab，内部主控件是 checkbox 形态 |
| AI 入口 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/20-ai-open.png` | 右下角浮动 `AI` 按钮打开右侧抽屉，URL 不变 |
| AI 关闭 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/21-ai-after-esc.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/23-ai-after-outside-click.png` `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/27-ai-after-close-button.png` | `Esc` 和点击空白无效，只能点右上角 `X` |
| AI 结构 | `/mnt/Data1T/mnote/tmp/wolai-editor-parity/page-settings-ai-baseline/20-ai-open.json` | 标题“智能问答”，有会话区、模型区、输入框和发送按钮 |

### 2.1 用户追加截图复核（2026-05-06）

用户追加的当前 `3000` 截图：

- `/mnt/Data1T/mnote/tmp/image copy 44.png`
- `/mnt/Data1T/mnote/tmp/image copy 45.png`

当前补充判断：

- `image copy 44.png` 和 `image copy 45.png` 暴露的是三类真实问题：页面设置 tab-panel 混显、页面设置保存后回退、页面 AI 抽屉没有真实文本返回。
- 这三类问题已经在本轮代码修复中逐项落地：
  - `styles.rs`：补 `[hidden]` surface 样式，修复 `页面选项 / 自定义页面 / 全局选项` 混显。
  - `documents.rs + bridge-runtime + document.rs + layout.rs`：修复页面设置写链、读链和 SSR 首屏注入，解决“闪一下又复原”。
  - `compat.rs + layout.rs`：修复真实 `/api/ai-agent/run` 返回文本，页面 AI 默认 provider 对齐为 `hermes`。

---

## 3. 通用证据矩阵

每项必须记录下列字段：

| 字段 | 要求 |
| --- | --- |
| Wolai 截图 | 绝对路径，保存在 `/mnt/Data1T/mnote/tmp/wolai-editor-parity/<task>/` |
| 本地截图 | 同视口、同动作链截图 |
| 入口 | 按钮、菜单、浮动入口、快捷键 |
| 关闭路径 | `Esc`、点击空白、再次点击入口、关闭按钮 |
| URL | 操作前后是否变化 |
| 容器类型 | `popover`、`drawer`、`sheet`、`modal` |
| 控件类型 | `checkbox`、`button`、`tab`、`textarea` 等 |
| 控件状态 | `checked`、`selected`、`focused`、`disabled`、`active` |
| DOM/ARIA | `role`、`aria-*`、`data-testid`、可聚焦性 |
| smoke | 对应 `scripts/task*-smoke.js` 或测试文件 |
| 剩余差异 | 不允许只写“基本一致” |

---

## 4. Phase A：页面设置基线与壳层

| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| A1 | BASELINE | Wolai 页面设置基线 | 已有 2026-05-06 Wolai 基线截图和 JSON |
| A2 | GREEN | 本地页面设置入口现状基线 | `task160` 已记录并复测当前文档页右上角 `更多` 打开页面设置容器，URL 不变 |
| A3 | GREEN | 页面设置入口 tooltip | `task160` 已断言入口 `title="页面选项和全局选项"` |
| A4 | GREEN | 页面设置容器类型 | `task160` 已断言本地打开右侧贴边 `popover`，不再是空按钮 active |
| A5 | GREEN | 页面设置 URL 合同 | `task160` 已断言打开和关闭页面设置时 URL 不变化 |
| A6 | GREEN | 页面设置关闭语义 | `task160` 已断言 `Esc`、点击空白、再次点击入口全部有效 |
| A7 | GREEN | 页面设置 3 tab | `task160` 已在真实后端端口上断言 `页面选项 / 自定义页面 / 全局选项` 的 tab-panel 隔离行为 |
| A8 | GREEN | 页面选项主控件形态 | `task160` 已断言首 tab 使用 checkbox 行，而不是旧 inspector 大块按钮 |
| A9 | GREEN | 最小设置项保留清单 | `task160` 已断言 `wideLayout / smallText / showToc / showHeadingNumbers / protectEditing` 出现在首 tab |
| A10 | GREEN | 未接通项显式降级 | `task160` 已断言 `showToc / protectEditing` 当前 disabled 且带“待接线”说明 |

### 4.1 本阶段 smoke 建议

- `scripts/task160-wolai-page-settings-shell-smoke.js`

首轮最小断言建议：

- 点击右上角 `...` 后 URL 不变
- 出现页面设置 `popover`
- 出现三 tab
- `Esc` 可关闭
- 点击页面空白可关闭
- 再次点击入口可关闭

### 4.2 task160 页面设置壳执行记录

2026-05-06 已新增并执行 `scripts/task160-wolai-page-settings-shell-smoke.js`，用于固化 A2-A7 的本地 RED 基线。

RED：

- 命令：`node scripts/task160-wolai-page-settings-shell-smoke.js`
- 结果：失败
- 失败信息：`页面设置入口必须打开右侧贴边 popover`
- 当前本地状态：
  - 点击右上角 `更多` 后 URL 保持文档页不变
  - 顶栏 `更多` 获得焦点，但没有打开页面设置容器
  - 当前页面中未出现页面设置 popover；探测到的唯一 `tablist` 仍是左侧 `我的页面 / Explorer / +`

证据路径：

- 本地点击后截图：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/01-after-click-more.png`
- 本地点击后状态：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/01-after-click-more.json`
- 本地失败截图：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/failure.png`
- 本地失败状态：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/failure-state.json`

当前判断：

- A2 已有本地基线
- A4 已形成真实 RED
- A5 目前从 failure-state 可见点击后 URL 未变化，但完整打开/关闭合同仍待容器实现后继续验证
- A6-A7 仍待容器出现后继续验证

GREEN：

- 命令：`node scripts/task160-wolai-page-settings-shell-smoke.js`
- 结果：通过
- 当前通过行为：
  - 右上角 `更多` 打开页面设置 `popover`
  - URL 保持不变
  - `Esc`、点击空白、再次点击入口均可关闭
  - 顶部存在 `页面选项 / 自定义页面 / 全局选项`
  - 页面设置首 tab 使用 checkbox 行
  - `showToc / protectEditing` 当前显式降级

新增证据：

- `task160` 最终截图：
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/01-after-click-more.png`
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/02-after-esc.png`
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/03-after-outside-click.png`
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task160-page-settings-shell/04-after-reclick.png`

修复补充（2026-05-06）：

- 在 `styles.rs` 中补了 `.wolai-page-settings-section[hidden] { display: none !important; }`
- `task160` 随后已在真实后端端口 `41327` 上验证 `页面选项` 不再混出 `自定义页面` 字段，`自定义页面 / 全局选项` 的 panel 行为恢复正常

---

## 5. Phase B：页面设置动作项与现有能力接线

| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| B1 | GREEN | `页面历史...` 接线 | `task160` 已断言页面设置动作项可打开 Rust Web 页面历史抽屉 |
| B2 | GREEN | `公开分享页面...` 接线 | `task160` 已断言页面设置动作项可打开 Rust Web 公开分享对话框 |
| B3 | GREEN | `移动到...` 入口策略 | `task160` 已断言当前显式为 disabled/placeholder |
| B4 | GREEN | `嵌入到...` 入口策略 | `task160` 已断言当前显式为 disabled/placeholder |
| B5 | GREEN | `删除页面` 入口策略 | `task160` 已断言当前显式为 disabled/placeholder |
| B6 | GREEN | 统计信息布局 | `task160` 已断言底部存在紧凑统计信息区 |
| B7 | GREEN | 页面设置项真实生效 | `task160` 已在真实后端端口上断言 `wideLayout`、`layoutDensity` 持久化并在刷新后回读成功 |

### 5.1 本阶段 smoke 建议

- 在 `task160` 基础上扩展动作项断言
- 新增针对已接通选项的可见结果断言

最低要求：

- 历史入口可打开现有历史抽屉
- 分享入口可打开现有分享对话框
- `wideLayout`、`smallText`、`layoutDensity` 这类已接通项能在页面可见变化中被捕获

### 5.2 task160 Phase B 执行记录

2026-05-06 `task160` 已继续覆盖 B1-B7，当前通过：

- `页面历史...` 可打开 `data-testid="wolai-page-history-drawer"`
- `公开分享页面...` 可打开 `data-testid="wolai-page-share-dialog"`
- `移动到... / 嵌入到... / 删除页面` 当前显式 disabled
- 页面设置底部显示字数、字符、块数、待办统计
- `wideLayout` 写链真实命中 `/api/documents/options`
- `layoutDensity` 写链真实命中 `/api/documents/options`
- `wideLayout` 打开后 `.document-shell` 宽度真实增大

修复补充（2026-05-06）：

- 先修了 `mnote-web` 页面设置 route payload 与 `bridge-runtime` command plan：不再把 `workspaceId` 和一组 `null` 选项继续下发到 `documents:updateOptions`
- 再修了 `DocumentPage` 的 SSR `data-page-*` 首屏注入，以及 `SIDEBAR_TREE_JS` 初始化顺序，避免在 `__MNOTE_PAGE_AGGREGATE__` 还未进入 DOM 时把默认 page options 缓存死
- 之后通过真实后端端口 `41327` 验证：
  - `/api/documents/options` 返回 200
  - `/api/page-aggregate/:id` 能读回 `wideLayout=true`、`layoutDensity=compact`
  - `task160` 刷新后 checkbox 和壳层 attr 不再回退

---

## 6. Phase C：页面 AI 入口与抽屉壳

| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| C1 | BASELINE | Wolai 页面 AI 基线 | 已有 2026-05-06 Wolai 基线截图和 JSON |
| C2 | GREEN | 本地页面 AI 入口现状基线 | `task161` 已记录并复测右下角 AI 可打开页面 AI 抽屉，URL 不变 |
| C3 | GREEN | 页面 AI 主入口迁到右下角 | `task161` 已断言页面级 AI 主入口为右下角浮动按钮 |
| C4 | GREEN | 顶栏 `页面AI` 降级 | `task161` 已断言顶栏不再保留 `页面AI` 主入口 |
| C5 | GREEN | 页面 AI 容器类型 | `task161` 已断言页面 AI 以右侧抽屉打开、无遮罩、不跳新页面 |
| C6 | GREEN | 页面 AI 关闭语义 | `task161` 已断言 `Esc`、点击空白无效，右上角 `X` 有效 |
| C7 | GREEN | 页面 AI 页面级绑定 | `task161` 已断言历史 `/api/ai-agent/run` 请求体携带当前 `documentId` 与 `pageOptions`；后续同类上下文应进入 Hermes run/session context |
| C8 | GREEN | 页面 AI 历史返回链不分裂 | 真实 `/api/ai-agent/run` 曾改为 `Next 兼容优先 -> 本地 mnote-cli fallback -> 旧 orchestrator 兜底`；`task162` 已验证真实页面可返回文本结果；长期主线已改为 Hermes client proxy + mnote plugin |
| C9 | GREEN | AI chrome 与 Wolai 接近 | `task161` 已断言标题、输入区、`新会话 / 历史会话 / mnote-cli` chrome 可见；后续文案应改为 Hermes session / model / history |

### 6.1 本阶段 smoke 建议

- 本机 gitignored `recycle/scripts/retired-ai-agent-run-smokes/task161-wolai-page-ai-shell-smoke.js`

首轮最小断言建议：

- 点击右下角 AI 后 URL 不变
- 打开右侧抽屉
- 抽屉无遮罩
- `Esc` 不关闭
- 点击页面空白不关闭
- 点右上角关闭按钮可关闭

### 6.2 task161 页面 AI 壳执行记录

2026-05-06 已新增并执行 `scripts/task161-wolai-page-ai-shell-smoke.js`，用于固化 C2-C6 的本地 RED 基线。该脚本现已随旧 `/api/ai-agent/run` smoke 迁入本机 gitignored `recycle/scripts/retired-ai-agent-run-smokes/`，只保留历史对照意义。

RED：

- 历史命令：`node scripts/task161-wolai-page-ai-shell-smoke.js`；当前本机归档路径：gitignored `recycle/scripts/retired-ai-agent-run-smokes/task161-wolai-page-ai-shell-smoke.js`
- 结果：失败
- 失败信息：`页面 AI 入口必须打开右侧抽屉`
- 当前本地状态：
  - 点击右下角 `AI 助手` 后 URL 保持文档页不变
  - 浮动 AI 按钮没有打开抽屉
  - 当前页面中未出现页面 AI 容器、关闭按钮、标题或输入框

证据路径：

- 本地点击后截图：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/01-after-click-ai.png`
- 本地点击后状态：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/01-after-click-ai.json`
- 本地失败截图：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/failure.png`
- 本地失败状态：`/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/failure-state.json`

当前判断：

- C2 已有本地基线
- C5 已形成真实 RED
- C6 仍待抽屉出现后继续验证
- C7-C8 仍待实现阶段继续验证

GREEN：

- 历史命令：`node scripts/task161-wolai-page-ai-shell-smoke.js`；当前本机归档路径：gitignored `recycle/scripts/retired-ai-agent-run-smokes/task161-wolai-page-ai-shell-smoke.js`
- 结果：通过
- 当前通过行为：
  - 右下角 AI 入口打开页面级右侧抽屉
  - URL 保持不变
  - `Esc` 和点击空白不会关闭
  - 右上角关闭按钮可关闭
  - 抽屉标题、输入区、会话/模型 chrome 可见
  - 发送动作在历史实现中继续命中 `/api/ai-agent/run`
- 历史请求体继续携带当前 `documentId` 与 `pageOptions`；后续应转为 Hermes run/session context

新增证据：

- `task161` 最终截图：
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/01-after-click-ai.png`
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/02-after-esc.png`
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/03-after-outside-click.png`
  - `/mnt/Data1T/mnote/tmp/wolai-editor-parity/task161-page-ai-shell/04-after-close-button.png`

修复补充（2026-05-06）：

- `compat.rs` 的 `/api/ai-agent/run` 已改为：
  - 先尝试代理到 Next 的 `/api/ai-agent/run`
  - 失败时本地直接 `mnote-cli` host fallback
  - 再失败才走旧 orchestrator
- 同时补了认证头显式转发，避免被 Next 侧 307 `/auth` 拦截
- 页面 AI drawer 默认 provider 改为 `hermes`
- 新增 `task162-wolai-page-ai-real-response-smoke.js`，并在真实后端端口 `41327` 上验证：页面 AI 不再显示 `page_ai_failed_502` / “没有返回文本结果”，而是会回填真实文本
- 2026-05-13 口径更新：上述修复只证明历史页面 AI 抽屉可返回文本，不再作为后续 AI 长期执行面依据；新的页面 AI 应直接调用 Hermes client proxy，不再通过 `/api/ai-agent/run` 的 provider / fallback 分支模拟 Hermes

### 6.3 task162 页面 AI 真实返回执行记录

2026-05-06 已新增并执行 `scripts/task162-wolai-page-ai-real-response-smoke.js`，用于补齐 C8 的真实返回验证。

- 命令：`MNOTE_UI_BASE_URL=http://127.0.0.1:41327 node scripts/task162-wolai-page-ai-real-response-smoke.js`
- 结果：通过
- 当前通过行为：
  - 页面 AI 不再出现 `page_ai_failed_502`
  - 不再显示“当前页面 AI 已接通 \`mnote-cli\`，但这次没有返回文本结果。”
  - 页面 AI 会回填真实 `mnote-cli` 输出文本

---

## 7. Phase D：页面 AI 与页面设置的集成护栏

| ID | 状态 | 任务 | 验收要点 |
| --- | --- | --- | --- |
| D1 | GREEN | 不新造页面设置真相 | 页面设置继续围绕 `currentPageOptions -> /api/documents/options -> page.layout.updateOptions` |
| D2 | GREEN | 不新造 AI 执行面 | 历史实现围绕 `/api/ai-agent/run -> mnote-cli` 保持单链；后续不在 mnote 内新造 AI 执行面，而是调用 Hermes 并通过 mnote plugin 写回业务事实 |
| D3 | GREEN | 文档页 owner 行为合同固定 | `task160/task161` 已断言 owner 态页面设置和 AI 都不跳新页面、不改 URL |
| D4 | GREEN | mobile / 窄屏退化 | `task160/task161` 已断言移动视口下 popover / drawer 不超出视口 |
| D5 | GREEN | React compat 与 Rust SSR 边界 | 本轮实现仅落在 `mnote-web` Rust SSR 壳、脚本与样式；未再把入口回接 React compat |
| D6 | GREEN | checklist 与失败模式回填 | 已向 `wolai-aline/references/failure-patterns.md` 新增“本地 3000 进程未重启，smoke 误打旧实现” |

---

## 8. Deferred 清单

以下项当前明确延后，不混入首批验收：

| ID | 状态 | 任务 | 说明 |
| --- | --- | --- | --- |
| X1 | TODO | 演示模式 | 不是本轮页面设置与 AI 壳的主线 |
| X2 | TODO | 页面评论 | 用户已明确可延后 |
| X3 | TODO | 页面协作 | 用户已明确可延后 |
| X4 | TODO | 成员邀请 | 顶栏 owner 态能力，后续单拆 |
| X5 | TODO | 全局 AI 入口重构 | 本轮只做页面级 AI |
| X6 | TODO | 帮助浮动入口完全对齐 | 本轮优先 AI，不把帮助入口一起扩面 |

---

## 9. 完成判定

本清单只有在以下条件同时成立时，才可以视为本轮设计进入可实现状态：

- 页面设置 `popover` 行为已通过本地 smoke 和 Wolai 基线复核
- 页面 AI 抽屉行为已通过本地 smoke 和 Wolai 基线复核
- 页面设置仍然围绕 `page.layout.updateOptions`
- 页面 AI 历史验证仍然围绕 `/api/ai-agent/run -> mnote-cli`；后续执行主线改为 Hermes client proxy + mnote plugin
- deferred 项没有被误报为已完成

本轮完成后的正确口径：

> **页面设置与页面 AI 的交互壳已开始对齐 Wolai；AI 后续执行主线改为 Hermes 面板 + mnote plugin，评论、协作、成员、演示模式仍是后续独立任务。**
