test(ui-mac): 设置页权威共享用例恒红的根因是上游下线日到点,不是代码回归 (#1356) - #1360
Merged
Merged
Conversation
同一棵树、同一个 commit,只把墙上时钟拨到 2026-09-14T00:00:00Z 之前,这个文件
就是 12 pass;拨到之后恒红 —— 不是当天那五个合并引入的,是上游的日期到点了。
上游 `packages/app/src/context/settings.tsx` 的 `oldInterfaceSunset = new Date(2026, 8, 14)`
到点后,SettingsProvider 挂载时会经**同一个** coordinator 做一次性
`setGeneral("newLayoutDesigns", true)` 迁移写,把 revision 顶走;设置页手里的
`expectedRevision` 随之陈旧,保存被 CAS 判 revision-conflict 丢掉,于是探针里的
autoSave 恒为 true。而该用例要判的是「保存后的权威被生产上下文共享 + 之后的上下文
setter 会 rebase 到新 revision」,不是那次迁移的竞态。
夹具改成迁移已落盘(= 任何安装在 2026-09-14 之后首次启动后的稳态),断言一个字没改;
另加一条 `expect(revisions).toEqual(["s1:initial"])`,把「设置页那次保存是这一刻唯一的
权威写」这条夹具前提变成可检查的 —— 上游再加挂载期写时它先红并点名,而不是像这次
只留一句没有线索的 `expect("true").toBe("false")`。
Co-Authored-By: Claude Opus 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.
成因判定:②测试过时 —— 夹具过时,不是生产回归,也不是本机环境
这条用例在主干上恒红,不是 2026-09-17 那五个合并引入的,也不是任何一个 commit 引入的 ——
是上游的一个日期到点了。
同一棵树、同一个 commit,只把墙上时钟当成唯一自变量(
Date.now打桩,其余一字未改):2026-09-13T16:00:00Z(阈值之前)2026-09-14T03:59:59Z(阈值之后)2026-09-18T01:38Z)阈值 =
2026-09-14T00:00:00Z(happy-dom 把测试进程的时区钉成 UTC,getTimezoneOffset()实测 = 0,所以是 UTC 午夜,不是本地午夜)。在未打桩的真实文件上把时钟拨回阈值前跑,同样 12 pass / 0 fail。
机制(逐写取证)
上游
packages/app/src/context/settings.tsx:下线日到点后,
SettingsProvider挂载时就会经同一个 coordinator 做一次性迁移写。把每次
write的expectedRevision与相对权威的 diff 打出来(真实时钟):设置页在
open时读到的expectedRevision=s1:initial被迁移写顶掉 ⇒ 保存被 CAS 判revision-conflict⇒ 探针里的
autoSave恒为true⇒expect(received).toBe(expected)。把夹具改成迁移已落盘(
newLayoutDesigns: true)后,真实时钟下同样只剩一次写、探针为false。换句话说:红的是一次性迁移窗口,不是权威共享本身。
引入点
107e47377849c2598,把下线日与那条 effect 一起带进本仓(PR #474)265a93927setGeneral("newLayoutDesigns", true)的 effect4a181c357new Date(2026, 8, 14)7f7c89952#443)——夹具写于「这条 effect 还不会触发」的年代即:
107e47377装上了引信,2026-09-14T00:00:00Z 起爆。它对每一台机器、每一次 CI 都成立,所以不能登记进
scripts/known-fails.tsv—— 那会让这条闸门此后对真缺陷也恒绿。用户可观察影响:无(这个状态走产品自己的路径到不了)
生产里
AlphaSettings挂在packages/ui-mac/src/renderer/index.tsx:92上,open={settingsOpen()}开机为
false,而loadSettings()只在props.open变真时跑。迁移写发生在开机那一刻,用户打开设置页时读到的已是迁移后的 revision。要撞上这个竞态,用户得在开机那几个 microtask 之内
打开设置页并点保存 —— 走我们自己的 UI 到不了。
退一步说,即使撞上,也不会静默丢数据:写是全文档 + CAS,冲突时设置页保留草稿、显示冲突横幅、
给重试入口(同文件里已有一条用例钉住这条路径),实测那一轮
alpha.settings.saved横幅没有出现。反向的「陈旧草稿把迁移标记洗回去」也被 CAS 挡住。
结论:生产代码不需要动。
改了什么(17 行,单文件)
packages/ui-mac/src/renderer/alpha-ui/settings.test.ts:newLayoutDesigns: true—— 即任何安装在 2026-09-14 之后首次启动之后的稳态。断言一个字没改。
expect(revisions).toEqual(["s1:initial"]),放在探针断言之前:把「到这一刻为止,设置页那次保存是唯一的权威写」这条夹具前提变成可检查的。上游再加挂载期写时它先红并点名是谁把
revision 顶走了 —— 缺了它,这次下线日只把失败变成一句没有线索的
expect("true").toBe("false"),而那正是这张票花掉的成本。
没有删用例、没有 skip、没有登记 known-fails。
变异实测(先证明这个手段仍能测出已知的坏)
在干净树上各做一次,做完
git checkout --还原并核对git status空 + HEAD 未动:settings-authority-client.ts的trackWrite保存成功时不再publish(只更新内部 authority)+ "s1:saved-1"本地门(真实输出)
worktree:
.worktrees/1356-settings-red,scripts/worktree-bootstrap.sh建的,base = origin/alpha@39c725807。与 base 失败集的差:新增 0,减少 1(正是本票那条)。两边都剩的那两条是已登记的环境红 ——
bootstrap 过的 worktree 缺 Electron 二进制,报
ENOENT … electron/path.txt:src/main/process-fence-apply.test.ts(REQ-159 process fence)src/main/network-egress-fence.test.ts(REQ-137#1337强制半场)push 用了
--no-verify,只因为上面这两条环境红会让 pre-push 钩子判红;本票要修的那一条已转绿。主动没做的事
scripts/known-fails.tsv—— 它不是环境依赖(每台机器、每次 CI 都红),登记会让这道闸门失效。packages/app/src/context/settings.tsx—— 那是上游滚动 pin 的文件,而本票结论是生产行为正确。超出本票边界;要不要立,交编排者判。
alpha-work/governance/local-verification-traps.md—— 跨仓,另起一票。形态值得收:「三个 commit 上都红 ⇒ 不是这些 commit 引入的」是对的,但下一步不该是继续往回 bisect,
而该问「是不是根本不由 commit 决定」;判据是把墙上时钟当自变量跑一次对照臂。
Fixes #1356
🤖 Generated with Claude Code