# 仓库协作指南（AGENTS）

## 当前主线

- 当前长期方向以 `tree-first graph kernel` 为准，不以 `BlockNote-first` 或 `Mindmap-first` 为准。
- 当前已经进入 local-first MVP 后阶段：最小可用闭环已建立，后续重点是底座统一、compat 瘦身和产品化闭环，不再把新增能力建立在旧 Convex / Next / BlockNote 主链上。
- 当前产品形态固定为：`VSCode 简化版工作区 + tiptap 的 Markdown 前端编辑器 + Hermes/Reasonix agent + simplemindmap/office 插件 + Wolai 主题 Web 壳 + 鉴权控制面`。
- 本地文件夹是早期产品默认数据真相；本地 `.md` 是页面正文真相。Rust SQLite `control-plane` 是默认 auth、membership、share grants、sync state、AI policy、ACP/Hermes runtime session 控制面；`Convex` / 服务端只保留为历史迁移源、显式 cloud source、compat 和 sync replica 边界，不再作为新增能力的默认正文、附件、AI 会话全文主存储或默认控制面。
- `Rust kernel` 持有树、子树、边、projection、query、command 的语义主导权；新增树规则不要继续散落到前端、Next route 或临时 compat 层。
- `mnote-web` 是当前 Rust Web 承载层，负责 transport、projection 分发、兼容切流；`compat` 与 `fixture` 只用于过渡和测试，不应继续承载长期业务语义。`3000` 是唯一前端公开入口；`3104` 已退役为仅显式 debug/internal 使用的边界。`/tree`、`/document-debug` 等 debug 壳默认关闭，仅在显式 debug/runtime 验证时启用。
- 前端 runtime 已完成第一轮模块级拆分：`layout.rs` / `tree.rs` / `web_shell.rs` 不再是大型内嵌 JS 的主要定位入口。查 Sidebar、FileTree、tree shell、document adapter 等浏览器功能时，默认先看 `rust/crates/mnote-web/browser/*.js`；查 tiptap island 行为时，默认先看 `rust/spikes/leptos-tiptap-spike/src/editor_runtime/*.rs`，再回到根 `lib.rs` / Rust route。
- 前端主路径应消费稳定 projection，不应在 UI 层重新拼出第二份对象真相。
- Next `documents/page` 读取主链已优先消费 Rust `mnote.page_aggregate.v1` 快照；TS `page-aggregate-builder` 仅保留为历史 adapter / test helper，不再作为 runtime fallback，也不再把“前端手工拼 `meta + content`”描述为当前主路径。
- `3000` 当前主壳已接入 Rust Web WebSocket push 主链（`/api/realtime/ws`）+ SSE fallback（`/api/tree/events`）的 snapshot / delta / resync consumer，并已有 browser smoke 验证（2026-05-17 WS 迁移 `57ec8322`）；后续收口重点是统一 live cache 与减少补偿链，而不是把它描述成“还没接 live stream”。
- 文档页默认主编辑器已切到页面内 `leptos-tiptap` island；`BlockNote` 已退出文档页默认主路径，只保留为历史参考实现 / 对照材料。
- Page Aggregate 当前已输出 `blockDocument / blockProjectionVersion / projectionSource`（`projectionSource=documents.content`），标题/正文/页面设置写入后 smoke 已通过（`task110`、`task-page-aggregate-body-sync-smoke`、`task-page-aggregate-options-sync-smoke`）；页面/块 AI 最小工具链已通过 Rust Hermes tools 读取和写入块投影；但这仍是从 `documents.content` / local markdown content 投影出来的过渡态，不是 EditorBlockDocument 原生落库完成态。客户端 `PageAggregateClientState` reducer 仍在，页面域单一真源未完全闭环。
- 当前最优先的架构收口不是继续扩编辑器 UI，而是在 local-first MVP 基线上推进 `WorkspacePath/ObjectIdentity` runtime 消费统一、`DocumentBuffer/BufferStore`、`Page Aggregate` 单一真源收口、`tree command cutover` 收尾、`tree realtime event stream` live cache 统一（WS push 主链 2026-05-17 上线，SSE 降级为 fallback）和 agent diff / 冲突合并 / 本地轻量搜索 / 分享同步产品化。AI 侧普通 Markdown 编辑主路径已收口为“当前文件引用 + selection + allowed roots + agent 原生 patch/diff + watcher 同步”；知识库问答、资料 OCR / parse / index / RAG 主路径已收口到 LightRAG，不再维护 LiteParse / 本地 OCR / evidence 资料索引多套 provider；`mnote.doc.fetch`、`mnote.doc.markdown_edit`、`mnote.doc.apply_block_ops`、`mnote.block.*` 只作为 cloud / remote agent / compat fallback 或复杂结构辅助；`review session`/流式 apply 属于 Phase C（设计冻结，当前不实施），不扩新 AI 功能，不把粗粒度 `mnote.page.save` 当成精确块编辑主入口。

## 组件定位

- `leptos-tiptap` island 是当前文档页默认主编辑区 runtime，但不是系统事实源。
- `BlockNote` 是历史参考实现 / 对照材料，不再是运行时系统组件、默认回退编辑器或系统事实源。
- `Mindmap` 是 `tree-first graph` 的一种视图和编辑挂件，不是对象真相层。
- `OnlyOffice` 是独立页面型编辑器，不直接嵌入 `BlockNote` 画布；正文中通常通过附件块跳转进入。
- `page-ai/block-edit-workflow` route 只保留为兼容门面或非 local source 的快捷路径，不作为 local-first 普通 Markdown 编辑默认主路径；local-first 下优先给 Hermes / Reasonix 授权文件引用并让 agent 使用自身文件编辑能力。`mnote.doc.markdown_edit` 是 cloud / remote agent / compat fallback；`mnote.block.*` 保留为结构性辅助。
- `LightRAG` 是当前唯一默认知识库 RAG provider，负责资料库 OCR、parse、chunk、vector、graph、rerank、query 与跨文档问答。MNote 只维护 source registry、allowed roots / 权限、FileTree 灯号、资料库设置 UI、dashboard/status UI、citation/open-reference 映射和 agent tool facade；LiteParse、旧 OCR sidecar、旧 evidence search / local-index agent tools 已退役到历史 / recycle 边界。
- 树域三层模型：`Resource Tree`（kernel 对象组织真源）→ `File Tree`（主组织投影，`{title}.md` 为页面正文行）→ `Page Tree`（导航投影，不持有结构真相）。涉及资源归属优先走 Rust kernel 的 `KernelObjectIdentity` / `KernelProjectionResourceKind`。

## Runtime 模块定位

- `mnote-web` 浏览器 runtime 的当前 canonical 入口是 `rust/crates/mnote-web/browser/`：
  - Sidebar 装配：`sidebar-tree-runtime.js`，已拆出 workspace、page tree、filetree command/open/upload、attachment open、page settings、live apply 等模块。
  - FileTree 通用能力：`filetree-runtime.js`、`filetree-selection-runtime.js`、`filetree-context-menu-runtime.js`、`filetree-dnd-runtime.js`、`filetree-keyboard-runtime.js`。
  - Page AI sidebar host：`sidebar-page-ai-runtime.js`，owner 属于 `07-ai`，不归 `03-rust-web` tree/filetree runtime。
  - 文档页 host adapter：`document-editor-adapter-runtime.js`，已拆出 pane、resource tab、mindmap host、slash positioning、Tiptap conversion、session 等模块。
  - debug/internal tree shell：`tree-shell-runtime.js`，已拆出 page、filetree、picker、DOM、render、icons、state 等模块。
- `leptos-tiptap` island 的当前 canonical 入口是 `rust/spikes/leptos-tiptap-spike/src/editor_runtime/`；新增编辑器行为不得继续直接堆入 `lib.rs`，除非它确实是 wasm-bindgen entrypoint、Leptos 壳层信号编排或仍未形成稳定模块边界。
- CodeGraph 查 JS 功能时应能直接定位这些 `.js` 文件中的顶层函数；若结果仍落到 Rust raw string 或大型旧壳，先检查是否查错历史 / recycle 路径或索引未同步。

## 目录优先级

- `/mnt/Data1T/mnote/recycle/wolai-frontend/src/`
  wolai-frontend（Next.js React 前端）已退役移入 recycle，不作为当前实现依据。页面、编辑器、Sidebar、树视图、阅读态、交互壳默认先看 Rust mnote-web SSR（`rust/crates/mnote-web/src/`）。
- `/mnt/Data1T/mnote/recycle/wolai-frontend/convex/`
  已随 wolai-frontend 移入 recycle，不允许作为当前 Convex deploy fallback。
- `/mnt/Data1T/mnote/recycle/20260522-convex-runtime-retirement/convex/`
  根 `convex/` functions 源码已软删除到这里，只作为历史审计 / 迁移对照素材；不再作为 active deploy source。默认控制面已由 Rust SQLite `control-plane` 承接。
- `/mnt/Data1T/mnote/rust/crates/core-protocol/`
  Kernel 类型、projection 协议、树/图核心术语先看这里。
- `/mnt/Data1T/mnote/rust/crates/bridge-runtime/`
  Kernel query / command / subtree / graph traversal 入口先看这里。
- `/mnt/Data1T/mnote/rust/crates/mnote-web/`
  Rust Web route、transport、compat、tree shell、projection 分发先看这里。
- `/mnt/Data1T/mnote/wolai-backend/app/`
  辅助后端、异步处理、接口配合先看这里。
- `/mnt/Data1T/mnote/recycle/20260522-convex-runtime-retirement/infra/convex/`
  Convex 自托管服务基础设施已软删除到回收区；只作为显式 cloud source / compat / sync replica 或历史数据导出的历史对照，不再被 `desktop:hot` / `dev:hot` 默认启动链路要求。
- `/mnt/Data1T/mnote/src/components/onlyoffice/`
  只在处理 OnlyOffice 静态资源、插件或兼容问题时进入。
- `/mnt/Data1T/mnote/recycle/`
  默认视为历史回收区，不作为当前实现依据，除非任务明确要求。

## 架构约束

