Skip to content

perf: incremental memory optimization across Maka - #5153

Draft
M4n5ter wants to merge 35 commits into
mainfrom
perf/desktop-idle-memory
Draft

perf: incremental memory optimization across Maka#5153
M4n5ter wants to merge 35 commits into
mainfrom
perf/desktop-idle-memory

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Sep 10, 2026

Copy link
Copy Markdown
Member
中文:内存优化进展

目标

持续排查 Maka 的内存增长和不必要驻留。每项优化先验证原因,再修复、测试并逐项提交;本 PR 保持 Draft,不自动合并。

相关工作:开发模式 React 性能记录保留已由 #5156 修复并合并,本 PR 不重复实现;该 PR 尚未声称完成原生 Windows 验证。分页构建的重复编码优化在 #5166 单独推进,本 PR 避免重复改动。

已完成

  • WorkHub 首次使用时才创建界面(9be32ca8f):启用设置只注册快捷键,不再预加载第二套应用。首次打开、停靠和控制请求仍可创建界面;使用后的草稿和待上传附件仍保留。

  • Bot SDK 按需加载(9be32ca8f):飞书、企业微信、Slack SDK 只在有凭据的连接启动时加载;Slack 凭据测试也按需加载。使用同步加载以保留原有启动/停止顺序。

  • 编辑器卸载时释放附件预览(e9289a60a):在图片解码前登记 Blob URL 所有权,卸载时回收并停止后续预览;阻止迟到的文件选择和类型检测重新暂存附件。隐藏、切换草稿及 StrictMode 重放仍保留有效预览。

  • 压缩 Runtime 消息重放记录中的历史正文(c864564f2):提交内容使用现有标准摘要,队列编辑正文使用保留 JS 字符串区分度的摘要;保持完整结果、其他参数、同一 Host Epoch 内的重放语义,不对记录做 TTL/LRU 淘汰。

  • 取消流式显示批次已失效的调度回调(d0f8b3e4d):rAF 与超时回退任一完成后,取消另一项;避免后台窗口暂停绘制时累计已完成批次的回调。

  • 释放历史 Agent 图执行轮次的完整快照(78f521df3):成功切换 epoch 后封住旧工具唤醒入口,等待显式读取结束后释放 reconciliation result;保留历史投影修复及关闭诊断所需的小型元数据,处理切换期间迟到的 epoch 查询。

  • 解除连接对已释放会话快照的保留(e5885fc60):用可移除的关闭监听替代两处连接生命周期 Promise.race,准备完成即解绑,避免已关闭订阅的临时 transcript Buffer 被连接继续持有。

  • 浏览器释放标记只随连接尝试存活(46c82111c):不再永久保存每个已释放会话的 epoch;在连接前登记、连接结束清除,仍防止删除与连接竞争导致浏览器复活。

  • 压缩历史 Root Turn 准入正文(34f4ea848):历史索引只保留内容摘要与独立身份元数据,最新 tip、恢复链和冲突返回保持完整;保留 Host Epoch 身份漂移校验和失败封锁,不增加 TTL/LRU。

  • 释放订阅激活后的准备状态(8908edd9b):成功激活并处理追赶事件后释放失败等待的 Promise 和 resolver,使上一代 replica、handle 和快照及时回收;保留刷新失败回退、重建与 PTY interests。

  • 释放 Zod 递归解析的历史状态(f3fbce26a):移除 schema 对上次 parse context 的强引用,并在同步异常时清理全局分配栈;保留单次解析内的循环和共享引用语义。以现有依赖补丁机制覆盖 ESM/CJS。

  • 释放微信 SSE 的已处理消息与输入块(d02caf96c):处理完成后不再让下一次等待保留最后的原始消息、映射消息和字节缓冲;保留重连游标、分块解析与迭代器关闭语义。这是固定空闲驻留优化,不是历史消息累积修复。

  • 释放 WebRTC 连接拥有的原生任务和资源(31a5a447a):单一生命周期守卫覆盖协商、活动连接、正常关闭及直接释放;取消初始化与数据通道任务,并关闭底层连接。成功连接的生命周期独立于已结束的协商请求。

  • 缩短本地消息重试正文的驻留(b634df8b8):将五秒重试回调移出发送函数作用域,只保留服务和消息标识;待重试内容仍由 SQLite 持久化,重试时间、去重和原身份不变。

  • 取消 Peer Mesh 提前唤醒后的旧定时器(e0dd3c87e):每轮等待拥有并清理自己的五分钟定时器和 abort 监听;超时、路由变化、改名及关闭行为保持正常。

  • 避免代码语言缓存持有完整旧消息(e055012e4):Astryx 共享分词器只缓存有效语言定义,不缓存任意未知标签的 null 结果;保留显示标签、纯文本回退及已知语言正则复用。

  • 释放 CLI 已消费事件的等待记录(cd3656394):可移除的当前失败等待者替代贯穿整个运行上下文的 Promise.race;事件读取或图轮询完成即解绑,保留首次失败、操作异常和现有关闭语义。

  • 避免 CLI 撤销快照重复复制大段粘贴文本(fcd7e0a4a):编辑器快照只复制可变状态、行数组和粘贴 Map,共享不可变字符串;保留全部撤销步骤、粘贴删除与编号恢复及提交清理,不设置历史截断。

  • 限制短文本截断的码点数组分配(c809a7e24):只收集非负预算所需的前缀和一个判定截断的码点,不再将整段大文本展开成数组;保留 NFC、控制字符/双向字符清理、空白折叠、后缀和数值预算的原有行为。

  • 限制诊断日志和 UTF-8 截断的临时分配(cb1ae620e):只为预算内的前缀建立码点数组,避免先编码完整大字符串及超长标记;保留完整脱敏、日志淘汰、字节预算与代理项/标记拼接行为。

  • 释放 Peer 已消费的接收缓冲(ae5d24674):活动路径不再保存认证余量,解析循环在下一次等待前释放已消费的 native chunk 和空切片 backing buffer;保留半帧、未读数据、未 ACK 重放及所有重连语义。

  • 思考正文首次展开时才挂载(4888ea80b):从未展开的 reasoning 不再提前创建 Markdown/代码子树;首次展开后仍保留节点和组件状态,以维持收起动画及流式更新。标题、摘要、键盘和原始 transcript 不变;首次展开前辅助功能树也不再包含隐藏正文。

  • 解除短搜索结果对完整原文的引用(719b64605):只在标题/摘要发生截断时复制保留的短前缀;长度上限、短文本快路径、URL 回退、孤立代理项和截断 emoji 的原有 UTF-16 行为不变。

  • 更新验签依赖按需加载(f4c1a3a20):启动阶段读取渠道信息不再加载 Sigstore/TUF;真实更新解析和默认验签时同步加载,原有哈希、签名、工作流身份与信任根检查不变。

  • 保持自定义模型请求的取消链路(5af4f263b):URL/init 转发直接使用调用方有效 AbortSignal,避免临时 Request 被 GC 后丢失取消传播;保留覆盖、显式 null、继承信号及所有请求正文路径。

  • 复用已经读取的 JSON 请求正文(fdc1c8203):请求叠加/最终策略不再第二次 clone 并读取完整正文,直接解码首轮 ArrayBuffer;保留初次读取、原始流错误、调用方 Request 锁状态及取消信号。

  • Computer Use 清理元数据只随活动任务存活(878520a39):未使用过 Computer Use 的会话清理不再创建 generation 和失效回调状态;队列最后一个任务结束后释放隔离标记,保留旧任务失效、执行器退出和同回合停止权限。

  • 释放会话删除后被拒绝上传的暂存数据(98e194492):在既有会话不存在分支释放该连接/Host Epoch 所拥有的上传,保持原错误响应;失败的 chunk、commit 和客户端清理不再留下已无用途的 Buffer,不增加定时器或改变 TTL。

  • 释放退役 Goal 的 token 计数元数据(1789afeac):归档/删除提交后删除该会话计数,关闭时清空;异步读取复核原有 control lease,防止旧读取重填或覆盖新 Goal。保留 rollback、独立预算基线和会话关闭权限记录。

  • 释放 MCP 背压下已结束请求的对象图(40866dea7):独立创建取消错误观察器,并在请求结束时释放发送观察器的原生 reject 引用;ESM/CJS 均修复。保留排队字节、帧顺序、连接、迟到错误清理和现代协议取消行为。

  • 共享跨回合相同的技能库存快照(2c282d247):每轮仍重新读取目录,仅共享 revision 相同且完整深比较相等的冻结快照;保留原有 100 项逐轮历史和所有路径/顺序/诊断差异。淘汰与晚完成校验防止共享引用形成新的驻留。

验证

  • 八项优化合并后,Linux 完整 Desktop 构建、Desktop/Runtime 类型检查和 449 项相关测试通过(0 失败、0 跳过);各项修改已做针对性 Biome 检查。

  • 相关 Bot、WorkHub、设置测试:239 项通过,0 失败。

  • 隔离 Electron/Xvfb + CDP:启用 WorkHub 后仅主界面;首次打开才创建 WorkHub renderer;编辑器正常出现,隐藏后重开复用同一 renderer。

  • 三次独立 Node 进程测量:Bot 入口导入后 GC 的 RSS 增量中位数约 85.6 → 47.4 MiB,JS 堆增量约 17.9 → 11.1 MiB。这是模块级测量,不代表整机或 Windows 打包应用的节省量。

  • 附件生命周期:7 项真实 Hook / Blob 测试与 21 项相关回归测试通过;UI 构建和类型检查通过。修复前三次编辑器卸载仍保留 3 MiB 可读取的 Blob;修复后全部不可再读取,卸载后也不再创建批次中的下一张预览。

  • Runtime Host 构建及全部 78 项消息协调器测试通过;超过 6 KiB 的正文请求转为不足 512 字符的身份记录,覆盖消费/撤回/idle 后重放及内容、附件、位置、版本冲突。记录数量和精确撤回结果仍保留,未声称完全有界。

  • 显示调度:修复前 150 次超时刷新保留 150 个待执行 rAF;修复后为 0。两种竞争顺序及既有流式交接测试共 24 项通过。

  • Agent 图:Runtime 构建与 19 项测试通过(含 GC,0 跳过)。保留协调器和全部旧工具闭包时,12 个旧 epoch 结果全部可回收;历史查询、并发读取、切换失败重试与迟到查询正常。

  • 会话快照:Runtime Host 编译与 57 项测试通过,另在 Electron 内置 Node 下运行 4 项新测试通过。实际协调器的合成工作负载中,24 次打开/释放/关闭订阅原本保留约 96 MiB(24 个 4 MiB Buffer),修复后保持连接打开也全部可 GC,arrayBuffers 回到约 0.137 MiB 基线。

  • 浏览器释放生命周期:10,000 次未连接释放与 200 次完整连接/释放后标记数为 0;同步重入、重复释放、并发连接和失败重试均通过,相关 18 项测试通过。

  • Windows 已完整构建 e5885fc;Electron 内置 Node 下 90 项针对性测试通过,包含 transcript Buffer GC、图快照 GC、消息重放及显示调度。

  • Windows 46c8211 主进程编译及 18 项浏览器测试通过。

  • Root Turn 准入:Runtime Host 构建及 122 项相关测试通过(含 GC,0 跳过)。真实 SQLite 合成工作负载含 256 轮、每轮 48 KiB 输入:恢复后 owner 额外驻留约 24.15 → 0.29 MiB,历史正文对象全部回收,仅当前 tip 的两份内容对象保留;历史冲突结果返回后也可回收。此优化不改变恢复时读取完整历史的瞬时峰值。

  • Windows Runtime Host 构建及 28 项准入/恢复测试通过(0 跳过);修复既有测试辅助函数遗漏 SQLite 关闭造成的临时文件占用(c66cffe97)。

  • 订阅激活:主进程编译及 42 项 observer/生命周期测试通过;实际订阅类经 100 次刷新与 100 次故障恢复后,只保留当前代,关闭后全部回收。这是固定额外驻留优化,不是无界增长修复。

  • Windows 8908edd 主进程编译及全部 42 项 observer/订阅生命周期测试通过。

  • 显示调度归入 Conversation 功能边界(6eea5ba34),架构约束未放宽;对 CI 基准的检查、103 项规则测试及 24 项显示回归通过。

  • Zod:ESM/CJS 在 Node 24/26 下通过循环、共享引用、异常、重入、并发和 GC 回归。分别撤销两处修复,测试重新失败。真实 backend 20 回合中 80 个消息对象全部回收,原来保留最近两个;单次受控实验堆减少约 8.3 MB。独立递归异常实验中,30 份 256,000 字符 payload 从全部保留变为全部回收;未确认该异常路径在普通产品操作中可达。20,001 节点微基准中位解析耗时约 4.19 → 4.94 ms(增加 0.75 ms)。

  • 全工作区测试构建通过。Node 26 高并发全量运行中 Runtime、Desktop、Core、UI 通过,但 Host 和 CLI 有失败;Host 十个失败项低并发重跑全部通过,CLI 完整重跑 929 项中 926 通过、3 跳过。完整 Host 的 Node 24 低并发复验已通过:1,854 项中 1,842 通过、12 跳过;首次高并发全量运行仍记录为失败。

  • Windows f3fbce2 完整 Desktop 构建、依赖补丁应用及 Electron 内置 Node 下七项重点 GC/竞态回归通过。补齐 Zod 源码补丁许可证清单(0fa4626a6),105 项 ASF 源码发布检查通过。

  • 微信 SSE:Runtime 编译、类型检查、108 项 Bot/生命周期测试通过;两项 GC 回归在旧实现下失败。实际本地 HTTP 通道空闲时,最后一批原始与映射消息全部可回收;合成 8 MiB 输入块在解析器等待下一块时也可释放。

  • Host 集成复测:真实 Host/SQLite/协议客户端完成 100 回合、202 次订阅和 4,206 个帧,400 个已结束 backend 对象全部回收;第 60 至 100 轮结算后堆约 73.30 → 73.66 MB,未见新的历史正文持有。

  • CI 0fa4626 的构建、类型检查、标准工作区与 Host 测试通过;Desktop e2e 为 36/37,WorkHub 拖动断言失败。本地同一 WorkHub 文件 2/2 通过,该失败案例额外独立重复 3/3 通过;31a5a447a 的 Desktop e2e 随后通过,未为此修改产品或测试代码。

  • WebRTC:全部 43 项原生测试通过,覆盖真实数据传输、背压、协商取消、升级失败及关闭中断。实际 32 对本机连接中,正常关闭原本残留 64 个任务;直接释放原本残留 128 个任务和 128 个文件描述符。修复后两种路径均为 0 个残留任务,文件描述符回到 7 个基线;初始化通道的连接强引用也释放。以上为 Linux 本机验证;Windows 全部 42 项原生测试及 release 插件构建也已通过。

  • Windows 31a5a44 完整 Desktop 构建及 19 项微信 SSE 测试通过;使用新原生插件重启后,主界面和 WorkHub 编辑器均正常加载。

  • N-API 集成复测:真实插件与 JS 流包装完成 159 个端点、304 个流和 38 MiB 本机传输;全部被观察对象可回收,文件描述符、socket 和线程回到预热基线。另有 12 次受阻的 32 MiB TCP 写入取消通过。RSS 增长伴随分配器空闲 arena,未据此认定泄漏或调整分配器;大块 QUIC 写入提前断连的原因未调查。

  • 本地重试:实际 Desktop 主进程构建、类型检查及 24 项测试通过;Node 24 独立复验通过。128 次完成并清理本地记录后的合成重试,旧实现仍保留 128 条发送记录、堆约 41.5 MiB;实际编译后的修复为 0 条、约 20.2 MiB。旧实现负对照失败,自动重试、待发送正文、原始身份和关闭保留均验证。这是五秒内额外驻留,不是持续空闲泄漏。

  • Peer Mesh:Runtime Host 编译、34 项相关测试及 Node 24 独立复验通过。200 次公开提前触发后只有一个当前定时器,关闭后为零,正常超时仍触发协调;旧实现第一次提前触发就出现两个定时器。原实现 3,100 次触发留下的 3,102 个定时器经真实五分钟等待自然回落到一个,明确属于短期积压;不以含测量开销的堆差值宣称产品节省量。

  • 31a5a44 的四平台原生构建、原生质量、Windows/Linux 打包及 Windows 恢复检查通过。Windows CLI 安装验证首次在停止测试进程树时超时,原代码重跑通过;主测试的 Desktop e2e 和 Storybook 已通过,但整轮在后续 CLI 构建阶段被新提交取消,未记作全绿。

  • Windows 0e7aa4f 的 Runtime Host 与 Desktop 主进程构建、58 项本地消息/重试/Peer Mesh 测试全部通过;新增回归无需跳过。修正既有测试将 POSIX 权限位用于 Windows 的断言,仅调整测试,不改变产品权限处理。重启后主界面与 WorkHub 均正常。

  • Astryx:实际 MarkdownBody 浏览器工作负载中,20/40 条约 300 KB 消息卸载后,未知语言的 sliced-string 缓存键原本保留约 6/12 MB 完整正文。实际补丁包经相同 40 条工作负载和两次 GC 后,该缓存引用链为零;有界的最新 React text prop 仍保留,未宣称全部对象为零。移除诊断 getter 后旧实现仍复现。新缓存回归旧实现失败,修复后同步/异步/流式和全部已知语言别名通过;UI 全量 440 项、构建、类型检查、Node 24 独立复验、法律清单与完整依赖补丁逆向重放通过。

  • Windows e055012:完整 Desktop 构建、依赖补丁和 Electron 内置 Node 下全量 UI 440/440 通过。初次全量运行额外执行了源码已删除的旧 dist 测试而失败;备份旧 UI 产物后清洁重建复验通过,未修改测试或产品逻辑。确认无草稿、附件及运行中任务后重启,主界面和 WorkHub 均正常。

  • CLI:真实公开运行入口接入合成驱动,单条长流处理 10,000 个 4 KiB 事件。旧实现全部保留,堆约 22.70 → 70.54 MB;实际编译修复约 22.70 → 23.24 MB,流完成后旧事件为零,运行上下文仍存活。堆快照确认并消除了失败 Promise 到旧事件的强引用链。最终回归对旧源码仅 GC 项失败、两项语义项通过;修复后 42 项针对性测试通过。Node 24 独立全量 CLI:932 项中 929 通过、3 跳过、0 失败;构建、类型检查及 Biome 通过。这是 CLI 运行期增长,不是桌面持续空闲归因。

  • Windows cd36563:CLI 构建及 Electron 内置 Node 下 42 项事件等待/运行回归全部通过(0 跳过),包含保留上下文时的事件 GC。此提交仅改 CLI,既有桌面应用继续运行,无需重启。

  • M018:实际 Maka CLI 编辑器粘贴 1 MiB 随机文本后,通过普通键盘输入 60 个短词,父代理独立复测堆从旧实现约 71.15 MB 降至约 8.23 MB;完整撤销历史仍在。原始依赖下两项语义测试通过、内存测试按预期失败;补丁后 3/3 通过,Node 24 完整 CLI 935 项中 932 通过、3 跳过、0 失败。构建、类型检查、Biome、45 项许可/声明测试及原始依赖补丁重放通过。修复限于重复字符串存储,真实编辑历史仍占用必要空间;Windows 已拉取 fcd7e0a,8 个依赖补丁全部应用成功;CLI 构建与 Electron Node 下 3/3 回归通过(无跳过),60 个短词后的堆约 5.75 MB,全部撤销仍可用。现有桌面会话未重启。

  • Windows 扩展 TUI 回归:219 项中 217 通过、2 项 SIGTERM 退出断言失败;仅在内存中恢复原版 pi-tui 编辑器后,两项仍以相同的 'SIGTERM' !== null 失败,排除 M018 补丁引入。未跳过或修改这些测试。

  • fcd7e0a:主测试、原生质量、四平台原生构建、Windows/Linux 打包、Windows 恢复、四平台 CLI 安装和 State Roots 验证均通过;条件型 installed CLI Eval 检查跳过。

  • 预览排查未提交替换:真实图片/PDF 组件的旧 DOM 均可回收,PDF 子进程退出;大部分图片驻留是受压可释放的 Chromium 解码缓存。独特 data URL 另有随文档存活的原生分配,具体持有者未定位。逐次新建并撤销 Blob 虽消除此分配,却在同图重开 20 轮中令解码缓存约 20→508 MB、关闭后 RSS 约 196→663 MiB;受压后两者均约 149 MiB,因此拒绝直接替换。已用独立 IPC、同图哈希和无 Network 观察者对照,未将调试器额外驻留算作产品收益。

  • M019:Core 构建、类型检查及 828/828 测试通过,父代理 Node 24 跨 Core/Storage/CLI 的 82/82 回归通过。旧源码下行为测试通过、同一分配测试失败(约 67.1 MB,阈值 24 MiB)。真实 ClaudeCodeSessionAdapter.listSessions() 读取合成 8 MiB 首条 ASCII 消息时,父代理采样总分配约 92.74→25.61 MB;实际编译产物复验约 25.54 MB,标题和缓存命中不变。这是冷读/文件变化时的瞬时分配优化,缓存标题未发现持有完整正文;完整输入的规范化和清理仍有开销。Windows 完整 Desktop 构建、46 项重点回归通过;全量 Core 初次扫到源码已删除的旧 dist 测试而失败,备份旧 Core 产物并清洁重建后 828/828 通过。确认无草稿、附件和运行任务后重启,主界面与 WorkHub 均正常。

  • M020:Core 构建、类型检查及 832/832 测试通过;父代理 Node 24 跨 Desktop/Host/Runtime/CLI 的 81/81 回归通过。旧源码下两项行为测试通过、两项分配测试分别以约 67.3/154.2 MB 失败,修复后 4/4 通过。8 MiB 合成直接日志的前缀原型独立测量约 0.82 MB;实际编译的错误诊断入口总分配约 154.26→2.82 MB,8 KiB 输出不变。此项减少临时分配,不是持久泄漏修复;脱敏仍扫描完整输入。Windows 已拉取 cb1ae62,Core 构建及全量 832/832 通过;扩展诊断回归 47/48,唯一失败为既有启动诊断测试对 POSIX 权限位的断言,在仅恢复旧截断源码的内存加载对照下仍以相同 54≠0 失败,未修改或跳过。桌面进程继续运行,未声称当前已加载新前端构建。

  • 原生预览补充:去除 React 的裸图片页面仍复现每个不同 data URL 的原生分配;成功执行更强清理后也保留,同图重复仅一份。无符号原生采样将分配大小定位为 data URL 长度加 12 字节,但具体 C++ 持有者仍未确认,未提交产品清理机制。

  • M021:Runtime Host 构建、类型检查、Biome 及父代理 Node 24 独立 23/23 回归通过,含 8 个种子的 64 MiB 断线重放和真实 TCP 控制操作恰好一次验证。旧源码下新增 GC 测试以仍保留 64 KiB 认证 backing buffer 失败;修复后,消费后的认证/native/parser 缓冲全部释放,半帧、未读及未 ACK 内容仍按需持有。原实现稳态额外 128 KiB 会在后续心跳释放、路径替换不累积:此项是有界驻留优化,不是 GB 级增长归因。Windows 已拉取 4888ea8,Runtime Host 构建和认证/重连 19/19 通过(含 GC 和真实 TCP),完整扩展组为 21/23;另外两项 peer-native 测试因将 Windows 路径直接动态 import 而失败,在只恢复旧接收循环源码的对照下仍以相同 ERR_UNSUPPORTED_ESM_URL_SCHEME 失败,未跳过或修改。

  • M022:UI 构建、类型检查、Biome、父代理 Node 24 全量 449/449 通过;旧源码负对照 4 项失败、5 项保留行为通过。父代理以不同 Chromium 进程运行真实 TurnView 的相同合成数据(20 段 reasoning、20 个工具、可见最终答案),GC 后 JS 堆约 10.77→4.83 MB,DOM 元素 5,020→679,reasoning 后代 4,340→0;不是整应用 RSS 或日常节省量。真实 Enter/Space、展开后节点身份、首次展开前更新及收起后更新正常。冷 reasoning-only 单测确认真实 Markdown 动态模块可加载,未测首次加载延迟;应用搜索原本排除 reasoning,首次展开前辅助功能曝光减少已明确记录。Windows UI 全量 449/449 及完整 Desktop 构建通过;确认两界面均无草稿、附件及运行任务后正常重启,主界面与 WorkHub 编辑器健康。

  • M023:Runtime 构建、类型检查、Biome、352 项相关测试与父代理独立 73/73 搜索/结果投影回归通过。保留 30 份来自合法小于 1 MiB JSON 响应的标题/摘要,GC 后堆增量约 24.05 MB→70 KB;旧源码对照仅内存测试失败,16 组字符及回退语义相同。父代理实际 ToolRuntime 的 30 个结果事件原本通过摘要引用约 24 MB 原文,实际编译修复后原文引用为零。此项是结果/待消费事件存活期间的放大修复,不是跨轮空闲泄漏;后续模型上下文本就从 SQLite 重读。Windows 已拉取 719b646,Runtime 构建及全部 73/73 对应回归通过,保留结果堆增量约 37.5 KB;日常桌面进程继续运行,没有再次重启,未声称已加载此新 Runtime 模块。

  • MCP 补充排除:Node 26 下,实际 stdio 与 HTTP 管理器各完成 48 次目录通知更新、64 次重连,并调用所有工具生成验证器;两种路径分别观察的 10,112 个旧对象均回收,连接期间 FD/绑定/订阅数量稳定。没有据 RSS 上升改动缓存;并发未完成调用和故障风暴未覆盖。

  • M024:Desktop 构建、完整类型检查、Biome 与父代理独立 53/53 更新回归通过,包括 Electron 内置运行时的真实 ECDSA/Ed25519 验证。旧源码对照准确捕获启动时提前加载。预先加载 electron-updater 后的三次独立 Node 24 模块级对照,GC 后堆增量中位数约 1.55 MB→0.12 MB、RSS 约 2.92 MB→0.26 MB,渠道读取加载的 Sigstore/TUF 模块为零。这是固定模块驻留优化,不是累计增长或整应用节省量;Windows 已拉取 f4c1a3a,主进程编译和 Electron 内置 Node 下全部 53/53 更新测试通过,包含真实加密验签;既有桌面会话未重启。

  • M025:Node 24 完整 Runtime 测试运行通过(并发 4),构建/类型检查/Biome 和 187 项针对性回归通过。父代理实际持久 ModelAdapter + SDK + 本地有限 SSE 复现:旧实现 6/6 次取消后 100 ms 仍保持底层响应和连接,直到服务端结束;编译修复后 6/6 均已结束读取并关闭连接,九类被观察对象全部回收。独立八项包装器回归通过,旧源码三项新测试失败,其中真实 HTTP 明确在 500 ms 超时。此项缩短取消后的请求资源驻留,不声称永久累积泄漏;调用方自行丢弃 native Request 的底层限制仍存在。Windows 已拉取 5af4f26,Runtime 构建及 Electron 内置 Node 下全部 170/170 模型/请求/代理回归通过。完整 Desktop 构建通过;确认两个界面都没有草稿、附件和运行任务后正常重启,主界面与 WorkHub 均健康。

  • Filesystem worker 排除性实验:真实 client/runner 与有效请求的真实 worker entry 共 145 次成功/失败/取消执行,每轮八类历史对象全部回收,监听器及存活 worker 为零,FD 恒定 22。sandbox 使用透传夹具,未覆盖 Windows sandbox 或 Linux pinned FD;没有据此添加缓存或生命周期补丁。

  • M026:构建、类型检查、Biome、81 项针对性测试及父代理独立 13/13 包装器回归通过。完整 Node 24 Runtime:3,393 项中 3,385 通过、8 跳过、0 失败。旧源码通过四项语义测试,仅大正文重复读取回归失败。父代理实际编译 SDK+本地 HTTP、8 MiB 合成提示词的 ArrayBuffer 采样峰值约 56→40 MiB,堆+ArrayBuffer 约 84.67→67.84 MB,发送与接收均为 8,388,688 字节;三次独立候选进程复验及 87 组语义对照一致。保留会改变错误/流锁语义的首次 clone/read,不采用更激进方案。完成 GC 后无正文规模残留,属于瞬时分配优化,不是空闲泄漏;Windows 已拉取 fdc1c82,Runtime 构建及 Electron 内置 Node 下 81/81 对应回归通过,包括原始流错误和 Request 锁断言;日常桌面进程继续运行,未再次重启。

  • M027:Computer Use/Runtime 构建、类型检查、Biome 与 398/398 相关测试通过;独立完整 Node 24 Runtime 为 3,394 项中 3,386 通过、8 跳过、0 失败。三个新增回归在旧源码下均失败,修复后均通过。保持实际 backend/tools 连接和对象存活,清理 50,000 个不同未使用会话后的额外堆驻留约 16.86 MB→97 KB;executor 始终 idle。真实 mock RPC 覆盖排队清理、同 ID 新任务、同步重入取消、100 次 begin/end 和自有执行器退出;不操作真实桌面。产品上该后端只在 macOS 选择,未做 macOS 原生硬件或 Windows 此项验证;已使用 CU 会话的停止状态仍保留,不声称所有会话状态均有界。

  • M028:Host 构建、类型检查、Biome、100/100 相关测试及独立父任务 57/57 回归通过;8 个新 GC 测试均通过,旧源码 8 个均失败。实际 Desktop 客户端→协调器→真实隔离 Artifact store,三次合法的 50+50+28 MiB 上传完成分块后,在 presence 边界模拟删除会话:旧实现 commit 和 abort 均返回 not_found,仍持有 128 MiB;时钟推进 24 小时并真实 GC 后仍不释放,关闭拥有连接才回收。实际编译修复在连接仍打开时全部回收,arrayBuffers 回到约 0.139 MiB 基线;响应相同。removed/absent × 四种请求覆盖错误连接/epoch隔离、其他 session/upload 保留和满池容量复用。删除由测试依赖模拟,并非 UI 删除或真实 24 小时等待;这是有 128 MiB 上限的暂存驻留,不改变其他路径的惰性过期策略,Windows 已拉取 9cbd018,Host 构建及 84/84 项 Artifact/Goal/Memory/退役回归全部通过(无跳过),包含全部 8 项上传 GC 测试;没有重启现有桌面进程。

  • 额外排除:真实定时协调器 + SQLite 的 360 次触发/编辑/删除/恢复后,2,572 个任务、1,098 个 fire 快照和 552 个历史定时器全部可回收;活动任务只有一个当前计时器。历史压缩的成功、修复重试、取消、真实 AI SDK 本地假模型及 checkpoint 清理链也释放全部已结束输入,只保留当前 checkpoint;明确持有和移除持有的对照均通过。未据此增加产品代码,未覆盖外部永不完成的依赖。

  • M029:Host 构建、类型检查、Biome、27 项 Host Goal 和 134 项 Runtime Goal 测试通过;独立父任务完整 Host 为 1,869 项中 1,857 通过、12 跳过、0 失败,覆盖 M028/M029。真实 SQLite/协调器的 275 个会话退役后,token Map 原保留 259 项,实际编译修复为 0;authority 均为 0,必要的关闭状态记录均保留 275 项。原版 4 个新测试均失败;仅移除异步 lease 校验时,提交生命周期仍通过,删除后重填、重建 Goal 后旧值 30 覆盖新值 120、关闭后重填三项均重新失败。rollback 与 unarchive/rearm 正常。只减少会话标识→数字元数据,不声明显著 RSS 收益;Windows 首轮 84 项中 12 项因测试遗漏关闭 execution store 而报 SQLite EBUSY(8 项原有、4 项新增);仅回退 Goal 生产源码仍复现原有 8 项同类错误。测试清理补丁 9cbd018 显式关闭存储,不跳过断言;重建后 84/84 通过,包含全部 Goal 缓存竞态。

  • M030:构建、类型检查、Biome 和父任务独立 267/267 MCP/Runtime 回归通过。原始 2.0.0 包在 ESM/CJS 下均通过语义测试、分别在 GC 测试保留全部 24 个观察对象;补丁重放后通过。实际 manager+工具调用、无 SDK 包装器、暂停读取的自有 stdio 子进程中,192 次调用取消并结束后参数对象由 192→0,堆约 71.45→45.62 MB;双方均保留 25,083,490 个排队字节和 383 个 drain 回调。恢复读取后全部释放,385 帧/25,214,792 字节发送流 SHA-256 完全相同。61 组独立错误时序/input_required 对照一致;另有 2,304 次 stdio/现代 HTTP 故障矩阵通过。仅减少背压期间多余的 JS 对象驻留,不丢弃已提交字节,也不声称解释原始整应用占用。Windows 已拉取 40866de、应用依赖补丁并构建:原生 Node 24.15 全套 267 项中 262 通过、5 项既有 stdio 协商失败;原始未打补丁 SDK 精确重现这 5 项,且重新触发两个新 GC 失败。Electron 内置 Node 24.18 下新增 GC、现代 HTTP、表单及 Runtime 的 70/70 通过;更大 Electron stdio 夹具尝试并非全绿,未隐藏或修补这些既有平台测试问题。日常桌面未重启。

  • 额外排除:合法历史权限结果的 256 项 LRU,在最大 8 KiB 命令下约 2.3 MB 后持平,淘汰后全部旧请求可回收;没有大正文切片放大。缩窄记录会改变完整请求契约及转录字节预算,未为这项有界成本增加产品改动。

  • M031:构建、类型检查、Biome、41 项针对性回归及父任务完整 Host 复跑通过:1,870 项中 1,858 通过、12 跳过、0 失败。首轮完整测试发现空缓存与旧夹具缺失 revision 都是 undefined 时误入比较,已改为显式存在性检查,未弱化夹具。真实 RuntimeKernel 复用一个后端完成 32 轮,实际编译修复把相同技能正文由 32 份/8,389,888 字节→1 份/262,184 字节,释放后端后为零;每轮改变内容仍保留 32 个历史版本。网络/模型由小型 backend 代替,内核、目录、composer 与正文扫描为真实组件,不是整应用内存数字。公开 composer 回归覆盖并发、失败重试、多 workspace、同 revision 的 15 种内容/路径/顺序/嵌套差异及淘汰后的 GC;原版只在共享数量断言失败,调整为原版预期 32 后其余断言全部通过。分别移除深比较、淘汰清理和晚完成校验均在对应断言失败。Windows 已拉取并构建 2c282d2,新增内存回归及单轮一致性测试通过;相关 41 项中 40 通过,原有符号链接用例在创建测试链接时因系统 EPERM 失败,尚未进入其待测修改路径,未更改系统权限或跳过断言。100 个不同历史版本、重复扫描的瞬时成本和提示词缓存仍保留;日常桌面未重启。

持续调查

  • 已确认、尚未修复:插件重载的 ESM 模块驻留。真实 HostPluginPlatform 重载 24 次后,25 份合成模块载荷(每份 2 MiB)在卸载/关闭/GC 后仍保留;旧激活状态和 Context 均可回收。失败插件的真实后台重试及加速 reconcile 同样增长,堆快照指向 Node ModuleWrap。仅启停入口的对照不累积模块。复用导入地址会改变全新模块状态语义,正在验证可卸载的执行边界;未声称已解释日常配置的占用。

  • 会话、订阅、事件监听器和待处理请求的生命周期。

  • Renderer、附件和预览缓存的增长与释放。

  • 内嵌浏览器非活动页面的驻留及安全回收边界。

  • Runtime Host、工具输出和长时间运行任务的内存。

  • 为后续确认的问题追加复现、修复和验证记录。

不通过丢弃未发送草稿、待上传附件或运行中任务来降低占用。尚未验证优化后的 Windows 打包应用及真实飞书/企业微信连接。

English: memory optimization progress

Goal

Continuously investigate memory growth and unnecessary retention across Maka. Verify each cause, then fix, test, commit and push incremental improvements. Keep this PR in draft; do not auto-merge.

Related work: development-mode React performance-entry retention was fixed and merged in #5156; this PR does not duplicate it, and that PR does not claim completed native Windows validation. Repeated page-builder encoding is addressed separately in #5166, outside this PR’s implementation scope.

Completed

  • Create WorkHub on first use (9be32ca): enabling registers the shortcut without preloading a second application. Opening, docking and control requests can still create the view; existing drafts and staged attachments survive hiding and disabling.

  • Load bot SDKs on demand (9be32ca): Feishu, WeCom and Slack SDKs load only when a credentialed connection starts; Slack credential probes load their SDK on demand too. Synchronous loading preserves the existing start/stop ordering.

  • Release attachment previews on composer unmount (e9289a6): own Blob URLs before decoding, revoke them on unmount and stop remaining previews; ignore late picker/sniff results. Hiding, draft switching and StrictMode replay preserve live previews.

  • Compact historical bodies in Runtime message replay records (c864564): canonical digests replace submit content and string-preserving digests replace queue edit text. Full results, other fields and Host-Epoch replay remain intact; no TTL/LRU eviction.

  • Cancel obsolete stream display callbacks (d0f8b3e): whichever wins between rAF and its timeout fallback cancels the other, preventing completed batch callbacks from accumulating while background painting is suspended.

  • Release complete historical Agent graph epoch snapshots (78f521d): successful handover fences old tool wakes and releases reconciliation results after explicit readers finish. Retain small metadata for historical projection repair/close diagnostics and handle epoch lookups that return after handover.

  • Detach released transcript snapshots from connection lifetime (e5885fc): removable close listeners replace two connection-lifetime Promise.race waits, preventing closed subscriptions' temporary transcript Buffers from remaining retained by a live connection.

  • Scope browser release fencing to pending connection attempts (46c8211): stop permanently retaining every released session's epoch. Register before connection acquisition and clear on settlement while preserving delete/connect race protection.

  • Compact historical Root Turn admission bodies (34f4ea8): retain content digests and independently owned identity metadata in the historical index. Current tips, recovery chains and conflict results remain complete; preserve Host-Epoch drift checks and poisoning without TTL/LRU eviction.

  • Release preparation state after subscription activation (8908edd): drop the failure Promise and resolver after activation and catch-up drain so previous replicas, handles and snapshots can collect. Preserve failed-refresh fallback, recovery and PTY interests.

  • Release historical Zod recursive parse state (f3fbce2): remove schema-owned strong references to previous parse contexts and clean the global allocation stack on synchronous throws. Preserve per-parse cycles and shared aliases through the existing ESM/CJS dependency-patch mechanism.

  • Release processed WeChat SSE messages and chunks (d02caf9): completed reads no longer retain the last raw message, mapped event and byte buffer during the next idle wait. Preserve reconnect cursors, chunk parsing and iterator cleanup. This removes fixed idle retention, not accumulating message history.

  • Release connection-owned native WebRTC tasks and resources (31a5a44): one lifetime guard covers negotiation, active connections, explicit close and direct drop. Cancel init/data-channel tasks and close the underlying peer connection; successful connections remain independent of retired signaling requests.

  • Release local-message bodies during retry waits (b634df8): create the five-second callback outside the delivery scope, retaining only the service and message key. SQLite still owns pending content; retry timing, deduplication and original identity are unchanged.

  • Cancel old Peer Mesh timers after early wake-up (e0dd3c8): each reconciliation wait owns and cleans its five-minute timer and abort listener, preserving interval, route-change, rename and shutdown behavior.

  • Stop code-language caches retaining complete old messages (e055012): the shared Astryx tokenizer caches only valid language definitions, not null results for arbitrary unsupported labels. Display labels, plain-text fallback and known-language regex reuse remain unchanged.

  • Release consumed CLI event wait records (cd36563): removable pending failure waiters replace the run-context-lifetime Promise.race. Detach when an event read or graph poll completes, preserving first-failure identity, operation errors and existing close behavior.

  • Avoid duplicating large pasted text in CLI undo snapshots (fcd7e0a): copy mutable editor state, line arrays and paste maps while sharing immutable strings. Preserve every undo step, paste deletion/renumbering and submission cleanup; no history truncation is introduced.

  • Bound code-point allocation for short-text truncation (c809a7e): collect only the prefix required by nonnegative budgets plus one code point to detect truncation, instead of expanding the entire large input. Preserve NFC, control/bidi cleaning, whitespace collapse, suffixes and existing numeric-budget behavior.

  • Bound transient diagnostic-log and UTF-8 truncation allocations (cb1ae62): collect only budget-relevant code points and avoid encoding entire large strings or oversized markers. Preserve complete redaction, log eviction, byte budgets and surrogate/marker boundary behavior.

  • Release consumed peer receive buffers (ae5d246): live paths no longer retain authentication remainders, and the parser drops consumed native chunks and empty backing-buffer views before its next wait. Partial frames, unread bytes, unACKed replay and reconnect semantics remain intact.

  • Mount reasoning bodies only on first expansion (4888ea8): never-opened reasoning no longer creates Markdown/code subtrees. After first expansion, nodes/state remain mounted through collapse and streaming updates. Headers, previews, keyboard behavior and raw transcripts are preserved; never-opened hidden body text is also absent from the accessibility tree.

  • Detach short search results from complete provider text (719b646): copy only title/snippet prefixes that actually truncate. Preserve limits, unchanged short-input fast paths, URL fallback, lone surrogates and the existing UTF-16 behavior of split emoji pairs.

  • Load update attestation dependencies on demand (f4c1a3a): startup channel metadata no longer loads Sigstore/TUF. Real bundle parsing and default verification load them synchronously, preserving artifact hashes, signatures, workflow identity and trust-root checks.

  • Preserve cancellation through customized model requests (5af4f26): URL/init forwarding uses the caller’s effective AbortSignal directly, avoiding lost cancellation after a temporary Request is collected. Overrides, explicit null, inherited signals and all body paths remain supported.

  • Reuse already-buffered JSON request bodies (fdc1c82): overlays/finalizers decode the first ArrayBuffer instead of cloning and reading the complete body again. Initial reads, original stream errors, caller Request locks and cancellation signals remain unchanged.

  • Scope Computer Use cleanup metadata to live operations (878520a): clearing sessions that never used CU no longer creates generation entries or observer-induced state. Last queue tails release fences while preserving stale-work invalidation, executor-death handling and same-turn stop authority.

  • Release upload staging rejected after Session removal (98e1944): the existing missing-session branch releases only the requesting connection/Host Epoch’s upload and preserves its error response. Failed chunk/commit/client cleanup requests no longer leave unusable Buffers; no timer or TTL change.

  • Release retired Goal token-count metadata (1789afe): committed archive/removal deletes the session’s cached total; drain clears it. Async context reads recheck the existing control lease to prevent stale repopulation or overwriting a new Goal, preserving rollback, independent budget baselines and close-authority records.

  • Release settled MCP request graphs behind blocked sends (40866de): independently scope cancellation error observers and revoke the send observer’s native reject reference at request settlement in both ESM/CJS. Preserve queued bytes, frame order, connections, late-error cleanup and modern cancellation.

  • Share identical skill inventory snapshots across turns (2c282d2): every new turn still rereads the catalog; sharing requires equal revision and full deep equality of frozen snapshots. Preserve the 100-entry per-turn history and every path/order/diagnostic difference; eviction and late-completion ownership checks prevent new retention.

Verification

  • With all eight improvements combined, the full Linux Desktop build, Desktop/Runtime typechecks and 449 affected tests passed (zero failures/skips); each change received focused Biome checks.

  • Affected bot, WorkHub and settings suites: 239 tests passed, 0 failed.

  • Isolated Electron/Xvfb + CDP: enabling leaves only the main renderer; first opening creates WorkHub, renders its editor, and hide/reopen reuses the same renderer.

  • Three fresh Node processes per revision: median post-GC RSS increase from importing the bot entry fell from 85.6 to 47.4 MiB; heap increase fell from 17.9 to 11.1 MiB. These are module-level measurements, not whole-app or packaged-Windows savings.

  • Attachment lifecycle: 7 real hook/Blob tests and 21 related regression tests passed, plus UI build/typecheck. Before the fix, three composer unmounts retained 3 MiB of fetchable Blobs; afterward all URLs are revoked and no next preview is created after unmount.

  • Runtime Host build and all 78 message-coordinator tests passed. Requests with >6 KiB bodies produce identity records shorter than 512 serialized characters; tests cover replay after consume/retract/idle and conflicts in content, attachment, placement and revision. Record counts and exact retraction results remain retained; this is not a claim of fully bounded history.

  • Display scheduling: 150 timeout flushes retained 150 queued rAF callbacks before the fix, versus 0 afterward. Both winner orderings and existing streaming handoff tests passed (24 total).

  • Agent graph: Runtime build and 19 tests passed (including GC, no skips). With coordinator and every old tool closure retained, all 12 old epoch results collect; historical queries, concurrent readers, failed handover retry and delayed lookups remain correct.

  • Transcript snapshots: Runtime Host compilation and 57 tests passed; the 4 new tests also passed under Electron's embedded Node. A synthetic workload using the actual coordinator previously retained ~96 MiB after 24 subscription open/release/close cycles (24 × 4 MiB Buffers); afterward all collect with the connection still open and arrayBuffers returns to its ~0.137 MiB baseline.

  • Browser release lifecycle: zero retained epochs after 10,000 unattached releases and 200 completed acquire/release cycles; reentrancy, repeated releases, concurrent acquisition and failure/retry passed (18 related tests).

  • Windows fully built e5885fc; 90 focused tests passed under Electron's embedded Node, including transcript Buffer GC, graph snapshot GC, message replay and display scheduling.

  • Windows 46c8211 main-process compilation and 18 browser tests passed.

  • Root Turn admissions: Runtime Host build and 122 affected tests passed (including GC, no skips). In a real-SQLite synthetic workload with 256 turns and 48 KiB input per turn, recovered owner retention fell from approximately 24.15 to 0.29 MiB. All historical content objects collect, with only the current tip's two content objects retained; historical conflict results also collect after return. Recovery still reads complete history, so its transient peak is unchanged.

  • Windows Runtime Host build and 28 admission/recovery tests passed (no skips); fixed the existing test helper's omitted SQLite close, which left temporary files locked (c66cffe).

  • Subscription activation: main-process build and 42 observer/lifecycle tests passed. Actual subscription classes retain only the current generation after 100 refreshes and 100 failure recoveries, and release all generations on close. This removes fixed extra retention, not unbounded growth.

  • Windows 8908edd main-process compilation and all 42 observer/subscription lifecycle tests passed.

  • Display scheduling now belongs to the Conversation feature (6eea5ba), without relaxing architecture constraints; the CI-base check, 103 checker tests and 24 display regressions passed.

  • Zod: ESM/CJS cycle, alias, exception, reentry, concurrency and GC tests passed on Node 24/26. Reverting either fix makes its regression fail again. All 80 observed messages collect after 20 real backend turns, versus two recent messages retained before; a single controlled experiment reduced heap by approximately 8.3 MB. A separate recursive-exception probe releases all 30 payloads of 256,000 characters, previously all retained; an ordinary product trigger for that exception path has not been established. A 20,001-node microbenchmark changed median parse time from approximately 4.19 to 4.94 ms (+0.75 ms).

  • The full workspace test build passed. The high-concurrency Node 26 run passed Runtime, Desktop, Core and UI but had Host and CLI failures. All ten failed Host cases passed at lower concurrency; the complete CLI rerun passed 926 of 929 tests with three skips. The complete lower-concurrency Node 24 Host rerun passed 1,842 of 1,854 tests with 12 skips; the initial high-concurrency full run remains recorded as failing.

  • Windows f3fbce2 passed the full Desktop build, dependency-patch application and seven focused GC/race tests under Electron's embedded Node. Added the Zod source-patch license inventory (0fa4626); all 105 ASF source-release checks passed.

  • WeChat SSE: Runtime build/typecheck and 108 bot/lifecycle tests passed; both GC regressions fail against the previous implementation. Last raw/mapped batches collect while the actual local HTTP stream remains open; a synthetic 8 MiB parser input chunk also collects during the next pending read.

  • Integrated Host soak: the real Host/SQLite/protocol clients completed 100 turns, 202 subscription opens and 4,206 frames; all 400 observed settled backend objects collected. Settled heap was approximately 73.30 → 73.66 MB from turns 60 to 100, with no new historical text retention found.

  • CI for 0fa4626 passed build, typecheck, standard workspace and Host tests; Desktop e2e passed 36/37 with a WorkHub drag assertion failure. The same WorkHub file passed 2/2 locally, and that case passed 3/3 independent repetitions; Desktop e2e subsequently passed on 31a5a44 without a product or test change for this failure.

  • WebRTC: all 43 native tests passed, including real data transfer, backpressure, signaling cancellation, failed upgrades and interrupted close. In 32 real local connection pairs, explicit close previously left 64 tasks; direct drop left 128 tasks and 128 file descriptors. Both paths now leave zero tasks and return to the seven-FD baseline; init-channel connection references also release. These are Linux loopback results; all 42 Windows native tests and the release addon build also passed.

  • Windows 31a5a44 passed the full Desktop build and 19 WeChat SSE tests. After restarting with the new native addon, both main and WorkHub editors loaded successfully.

  • N-API integration soak: the actual addon and JS stream wrapper exercised 159 endpoints, 304 streams and 38 MiB of loopback traffic; all observed objects collected and FD/socket/thread counts returned to warm baseline. Another 12 blocked 32 MiB TCP write cancellations passed. RSS growth accompanied free allocator arenas; this did not justify a leak claim or allocator tuning. Early connection loss on large QUIC writes was not investigated.

  • Local retry: the actual Desktop main build, typecheck and 24 tests passed, including an independent Node 24 rerun. After 128 completed and durably retired synthetic retries, the old implementation retained 128 sending records and approximately 41.5 MiB heap; the compiled fix retained zero records and approximately 20.2 MiB. The old-code negative control failed; automatic retry, durable pending text, original identity and shutdown preservation passed. This removes extra retention within five seconds, not an idle leak.

  • Peer Mesh: Runtime Host compilation, 34 related tests and an independent Node 24 rerun passed. After 200 public early triggers only the current timer remains; close leaves zero, and normal expiry still reconciles. The old implementation leaves two timers after its first early trigger. Its 3,102 timers after 3,100 triggers naturally fell to one during an actual five-minute wait, confirming bounded transient accumulation. Instrumented heap differences are not presented as exact product savings.

  • 31a5a44 passed four-platform native builds, native quality, Windows/Linux packaging and Windows recovery checks. Windows installed-CLI validation first timed out stopping a test process tree, then passed unchanged on retry. Desktop e2e and Storybook passed in the main test run, but the new commit cancelled that run during subsequent CLI build work; it is not recorded as fully green.

  • Windows 0e7aa4f passed Runtime Host and Desktop main builds plus all 58 local-message/retry/Peer Mesh tests, without skipping the new regressions. Corrected an existing test's POSIX mode assertion on Windows; product permission handling is unchanged. Main and WorkHub surfaces loaded successfully after restart.

  • Astryx: in an actual MarkdownBody browser workload, unsupported-language sliced-string cache keys retained approximately 6/12 MB of complete text after unmounting 20/40 messages of roughly 300 KB each. The actual patched package retained zero messages through that cache after the same 40-message workload and two GCs; one bounded latest React text prop remains, so this is not a zero-total-objects claim. The original bug also reproduced without diagnostic getters. The new cache regression fails on old code; sync/async/streaming and all supported aliases pass after the fix. All 440 UI tests, build/typecheck, independent Node 24 checks, legal inventory and full dependency-patch reverse/reapply passed.

  • Windows e055012: full Desktop build, dependency patches and all 440 UI tests passed under Electron's embedded Node. The first full run also picked up an orphaned dist test whose source had been deleted and failed; backing up old UI output and rebuilding cleanly resolved it without changing tests or product logic. After an idle/no-draft/no-attachment preflight, the rebuilt app restarted with both main and WorkHub surfaces healthy.

  • CLI: the actual public runtime entry with a synthetic driver processed one 10,000-event stream of 4 KiB payloads. The old implementation retained every event, with heap approximately 22.70 → 70.54 MB; the compiled fix stayed approximately 22.70 → 23.24 MB and retained zero historical events after stream completion while the context remained alive. Heap snapshots confirmed and removed the failure-Promise ownership chain. Against old source, the final GC regression alone fails while both semantic tests pass; all 42 focused tests pass after the fix. An independent full Node 24 CLI run passed 929 of 932 tests, with three skips and no failures; build/typecheck/Biome also passed. This addresses active CLI-run growth, not desktop-idle attribution.

  • Windows cd36563: CLI build and all 42 event-wait/run regressions passed under Electron's embedded Node, including event GC with the context retained (no skips). This commit changes only CLI; the existing desktop app remains running without another restart.

  • M018: after pasting 1 MiB of random text into the actual Maka CLI editor and typing 60 short words through ordinary key events, independent parent replay reduced heap from approximately 71.15 MB to 8.23 MB while preserving the complete undo history. On the original dependency, both semantic tests pass and only the memory regression fails; all three pass with the patch. The full Node 24 CLI suite passed 932 of 935 tests, with three skips and no failures. Build, typecheck, Biome, 45 license/notice tests and fresh-dependency patch replay also passed. This removes duplicate string storage; genuine edit history still needs memory. Windows pulled fcd7e0a and applied all eight dependency patches successfully; CLI build and all three regressions passed under Electron's Node with no skips, retaining all undo steps at approximately 5.75 MB after 60 words. The existing desktop session was not restarted.

  • Extended Windows TUI regression: 217 of 219 tests passed; two SIGTERM-exit assertions failed. Restoring only the original pi-tui editor through an in-memory loader reproduced both identical 'SIGTERM' !== null failures, ruling out the M018 patch as their cause. These tests were neither skipped nor changed.

  • fcd7e0a passed main tests, native quality, four-platform native builds, Windows/Linux packaging, Windows recovery, four-platform installed-CLI validation and State Roots qualification; conditional installed-CLI Eval was skipped.

  • Preview investigation did not ship a rewrite: historical image/PDF DOM collects and PDF child processes exit; most image residency is pressure-reclaimable Chromium decode cache. Distinct data URLs also leave document-associated native allocations whose exact owner remains unidentified. Per-open Blob creation/revoke removes that allocation but worsens 20 same-image reopen cycles: decode cache approximately 20→508 MB and closed RSS 196→663 MiB, versus approximately 149 MiB for both after pressure. A direct replacement was rejected. Independent IPC, identical-input hashes and no-Network-observer controls separate this from debugger overhead, which is not counted as product savings.

  • M019: Core build/typecheck and all 828 tests passed, plus 82 independent Node 24 Core/Storage/CLI regressions. Against old source, the semantic test passes while the same allocation test fails (~67.1 MB versus a 24 MiB threshold). The actual ClaudeCodeSessionAdapter.listSessions() reading a synthetic 8 MiB first ASCII message reduced independently sampled total allocations from approximately 92.74 to 25.61 MB; compiled-product replay measured 25.54 MB, with unchanged title/cache behavior. This reduces transient cold-read/changed-file allocation; cached titles did not retain complete text, and normalization/cleaning still scans the full input. Windows passed the full Desktop build and 46 focused regressions. The first full Core run picked up orphaned dist tests whose source had been deleted; backing up old Core output and rebuilding cleanly produced 828/828 passes. After a no-draft/no-attachment/no-running-work preflight, the app restarted with both main and WorkHub surfaces healthy.

  • M020: Core build/typecheck and 832/832 tests passed, plus 81 independent Node 24 Desktop/Host/Runtime/CLI regressions. Old source passes both behavior tests but fails both allocation tests at approximately 67.3/154.2 MB; the fix passes all four. Independent prefix-prototype measurement for a synthetic 8 MiB direct log was approximately 0.82 MB; the actual compiled failure-diagnostic path reduced total allocation from approximately 154.26 to 2.82 MB with identical 8 KiB output. This reduces transient allocation, not persistent retention; redaction still scans complete input. Windows pulled cb1ae62 and passed the Core build plus all 832 tests. Extended diagnostics passed 47/48; the sole existing startup-diagnostic POSIX-mode assertion failed with the same 54≠0 under an in-memory old-truncation-source control, without modifying or skipping it. The desktop process remains running; no claim is made that it loaded a new frontend build.

  • Additional native-preview control: a bare image page without React still retains per-distinct-data-URL native allocations after successful stronger cleanup; repeated identical content retains one. Unsymbolized native samples match data-URL length plus 12 bytes, but the exact C++ owner remains unidentified. No product purge mechanism was added.

  • M021: Runtime Host build/typecheck/Biome and 23/23 independent parent Node 24 regressions passed, including eight-seed 64 MiB fault/replay and real TCP exactly-once control dispatch. The old-source GC control fails on a retained 64 KiB authentication backing buffer. Consumed auth/native/parser buffers collect after the fix while partial, unread and unACKed data remain owned. An additional old steady-state 128 KiB releases on subsequent heartbeat, and replacements do not accumulate: this is bounded retention, not GB-scale growth attribution. Windows pulled 4888ea8 and passed the Runtime Host build plus 19/19 auth/resume tests, including GC and real TCP (21/23 in the extended group). Two peer-native tests directly import Windows paths and fail with ERR_UNSUPPORTED_ESM_URL_SCHEME; restoring only the old receive-loop source reproduces both identical failures. They were not skipped or modified.

  • M022: UI build/typecheck/Biome and all 449 independent parent Node 24 tests passed; the old-source control fails four lazy-body cases while five preservation cases pass. Separate Chromium processes running the actual TurnView with identical synthetic data (20 reasoning sections, 20 tools and visible final answer) measured post-GC JS heap approximately 10.77→4.83 MB, DOM elements 5,020→679, and reasoning descendants 4,340→0. These are not whole-app RSS or daily-profile savings. Real Enter/Space, retained node identity, pre-first-open updates and closed-body updates passed. A cold reasoning-only test loads the actual Markdown dynamic module; first-load latency was not measured. App search already excludes reasoning, and reduced pre-expansion accessibility exposure is explicitly documented. Windows passed all 449 UI tests and the full Desktop build. After verifying no drafts, attachments or running work on either surface, a normal restart loaded healthy main and WorkHub editors.

  • M023: Runtime build/typecheck/Biome, 352 related tests and 73/73 independent parent search/result-projection regressions passed. Retaining 30 title/snippet results from legal sub-1-MiB JSON responses reduced post-GC heap growth from approximately 24.05 MB to 70 KB. Old source fails only memory, while all 16 character/fallback vectors remain identical. In the actual parent ToolRuntime replay, 30 result events previously retained approximately 24 MB of source text through snippets; the compiled fix retains none of those raw strings. This removes amplification while results/pending events live, not cross-turn idle leakage; subsequent model context already reloads from SQLite. Windows pulled 719b646 and passed the Runtime build plus all 73 matching regressions, measuring approximately 37.5 KB retained-result heap growth. The daily desktop process remains running without another restart; no claim is made that it loaded this new Runtime module.

  • Additional MCP exclusion: actual stdio and HTTP managers on Node 26 each completed 48 catalog notifications and 64 reconnects, invoking every tool to prepare validators. All 10,112 observed retired objects per mode collected, with stable connected FD/binding/subscription counts. RSS growth alone did not justify a cache change; concurrent outstanding calls and fault storms were not covered.

  • M024: Desktop build, complete typecheck, Biome and 53/53 independent parent update regressions passed, including real ECDSA/Ed25519 verification under Electron’s embedded runtime. The old-source control detects eager startup loading. Three independent Node 24 module-level runs prewarmed electron-updater: median post-GC heap increment approximately 1.55 MB→0.12 MB and RSS 2.92 MB→0.26 MB, with zero Sigstore/TUF modules loaded by channel reads. This reduces fixed module residency, not cumulative growth or whole-app memory; Windows pulled f4c1a3a and passed main-process compilation plus all 53/53 update tests under Electron’s embedded Node, including real cryptographic verification; the existing desktop session was not restarted.

  • M025: the full Node 24 Runtime test run passed at concurrency four, along with build/typecheck/Biome and 187 focused regressions. Independent actual persistent ModelAdapter + SDK + finite local SSE replay: previously 6/6 cancelled attempts still held their response and connection after 100 ms until the server ended; the compiled fix finishes reading and closes connections in all 6/6, with all nine observed object classes collectible. Eight parent wrapper tests passed; all three new tests fail on old source, including an actual HTTP read timing out at 500 ms. This shortens cancelled-request resource residency, not a claim of permanent cumulative leakage; the native limitation when callers themselves discard a Request remains. Windows pulled 5af4f26 and passed the Runtime build plus all 170/170 model/request/proxy regressions under Electron’s embedded Node. Full Desktop build passed; after verifying both surfaces had no drafts, attachments or running work, a normal restart loaded healthy main and WorkHub editors.

  • Filesystem worker exclusion: 145 success/failure/cancellation executions through real client/runner and the real worker entry for valid operations release all eight observed historical object classes each round; zero listeners/live workers and 22 stable FDs. The sandbox transform was a passthrough fixture, not Windows sandbox or Linux pinned-FD coverage; no cache/lifecycle patch was justified.

  • M026: build/typecheck/Biome, 81 focused tests and 13/13 independent parent wrapper regressions passed. Full Node 24 Runtime: 3,385 passed out of 3,393, eight skips, no failures. Old source passes four behavior tests and fails only the large-body duplicate-read regression. Actual compiled SDK plus local HTTP with an 8 MiB synthetic prompt reduced sampled ArrayBuffer peak approximately 56→40 MiB and heap+ArrayBuffer 84.67→67.84 MB; sent/received bytes both equal 8,388,688. Three independent candidate-process repetitions and 87 differential behavior vectors agree. The initial clone/read remains because removing it changes errors/stream locks. No body-sized retention remains after completion/GC: this reduces transient allocations, not an idle leak; Windows pulled fdc1c82 and passed the Runtime build plus all 81/81 matching regressions under Electron’s embedded Node, including original stream-error and Request-lock assertions. The daily desktop process remains running without another restart.

  • M027: Computer Use/Runtime builds, typechecks, Biome and all 398/398 related tests passed. Independent complete Node 24 Runtime: 3,386 passed out of 3,394, eight skips, no failures. All three new regressions fail against old source and pass after the fix. With the actual backend/tools wiring and owners still alive, clearing 50,000 distinct unused sessions reduced extra retained heap approximately 16.86 MB→97 KB; the executor stayed idle. Actual owned mock RPC covers queued clears, new work with reused IDs, synchronous abort reentry, 100 begin/end cycles and executor death, without touching a real desktop. This backend is selected only on macOS in the product; native macOS hardware and this change on Windows were not verified. Stop authority for previously used CU sessions remains retained: this is not an all-session-state-is-bounded claim.

  • M028: Host build/typecheck/Biome, 100/100 related tests and 57/57 independent parent regressions passed. All eight new GC tests pass and all eight fail on old source. Actual Desktop client→coordinator→real isolated Artifact store, with three legal fully chunked uploads of 50+50+28 MiB and Session removal simulated at the presence boundary: old commit and abort both return not_found yet retain 128 MiB, even after a +24-hour injected clock and real GC, until the owner connection closes. The compiled fix releases all staging while the connection stays open; arrayBuffers returns to approximately 0.139 MiB baseline with identical responses. Removed/absent × four request kinds cover foreign connection/epoch isolation, unrelated session/upload preservation and full-pool capacity reuse. This is simulated presence removal, not UI deletion or a real 24-hour wait, and bounded 128 MiB staging retention rather than a change to generic lazy expiry. Windows pulled 9cbd018 and passed the Host build plus all 84/84 Artifact/Goal/Memory/retirement regressions with no skips, including all eight upload GC cases; the existing desktop process was not restarted.

  • Additional exclusions: real scheduled coordinator + SQLite completed 360 fires/edit/delete/recovery operations; all 2,572 task snapshots, 1,098 fire snapshots and 552 historical timers collect, with one timer for an active task. History compaction success/repair retry/abort, actual AI SDK local fake models and checkpoint cleanup chains also release all settled inputs, retaining only the current checkpoint. Explicit held/released controls passed. No product code was added from these negative results; never-settling external dependencies were not covered.

  • M029: Host build/typecheck/Biome, 27 Host Goal and 134 Runtime Goal tests passed. Independent complete Host run covering M028/M029 passed 1,857 of 1,869 tests, with 12 skips and no failures. After 275 real SQLite/coordinator session retirements, the original token Map retains 259 entries and the compiled fix retains zero; authority is zero in both, while all 275 necessary close fences remain. Old source fails all four new tests. Removing only the async lease guard preserves the commit-lifecycle test but reintroduces all three late-write failures: refill after removal, old 30 overwriting fresh 120 after rearm, and refill after drain. Rollback and unarchive/rearm remain correct. Savings are session-ID→number metadata only, not a significant RSS claim; The initial Windows run failed 12 of 84 tests with SQLite EBUSY from unclosed fixture execution stores (eight existing and four new); restoring only pre-fix Goal production source reproduces all eight existing cleanup failures. Test-only cleanup commit 9cbd018 closes those stores without skipping assertions. After rebuilding, all 84/84 pass, including every Goal token-cache race.

  • M030: build/typecheck/Biome and the parent’s independent 267/267 MCP/Runtime regressions passed. Pristine 2.0.0 passes semantics but fails GC in both ESM/CJS, retaining all 24 observed objects per format; isolated patch replay passes. With actual manager/tools, no SDK wrapper, and an owned stdio peer paused after handshake, 192 cancelled/settled caller arguments drop from 192 alive to zero; heap is about 71.45→45.62 MB while both variants retain exactly 25,083,490 queued bytes and 383 drain callbacks. Resuming releases everything; the 385-frame/25,214,792-byte outgoing stream has identical SHA-256. All 61 independent error-order/input_required comparisons match; an additional 2,304-call stdio/modern-HTTP fault matrix passes. This removes avoidable JS ownership during backpressure, not already submitted bytes or a claimed explanation for original whole-app usage. Windows pulled 40866de, replayed dependency patches and built: native Node 24.15 passes 262/267, with five existing stdio-negotiation failures reproduced exactly using the pristine SDK, which also restores both new GC failures. Electron’s Node 24.18 passes all 70/70 new GC/modern-HTTP/form/Runtime tests; its broader stdio-fixture attempt was not green, and those existing platform-test problems were not hidden or patched. The daily desktop process was not restarted.

  • Additional exclusion: the 256-entry historical permission-outcome LRU plateaus around 2.3 MB for maximum legal 8 KiB commands; all evicted old requests collect, without large backing-string amplification. Narrowing the record changes its complete-request contract and transcript byte accounting, so no product change was added for this bounded cost.

  • M031: build/typecheck/Biome, 41 focused tests and the parent’s complete Host rerun passed: 1,858/1,870, 12 skips, zero failures. The first full run exposed an empty-cache comparison when a legacy fixture omitted revision; an explicit existence guard fixes it without weakening the fixture. With one real RuntimeKernel backend reused for 32 completed turns, the actual compiled fix reduces identical skill bodies from 32 copies/8,389,888 bytes to one/262,184 bytes, then zero after backend disposal. Changing content each turn still preserves all 32 historical versions. A small backend substitutes model/network behavior; kernel, catalog, composer and source scanning are real, not a whole-app measurement. Public-composer regressions cover concurrency, retry, workspaces, 15 same-revision content/path/order/nested variants and eviction GC. Old source fails only the sharing-count assertion; changing that expectation to the original 32 makes every other assertion pass. Independently removing deep equality, eviction clearing or late ownership checks causes the corresponding regression failure. Windows pulled/built 2c282d2 and passed the new memory test plus the single-turn consistency test. Its 41-test related group passed 40; an existing symlink fixture fails with OS EPERM while creating its link, before the modification path under test. No system permissions or assertions were bypassed. The 100 distinct historical versions, transient rescanning and prompt cache remain; the daily desktop process was not restarted.

