feat(item6): transcript 磁盘裁剪 79x + 崩溃安全 checkpoint (CC 2.1.208) - #114
Merged
Conversation
问题: compact 内存裁前缀 (QueryEngine.splice) 正确, 但磁盘 .jsonl 纯追加 (appendEntryToFile), pre-compact 段永留盘。编辑密集会话同文件反复 Read/Edit → tool_result 巨大 → 79x 放大, 多 GB (inc-3930)。 方案: compact 收尾阈值触发磁盘 JSONL 裁剪, 保留 [metadata + boundary + post-compact] 段。崩溃安全 — checkpoint 文件记录裁剪点, resume 恢复协议。 三重数据安全: 1. default off — FUSION_TRANSCRIPT_TRIM_THRESHOLD 未设则永不裁 (byte-identical) 2. atomicWriteFile tmp+rename — 崩溃不留半写 3. preservedSegment boundary 不裁 — 防丢 preserved 消息 文件: - src/utils/sessionTranscript.ts (新 ~350 行): 纯函数裁剪逻辑 shouldTrimTranscript (env gate, default Infinity=off) computeTrimBoundary (单遍正向扫找最后非-preserved compact_boundary + 收 pre-metadata) performTrim (checkpoint 先写 → atomicWriteFile 换主文件 → 删 checkpoint) recoverTrimIfNeeded (checkpoint 不存在=no-op; 主文件OK=幂等删; 主文件坏=fail-visible 保留) - src/utils/sessionStorage.ts: Project 类方法 trimTranscriptOnDisk/recoverTrimIfNeeded (走 trackWrite 串行, 同 removeMessageByUuid 模式) + standalone 包装 + loadTranscriptFile 恢复钩子。错误细节走 logForDebugging (logEvent LogEventMetadata 不允许 string, 用 boolean) - src/services/compact/postCompactCleanup.ts: 主线程 compact 收尾 fire-and-forget 触发 - src/__tests__/utils/sessionTranscript.test.ts (新): 9 case 真实磁盘 I/O default-off / threshold / 裁剪 / metadata 保留 / preservedSegment / 无 boundary / 崩溃恢复 (幂等 + fail-visible) / default-off recover 验证: typecheck 0 / 9 新单测 pass / 244 全测 pass 无回归 / build + build:dev:full pass / lint baseline 不变 (新文件 0 error) / surgical diff (+10/-1 postCompact, +89/-0 sessionStorage)。 live MLX smoke: 二进制启动 + 模块导入安全 (trim 路径 post-compact 触发, 启动不调)。 gateway auth 401 为 pre-existing 传输问题, 非 item 6。 closes #113 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
item 6 — transcript 磁盘裁剪 + 崩溃安全 checkpoint (CC 2.1.208, §188/§628)
closes #113
问题 (实读确认)
compact 发生时, 内存里
QueryEngine.splice(0, boundaryIdx)丢掉 pre-compact 消息 (已正确)。但磁盘从不裁剪:compact_boundary系统消息带内写盘 (纯追加appendEntryToFile)readTranscriptForLoad流内截断内存累积, 但磁盘字节永留方案
compact 收尾阈值触发磁盘 JSONL 裁剪, 保留
[metadata + boundary + post-compact]段。崩溃安全 — checkpoint 文件记录裁剪点, resume 恢复协议。三重数据安全:
FUSION_TRANSCRIPT_TRIM_THRESHOLD未设则永不裁 (byte-identical 旧行为)文件
src/utils/sessionTranscript.ts(新 ~350 行)shouldTrimTranscript(env gate),computeTrimBoundary(单遍扫找最后非-preserved boundary + 收 pre-metadata),performTrim(checkpoint→atomicWriteFile→删 checkpoint),recoverTrimIfNeeded(no-op/幂等删/fail-visible 保留)src/utils/sessionStorage.tstrimTranscriptOnDisk/recoverTrimIfNeeded(走trackWrite串行, 同removeMessageByUuid) + standalone 包装 +loadTranscriptFile恢复钩子src/services/compact/postCompactCleanup.tssrc/__tests__/utils/sessionTranscript.test.ts(新)验证
bun run typecheck— 0 errorsbun test src/__tests__/utils/sessionTranscript.test.ts— 9/9 pass (33 expect)bun test src/__tests__/— 244 pass, 0 fail (235 现有 + 9 新, 无回归)bun run build:dev+bun run build:dev:full— pass关键设计决策
LogEventMetadata = { [key: string]: boolean | number | undefined }不允许 string。错误细节走logForDebugging(接受 string, 进本地 debug 日志), 遥测只记 boolean{ failed: 1 }(避免错误字符串含敏感数据进遥测)。removeMessageByUuid模式)。Co-Authored-By: Claude Fable 5 noreply@anthropic.com