Skip to content

feat: 发布历史 diff 从摆字段变成读得懂——方向钉死时间序,危险有底色 - #98

Merged
YoungSx merged 1 commit into
mainfrom
critique/release-history-diff
Sep 5, 2026
Merged

feat: 发布历史 diff 从摆字段变成读得懂——方向钉死时间序,危险有底色#98
YoungSx merged 1 commit into
mainfrom
critique/release-history-diff

Conversation

@YoungSx

@YoungSx YoungSx commented Sep 5, 2026

Copy link
Copy Markdown
Owner

/impeccable critique 审计了发布历史 diff,然后把报告里 2 个 P0 + 3 个 P1 + 全部 P2 一次做完。评审快照进了 .impeccable/critique/(15/40,Poor)。

为什么

这一屏的账本记得很老实(无快照 / 断档 / 路由数未知三种不完整记录各说各的话,回滚复用发布的两段式闸门),读账的那一半没做完:diff 正确、诚实,但真正在做 diff 的是人不是工具。四处缺陷全在主任务路径上,而 detector 全绿 —— 没有一条是正则能扫出来的。

改了什么

结果送达(P0)。对比区从列表尾部挪到列表之前,勾第一个 revision 就有一行常驻状态行说话。实测:6 版时 diff 标题 top1001 → 269(视口 950);50 版(快照保留上限,成熟部署的常态)从文档 6497px → 269pxscrollY 不用动。列表首屏收到 20 张,给出总数与「显示更早的」。

方向钉死时间序(P1)from 取较小的 revision,两侧改用绝对指称 #46 的值 / #47 的值,标题从 换成 #46 → #47。从前自上而下勾(列表从新到旧,唯一自然的动作)得到的是反向 diff 却仍标着「原值 / 新值」—— 事故排查里那不是不便,是错误决策生成器。挤出规则同时改成先进先出,与卡上那句提示一致(旧注释写的正是这个语义,代码却把先勾的钉死了)。

卡片不再是 role="button"(P0),勾选换成官方 Checkbox。一并修掉:

  • 键盘聚焦「回滚」按 Enter 弹窗打不开、反而把卡勾进对比(实测;WCAG 2.1.1,破坏性动作对纯键盘用户完全不可达)
  • 卡片 118 字的可访问名,内含两个内层按钮的标签(ARIA 规定 role="button" 的后代是 presentational)
  • 选中态「对比」按钮可访问名为空(4.1.2)
  • border-primary / hover:border-ring 两处死类(Card 只有 ring-1,没有 border 宽度工具类)

危险判定随 diff 下发(P1)。服务端在 DiffEntry 上带 routeId / field / risk,判定仍只有 dangerFlags 一份(发布闸门用的就是它),前端仍然只渲染。命中的行铺 danger-surface + DANGER_REASONS 那句中文后果 —— 从前 allowPrivateUpstream: false → truetimeoutMs: 30000 → 10000 同款灰字,而面板别处专门为前者准备了红底和二次确认。顺手补齐 7 条只有英文 reason 的字段。

其余(P1/P2):diff 按路由分组而不是按动词分组(routeId 由服务端给定 —— 路由 id 可以含点,routes.foo.bar 在浏览器里切不开);新增 不再拿全系统最重的 primary 实底,删除 是唯一带色相的一档;值不换行、可横滚、挂全文 title、超长给「看全文」并按 code point 截断(旧 slice 会把字符切在代理对中间);启用三个死文案键、删掉无处可用的 valueLabel;报错三套语法收敛成 Alert variant="destructive" + 重试,同一对 diff 失败后也能重试(旧 effect 依赖不变,重试无门),并把服务端 409 的 detail(哪一侧、为什么)说出来;version 从「路由」组挪进「文档本身」;时间戳等宽 + tabular-numsliveRevision 不再被丢弃;reasonOf 的三份拷贝收敛成 dangerReason 一份。

刻意留在原地

  • 删除 badge 浅色主题 3.97:1(12px 门槛 4.5):它是 base-nova 官方原样件的 destructive 变体,红线要求不改一行。这是设计系统层面的决定,不该由这个功能顺手动。
  • 500 字符备注不加 line-clamp:那是前一位操作者的意图,卡上最值钱的字符串。

测过什么

  • npm run check 全绿:lint 0 error(38 条既有 no-await-in-loop warning)、format、build、typecheck、36+12+2+12 个测试文件
  • 新增回归测试各钉一个真实缺陷:键盘可开回滚、方向按时间序、同一对可重试;diff.test.ts 补 7 条覆盖 routeId/field/risk(含含点 id、祖先继承风险、guarded 与 presence 两种规则语义)。
  • impeccable detector 对三个改动文件 0 条发现
  • playwright 多视口取证(1440×950 / 390×844):无 console 错误,窄屏零横向溢出,role=alert 到位。

