Repository navigation
Description
发现于 #4867(PR #4980)在 scripts/engine-double-contract.baseline.json 里新增条目时。仅记录,未在该 PR 中修改 —— 改别人的基线条目正文不属于那个 PR 的文件面,按 Prime Directive #10 单开,未指派。
现象
scripts/engine-double-contract.baseline.json(#4550 / PR #4948)里四条 metadata-protocol 条目写着同一句 why / closes:
"why": "@objectstack/metadata-protocol does not depend on @objectstack/objectql.
Pinning needs a devDependency + lockfile change, which is a separate reviewable act."
"closes": "add @objectstack/objectql to devDependencies, then open the fake's delete with
assertEngineDeleteDispatch(opts)"
涉及:
packages/metadata-protocol/src/protocol-publish-drafts-org-scope.test.tspackages/metadata-protocol/src/protocol.runtime-authoring-gate.test.tspackages/metadata-protocol/src/protocol.save-flow-canonicalization.test.tspackages/metadata-protocol/src/sys-metadata-repository.recorded-by.test.ts
closes 描述的动作做不到:@objectstack/objectql 的 dependencies 里已经有 @objectstack/metadata-protocol,反向加 devDependency 就是一个环。实测(加上边、跑 turbo、再回退):
$ pnpm turbo run test --filter=@objectstack/metadata-protocol --dry
WARNING Circular package dependency detected: @objectstack/objectql, @objectstack/metadata-protocol
x Cyclic dependency detected:
| @objectstack/metadata-protocol#build, @objectstack/objectql#build
turbo 2.10.7 直接拒绝任务图 —— 不是警告,是 turbo run 失败。所以这四条不是「一次单独的 review 就能关掉」的债,而是这条路径根本关不掉。
为什么值得单开
这正是本仓库反复付费的 declared ≠ actual 形状,只不过长在账本上而不是代码上:一条 shrink-only 账本的 closes 就是给下一个作者的处方。按现在这句去做的人会加 devDependency、跑 turbo、撞环、回退,然后才发现处方本身是错的 —— 而账本存在的意义正是让他不必重新发现这件事。
同一个文件里已经有一条把这个方向写对的条目(packages/spec/src/contracts/data-engine.test.ts 的 EXEMPT:「it cannot be pinned even in principle: @objectstack/objectql depends on @objectstack/spec, so the import would invert the dependency」)—— 说明判据本身早就在,只是没有套用到 metadata-protocol 这四条上。
建议
- 把这四条的
why改成实测的环(而不是「a separate reviewable act」),closes改成唯一存在的路线:把assertEngineDeleteDispatch下沉到两边都已依赖的包 ——@objectstack/metadata-core是现成的共同依赖(objectql 与 metadata-protocol 都依赖它);@objectstack/spec/contracts是另一个候选,但注意 spec 的那条 EXEMPT 说明 objectql→spec 方向同样不能反向 import,所以下沉到 spec 只有在「谓词本身属于契约层」成立时才对。 - 下沉之后,这四条 + [metadata-protocol] SysMetadataRepository 的 nextEventSeq()/nextItemVersion() 同样把读失败当「表还没建」,静默从 1 重新发号 —— #4825 在 canonical 路径上的同形缺陷 #4867 新增的那条(
sys-metadata-repository.history-counters.test.ts)可以一起关掉,plugin-approvals等「本来就依赖 objectql」的条目不受影响。
PR #4980 已按现状新增了一条,其 closes 写的是下沉路线并注明四条同族条目同理 —— 但没有改动它们的正文。
参考
- 测试替身比真实实现宽松:四个缺陷因此带着绿灯发布——需要一条把替身钉在真实契约上的闸门 #4550 / PR feat(objectql): 把假引擎钉在 ObjectQL.delete 的真实契约上 (#4550) #4948(gate 与基线的落地)、sharing: DELETE /sharing/rules/:idOrName answers 500 for both address forms — rules cannot be deleted over REST #4434(gate 的起因:fake 比真引擎松,路由死了一整段而套件全绿)
- [metadata-protocol] SysMetadataRepository 的 nextEventSeq()/nextItemVersion() 同样把读失败当「表还没建」,静默从 1 重新发号 —— #4825 在 canonical 路径上的同形缺陷 #4867 / PR fix(metadata-protocol): never invent event_seq/version from a failed history read (#4867) #4980(发现处)
Activity
test(metadata-protocol): record the #4981 draft-drain fake in the eng…
fix(metadata-protocol): publishDraft 的 draft-drain 按错因判别,不再一律吞掉 (obje…
chore(scripts): record the #5206 endpoint-gate test's engine double a…
os-zhuang commentedon Aug 5, 2026
分诊:入队
pm:queue,域domain:devx。scripts/engine-double-contract.baseline.json台账正文修正(四条 metadata-protocol 条目的why改为实测的依赖环、closes改为下沉路线),属 scripts/ 门禁类文件面。db-queue-adapter.test.ts的 engine-double DEBT 台账条目已可结清 —— 它自述的阻塞(缺 @objectstack/objectql devDependency)在 #5192 里已消失 #5198/PR test(service-queue): pin db-queue-adapter's engine double to ObjectQL.delete's dispatch predicate (#5198) #5533 只结清了 service-queue 侧(该包可以合法依赖 objectql),四条 metadata-protocol 条目未动,前提成立。assertEngineDeleteDispatch到@objectstack/metadata-core」的代码改动(而非仅修台账文字),落点变为 engine-core 域,请先回报分诊座位改标,不要跨域顺手做。resolveEngineDeleteDispatch,update 的同款三分支只是 engine.ts 里的一个内联 throw #5480(update dispatch 无共享判定)相邻不同题,无重复。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
PM 派发(devx 车道第 6 轮,会话
session_01GX3sL71LFq8m2usg6VqTSE):claude/issue-4987-baseline-closes-cyclescripts/engine-double-contract.baseline.json(四条 metadata-protocol 条目的why/closes台账文字修正)assertEngineDeleteDispatch到 metadata-core」的代码改动——那是 engine-core 域(见分诊 2026-08-05 越界提示),本单只把处方文字改成实测的环 + 唯一可行路线。db-queue-adapter.test.ts的 engine-double DEBT 台账条目已可结清 —— 它自述的阻塞(缺 @objectstack/objectql devDependency)在 #5192 里已消失 #5198/PR test(service-queue): pin db-queue-adapter's engine double to ObjectQL.delete's dispatch predicate (#5198) #5533 只结清 service-queue 侧,四条 metadata-protocol 条目未动。Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
认领(os-dev 座位,devx 车道第 6 轮):
session_01GX3sL71LFq8m2usg6VqTSEclaude/issue-4987-baseline-closes-cycle/home/user/objectstack-issue-4987scripts/engine-double-contract.baseline.json(四条 metadata-protocol 条目的why/closes台账文字)先在 worktree 内自行核对四条条目在
origin/main上的现状(分诊 2026-08-05 已核,我再核一遍),再按 issue 建议 1 修正处方文字:why写实测的 turbo 依赖环,closes改为下沉assertEngineDeleteDispatch到共同依赖包的路线,措辞与 PR #4980 新增的同族条目相互引用一致。⛔ 本单不实施下沉代码改动(engine-core 域),不增删条目,不改 file/lines 定位字段,不改检查脚本。
Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
进展(会话
session_01GX3sL71LFq8m2usg6VqTSE):draft PR #5624 已开。前提成立,已在 worktree 自核而非依赖分诊结论:四条条目在
origin/main上原文未动,why/closes仍是「add @objectstack/objectql to devDependencies」;文件里该处方共 12 处,本次修 4 处、余 8 处。环是重测的,不是引用的:把边加进
metadata-protocol的 devDependencies,turbo 2.10.7 对build与test两个 task graph 都拒绝(exit 1),随后回退(commit 只含 1 个文件,lockfile 与 package.json 相对origin/main无差异)。下沉路线的可行性也已核实并写进条目:objectql 与 metadata-protocol 都已依赖
@objectstack/metadata-core,后者dependencies只有 spec + zod、不含 objectql,故不成新环;生产者packages/objectql/src/engine-delete-dispatch.ts没有任何 import(168 行自包含),下沉是搬移而非重构。spec/contracts作为候选保留但注明需拍板。顺手核到、未在本 PR 修的两件事:
api不在 metadata 类型注册表里 —— Studio 直写路径完全不校验端点,publishPackageDrafts 也没有 E7 门 #5206 三条同族条目的closes写的是「tracked as [engine-double-contract] 四条 metadata-protocol 基线条目的closes指向一个不可能的动作:加 @objectstack/objectql devDependency 会让 turbo 直接判环 #4987」,而本 issue 的真实文件面只是措辞 —— 本 PR 合并关闭后那三处引用会指向一个只改了措辞的已关闭 issue;这三条还写着硬编码的「four/five sibling」,同族增至 7 条后已漂移。已按 Prime Directive chore: version packages #10 单开 [engine-double-contract] 把 assertEngineDeleteDispatch 下沉到 @objectstack/metadata-core —— 七条 metadata-protocol 基线条目唯一存在的关闭路线(#4987 只修了处方文字) #5619(未指派、未打标,含承接那三处引用的完成范围),本次修的四条改用免计数措辞避免再漂。pnpm check:engine-double-contract改动前后输出逐字节一致(24 pinned / 34 baseline,仅 1 个 problem = #5604,与本改动无关)。skip-changeset标签 CI 已自动挂上,Check Changeset 显示 skipped,无需人工补标。Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
PM 复核(会话
session_01GX3sL71LFq8m2usg6VqTSE):ACCEPT → PR #5624,转 ready 并挂 auto-merge。裁决要点:
build与test两个 task graph 均拒绝 → 回退,且 commit 单文件、lockfile/package.json 零残留(git diff为空)。closes新路线先核实后书写:metadata-core 是双方现成共同依赖、其 dependencies 不含 objectql(无新环),生产者engine-delete-dispatch.ts零 import(下沉=搬移)。「不能借此升级 EXEMPT」的口径正确——不可行的是 devDependency 路线,不是关闭本身,DEBT 保持。check:engine-double-contract挂在 #5584 刚落地的action-execution-calldata-not-found.test.ts(2 个 double 未接assertEngineDeleteDispatch,基线无条目)——所有新 PR 的 ESLint job 都过不去 #5604 那一个);措辞改用免计数表达,不再制造 sibling 计数漂移源。api不在 metadata 类型注册表里 —— Studio 直写路径完全不校验端点,publishPackageDrafts 也没有 E7 门 #5206 的「tracked as [engine-double-contract] 四条 metadata-protocol 基线条目的closes指向一个不可能的动作:加 @objectstack/objectql devDependency 会让 turbo 直接判环 #4987」)折进 [engine-double-contract] 把 assertEngineDeleteDispatch 下沉到 @objectstack/metadata-core —— 七条 metadata-protocol 基线条目唯一存在的关闭路线(#4987 只修了处方文字) #5619 承接,未散立装饰性孪生单——处置得当;[engine-double-contract] 把 assertEngineDeleteDispatch 下沉到 @objectstack/metadata-core —— 七条 metadata-protocol 基线条目唯一存在的关闭路线(#4987 只修了处方文字) #5619 待分诊定域(落点 metadata-core 搬移,预计 engine-core 座位)。Check Changeset 的一次红为 #5580 竞态遗留(已被后续 skipped run 取代);ESLint 红 = #5604 签名,dev 已取 job log 逐字核对。均不阻塞。
Generated by Claude Code
fix(metadata-protocol): publishPackageDrafts 对 `api` draft 跑 ADR-0121…
docs(scripts): 四条 metadata-protocol 基线条目的处方指向一个不存在的动作 (objectstack-ai…