# 执行记录存储与升级回收 通用迁移、备份、性能测量和发布要求见 [数据库迁移与大数据升级指南](../../development/database-migrations.md)。 ## 用户行为 子任务仍实时显示完整的文字、思考、工具过程和最终结果。运行时间较长、工具输出较多时, 数据库不再为每个流式更新重复保存此前的整份过程;本机和托管 SSH OpenCode 使用相同 的桌面存储机制。此修复不关闭子任务、不截短已有过程,也不增加 Execute 权限门槛。 已有数据库在首次升级时自动处理。启动页铺满窗口,显示处理数量、全宽进度条和近期 处理速度;处理时间取决于历史数据量与磁盘速度,不承诺固定几分钟。用户可以退出, 下次启动重新检查并继续转换未完成的数据;完成后回收空闲页并进入应用。失败时留在 该页提供重试与退出,磁盘空间不足会明确说明,不删除聊天来腾出空间。 ## 存储规则 - `messages.metadata_json` 继续保存供会话显示的完整子任务过程。 - `task_events` 的 `subagent` 内容由共享 `SubagentProgressStorage` 编码。 `progressUpdates` 只保存文字追加、变更的块,或确有删除/重排时的完整重置。 完全相同的过程使用空更新数组。其他事件内容不改变。 - 每个任务内按事件 ID 顺序、按 `childTaskId` 独立还原过程。事件 ID、顺序、状态、 最终输出、错误、时间及远程来源字段均保留,不按天数裁剪或删除旧事件。 - Runtime、Agent transcript、Preload 和 Renderer 的公共 `SubagentEvent` 仍传完整 `progress`;差量表示只存在于桌面数据库内部,不要求更新远端 Agent 协议。 - 远程消息投影与事件插入仍共用 SQLite 事务。重放时还原已保存内容进行等值校验, 相同来源重复事件不重复投影,不同内容继续报冲突。内存过程缓存通过已提交事件 ID 核对;事务回滚或重新打开后从数据库重建,不保存独立快照或回收日志。 ## 旧库升级 桌面在打开业务数据库之前启动独立 Node 工作线程,使用同一套编码和还原函数转换旧库。 按任务有序读取,每批最多 32 条,提交后报告进度;SQLite 保留事务原子性及正常 WAL 自动 checkpoint,每个任务结束时截断 WAL。读取缓存为 64 MiB,避免 1 MiB 级历史 快照在过小缓存中反复读取;不以关闭事务或同步落盘换取速度。 转换可以混合读取旧完整记录与已经转换的记录,因此退出、磁盘写入失败后可以重新扫描 并继续,不建立额外的恢复状态表。最后运行 SQLite `VACUUM` 回收已释放的空间,而非 在转换前复制整份膨胀内容。回收仍需要额外可用磁盘空间,失败保留已提交转换并允许重试。 业务初始化随后将数据库升级为 schema 34,并建立子任务事件的部分索引。 低于该 schema 的旧版客户端不能重新打开已经升级的数据库。需要回退客户端时,必须使用 升级前备份,不要修改 `user_version` 强行绕过版本检查。 ## 验证要求 - 使用可还原的合成过程验证文字追加、内容修订、块重排、清空和多次打开。 - 验证远程重复事件、冲突事件,以及消息更新失败时事件和过程缓存的事务回滚。 - 在真实旧库的已核验备份副本上运行 portable 的正常启动入口,核对事件逐条等价、 其他用户表内容、数据库完整性和实际文件大小,不能只统计空闲页或只测试内存 fixture。 - 同时验证真实本地 Runtime 和共享 Linux Host 的桌面持久化路径。具体证据见 [实现与验证进度](./progress.md)。