需要人看一眼的

diff 的信息密度是这次唯一有品味分歧余地的地方:13 项差异全展开,按路由分了 5 块。如果实际排障里更想要「先只看危险的那几条」,那应该是一个折叠默认值,而不是继续加信息。

🤖 Generated with Claude Code

这一屏的账本记得很老实,读账的那一半没做完:diff 正确、诚实,但真正在做 diff
的是人不是工具。四处都在主任务路径上。

- **结果送达**。对比区从列表尾部挪到列表之前,勾第一个 revision 就有一行常驻
  状态行说话(从前第一次点击视口零变化)。实测:6 版时 diff 标题从 y=1001 回到
  269,视口 950;50 版(快照保留上限,成熟部署的常态)时从文档 6497px 回到
  269px,`scrollY` 不用动。列表首屏收到 20 张,给出总数与「显示更早的」。
- **方向不再由勾选顺序决定**。`from` 取较小的 revision,两侧因此能用绝对指称
  「#46 的值 / #47 的值」,标题也从双向 `↔` 换成 `#46#47`。从前自上而下勾
  (列表从新到旧,唯一自然的动作)得到的是一个反向 diff,却仍标着「原值 /
  新值」——事故排查里那不是不便,是错误决策生成器。挤出规则同时改成先进先出,
  与卡上那句提示一致(旧注释写的正是这个语义,代码却把先勾的钉死了)。
- **卡片不再是 role="button"**,勾选换成官方 Checkbox。一并修掉:键盘聚焦
  「回滚」按 Enter 时弹窗打不开、反而把卡勾进对比(实测,WCAG 2.1.1,破坏性动
  作对纯键盘用户完全不可达);卡片 118 字的可访问名(内含两个内层按钮的标签,
  而 ARIA 规定 role="button" 的后代是 presentational);选中态「对比」按钮可访
  问名为空(4.1.2)。`border-primary` / `hover:border-ring` 两处死类随之删除
  ——Card 只有 `ring-1`,没有任何 border 宽度工具类。
- **危险判定随 diff 下发**。服务端在 `DiffEntry` 上带 `routeId` / `field` /
  `risk`,判定仍只有 `dangerFlags` 一份(发布闸门用的就是它),前端仍然只渲染。
  命中的行铺 `danger-surface` 并带上 `DANGER_REASONS` 那句中文后果——从前
  `allowPrivateUpstream: false → true` 与 `timeoutMs: 30000 → 10000` 同款灰字,
  而面板别处专门为前者准备了红底和二次确认。顺手补齐 7 条只有英文 reason 的字段
  (bodyRewrite.inject/replace、cache.key.headers、respond、
  respond.redirect.allowExternal、mirror.methods/includeBody)。

其余:diff 按路由分组而不是按动词分组(`routeId` 由服务端给定——路由 id 可以含
点,`routes.foo.bar` 在浏览器里切不开);`新增` 不再拿全系统最重的 primary 实底,
`删除` 是唯一带色相的一档;值不换行、可横滚、挂全文 title、超长给「看全文」并按
code point 截断(旧 `slice` 会把字符切在代理对中间);启用了三个死文案键
(truncated / failed)、删掉无处可用的 valueLabel;报错三套语法收敛成
`Alert variant="destructive"` + 重试,同一对 diff 失败后也能重试(旧 effect 依赖
不变,重试无门),并把服务端 409 的 `detail`(哪一侧、为什么)说出来;`version`
从「路由」组挪进「文档本身」;时间戳等宽 + tabular-nums;`liveRevision` 不再被
丢弃,线上那一版滚出保留窗口时有一句交代;`reasonOf` 的三份拷贝收敛成
`dangerReason` 一份。

留在原地的两处,理由写在这里而不是悄悄改:`删除` badge 在浅色主题下 3.97:1
(12px 正文门槛 4.5),但它是 base-nova 官方原样件的 destructive 变体,红线要求
不改一行——这是设计系统层面的决定,不该由这个功能顺手动;500 字符的备注不加
line-clamp,它是前一位操作者的意图,是卡上最值钱的字符串。

实测与验证:`npm run check` 全绿(36+12+2+12 个测试文件);impeccable detector
对三个改动文件 0 条发现;playwright 多视口取证(1440×950 / 390×844)无 console
错误、窄屏零横向溢出。新增回归测试各钉一个真实缺陷:键盘可开回滚、方向按时间
序、同一对可重试。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@YoungSx
YoungSx merged commit 2c7faad into main Sep 5, 2026
1 check passed
@YoungSx
YoungSx deleted the critique/release-history-diff branch September 5, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant