refactor(metadata-core,objectql): 两个写动词的派发判定下沉到 metadata-core —— 一次关闭 26 条 engine-double 基线条目 (#5619) - #5871
Merged
Conversation
…cates into metadata-core (#5619) Move `engine-delete-dispatch.ts` (#4550) and `engine-update-dispatch.ts` (#5480) from `packages/objectql/src/` to `packages/metadata-core/src/` unchanged, and keep the original objectql paths as re-export shims so no caller, no public export and no pinned call site moves. `@objectstack/objectql` depends on `@objectstack/metadata-protocol`, so that package's 13 fake engines could not import either predicate without closing a dependency cycle turbo 2.10.7 refuses outright. `@objectstack/metadata-core` is a package both sides already depend on and which depends on neither, so the sink is the one route that pins those doubles without inventing an edge. - 13 metadata-protocol test files: both fake write verbs now open with the producer's own predicate, imported from `@objectstack/metadata-core`. - 26 (file, verb) ledger entries deleted from `scripts/engine-double-contract.baseline.json`; the gate's counts move from 37 pinned / 165 ledger / 2 exempt to 63 pinned / 139 ledger / 2 exempt. - The gate's two slices now accept `@objectstack/metadata-core` alongside `@objectstack/objectql`, and its remediation message names the right one. - Six ledger entries whose `closes` prescribed exactly this sink ("tracked as #5619") are rewritten: the blocker is gone, what remains is the one-line pin, tracked as #5855. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Q7oc7ASjh8yxyS3Yz78We
…k-engine-dispatch
…k-engine-dispatch
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 14 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 10:40
This was referenced Aug 6, 2026
Merged
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 #5619
前提核验(先做,再动手)
issue 的前提成立,PM 的扩展前提也成立,两条都是实测:
packages/objectql/src/engine-delete-dispatch.ts(168 行)与packages/objectql/src/engine-update-dispatch.ts(229 行)都是零 import 的自包含模块 ——grep -n "import"两个文件的全部命中都在注释里(delete 的第 23 行、update 的第 22 / 44 行,都是「a double that imports the producer's own decision」这句散文)。所以下沉是一次搬移,
不是重构:判定逻辑一个字未改。
@objectstack/metadata-core的dependencies只有{ @objectstack/spec, zod },不含 objectql;objectql -> metadata-core与metadata-protocol -> metadata-core两条边都已存在。下沉后
npx turbo run build --dry(全仓)、--filter=@objectstack/metadata-core --dry、--filter=@objectstack/metadata-protocol --dry三次 grepcircular|cyclic命中数均为 0。作用域按 PM 预裁取扩展版:两个 dispatch 模块一并下沉,一次关闭全部 26 条
(metadata-protocol 26 条 / 13 文件 = delete 13 + update 13,#5754 给门禁加 update 切片后的现状)。
改了什么
1. 搬移(
git mv,判定逻辑零改动)packages/objectql/src/engine-{delete,update}-dispatch.ts→packages/metadata-core/src/。两个模块的头部注释各加一节「为什么住在 metadata-core」,记下被拒的环与判据来源
(门禁台账里
packages/spec/src/contracts/data-engine.test.ts那条 EXEMPT:反向 import 不可行时,唯一出路是下沉到两边都已依赖的包)。
2. objectql 侧改为 re-export shim,公共 API 与全部既有调用点零变化
原路径
packages/objectql/src/engine-{delete,update}-dispatch.ts保留,内容改为从@objectstack/metadata-corere-export 那 10 个值 + 7 个类型。于是:packages/objectql/src/engine.ts零改动(它 import 的是./engine-delete-dispatch.js,shim 就在原路径)—— 与合并队列里的 PR perf(objectql): update() 单 id 前置行门按对象判定需求(#5284),并校准 #4743 事实一的三处注释 #5850 避让成功,本 PR 与其无文件交集;
packages/objectql/src/index.ts零改动,@objectstack/objectql的导出面一字未变;ENGINE_*_DISPATCH_CASES」的测试(
engine-{delete,update}-dispatch.test.ts)留在 objectql 且零改动 —— 它们 importObjectQL,不能随模块下沉,而「测试继续钉住真引擎与谓词一致」正是它们的职责。
构建产物实测:
require('packages/objectql/dist/index.js').assertEngineDeleteDispatch === require('packages/metadata-core/dist/index.cjs').assertEngineDeleteDispatch→true(同一个函数对象,不是两份拷贝),10 个符号全部在位。
3. 13 个 metadata-protocol 假引擎的两个写动词都接上谓词
每个文件的 fake
delete()开头assertEngineDeleteDispatch(opts)、fakeupdate()开头assertEngineUpdateDispatch(data, opts),均从@objectstack/metadata-coreimport。其中 6 个 fake 原本
delete()/update()不声明参数(async delete() { ... }),补上参数才能把 options 交给谓词 —— 只补参数,不动行为。
⛔ 没有为了让 fixture 过而放松谓词,也没有手抄
if (!where?.id && !multi)。一条 fixture 都不需要改:13 个文件、461 个用例在装上谓词后全绿,说明这些替身此前虽然
结构上可以比真引擎松,实际驱动的调用形状都合规(生产侧
sys-metadata-repository.ts:577与
protocol.ts的删除路径都是where: { id })。4. 基线删 26 条 + 计数
改前读数不是抄 issue 的(issue 的「24 pinned / 34 baseline」是立单时的旧世界),而是在
origin/main的 detached worktree 上现跑的:38 pinned, 165 in the DEBT ledger, 2 exempt。差额 26 = 本 PR 关闭的条目;改后多出的那 1 条 pinned 来自 main 上新合入的 #5850
(
engine-update-prior-read-scope.test.ts)。issue 步骤 4 说的「tracked as #4987」引用与硬编码 sibling 计数,随这 26 条整批删除已自然消失
(
grep基线,残留的 #4987 只剩一处历史陈述,已改写,见下)。5. 门禁两处配套改动
modules现在同时接受@objectstack/metadata-core与@objectstack/objectql两种拼写 —— 它们指向同一个函数,而这正是这份名单唯一在乎的性质。
packages/spec那条 EXEMPT:metadata-core -> spec,所以 spec 反向 import仍然倒置依赖,理由原样成立(已在 slice 注释里写明)。
@objectstack/objectql(add it as a devDependency if the packagelacks it)」—— 对 objectql 依赖的那些包这条建议现在是错的(那条边成环)。改为同时给出
metadata-core,并明确「objectql 依赖你要 pin 的包时优先选 metadata-core」。
顺带修好的悬挂引用(与 issue 步骤 4 同一族)
删掉 26 条之后,台账里另有 6 条条目的
closes写着「sink assertEngine{Delete,Update}Dispatchinto a package BOTH sides already depend on —— tracked as #5619」:
packages/core/src/utils/migration-journal.test.ts(delete+update)、packages/metadata/src/migrations/migrate-sys-notification-to-event.test.ts(delete+update)、packages/platform-objects/src/plugin.test.ts(update)、packages/platform-objects/src/system/migration-flag.test.ts(update)。本 PR 一合,#5619 关闭,这 6 条就指向一个已关闭 issue —— 正是 #5619 自己从 #4987 那里继承的
那个形状。所以把它们的
closes改写成「阻塞已解除 + 剩余的一行 pin + 各包的配置差异」,并指向新开的 #5855(未指派)。各包剩余动作已实测:
@objectstack/metadata/@objectstack/platform-objects:dependencies已含@objectstack/metadata-core→ 零配置;@objectstack/core:需新增一条 devDependency。已实测 —— 把@objectstack/metadata-core: workspace:*加进packages/core/package.json的devDependencies,npx turbo run build --filter=@objectstack/core --dry无 circular / cyclic 输出,随后已还原。这与该条目
why里旧测量(加@objectstack/objectql边 → turbo 拒绝)是两条不同的边,不矛盾。另有 12 条
why写着「unlike the metadata-protocol family in this ledger」—— 那个 family 已被本 PR 删除,改为「the metadata-protocol family this ledger carried until #5619 removed it」;
1 条「Same route, same refusal the #4987 and #5206 entries in this ledger already record」同理改写。
纯文字,
unguarded计数一个没动。验证(全部前台阻塞,容器级
flock /tmp/os-heavy-verify.lock,--filter限定)合
origin/main之后(⛔ 未 rebase;两次 merge 均无冲突,main 上 #5857 触及的protocol.ts/discovery-schema-conformance.test.ts/protocol.metadata-store-outage.test.ts与本 PR 接线的 13 个文件无交集)重跑全部:
@objectstack/metadata-protocol没有typecheck脚本(在check-type-check-coverage的 DEBT 台账里,本 PR 不改变它的状态)。反向验证 —— 方向先预测后运行
预测:红(常规方向)。条目已从基线整条删除,所以一旦把谓词调用拿掉,该 (file, verb) 既不
PINNED 也无台账条目,门禁必须报 PINNED 失败。两次都验了,delete / update 各一次:
sys-metadata-repository.recorded-by.test.ts的assertEngineDeleteDispatch(opts)→x PINNED [delete]: ... does not route through assertEngineDeleteDispatch (line 57),1 problem(s)。恢复后 OK。sys-metadata-repository.history-counters.test.ts的assertEngineUpdateDispatch(data, opts)→x PINNED [update]: ... does not route through assertEngineUpdateDispatch (line 99),1 problem(s)。恢复后 OK。额外测量:这 26 条里哪些是活的,哪些是休眠的
台账对 metadata-protocol 的 update 切片明确声明没有做过 dormancy 探测,delete 侧也只有
per-file 的旧探针。本 PR 顺手补了一次真测量:在已构建的
metadata-core/dist/index.js里给两个assert*临时加一行process.stderr.write栈标记(只动 dist 产物,不动源码),跑一遍@objectstack/metadata-protocol全套(461 全绿),再把 dist 还原并重新构建。结果:migrations/recorded-by-sentinel.test.tsprotocol.stored-migration.test.tssys-metadata-repository.draft-drain.test.tssys-metadata-repository.history-counters.test.tsprotocol-publish-drafts-endpoint-gate.test.tsprotocol-publish-drafts-org-scope.test.tsprotocol.read-decorations.test.tssys-metadata-repository.recorded-by.test.tsprotocol.runtime-authoring-gate.test.ts即 26 条里 9 条是当下就被驱动的(谓词真的在跑,且真引擎会拒的形状一个都没出现),
另 17 条是休眠的 —— 休眠不等于无害,它意味着今天没人走这条路,而将来第一个走的人会继承一个
比真引擎松的替身,这正是 #4434 的形状。两类都已 pin。
Changeset
.changeset/sink-engine-dispatch-to-metadata-core.md——@objectstack/metadata-core+@objectstack/objectql各 patch(模块搬移 + re-export,公共 API 无变化;metadata-protocol 仅测试改动)。🤖 Generated with Claude Code
https://claude.ai/code/session_019Q7oc7ASjh8yxyS3Yz78We
Generated by Claude Code