Skip to content

fix: summary diff cap discards trailing in-budget diffs when an earlier file exceeds 256KB; summary_diffs column is legacy dead code #525

Description

@LeXwDeX

Why

481e31e2b7(2026-08-28,已在 dev 上)给 summary.diffs 加了 256 KiB 闸,实测把事件峰值从 36.12 MiB 压到 0.25 MiB(见 #522 撤回说明)。该 commit 同时引入了 239 行的 packages/opencode/test/session/summary-diff-guard.test.ts。闸本身仍有两处问题:

truncateSummaryDiffs 的混合场景缺口(session.ts:77

for (const item of diffs) {
  const size = Buffer.byteLength(JSON.stringify(item)) + (kept.length > 0 ? 1 : 0)
  if (total + size > MAX_SUMMARY_DIFF_BYTES) break   // ← :77
  total += size
  kept.push(item)
}

现有测试覆盖:

测试 输入 期望
summary-diff-guard.test.ts:180 [] / undefined [] / undefined
:185 单项超预算 [](已钉为有意行为,"without throwing")
:190 等长小项 × (count+5) 恰好填满预算的 count
:115 giantDiffs(300) f000.txt 起的连续前缀,字节 ≤ 预算

未覆盖[超限项, 小项, 小项…] —— 首项超预算时 break 立刻退出,后面本可容纳的小项被一并丢弃。实测存在单个 patch 长 7,097,898 字符(7.5 MiB)的真实数据,故该场景会实际发生;此时 SessionSummary.diff()summary.ts:135message.info.summary?.diffs)返回空列表。

breakcontinue 与上述 4 处断言全部兼容

  • :185 单项超限 → continue 后循环结束 → 仍返回 []
  • :190 等长序列 → 首个超限后其余同尺寸亦超限 → kept.length 仍为 count
  • :115 / :134-137 连续前缀断言 → 等长输入下仍是前缀 ✓

summary_diffs 列是 legacy 死代码(session.ts:97 / :168

summary.ts:106-113setSummary 只传 {additions: 0, deletions: 0, files: 0}从不传 diffs,故写 session 行时 info.summary?.diffs 恒为 undefined,:168truncateSummaryDiffs 直接走 if (!diffs) return undefined 分支;:97stripOversizedDiffs(row.summary_diffs) 同理恒返回 undefined。

实测:summary_diffs2,025/2,025 全为 NULL,而 summary_additions / summary_files1,999 个非空 —— 与上述路径分析完全一致。diffs 实际只存在于 message 侧(summary.ts:125 写、:135 读)。

测试 :144 的标题已自称 "strips oversized legacy summary_diffs on read" —— house 侧认知里该列就是 legacy,倾向删除而非复活。

Scope

  • packages/opencode/src/session/session.ts:71-82 truncateSummaryDiffs:84-88 stripOversizedDiffs:90-99 fromRow:165-168 行写入)
  • packages/opencode/test/session/summary-diff-guard.test.ts(扩展边界用例)
  • 若选择删列:packages/core/src/session/sql.tspackages/core/src/session/projector.tspackages/core/src/database/migration/

Approach

  • :77breakcontinue,跳过超限单项后继续累积其余项。可选加强:对单个 patch 做长度级截断,避免一个大 patch 独占整个预算(若做,需同步评估 :190count 断言)
  • :按 :144 已表明的 legacy 定位,倾向删除 summary_diffs 列与 :97 / :168 两处死代码,而非让 setSummary 开始传 diffs。删除需配 migration,并确认 projector.tssummary_diffs 投影与 core/src/session/sql.ts 的列定义同步移除
  • 若最终决定保留该列,则需让 setSummary 真正传 diffs,并复核 stripOversizedDiffs 的全有/全无语义(超预算直接 undefined)与 truncateSummaryDiffs 的部分保留语义为何不一致

Acceptance

  • 新增单测:输入 [超预算项, 若干小项],断言 truncateSummaryDiffs 返回那些小项而非 []
  • 新增单测:断言任意输入下返回值序列化后 ≤ MAX_SUMMARY_DIFF_BYTES
  • 既有 summary-diff-guard.test.ts 全部 4 处断言在不修改的前提下继续通过:180 / :185 / :190 / :115)—— 这是 breakcontinue 向后兼容的硬门槛
  • 若删列:rg summary_diffs packages/ 无残留引用,migration 可正向/回滚执行,fromRow 不再产出 summary.diffs
  • 回归:session / summary / revert / projector 相关测试全绿

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions