Skip to content

fix(metadata-protocol): 保存的 overlay 立即可派发 —— 写路径直写 SchemaRegistry(#4521) - #4622

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-4521-meta-overlay-cache-window
Aug 2, 2026
Merged

fix(metadata-protocol): 保存的 overlay 立即可派发 —— 写路径直写 SchemaRegistry(#4521)#4622
os-zhuang merged 1 commit into
mainfrom
claude/issue-4521-meta-overlay-cache-window

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #4521

问题

#4432 F1 验证发现:PUT /api/v1/meta/action/{name} 成功后的一小段窗口内,GET /api/v1/meta/action 已经能列出该 overlay,但 POST /api/v1/actions/{object}/{name} 却返回 ADR-0110 的 "has no declaration" 404,稍后再调用又成功。期间没有任何东西过期——是那次列表读取修好了派发路径。

根因

滞后的"缓存"就是引擎的 SchemaRegistry。运行时派发路径(resolveRouteActionDeclaration)把 registry 当作元数据的实时视图来读(来源 2),但 saveMetaItem 只对 object 类型做写后同步(applyObjectRegistryMutation 对其它类型直接返回);其余 overlay 类型进入 registry 的唯一途径是 getMetaItems 的读侧水合。于是"这个类型有没有人列过"悄悄决定了刚保存的 action 能不能被调用——写后读一致性取决于读取顺序。

修复(生产者侧,符合 Prime Directive #12)

没有在派发点加任何重试、休眠或容错回退,而是让写入本身把 registry 写透:

  • 新增 applyRegistryWriteThrough,在三个"写入已生效"的时点调用:saveMetaItem(仅 mode === 'publish')、runPublishSideEffects(草稿晋升发布)、rollbackMetaItem(回滚后的正文即为线上正文)。对所有 overlay 类型生效,object 分支行为不变。
  • 把读侧水合规则抽取为共享的 hydrateOverlayIntoRegistry(含 ADR-0010 §3.3 保护信封嫁接、ADR-0048 按行所属包做 artifact 查找),getMetaItems 与写透共用一份实现——读和写不可能再把 registry 留在两种不同状态。
  • 写透与读侧携带相同的 environmentId === undefined 门:环境作用域的行不会泄漏进控制面共享的 registry。写不会比读更宽松。
  • 写透是 best-effort(与原 object 分支一致):行已持久化,registry 打嗝只会退化为修复前的行为(下次列表水合),绝不会丢写。

边界(测试钉住)

  • 草稿保存仍然进入实时 registry(暂存区语义不变);
  • 从未声明过的名字仍然解析为空——ADR-0110 的 404 原样保留;
  • DELETE("恢复 artifact 默认值")仍能还原打包 artifact:overlay 是明键 shadow,不是就地覆盖(这正是旧测试 "saveMetaItem 不得改 registry" 曾守护的风险,现已由 restoreArtifactRegistryView 结构性保证,该测试已反转并注明缘由)。

测试

  • 新增 packages/runtime/src/meta-overlay-read-your-writes.test.ts(7 例):用真实的 ObjectStackProtocolImplementation.saveMetaItem + 真实 SchemaRegistry + 真实 resolveRouteActionDeclaration 复现 PUT→POST 原始场景(中间无任何列表调用),并钉住上述三条边界;去掉写透即失败。
  • 反转 packages/objectql/src/protocol-meta.test.ts 中的旧断言并注明历史缘由。
  • pnpm --filter @objectstack/metadata-protocol test:25 文件 206 例通过;--filter @objectstack/objectql test:98 文件 1596 例通过;--filter @objectstack/runtime test:77 文件 1063 例通过。
  • @objectstack/objectql typecheck 通过;check:type-check-coverage 棘轮 OK(metadata-protocol / runtime 在 DEBT 账本内,未新增超额)。

备注

🤖 Generated with Claude Code

https://claude.ai/code/session_012C2cd7tL8QDoZ2QKN3djJ5


Generated by Claude Code

…ry so they are dispatchable immediately (#4521)

A just-saved overlay was listed but not dispatchable for a short window:
saveMetaItem only wrote the registry through for `object`, so every other
overlay type reached it solely via the READ-side hydration in getMetaItems —
the listing call is what repaired the dispatch path. resolveRouteActionDeclaration
reads the registry, so `PUT /meta/action/x` followed by `POST /actions/<obj>/x`
answered the ADR-0110 "has no declaration" 404 until someone listed the type.

- Extract the read-side hydration rule (ADR-0010 §3.3 protection graft,
  ADR-0048 package-scoped artifact lookup) into hydrateOverlayIntoRegistry and
  share it between getMetaItems and the new applyRegistryWriteThrough.
- Call the write-through from saveMetaItem (publish mode), runPublishSideEffects
  (draft promotion), and rollbackMetaItem — for EVERY overlay type, with the
  same environmentId scoping gate the read carries.
- Boundaries pinned by tests: drafts never leak into the live registry,
  ADR-0110's 404 for a genuinely absent declaration stands, and DELETE still
  restores the packaged artifact (the overlay is a plain-key shadow).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012C2cd7tL8QDoZ2QKN3djJ5
@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 2, 2026 11:46am

Request Review

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/metadata-protocol.

3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/metadata-protocol)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/metadata-protocol)
  • content/docs/releases/v9.mdx (via @objectstack/metadata-protocol)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review August 2, 2026 11:47
@os-zhuang
os-zhuang enabled auto-merge August 2, 2026 11:47
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 2, 2026
Merged via the queue into main with commit 6beb708 Aug 2, 2026
21 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-4521-meta-overlay-cache-window branch August 2, 2026 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants