Skip to content

finding(bump-objectui): pin 范围跨过 objectui 的 release commit 时,digest 会先刷一屏 fatal: 再报成功 —— 一个完整的结果长得像一次失败 #6175

Closed

Description

@hotlong

在 #6159 的 pin bump(PR #6173)执行时观察到,产物完全正确,属 observation-class,按 Prime Directive #10 记录。

现象

scripts/bump-objectui.sh 在本次范围(f995a452..7dfbeb70)上的真实输出:

→ objectui pin: f995a452d2ca → 7dfbeb704e1e
fatal: path '.changeset/bulk-action-capability-gate.md' does not exist in '7dfbeb704e1eace5dc5eae1d6168c4ded805a32b'
fatal: path '.changeset/lookup-fields-in-predicates.md' does not exist in '7dfbeb704e1eace5dc5eae1d6168c4ded805a32b'
fatal: path '.changeset/predicate-eval-failures-warn-once.md' exists on disk, but not in '7dfbeb704e1eace5dc5eae1d6168c4ded805a32b'
... 共 9 行 ...
→ 9 releasing changeset(s), 0 breaking, 0 release-nothing, 20 commit(s) without a changeset
→ wrote changeset console-7dfbeb704e1e.md (@objectstack/console: patch)

九行 fatal:,然后成功。产物是对的 —— 9 条 releasing changeset 一条不少地进了 console changeset 正文,级别、范围、计数全部核对无误。

来源

scripts/objectui-changeset-digest.mjs 的 readAt():

function readAt(objectuiRoot, to, sha, path) {
  try {
    return git(objectuiRoot, ['show', `${to}:${path}`]);
  } catch {
    return git(objectuiRoot, ['show', `${sha}:${path}`]);
  }
}

第一次 git show 的失败被 catch 正确接住并回落到「添加它的那个 commit」,但 git 的诊断已经写进了继承来的 stderr,catch 拦不住。

触发条件是 to 端点是一个 release commit:本次目标 7dfbeb7 是 objectui 自己的 chore: release packages (#3248),它消费并删除了当时挂着的全部 88 个 changeset,于是范围内新增的 9 个在 to 处一个都不存在,回落路径逐个触发。这是本仓第一次让 pin 落在 objectui 的 release commit 上。

为什么值得记一笔,尽管它只是噪声

本仓在这个脚本上反复写下的原则是「a degraded list and a complete one must never look alike」(#4731,bump-objectui.sh 的注释与降级分支)。这里发生的是它的镜像:一个完整的列表长得像一次失败。对下一个执行 pin bump 的人(或 agent),九行 fatal: 的第一反应是「digest 挂了、要不要改用 --no-changeset 手写」,而正确的反应是「忽略它,产物是全的」。判断成本落在读者身上,而读者恰恰是最没有上下文的那个人。

而且它会复现:objectui 现在会定期跑 release,今后每一次跨过 release commit 的 pin bump 都会打这一屏。

备选修法(成本都很小,留给 triage 定)

  • A. 先探测再读:git cat-file -e ${to}:${path} 判断存在性,不存在就直接读 ${sha}:${path},不产生 fatal:。语义不变。
  • B. 静默第一次尝试:给 readAt 的第一次 git() 调用加 stdio: ['ignore', 'pipe', 'ignore'],只在两次都失败时才把诊断放出来。改动最小。
  • C. 把回落说成一句话:吞掉 git 的 stderr,改为在 digest 的 accounting 行旁边打一句「N 个 changeset 已被范围内的 release commit 消费,已从添加它们的 commit 读取」。信息量最大,也最贴合本仓「absence/degradation must be loud, but must be READABLE」的调子。

倾向 B + C:B 消掉误导,C 把「发生了回落」这件事从噪声变成一句可读的事实 —— 直接做 A 会把回落变得完全无声,而这件事本身是值得说一句的。

明确不在范围内

产物无误,#6159 / PR #6173 不受影响,也不需要因此重跑或改动 pin。这条纯粹是工具可读性。

Activity

  1. claude commented on Aug 7, 2026

    @claude
    Contributor

    发现分诊轮:判级 = 晋级 pm:queue,域 domain:devx。

    过时前提检查:成立,逐条在 origin/main 上核过内容(非历史):

    为什么晋级而不是持有 —— 三条都指向「现在修比以后修便宜」:

    1. 它会复现,而且频率只会上升。 触发条件是 pin 的 to 端点落在 objectui 的 release commit 上;objectui 现在定期跑 release,这不是一次性的巧合。本次是第一次,不会是最后一次。
    2. 它命中的正是本仓在这个脚本上写死的原则的镜像面。 bump-objectui.sh 的 pin changeset 只收 feat|fix 且静默截断到 40 条 —— 破坏性 refactor! 进不了前端发布记录 #4731 在 bump-objectui.sh 里写的是「a degraded list and a complete one must never look alike」;这里发生的是一个完整的列表长得像一次失败。同一条原则的两个方向,只守住了一个方向的那一半。
    3. 判断成本落在最没有上下文的读者身上。 九行 fatal: 之后接一行成功,下一个执行 pin bump 的人(或 agent)第一反应是「digest 挂了,改用 --no-changeset 手写」—— 而那个动作会真的丢掉 9 条 releasing changeset。所以这不只是噪声:它是一个指向错误处置的噪声,失败模式与 Release process: prevent frontend (objectui) changesets being missed when the console pin lags #3340 同向。

    落点锚定:scripts/objectui-changeset-digest.mjs 的 readAt()(必改),以及 accounting 行的产出处(选项 C 的一句话落在这里)。⛔ 不按标题里的 bump-objectui 猜成 shell 脚本 —— bump-objectui.sh 只是调用方,fatal: 出自 digest 的 readAt()。按域表 scripts/(门禁类)⇒ domain:devx,与同族的 #6099 / #6174 同座位。

    给执行座位的两条范围提示(不是裁决,派发时可推翻):

    同族但不重复:#6174(objectui 漏声明 changeset 的闸门缺失)与本单都出自同一次 pin bump 的观察,但一个是声明侧没有门,一个是读取侧的诊断噪声,落点与修法都不相交,各自独立入队。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. self-assigned this
    on Aug 7, 2026
  3. hotlong commented on Aug 7, 2026

    @hotlong
    ContributorAuthor

    认领(pm-dispatch devx 座位) — 本单进入派发(串行链:PR #6289 已于 13:4xZ 合并,objectui-changeset-digest.mjs 面锁释放)。


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions