# 会话目录本地恢复与增量同步

初始实现基线：插件 official/dev 121f68e；客户端 origin/master 02f86d2。参考 前端 pre-release 6157a309c 的本地快照、首屏提交、后台自动补齐和独立加载状态。

## 行为合同

当前账号先恢复 SQLite 目录和本地头像，再校准服务端。无缓存时第一页立即发布，不等待头像下载、缓存写盘或第二页。每页固定 20 条，自动遍历至 hasMore=false；每页只按稳定身份增量合并，缺席不删除。缓存、远端首屏、完整扫描分别记录；失败不把部分结果标成完整。旧账号结果、旧消息水位和旧置顶版本不得回退新状态。

Host 统一拥有目录扫描和持久化，通知基线复用同一轮取数但仍校验连接代次。隐藏状态由既有权限和偏好 owner 确认后投影；本地头像保存图片字节，下载失败保留旧图片。Browser 只订阅目录变化并展示。

## 能力矩阵

| 面 | 接入 | 验证要求 |
| --- | --- | --- |
| UI | 现有 sources.list 的 localFirst 模式与现有 SSE | 冷/暖首屏、分页、头像、置顶和隐藏恢复 |
| SDK | listSources(root, localFirst)、setBotDirectoryPin 类型安全选项与能力声明 | 仓外 consumer 编译及真实 Host 调用 |
| Tools | arkme_sources_list 的 local_first 选项及 arkme_bot_conversation_pin | 注册、grant 和真实 Harness 会话调用 |
| Host | 一个目录 owner、SQLite 增量写入与媒体缓存 | 并发、取消、账号、陈旧结果、失败和重启测试 |
| Client | 现有独立 App Data 与本地插件装配 | 隔离 macOS Electron 场景和制品安装验证 |

## 验收工作负载

记录插件和客户端 SHA、运行环境、数据规模、每页数量。区分应用启动、目录请求到第一条可点击、首屏头像完成、全目录完成。相同数据与网络条件分别测试无目录/头像缓存、有完整持久缓存和重启后离线恢复；阻塞第二页、头像和持久化验证冷首屏不被阻塞。真实环境与受控网络数据分别报告，不将模拟耗时当线上实测。

完整目录仅保存摘要，媒体由既有下载并发限制和明确磁盘容量管理；同步游标循环、账号切换和超限必须显式失败。浏览器可视窗口限制 DOM，数据完整性不受窗口大小影响。

## 实施状态

已实现并完成 macOS 隔离客户端验收。全量测试、实际账号冷/暖加载、业务网络不可用恢复、SDK Consumer、官方 Session ToolRuntime 和制品安装证据见本任务交付报告；生产渠道交付独立于本地验收，不随此功能自动发布。

## 资源和兼容边界

- SQLite 目录最多 20,000 条／32 MiB；达到预算会显式失败，不把截断结果当完整列表。
- 头像沿用单图 8 MiB 限制，磁盘缓存预算 256 MiB；已被目录引用的图片受保护，容量不足保留旧图并报告缓存失败。
- Browser 只保留附近的20行分块，已选中的分块保持可用；不活跃头像最多保留256项，等待队列最多512项。
- 页面恢复和本地 Bot 置顶通过 `sources.list(localFirst)`、`conversation.directory.bot-pin` 与公开 SDK/Tools 消费；写操作保留明确用户授权。
- 缓存是派生数据；操作权限继续由现有服务校验。分页缺席不作为删除证据。

## 后台同步展示

首次无缓存、增量补齐和后台刷新均不显示加载横条、转圈、骨架或同步文案；首批数据到达后直接展示。失败提示和重试入口按既有规则保留。同步状态继续由 Host 持有，展示隐藏不改变分页、持久化或失败状态语义。


## 合并前场景复核修正

- 已读采用后端 `unread_snapshot.read_seq`；消息序号、已读游标与 policy.update_at 分别比较，不以同一消息水位下未读数只减不增作假设。
- 同步中的目录偏好失效合并为一次后续扫描；一个消费者取消只退出等待，账号切换取消整个 owner。已完成的通知基线不能供后续连接复用。
- Bot 缓存缺席不删除，明确删除独立投影；新建、联系人打开和普通 Bot 查询保持原业务能力。旧 Browser 置顶逐项迁入 Host，写入成功才消费旧记录。
- Bot 头像同样持久化；缓存读写故障不覆盖已成功下载的图片。实时事件的稀疏头像字段与权威头像删除分别处理。
- 磁盘缓存故障保留最后成功快照并记录诊断；本地 Bot 置顶必须持久化成功。远端扫描完成不等于磁盘写入成功，二者不得混作一个成功状态。
- Tool 限制输出时显式标记 truncated 并提示使用普通游标目录，不把输出截断伪装成完整枚举。

退出/解散群的成功回执通过独立的 removedSourceKeys 投影移除缓存行；旧分页、装饰与实时增量不得复活该条目。后续权威目录确认重新入群时才恢复。分页缺席仍不作为成员变更证据。

缓存 Bot 条目使用独立的、账号绑定的目录查询引用，操作时重新向 Bot owner 确认目标；不延长原进程 Bot 句柄或过期图片 URL 的授权。历史 Bot 头像只允许按当前账号缓存键读取本地字节。

## 侧边栏切换

对话与联系人目录按账号分别延迟挂载，首次访问后切换只隐藏，不重新挂载或重新请求会话目录。隐藏时暂停联系人后续自动翻页和 Arko 预览轮询，关闭浮层，后台共享目录更新不得抢走当前导航。虚拟分块区分整面板隐藏与实际滚动离屏，隐藏时保留已显示行；显示前恢复原滚动位置。账号切换仍销毁旧账号组件状态。

已有本地或服务端目录、Bot、Arko 或发给自己的数据时，不显示全局会话加载失败及重试占位；完全没有可用数据才保留失败重试入口。Host 同步失败状态继续保留，不改变真实同步结果。
