chore(objectql): 退休 applyFormulaPlan 的零调用者 nowSnapshot 形参,并把 docstring 收窄到实际成立的范围 (#5699) - #5894
Merged
Merged
Conversation
…rameter (#5699) The fourth optional parameter `nowSnapshot?: Date` had exactly one effect, `nowSnapshot ?? new Date()`, and not one of the three call sites (find, findOne, and #5504's write-response hydration) ever passed it. Dormant from birth, so it is removed rather than archived: a parameter that looks live makes every reader conclude the caller can pin the instant. Narrows the docstring's "mirrors applyFieldDefaults" claim to the half that holds (same context shape, one expression vocabulary) and records the half that does not (each side pins its own `now`, so an insert's `NOW()` default and its `now()` formula are one driver round-trip apart), naming #5699 as where sharing one instant would have to be argued. Adds the determinism pins the parameter's appearance stood in for: one snapshot per call across every row x every formula field, asserted by object identity so a per-evaluation clock read fails even when the milliseconds agree, on both the write and read paths, plus a tripwire on the two instants staying independent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Q7oc7ASjh8yxyS3Yz78We
…ire-nowsnapshot-param
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
baozhoutao
marked this pull request as ready for review
August 6, 2026 11:31
This was referenced Aug 6, 2026
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.
Fixes #5699
结论:前提成立,走方向 (2)(退休零调用者形参 + docstring 收窄)
先在
origin/main上核前提,三项全部复现:packages/objectql/src/engine.ts:546的applyFormulaPlan确实声明第四个可选形参nowSnapshot?: Date,函数体const now = nowSnapshot ?? new Date();。applyFormulaPlan(三个调用点,无一传第四参:engine.ts:614([17.0-rc2验收] REST create/update 回包的 record 缺所有 formula 字段(GET/LIST 有)—— applyFormulaPlan 只挂在 find/findOne 上,写路径回包不做公式水合 #5504 的写路径共享水合点hydrateWriteFormulas)、engine.ts:4791(find)、engine.ts:4923(findOne)。测试文件里也没有任何一处直接调用它(该函数是模块私有,从未 export),所以没有「测试传第四参」需要一并清理。insert中间件体开头的nowSnap(engine.ts:5004)只喂给applyFieldDefaults,与水合点无关。即:该形参自诞生起只走
?? new Date()分支,是休眠代码。没有发现即将到来的调用者:
is:open搜索 PR/issue 正文里的nowSnapshot/nowSnap/applyFormulaPlan,除本单外零命中;没有在飞 PR 或已裁决需求要传它。因此按 PM 预裁取方向 (2),不退到 (3)。⛔ 方向 (1)(insert 传nowSnap)未实现 —— 它会让写路径比读路径多一条确定性保证,是语义决策。改了什么
签名:
applyFormulaPlan(plan, records, execCtx)—— 删掉nowSnapshot?: Date,函数体const now = new Date();。私有函数、无公共 API 变化、行为不变(被删的分支从来不可达)。docstring 收窄。原文「The eval context mirrors
applyFieldDefaults」只成立一半:formula与defaultValue共享一套表达式词汇;now。applyFieldDefaults拿的是 insert 的写前快照,applyFormulaPlan自己读一次时钟 —— 因为 formula 是「记录被物化时」求值(读时,以及写响应上),不是「该行 default 被解析时」。docstring 现在把这条差异写明,并点名
applyFormulaPlan的nowSnapshot形参零调用者 —— 同一次 insert 里 defaultValue 的 now() 与 formula 的 now() 观察到两个不同瞬时 #5699 是「要不要让两者共享瞬时」该被论证的地方,同时记下形参已按 enforce-or-remove(ADR-0049 对 spec 属性用的同一条反射)退休 —— 理由正是立单说的:形参看起来是活的,任何按它推理的人都会得出「两边已共享瞬时」的错误结论。补确定性 pin(
engine-write-formula-hydration.test.ts新增#5699一组三条)。形参退休后,「一次调用一个new Date()」是这个函数唯一的确定性来源,所以它必须被真正钉住,而不是靠一个形参的外观暗示。反向验证 —— 三个方向,先预判再跑
nowSnapshot?: Date+?? new Date(),无人传)Test Files 1 passed / Tests 21 passed{ now: new Date(), ... }放进内层循环)engine.test.ts既有的pins now once per find (#1979)也红了(它是值比较,本次跑到了跨毫秒)。Tests 3 failed / 148 passednowSnap一路传到水合点)× the insert's defaultValue instant and the response formula's instant are INDEPENDENT→expected 2026-08-06T10:59:45.324Z not to be 2026-08-06T10:59:45.324Z // Object.is equality,其余 20 条全绿A 是「模板预设的 before-green/after-red 在这里不可能成立」的如实记录;B 证明新 pin 可证伪;C 证明 tripwire 真的会在方向 (1) 落地时响 —— 也就是说,以后谁想走方向 (1),会被一条测试逼着把决定说出口,而不是悄悄改掉。
为什么 identity 而不是值比较:逐次
new Date()在同一毫秒内产生的两个对象,值相等而对象不同。断言在ExpressionEngine.evaluate收到的上下文对象上做===,毫秒是否恰好相同就不再影响判定 —— B 里既有的 #1979 值比较测试这次红了,但它本来是可能侥幸绿的,新 pin 不依赖运气。验证
行为不变性的证据就是 find / findOne / insert 水合三条路径的既有测试全绿 —— 上面 127 个文件、2087 条测试是在
git merge origin/main(dc6abfd,含 #5871 的 dispatch 迁移)之后重跑的。新增测试没有引入任何新的 fake engine —— 三条 pin 复用
engine-write-formula-hydration.test.ts既有的 stub driver 装置(它是 driver 替身,不是 engine 替身),所以check:engine-double-contract的assertEngineDeleteDispatch/assertEngineUpdateDispatch要求在本 PR 无适用面,gate 也实测为绿。未触碰的区域
按派发令:diff 只动
applyFormulaPlan的定义与 docstring;update单 id 门与 #5850 刚校准的三处注释零改动(git diff origin/main只含三个文件:engine.ts的 43 行、测试 147 行、changeset 36 行)。hydrateWriteFormulas自己的 docstring 也没动 —— 新的applyFormulaPlandocstring 已经显式覆盖写路径。changeset
@objectstack/objectqlpatch。内部私有函数签名变化、无公共 API 变化,changeset 正文写明「行为不变 + docstring 收窄的边界在哪」,给发布说明一个可读的落点。Generated by Claude Code