返回 DeepSeek-Reasonix
RESOURCE_GOVERNANCE_UPGRADE.zh-CN.md
根目录 / docs / RESOURCE_GOVERNANCE_UPGRADE.zh-CN.md
1 # 会话资源治理升级说明
2
3 > 基线:`main-v2` @ `2553bb31c`(2026-09-15 合并点)
4 > 范围:Desktop 会话历史、流式 Markdown、工具详情、正文读取、媒体释放与 skillwatch 诊断
5
6 ## 为什么要改
7
8 1.38.8 的 CPU/内存反馈暴露的是资源所有权问题,而不是单个热点:历史记录、实时尾部、Markdown 解析、详情正文和媒体解码分别增长,却没有共享的驻留、并发和释放契约。旧实现中的全量历史物化、活跃会话绕过页预算、流式解析重复传输全文和反复重建 worker,均可从源码确认;它们对用户反馈的实际贡献比例仍需在 1.38.8 原生包上采样,当前不能用源码推断替代测量。
9
10 本次重构借鉴 DeepSeek Harness 的几个设计原则:资源由明确的 owner 持有;数据可回收但必须可重新到达;能力协商使用类型化结果;后台工作按交互优先级调度;诊断只记录有界、无正文的计数。
11
12 ## 架构变化
13
14 ### 1. 有界、双向、可恢复的历史窗口
15
16 - 默认只驻留相邻 3 页,每页 32 条;活跃会话与历史会话遵守同一页预算。
17 - 支持“更早内容”“更新内容”“回到最新”,回收远离读者的一端。
18 - 回收会返回必须卸载的稳定 item ID;工具调用和结果作为一个所有权单元释放,不留下孤儿结果。
19 - 被回收内容仍可通过游标重新到达。游标失效返回类型化 `stale_cursor` 并重新定位,不通过错误文本猜测控制流。
20 - 翻页前检测 transcript 内原生选区,避免卸载用户正在复制的节点。
21 - `turn_done` 后把实时尾部重新绑定到最新的持久化有界窗口,长跑活跃会话不再无限追加到页预算之外。
22
23 ### 2. 分层正文与统一资源预算
24
25 资源默认值集中在 `desktop/frontend/src/lib/resourceBudgets.ts`:
26
27 | 资源 | 默认预算 | 超出后的行为 |
28 | --- | ---: | --- |
29 | 历史正文 | 32 MiB / 进程 | 按加权 LRU 回收非活跃会话 |
30 | 历史窗口 | 3 × 32 条 / 会话 | 回收远离读者的一端,保留游标 |
31 | 正文读取 | 全局 4、每会话 2 | 排队、去重;会话释放时取消 |
32 | Markdown AST | 12,000 元素 / 发布页 | 保持顶层语义块完整,用户按页继续加载 |
33 | 超大 Markdown 表格 | 2,000 单元格 / 页 | 表内继续加载 |
34 | 工具预览 | 16 KiB、64 块 | UTF-8/代理对安全截断;完整值仍可按需读取 |
35 | 工具关联项 | 20 项 / 页 | 详情抽屉内继续加载 |
36
37 12,000 是渐进挂载目标,不是删除阈值。单个不可拆的顶层 AST 块即使超过目标也会完整呈现,以保持 Markdown 语义;超大纯文本表格另有单元格分页。完整复制走解析期 selection projection,不依赖当前已挂载页。
38
39 ### 3. 流式 Markdown worker 文档协议
40
41 worker 从“一次性全文请求”升级为文档生命周期:
42
43 ```text
44 open -> append* -> replace* -> finalize -> release
45 ```
46
47 - 前缀增长只传新增后缀;非前缀变更使用 `replace`,结束时用权威全文 `finalize`。
48 - 新流式提交 supersede 旧解析时只丢弃旧响应,不终止并重建 worker。
49 - 调度优先级为:交互流式正文 > 可见历史 > 后台历史。
50 - worker 不可用时继续使用异步主线程解析;失败不会卡死队列。
51 - 解析时同时生成 block fingerprint 与元素计数;渲染端用整数身份复用稳定 AST,不再对每块做两次 `JSON.stringify`。
52 - 当前 Markdown parser 仍是 whole-document 语义解析;增量协议消除了线程抖动和重复桥接全文,但没有宣称 parser 本身已成为增量语法解析器。
53
54 ### 4. 导出、详情和媒体释放
55
56 - 本地 Markdown 导出在 host 侧用 64 KiB 缓冲写临时文件,完成 `flush/sync/close` 后原子替换目标;renderer 不再拼接完整会话字符串。
57 - 本地导出明确按 tab 身份读取;远端旧协议保留 renderer 投影降级。远端降级只能导出当前已加载窗口,因此 UI/发布说明必须保留该兼容限制。
58 - 音频和视频在 URL 变化或卸载时执行 `pause -> remove src -> load`,主动释放解码器和网络资源。
59 - 工具预览、子调用列表和全文读取共享显式预算,折叠/切换后不保留无主请求。
60
61 ### 5. 可观测性
62
63 Runtime Doctor 与 Desktop 诊断面板现在显示 skillwatch 的物理/逻辑 watcher、扫描次数、降级状态和详细计数;session pipeline 记录窗口驻留条目、最大页数和回收页数。所有指标只包含计数、耗时、大小和闭集状态,不记录消息正文或路径。
64
65 ## 兼容性与回退
66
67 - 新 `history-window-v1` 能力由绑定身份决定路由;旧 Serve 返回 `unsupported` 后保持协议 7 的只向旧页读取,不用全量下载伪造“更新内容”。
68 - 本地/远端读失败不会自动跨 host 重试,避免瞬时错误从另一个身份源返回不同会话。
69 - 旧 `HistorySlice`、一次性 Markdown `parse` 和远端导出路径保留一个兼容周期。
70 - 所有回收都只影响内存/DOM 驻留,不删除持久化记录。
71
72 ## 本地验证
73
74 - Go:`./internal/session/... ./internal/serve/... ./internal/skill/... ./internal/boot/...`;race 覆盖 skillwatch/session;`desktop/ go test ./...`。
75 - Frontend:`typecheck`、`test:typecheck`、`test:transcript`、`pretest`、hooks lint、单滚动写入者与 app layer 门禁。
76 - 关键专项:10,000 turn 双向可达与 3 页驻留、实时尾部回收、工具调用/结果成对释放、4/2 正文并发、16 KiB/64 块预览、20 项详情分页、worker 文档协议与优先级、媒体释放、host 导出原子发布。
77 - `repolint` 无新增预算债务,不需要更新基线。
78
79 2026-09-15 在 macOS arm64 / Chromium 153 上实跑的浏览器 fixture 首次通过:240 turns 的初载 129.3 ms、深翻页 2040.7 ms、流式提交 1173.6 ms、输入 p95 24.1 ms、DOM 12,090;1000 turns 兼容压力场景的对应值为 147.6 ms、23175.6 ms、4987.7 ms、45.9 ms、DOM 47,834。会话切换 p95 44 ms,测试区间 JS heap 增长 349,380 bytes,anchor drift 0。1000 turns 的全页 DOM 数字也说明 12,000 预算目前按单个 Markdown 发布页执行,并非全会话全局硬上限。
80
81 生产前端构建的全部 bundle 预算通过;`desktop/ go test ./...` 全绿(主包 335.895 s)。根 `go test ./...` 仅有 3 个 `cmd/reasonix-legacy-migrator` 既存失败,错误均为 `pending update belongs to a different installation: pending update bundle is not the current Guard installation`;资源治理涉及的其余根包通过。
82
83 ## 尚未被本地证据证明的事项
84
85 - 未在 1.38.8 原生包采集 CPU、RSS、JS heap、DOM、轮询频率基线,因此不能给出可信的版本前后百分比。
86 - macOS 浏览器/Electron 基准只能证明当前分支的预算和回归门禁;不能替代 Windows WebView2、Linux WebKit 或三平台安装包验证。
87 - Windows 轮询与全量挂载对原反馈的贡献仍是源码推断,需在真实包上用相同 fixture 采样。
88 - 本地 Markdown 文件是流式写入,但兼容控制器仍可能先提供完整 `HistoryForTab` 切片;它解决 renderer 全量字符串峰值,不等同于所有旧存储路径都已常量内存化。
89
90 发布前应使用同一长会话 fixture 对 1.38.8 与候选包各进行冷启动、会话切换、15 分钟流式运行、深翻页和导出采样,并记录主进程/renderer CPU、RSS、JS heap、DOM 节点、worker 创建次数与读取并发峰值。三平台任一出现游标不可达、选区丢失、导出不完整或持续增长,应阻止发布而不是放宽预算。
91
91 lines MARKDOWN