fix TUI diff context line accounting

This commit is contained in:
kingwl
2026-07-31 11:41:16 +08:00
parent 7239a2201e
commit e98cd522ee
12 changed files with 153 additions and 49 deletions
@@ -0,0 +1,29 @@
# Agent Note: TUI diff 上下文行保持中性
Status: implemented
[English](2026-07-31-tui-diff-context-line-accounting.md) | 中文
## 问题
文件系统 diff 返回结果时,每个 `FileDiff.oldText` 和 `FileDiff.newText` 都会包含已应用的变更及其前后各 3 行上下文。TUI 将旧侧的每一行都渲染为删除行,将新侧的每一行都渲染为新增行,其中包括两侧相同的上下文。因此,一行编辑会显示为删除 7 行并新增 7 行,页脚还会重复这些虚高的合计值。
## 决策
对于每个不对应文件创建的 `FileDiff`,TUI 在渲染时比较 `FileDiff.oldText` 和 `FileDiff.newText`。新增行和删除行仍分别使用绿色 `+` 和红色 `-` 标记;相同的上下文行则使用弱化的正文色调,并带有由两个空格构成的中性前缀。页脚只汇总归类为新增或删除的行。创建操作(`oldText: null`)仍将新内容中的每个非空行归类为新增行。
该行为仍然只是消费方对现有 `FileDiff` 契约的解释。文件系统工具仍会持久化带上下文的变更前后片段,因此其他消费方仍能获得定位上下文,已有会话日志在回放时也会采用修正后的 TUI 呈现。TUI 与 `dsh-tool-fs` 共用同一个受维护的 `diff` 包(package),无需引入第二套逐行 diff 实现。
## 考虑过的替代方案
**从文件系统结果元数据中移除上下文。** 不予采纳:带上下文的已应用 hunk 是有意保留的生产方输出,供具备相应能力的编辑器使用;更改这些内容会让所有消费方丢失信息,同时旧会话日志在 TUI 中仍会产生误导。
**为 `FileDiff` 扩展持久化的逐行标签。** 不予采纳:这些标签可以根据现有的变更前后文本对确定性派生;仅为一个渲染器持久化标签,会扩大跨包契约和会话日志契约。
**不使用 diff 算法,按位置匹配相同行。** 不予采纳:插入和删除会使后续上下文发生位移,因此按位置配对会把有效 hunk 错误分类。
## 后果
TUI diff 卡片会区分用于佐证的上下文与变更本身,其 `+A -R` 页脚报告实际的行变更量。回放已有的上下文 diff 无需迁移即可获得修正后的渲染。渲染每个不对应文件创建的 hunk 时,会额外执行一次逐行比较;结果时刻的 hunk 本就受上下文范围限制,创建卡片则会跳过比较。
聚焦的 TUI 测试覆盖中性上下文和精确合计值。组装后的 `advanced-cards` 终端快照在卡片折叠和展开状态下固定了中性上下文样式、变更行的语义色彩,以及 `+1 -1` 页脚。