- 涉及树、页面结构、文件树、Sidebar、阅读投影、搜索投影、引用边语义时，优先判断是否应落到 Rust kernel，而不是直接改前端拼装逻辑。
- 前端可以做展示、交互和局部适配，但不要新增第二套树真相、排序真相或 projection 契约。
- `mnote-web` 的 `compat route` 可以承接过渡流量，但不要把新的长期业务逻辑继续堆进 compat。
- 浏览器主链默认禁止新增基于 `setInterval`、周期 `setTimeout` 或轮询 fallback 的数据刷新、状态同步和资源存在性检查，尤其是页面树、文件树、文档页、附件、AI 面板等高频可见路径。优先使用 Rust realtime event stream、WebSocket/SSE、watcher、`tree:delta/resync`、`page-aggregate-synced`、`MutationObserver` 和显式 command result 驱动刷新；只有在明确标注的 legacy/debug/internal 边界下，才允许短期保留轮询，并且必须在设计/bug 说明里记录原因、退出条件和内存/CPU 风险。
- 涉及文档页标题、页面设置、正文保存、页头与树一致性时，优先判断是否应收口到 `Page Aggregate`，不要继续在页面壳或 island 外侧拼第二份页面真相。
- 涉及页面新建、重命名、移动、归档、恢复、嵌入时，优先沿 `tree.*` 正式命名推进；`documents.*` 只视为兼容层，不应继续扩写为长期命令面。
- 涉及 local-first AI 普通 Markdown 编辑时，优先沿“授权文件引用 + `AiAccessScope` + allowed roots + agent 原生 patch/diff + 文件版本冲突模型 + watcher 同步”推进；涉及 cloud / remote agent / 复杂结构辅助时，才沿 `mnote.doc.*` / `mnote.block.*` Hermes tools 与 Rust `EditorCommand` 推进。`mnote.page.save` 只作为页面级兜底写入工具。
- 涉及资源归属（哪个页面拥有哪个 mindmap/附件）、object identity 和资源生命周期时，优先沿 Resource Tree → File Tree projection → `tree.resource.*` 命令面推进；`tree.*` 是正式命令面，`documents.*` 只视为兼容层。
- 页面 AI 编辑当前 local-first 主路径为：页面定位到真实 `.md` 文件，MNote 计算 `AiAccessScope` / allowed roots / selection，Hermes 或 Reasonix 在白名单目录内用自身 patch/diff/文件编辑能力写入，MNote 通过 watcher / refresh 同步 tiptap。`mnote.doc.markdown_edit` 只作为 cloud / remote agent / compat fallback；`mnote.block.*` 保留为结构性辅助（拖拽排序等）。两层操作模型已获 CLI Main（Lark Doc）参考实现验证。流式 apply + suggest/review（参考 BlockNote AI）作为 Phase C 设计冻结，当前不实施。
- 涉及知识库资料索引 / OCR / RAG 时，默认沿 `mnote.knowledge_rag.*` / `/api/knowledge-rag/*` 和 LightRAG source registry 推进。图片源不能直接假设会被 LightRAG `/documents/scan` 识别，当前通过 MNote 生成 Markdown wrapper 后进入 LightRAG；LightRAG 后台完成状态通过 MNote 有界 status bridge/backoff 同步到 registry 与 FileTree 灯号，而不是新增无界轮询。
- 需要架构判断时，优先参考：
  - `/mnt/Data1T/mnote/ARCHITECTURE.md`
  - `/mnt/Data1T/mnote/CURRENT_ARCHITECTURE.md`
  - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-8-mvp-post-process-execution-order-v1.md`
  - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md`
  - `/mnt/Data1T/mnote/design/02-convex-rust-long-term-architecture/done/2-2-local-first-workspace-convex-control-plane-v1.md`
  - `/mnt/Data1T/mnote/design/05-editor-mainline/reference/5-5-page-aggregate-single-truth-alignment-v1.md`
  - `/mnt/Data1T/mnote/design/05-editor-mainline/done/5-6-page-aggregate-alignment-checklist-v1.md`
  - `/mnt/Data1T/mnote/design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`
  - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-6-tree-command-protocol-cutover-stage2-v1.md`
  - `/mnt/Data1T/mnote/design/03-rust-web/done/3-3-rust-web-tree-realtime-event-stream-v1.md`
  - `design/03-rust-web/done/3-14-rust-web-tree-realtime-ws-push-v1.md`
  - `/mnt/Data1T/mnote/design/10-review/done/08-kernel-architecture-next-priority-review-and-checklist.md`
  - `/mnt/Data1T/mnote/design/10-review/done/09-page-ai-fast-block-edit-runtime-review.md`
  - `/mnt/Data1T/mnote/design/10-review/done/10-current-mnote-ai-runtime-review-v1.md`
  - `/mnt/Data1T/mnote/design/10-review/done/11-current-full-architecture-review-v1.md`
  - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-24-resource-tree-filetree-pagetree-source-contract-checklist-v1.md`
  - `/mnt/Data1T/mnote/design/05-editor-mainline/done/5-12-main-editor-object-tab-resource-alignment-checklist-v1.md`
  - `/mnt/Data1T/mnote/design/10-review/done/16-mnote-web-runtime-module-maintainability-checklist-v1.md`
  - `/mnt/Data1T/mnote/design/03-rust-web/reference/3-23-sidebar-local-folder-resource-runtime-followup-v1.md`
  - `/mnt/Data1T/mnote/design/07-ai/process/7-38-page-ai-sidebar-runtime-owner-split-v1.md`
  - `/mnt/Data1T/mnote/design/07-ai/done/7-50-lightrag-knowledge-rag-provider-v1.md`

## 设计稿目录规则

- `design/01-*` 到 `design/10-*` 主线大类统一按目录表达状态：`process/` 放当前可执行项，`done/` 放已完成项，`reference/` 放参考材料，必要时用 `draft/` 放未成形草稿。
- 主线设计稿在推进中、且可直接拆 checklist 执行时放到对应大类的 `process/`。
- 主线设计稿在当前真实代码中已完成后，必须移动到对应大类的 `done/`。
- 参考实现、review 证据、对照矩阵、候选合同、测试流程基线等不直接执行的材料必须移动到对应大类的 `reference/`，不要继续占用 `process/`。
- 尚未形成可执行 checklist 的新设想先放 `draft/`；进入实施前必须拆成明确 owner、验收和归档条件。
- 已被后续实现或更新稿明确覆盖、但又不属于 `done` 的旧主线稿，必须移动到 `design/old/` 并标记为 `[recycle]`，不要继续占用活跃 `process/`。
- `design/old/` 下的历史废弃稿也统一按 `process/` 与 `done/` 分层，但标题继续标记 `[recycle]`。
- `design/90-reference/` 只放参考资料，不参与 `process/done` 状态迁移。

## Bugs 目录规则

- `bugs/` 默认镜像 `design/` 的主线分类方式，按对应大类放置缺陷。
- 每个大类继续按 `process/` 与 `done/` 分层：
  - `process/`：缺陷已确认存在，仍在修复或验证中
  - `done/`：缺陷已修复，且已有真实代码与验证证据
- 新确认的缺陷先放 `process/`；修复完成后必须移动到同类目的 `done/`，不要在两个目录同时保留同一条缺陷。
- 缺陷归类以真正 owner 和长期主线为准，不以表面症状命名：
  - `sidebar/topbar/breadcrumb/文档页壳/Wolai 体验对齐` 优先归到 `05-editor-mainline/`
  - `projection/row model/selection/focus/keyboard/DnD/tree command` 优先归到 `04-tree-domain/`
- 当发现bug时，不仅仅是修bug，因为我们当前还处于mvp，需要看bug后面是否反映的是系统的缺失，如果需要系统性的开发，可以写deisign。如果边界不清，应该让user确认。
## 协作边界

- 仅修改与当前任务直接相关的文件。
- 不要擅自恢复、覆盖、删除用户已有改动。
- 若发现与当前任务无关的脏改动，保持不动；若怀疑会影响当前任务，先确认再处理。
- 若当前问题只是 UI 表现异常，先确认是否是实验性 tree shell、compat 路径、轮询或 fallback 混入首屏主链，而不是直接怀疑 Convex 本身。
- 若发现现有轮询或定时刷新链路，不要直接在其上继续叠加补丁；先确认是否能改成事件驱动、watcher/realtime 推送或命令结果定点刷新，再决定是否保留临时 fallback。
- Reasonix / subagent 只能作为受控叶子 worker：任务书必须限定读写范围、验证命令、交付文件和禁止项；不得自行再启动 runner、subagent、额外 worktree 或修改任务书。Codex/Hermes 主控必须复核 diff、handoff/result、验证证据和 git 状态后才能采纳。

## CodeGraph 使用

- 当前项目已配置 CodeGraph MCP；结构性代码问题优先使用 `codegraph_*` 工具：`codegraph_search` 查符号，`codegraph_callers` / `codegraph_callees` 查调用关系，`codegraph_impact` 做影响分析，`codegraph_context` / `codegraph_explore` 获取聚焦上下文，`codegraph_files` 查看索引文件结构，`codegraph_status` 检查索引健康。
- CodeGraph 是当前开发态代码图主工具；代码改动后运行 `codegraph sync .`，大范围重构、排除规则变化或索引异常时运行 `codegraph index . --force`。只有查找字面文本、日志字符串、注释原文，或已经明确目标文件时，才优先用 `rg` / 直接读文件。
- 提交 git 前必须再次运行 `codegraph sync .`，随后用 `codegraph status .` 或 `codegraph_status` 确认没有 pending changes；若仍有 pending、索引异常或本轮改动包含大范围重构 / 排除规则变化，改跑 `codegraph index . --force` 后再提交。

## Reference-Code 快速对照流程

- 对照 VSCode / Sidex / Zed / Lapce / Tiptap 等参考实现时，先确认实际源码目录和对应 `.codegraph/` 是否存在；当前优先参考 `/mnt/Data1T/mnote/reference-code/sidex-main` 的完整 VSCode 工作台源码，`reference-code/vscode` 只作为裁剪版辅助证据。
- 每次只围绕一个功能切面做对照，例如 Explorer 打开目标、编辑器 tab、资源生命周期、拖拽排序、快捷键或 overlay 定位；不要一次性抽象迁移整个参考项目。
- 推荐步骤：`codegraph_status` 确认索引 -> `codegraph_search/context` 找参考实现入口 -> `codegraph_callers/callees` 看调用链 -> 对应查 MNote 当前链路 -> 映射到 Rust kernel / mnote-web / 前端 host 的正确边界 -> 补 smoke 或测试。
- 对照结论必须区分“可直接采用的交互/状态模型”“只适合作参考的实现细节”“不符合 MNote local-first / tree-first 主线的内容”；不要把参考项目中的 UI 层状态当成 MNote 的新事实源。

## 常用命令

- 根目录热启动：`npm run desktop:hot`
- 前端开发（已迁移至 Rust SSR）：`npm run desktop:hot` 启动后直接访问 `http://localhost:3000`
- 前端检查：Rust 测试 `cargo test -p mnote-web`（Rust SSR 与 API），旧 React 前端已移入 recycle
- 后端开发：`cd /mnt/Data1T/mnote/wolai-backend && uvicorn app.main:app --reload --port 8000`
- Convex 自托管：仅在显式 cloud / compat / sync replica 或历史导出场景参考 `/mnt/Data1T/mnote/recycle/20260522-convex-runtime-retirement/infra/convex/README.md`

## Smoke 基线

- 当前 smoke 分类与默认基线以 `scripts/TESTING_REFERENCE.md` 为准。
- 默认浏览器验证入口是 `3000 Rust SSR + leptos-tiptap island + local-first workspace + SQLite control-plane auth`。
- 退役 Convex / Next / 3104 / BlockNote 路径的 smoke 不作为默认回归基线；只有显式 legacy/cloud/compat 任务才运行对应脚本。

## 默认测试账号

- 后续网页测试、浏览和 smoke 默认使用当前 SQLite control-plane Auth 测试账号：邮箱 `mnote.e2e@example.com`，密码 `MnoteE2E123!`，用户名 `mnote-e2e`。
- 优先从 `http://localhost:3000/auth` 点击“测试账号快速登录”进入；若需手动注册，也必须注册同一组账号，不要改用 `MNOTE_DEV_AUTH=1` 跳过真实 auth。
- 需要核验登录是否真实生效时，优先检查当前 `mnote_session` 是否能解析到 SQLite control-plane 用户会话，避免把 `devFallback` 当成真实登录；Convex JWT 只属于历史 / cloud compat 边界。

## 前端测试方法

- 看页面当前真实渲染结果、登录态下实际内容、JS 渲染后的 `localhost` 页面时，优先用 `/doko`；它适合读取真实 Chrome 中已经渲染完成的页面。
- 做交互测试、文件创建/删除/移动、上传、快速登录、侧边栏展开、回归断言时，优先用浏览器自动化测试工具；这类任务不要只靠 `/doko`。
- 推荐顺序是：先用 `/doko` 快速确认页面是否正常渲染，再用浏览器自动化测试工具验证关键交互链路。
- 影响主页入口、Sidebar、tree shell、文档页首屏时，优先补或复用 `scripts/task*-smoke.js` 这类 smoke 脚本。
- 排查高 CPU / 高内存 / 卡顿时，先看是否存在首屏误走实验性 tree shell、compat fallback、重复请求、轮询或回链面板持续刷新，再看数据底座。


## Wolai-aline 对标流程

- 凡任务涉及 `wolai-aline`、Wolai 对标、复刻 Wolai 体验或把 `3000` 行为与 Wolai 页面比对，必须启用 `/home/lix/.codex/skills/wolai-aline` skill，并参考 `/mnt/Data1T/mnote/design/08-wolai-aline-test-flow/reference/wolai-aline-test-flow-v1.md`。
- Wolai-aline 任务默认采用“Wolai 基线取证（默认只读，编辑器任务可用 Hermes editable-test mode）-> 本地 RED smoke -> 小范围实现 -> 本地验证 -> subagent 浏览器对标复测 -> 主线程截图复核 -> 汇报剩余差异”的流程。
- 浏览器对标测试必须使用 subagent 执行；subagent 只做浏览器验证和截图，不修改源码、不还原文件、不清理证据；编辑器任务可在明确声明的 Hermes editable-test mode 下做最小编辑验证。
- Wolai 默认优先只读；当前 Hermes 测试页 `https://www.wolai.com/liaibo/ikFSSM1a4GgvmHBYFCNfVd` 已授权用于 Wolai-aline 编辑器对标，可做最小范围编辑测试。其他 Wolai 页面写入仍需沙盒页 URL 和明确授权。
- 即使在 Hermes 测试页，也禁止未经确认地删除、移动、归档、发布、评论、改权限或批量修改既有非测试内容；编辑测试必须记录前后截图、动作链、输入内容和清理状态。
- 对标验收不能只看文案或 DOM 是否存在；必须检查截图中的控件形态、开启/关闭状态、hover/active 状态、快捷键行为、URL 是否跳转等真实体验差异。
- 发现截图或实测行为与本地实现不一致时，先把差异补进 smoke 形成可复现失败，再修改实现并复测。
- Wolai owner 登录态优先复用 `/mnt/Data1T/mnote/tmp/wolai-playwright-profile`；遇到登录或滑块验证，不绕过，记录阻塞并让用户介入。

## 文件编码与风格

- 所有新增或修改文件统一使用 UTF-8。
- TS/TSX 默认 2 空格缩进，Python 默认 4 空格缩进。
