# 存储版本与手动迁移 ## 使用 设置 → 基本设置 → 升级迁移:先检查,再确认升级。启动时不会自动迁移。 伙伴任务或关注检查正在执行时拒绝迁移;请等待结束后重试。 迁移期间暂停插件读写、渠道与调度,完成或失败后重载插件。 提交接口即时返回 202,迁移不绑定浏览器请求生命周期。页面只重试 GET 状态查询, 容忍重载时的 404/502/503/504,恢复后以实际版本显示成功或失败,绝不自动重发迁移。 自动检查有次数上限和单请求超时,可取消;登录失效则提示重新登录。 刷新或客户端重载时,30 分钟内的当前标签页迁移标记会恢复基本设置入口。 启动时只比较已读取的存储版本;需要升级时向卡片消息箱添加一条本地系统通知, 复用未读翻面提示。通知中的「前往升级迁移」直接打开基本设置,不执行迁移。 同一目标版本去重,已读状态跨重启保留;完成迁移后清除过期提醒。 系统通知保存在公共消息库,不归属伙伴、不调用模型、不投递到聊天渠道。 ## 版本 插件发布版本、PartnerState schemaVersion 和 storageVersion 相互独立。 缺失存储配置表示 0;当前支持 0 和 1。持久化版本保存在原 statePath 同目录的 storage-config.json,由插件管理,不提前重载宿主 YAML。 每步独立为 src/storage/migrations/vN-to-vN+1.ts,在 index.ts 注册。 注册器验证连续路径,依次 execute → verify → commitVersion。 失败立即停止;重试按持久化版本继续,已提交步骤不重复执行。 缺失步骤、重复注册、降级及未实现步骤均拒绝。未来新增迁移文件, 不要修改已发布步骤的语义,也不要手工设置版本跳过迁移。 ## 版本 1 布局 - 公共根:dirname(statePath)/storage-v1/,保存公共任务、需求、协作状态、Skill 和索引。 - 私有根:defaultCwd/partners//.partner/,保存身份配置、渠道配对、会话关联、 关注、记忆、Skill 绑定、计划、执行记录、通知和附件投递数据。 - memory-backup、memory_back、memory_backup 及带日期后缀的同类目录,按原名 保存在私有 backups/legacy-memory/<原目录名>/,不合并到活动记忆。 - 凭据仍由宿主管理;宿主会话、Preset、知识库及挂载不迁入插件。 - runs、inbound、task-results 工作文件保留原位置,避免破坏绝对路径引用。 - 浏览器卡片设置与位置仍保存在浏览器。 ## 一致性与恢复 暂停并排空写入后,复制到有事务标记的暂存目录,校验文件哈希、SQLite 完整性与拆分状态,安装全部目录,最后提交版本。公共清单原子引用私有 不可变快照,不保留私有配置的第二份真源,避免半新半旧的状态。 运行期 SQLite 排他锁阻止使用相同共享数据路径的新版本插件并行启动。 迁移先生成完整备份:migration-backups/<事务 ID>/state.json 是旧配置快照, originals/<序号> 保存公共和私有的全部登记源,archive.json 记录对应来源和哈希。 包括记忆、关注、历史备份、通知数据库及其 sidecar、附件交付、Skill 文件。 备份可能包含敏感配置,应限制访问,不自动删除。 版本提交且新状态可读取后,逐项重新核对备份和源内容,才清理原路径。 不清理整个伙伴工作区或公共根,不处理用户工作文档、不猜测未登记目录。 清理失败或内容变化时保留该项,cleanup.json 记录结果,设置中显示待清理提示。 「重试清理旧路径」需要显式确认,暂停服务后只重做校验和清理,不重跑迁移。 不会在启动时自动扫删旧文件。提交前中断时绝不删除旧源。 未提交版本时,重试只清理匹配事务标记的生成目录,再从旧数据重建。 不属于该事务的目标、符号链接、特殊文件和检测到的挂载点会阻止迁移。 损坏清单、未知高版本或工作区根路径变化均报错,不静默回退旧数据。 迁移期间不要外部修改文件,也不要并行运行不支持此锁的旧版插件。 新布局产生数据后不能直接切回旧目录;恢复前应停止服务并备份全部新旧数据。 ## 验证范围 临时数据测试覆盖真实 SQLite、私有拆分、已读状态、附件投递、中断重试、 提交失败、写入失败、目标冲突、哈希损坏、符号链接、排他锁与忙碌拦截, 以及带日期的备份、空目录、备份损坏不删除、源变化保留和清理重试。 接口测试验证 202 与运行期状态可读;浏览器验证连续 504/404 后恢复、确认、 取消、失败、移动端/桌面端与浅深色主题。这里只自动重试读取,不重复写入。 测试不代表已经迁移生产数据;部署和实际迁移是两个独立操作。