chore: align local-first control plane and editor fixes

- wire SQLite control-plane access/session paths into Rust web local-folder routes

- preserve local Markdown attachment semantics across upload, reload, and secondary-pane resource tabs

- refresh design governance docs, Reasonix task templates, and bug records

- retire root .mcp.json local MCP config
This commit is contained in:
lix-2026
2026-05-23 23:38:42 +08:00
parent 42fb58310c
commit 5f97800489
110 changed files with 5344 additions and 889 deletions
@@ -0,0 +1,112 @@
# 3-23 [done][bug] dev:hot 启动 inotify 限制导致 local-folder events 500 v1
> 发现时间:2026-05-23
>
> 状态:`[done]`
>
> 关联主线:`03-rust-web`
## 1. 用户可见症状
执行:
```bash
npm run dev:hot
```
启动日志出现:
```text
WARN System notification limit is too small, falling back to polling mode.
WARN Polling for changes every 500ms
ERROR response failed classification=Status code: 500 Internal Server Error latency=0 ms
```
`mnote-web` 本身能启动,但首屏随后会打一条 500。
## 2. 根因
浏览器网络请求定位到失败 endpoint:
```text
GET /api/local-folder/events?rootUri=...
```
该请求返回的错误体为:
```json
{
"code": "internal_error",
"message": "本地文件夹监听失败: OS file watch limit reached. about [\"/mnt/Data1T/Mnote_data/users/mnote-e2e/workspaces/my-space\"]"
}
```
因此根因不是 route 业务逻辑回归,而是 Linux `inotify` watcher 容量不足:
- `cargo watch` 在启动时检测到系统通知额度不足,降级为 polling。
- `mnote-web` 首屏建立本地工作区 SSE watcher 时也申请 watcher。
- 当前用户已有 watcher 占用接近系统上限,导致 `/api/local-folder/events` 创建监听失败并返回 500。
## 3. 修复
已在系统层即时提高并持久化 inotify 容量:
```bash
sudo sysctl fs.inotify.max_user_watches=1048576 fs.inotify.max_user_instances=1024 fs.inotify.max_queued_events=32768
```
持久配置写入:
```text
/etc/sysctl.d/99-mnote-dev.conf
```
内容:
```text
fs.inotify.max_user_watches=1048576
fs.inotify.max_user_instances=1024
fs.inotify.max_queued_events=32768
```
## 4. 验证
验证系统参数:
```bash
sysctl fs.inotify.max_user_watches fs.inotify.max_user_instances fs.inotify.max_queued_events
```
结果:
```text
fs.inotify.max_user_watches = 1048576
fs.inotify.max_user_instances = 1024
fs.inotify.max_queued_events = 32768
```
验证 SSE
```text
/api/local-folder/events?... 返回 200,并收到 ready 事件。
```
验证启动:
```bash
FRONTEND_PORT=3107 timeout 10s npm run dev:hot
```
结果:无 `System notification limit` warning,无启动期 500。
重新启动真实入口:
```bash
npm run dev:hot
```
结果:`http://localhost:3000` 正常启动;浏览器首屏网络请求中 `/api/local-folder/events?...` 为 200。
## 5. 剩余边界
这是系统资源配置问题,本仓库代码不需要为本次 inotify 限制做业务改动。若后续再次出现同类 500,应先统计当前 inotify watcher 占用和后台进程,再判断是继续提高系统额度还是清理异常 watcher 进程。
@@ -0,0 +1,38 @@
# 4-49 [process][bug] 文件树拖拽上传文件落到同级而非目标文件夹下 v1
> 发现时间:2026-05-23
>
> 状态:`[process]`
>
> 关联主线:`04-tree-domain`
## 1. 用户可见症状
原始记录:
```text
我的空间:向文件树中拖动文件上传文件,能正常在主编辑 md 中显示,点击也能正常打开,但是见 /mnt/Data1T/mnote/tmp/image copy 65.png,文件是和主文件夹同级(应该在我的文件夹下级)。
```
## 2. 初步判断
这是文件树拖拽上传目标解析问题,不是附件点击打开问题:
- 上传后的附件块能正常插入主编辑器。
- 点击附件能正常打开。
- 异常点是资源文件在文件树中的落点:实际落到主文件夹同级,而不是拖拽目标文件夹下级。
## 3. 待排查方向
- 文件树拖拽上传时的 target row / parent folder 是否正确写入 upload preflight。
- `local_folder/assets/upload` 或 upload target plan 是否丢失目标目录。
- 页面文件夹 / 当前页面资源归属和文件树手动目标目录之间是否存在优先级覆盖。
## 4. 验收建议
后续修复时应补 smoke
- 在文件树中创建一个目标文件夹。
- 将附件拖拽到该文件夹行。
- 断言附件在文件树中位于目标文件夹下级。
- 断言主编辑器附件块仍能点击在 tab 打开。
@@ -0,0 +1,61 @@
# 5-38 [done][bug] 第二视图 Markdown 附件上传后主编辑区点击失效 v1
> 发现时间:2026-05-23
>
> 状态:`[done]`
>
> 关联主线:`05-editor-mainline`
## 1. 用户可见症状
打开第一视图和第二视图后,在第二视图上传 Markdown 附件会出现一组连续问题:
- 第一次点击第二视图上传后的文件时,第一视图菜单会短暂弹出后消失。
- 上传第二个 Markdown 文件后,页面会卡住或主编辑区附件点击无反应。
- 刷新后上传的 `.md` 附件曾退化成普通链接,只能新窗口打开。
- 修复退化为链接后,仍存在“上传第二个文件后,之前所有附件都不能从主编辑器点击在 tab 打开”的问题。
- 同时点击左侧文件树会把焦点跳到当前文件夹最上方文件,但文件树直接打开文件仍可工作。
## 2. 根因
问题不是第二视图和主视图是否应完全隔离这么简单,而是附件打开、上传插入、刷新重建三条链路没有共享同一个 pane-aware 资源 tab 合同:
- 编辑器内上传后的本地 `.md` 附件在 Markdown 回写 / 重新解析时没有稳定保留为 `data-mnote-attachment-link` 语义,刷新后容易回退成普通链接。
- 资源 openTarget=side 和 document secondary pane 的 URL / DOM 状态边界不完整,导致 secondary 资源 tab 打开时可能污染 primary 的 slash menu / active tab。
- 主编辑器内附件点击只识别部分增强后的链接形态,第二次上传后 DOM 重建路径会让既有附件链接失去可点击的 tab 打开行为。
- 文件树 active/reveal 逻辑和编辑器附件打开逻辑共享了一部分全局焦点状态,导致点击文件树时出现跳到顶部文件的伴随现象。
## 3. 修复
本轮修复把上传、解析、回写、点击打开统一到附件资源 tab 语义:
- 本地 Markdown 页面和 Markdown 资源读取时,根据 `.mnote` 元数据把属于当前文档的上传附件路径传给 Markdown parser,恢复附件链接语义。
- Markdown 回写时支持把 `/api/local-folder/files/open?...` 这类本地打开 URL 改写成相对路径,避免刷新后退化为不可识别的普通链接。
- 编辑器附件增强逻辑扩大到 `.ProseMirror a[href*="/api/local-folder/files/open"]`,即使 DOM 重建后仍能恢复 `data-mnote-attachment-link`、附件样式和 tab 打开行为。
- 上传插入使用当前编辑器 root / pane role 作为目标上下文,secondary 上传只插入 secondary 资源编辑器,不污染 primary。
- 资源 `openTarget=side``secondaryDocumentId` 分离:资源 tab 可在 secondary 打开,但不冒充 secondary 文档页。
- smoke 覆盖连续上传两个真实 `.md` 附件、刷新后点击两个附件、再次上传第二个资源并确认都在对应 pane 的 tab 内打开。
## 4. 验证
已执行过的关键验证:
```bash
cargo check -p mnote-web
node scripts/task459-local-markdown-attachment-tab-smoke.js
node scripts/task472-side-target-secondary-pane-smoke.js
```
本次提交前已重新执行:
```bash
cargo check -p mnote-web
node scripts/task459-local-markdown-attachment-tab-smoke.js
node scripts/task472-side-target-secondary-pane-smoke.js
```
结果:全部通过。
## 5. 剩余边界
本记录只覆盖本地文件夹 Markdown 附件在主编辑器 / secondary pane / resource tab 中的上传和打开链路。OnlyOffice 编辑保存、Office 插件噪声和远端 cloud source 附件合同仍由对应 Office / Rust Web 缺陷记录继续跟踪。