Ongoing investigation

  • Confirmed, not yet fixed: plugin reload ESM module retention. After 24 actual HostPluginPlatform reloads, 25 synthetic module payloads (2 MiB each) survive uninstall/close/GC; retired activation state and Contexts collect. Actual failed-plugin background retries and accelerated reconciles also accumulate modules, with snapshot roots through Node ModuleWrap. Entry disable/enable controls do not accumulate modules. Reusing import URLs changes fresh-module-state semantics, so an unloadable execution boundary is under investigation; this is not claimed as measured daily-profile impact.

  • Session, subscription, event-listener and pending-request lifetimes.

  • Renderer, attachment and preview cache growth and disposal.

  • Inactive embedded-browser retention and safe reclamation boundaries.

  • Runtime Host, tool output and long-running task memory.

  • Append reproductions, fixes and verification for additional confirmed issues.

Do not reduce memory by dropping unsent drafts, staged attachments or running work. The optimized packaged Windows app and live Feishu/WeCom connections have not yet been verified.

AI use / AI 使用声明
  • Generative tooling made a substantive contribution / 生成式工具有实质贡献
  • No generative tool made a substantive contribution / 无生成式工具实质贡献

OpenAI Codex: investigation, implementation, regression tests, local verification and PR maintenance. Commits carry Generated-by: OpenAI Codex.

Create the WorkHub renderer on first use rather than on enable, while retaining drafts after use. Load platform SDKs only when a configured bot starts or Slack credentials are tested.

Generated-by: OpenAI Codex
@github-actions github-actions Bot added the effort/S Under 100 readable lines label Sep 10, 2026
@M4n5ter M4n5ter changed the title perf: incremental memory optimization across Maka / Maka 内存优化 perf: incremental memory optimization across Maka Sep 10, 2026
Track Blob URL ownership before decode and stop asynchronous staging after unmount while preserving hidden drafts and StrictMode replay.

Generated-by: OpenAI Codex
Retain canonical content digests instead of historical submit and queue edit bodies, without evicting epoch-long outcomes or changing pending operations.

Generated-by: OpenAI Codex
Cancel the losing animation frame or timeout after a stream display batch flush, preventing suspended background frames from retaining completed handlers.

Generated-by: OpenAI Codex
Fence old supervisor callbacks and preserve explicit reconcile readers across epoch handover. Retain lightweight driver metadata for historical projection repair and close diagnostics.

Generated-by: OpenAI Codex
Replace connection-lifetime Promise races with removable abort listeners so released transcript overlay buffers can be collected while the connection remains open.

Generated-by: OpenAI Codex
Drop per-session release epochs when connection attempts settle and avoid retaining tombstones for sessions that never acquired a browser, preserving reentrant teardown and single-flight fences.

Generated-by: OpenAI Codex
Retain canonical content digests and owned identity metadata for historical admissions while keeping full current tips and validated recovery or conflict results.

Generated-by: OpenAI Codex
Release the SQLite lease before removing temporary files so root admission tests clean up on Windows and do not retain fixture database owners.

Generated-by: OpenAI Codex
Keep frame cleanup within the renderer architecture boundary without widening legacy budgets.

Generated-by: OpenAI Codex
Keep cycle memoization scoped to each parse and restore allocation state when parsing throws.

Generated-by: OpenAI Codex
Generated-by: OpenAI Codex
Keep iterator result and decoded message lifetimes within each completed read. Preserve reconnect cursors, parser boundaries and iterator cleanup semantics.

Generated-by: OpenAI Codex
Cancel connection-owned channel workers and close the native peer on explicit close, unpolled muxer drop and failed or aborted upgrades. Keep successful connection lifetime separate from signaling-attempt cancellation.

Generated-by: OpenAI Codex
Keep retry callbacks outside the delivery lexical context so pending or completed attempts do not retain parsed message bodies for the five-second retry interval. Preserve durable intents, timer behavior, and replay identity.

Generated-by: OpenAI Codex
Own the five-minute timer and abort listener in each reconciliation wait. Early public triggers release both immediately while normal expiry and endpoint shutdown still wake the loop.

Generated-by: OpenAI Codex
Keep local restart and retry assertions running on Windows without equating stat mode bits with ACL permissions. Production permission handling is unchanged.

Generated-by: OpenAI Codex
Generated-by: OpenAI Codex
Copy mutable editor state and paste maps without deep-cloning each stored paste for every typed word. Preserve all undo steps and cover public editing, paste renumbering, and retained heap growth.

Generated-by: OpenAI Codex
Collect only the code-point prefix needed for nonnegative budgets while preserving cleaning and numeric slice semantics. Cover transient allocations and Unicode behavior with regression tests.

Generated-by: OpenAI Codex
Preserve complete redaction and byte-budget semantics while limiting temporary code-point arrays and UTF-8 encoding to the useful prefix.

Generated-by: OpenAI Codex
Keep startup channel metadata free of Sigstore and TUF module graphs. Load the parser and verifier only when an update is actually verified, preserving fail-closed trust checks.

Generated-by: OpenAI Codex
Forward the caller's effective AbortSignal instead of a temporary Request's GC-sensitive derived signal. Preserve explicit null, inherited and overriding signals on every body path, and cover prompt native HTTP cancellation after GC.

Generated-by: OpenAI Codex
Decode the bytes already read for request customization instead of cloning and reading the complete body twice. Preserve the original read boundary, stream error identity, caller locks and cancellation semantics.

Generated-by: OpenAI Codex
Avoid allocating unknown-session state during ordinary cleanup. Retain cancellation generations only while queued operations own them, preserving same-turn stop authority and executor-release fencing.

Generated-by: OpenAI Codex
Release only connection-owned staging in the existing missing-session rejection path. Preserve response and TTL contracts while preventing failed commit and cleanup requests from retaining completed upload buffers.

Generated-by: OpenAI Codex
Scope cached token totals to the existing Goal control lease so late context reads cannot repopulate retired entries or overwrite a new Goal. Delete only after committed retirement and clear during drain, retaining rollback and close fences.

Generated-by: OpenAI Codex
Release SQLite execution-store handles before removing temporary roots. Covers the new lifetime regressions and existing Goal coordinator tests that reproduced the same Windows EBUSY failure on pre-fix production source.

Generated-by: OpenAI Codex
Scope cancellation error observers independently and revoke the pending send observer's native rejection reference when the request settles. Preserve queued frames and late error handling in both SDK module formats.

Allow the required unified-diff context prefix before upstream tabs while retaining other patch whitespace checks.

Generated-by: OpenAI Codex
Reuse only fully equal frozen snapshots after each fresh catalog read. Preserve per-turn historical state, the 100-entry FIFO and failed-read retry behavior, and prevent evicted late reads from adding retention.

Generated-by: OpenAI Codex
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/S Under 100 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant