You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug][session-order] Snapshot capacity handling drops newest conversations and exceeds the KV limit #6255
At master dc041dd1ab1a014efa352ba47a6f31fc47f55284, normalizeForWrite() sorts session-order skeletons by recency only when their count exceeds 1,024. The byte budget can bind much earlier: with 40 conversations containing 4,000 kind/fragment pairs each, the legacy writer retains the 27 oldest records and drops the newest 13. After clearing memory and hydrating the file, the most recently active conversations have no persisted skeletons.
The same producer also uses its 8 MiB legacy-file budget for unified KV writes, although the store rejects extension values over 4 MiB. In the real SQLite migration regression, the write fails with extension value exceeds 4194304 bytes, leaving the KV snapshot empty and hydration on the legacy fallback path.
Proposed fix
Treat this as one bounded-snapshot producer fix: sort the union newest-first before either cap, measure serialized UTF-8 bytes, and use the existing store ceiling for KV migration and steady-state writes. Keep the legacy-file ceiling and the existing single-oversized-record fallback behavior. No new configuration, schema or fragment truncation.
Validation
Unchanged master: legacy recency and actual KV migration regressions fail; the small-entry/timestamp-tie control passes.
Fixed: 24 tests pass across order persistence, unified storage, neutral skeleton resolution and persona restart stability.
Coverage clears in-memory skeletons and removes the legacy file before KV-only rehydration, then exercises a subsequent bounded write with a new most-recent conversation.
Whole-project typecheck, build and diff whitespace checks pass.
Duplicate screening: existing PRs/issues and Afloat16's prior issues/fork branches were checked. #3405 introduced this producer and #5757 migrated it to KV. #6186 fixes write lifecycle, while #6203 fixes generic extension validation; neither makes the snapshot producer respect its carrier's size limit or prioritize recent entries under that limit.
Activity
maozhuoshushu commentedon Nov 12, 2026
本机 0.1.213(Windows,
storage.unified=full)实测可以给这份复现补一组真实机器数字,两条都在同一台机器上同时成立:1)8 MiB 帽丢的是最新创建的会话。
session-order解压后 8,347,598 字符,距MAX_SNAPSHOT_BYTES只剩 41,010 B;条目数 103(< 1,024),所以normalizeForWrite不走按lastSeen排序那一支,数组保持写入序——新建会话 append 在尾部。一旦越帽,break截掉尾部,之后新建的会话全部静默丢弃,重启后没有持久化骨架(本机当前活跃会话在 idx 57,不在尾部,所以先丢的是 11-08/09 那批新建会话,再往后的新会话同样落不了盘)。这与你的 40 会话复现是同一机制。2)8 MiB 快照帽与 4 MiB KV 帽冲突,迁移会静默降级。 含 #5757 的构建里
hydrateOrderUnified()首次迁移会走setKvAsync(ORDER_NS, ORDER_KEY, {version,entries});8.34 MB 的 JSON 超过EXT_VALUE_MAX_BYTES = 4 MiB,抛[storage] extension value exceeds 4194304 bytes→kvReady = false→ 之后每次 flush 回落 legacy 文件路径(上游是明文 JSON,8.34 MB/次)。也就是说本机升级后 kv_store 会一直是 0 行,写入量反而从打补丁后的 2.87 MB/次涨到 8.34 MB/次。3)TTL 救不了这个冲突。 按
lastSeen丢整条后重压:7 天 5.23 MB、14 天 5.83 MB,都仍 > 4 MiB;要落进 KV 得压到 ≤3.8 天,代价是丢掉 3–4 天前 21 条共 4.3 MB 的活跃大条目。所以同意你的方向:先修生产者(两种帽都先按 recency 排序、按 UTF-8 字节计量、KV 用 4 MiB 帽),TTL 只能当 8 MiB 帽的安全阀,不能当迁移前提。