Repository navigation
getMetaItemLayered 的 overlay 读用裸 catch:sys_metadata 读失败时三层视图把「读不到」画成「没有 overlay」 #5707
Description
Activity
发现分诊(finding 轮):持有,补域
domain:engine-core(落点同packages/metadata-protocol/src/protocol.ts)。- 持有理由:后果是展示失真(Studio 三层 diff 把「定制读不到」画成「没有定制」),无安全/数据后果;且修向存在真分叉 —— 503 化(复用 PR fix(metadata-protocol): 元数据存储读不到不再被讲成「这一项不存在」 (#5532) #5705 的 helper)vs 给诊断形状加
overlay「读失败」第三态。后者动返回形状需维护者拍板,正文自己也要求先测量消费方渲染再选,现在入队会让 dev 在未测量时被迫选边。 - 重启条件:PR fix(metadata-protocol): 元数据存储读不到不再被讲成「这一项不存在」 (#5532) #5705(getMetaItem 的 overlay 读用裸 catch 把「sys_metadata 不可达」吞成「该项不存在」—— GET /meta/:type/:name 在存储故障时回一个无 code 的 400「not found」 #5532)落地后复判 —— 届时 helper 可复用、同文件串行序已排开;复判时先做正文点名的消费方测量,若结论指向第三态形状,转决策箱而非直接入队;若 503 化无面板全空白副作用,与 getEffectiveLock 的 overlay 读用裸 catch,sys_metadata 读失败时保护闸门 fail-open(_lock 落成 'none',写/删被放行) #5706 的派发协调后入队。
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- 持有理由:后果是展示失真(Studio 三层 diff 把「定制读不到」画成「没有定制」),无安全/数据后果;且修向存在真分叉 —— 503 化(复用 PR fix(metadata-protocol): 元数据存储读不到不再被讲成「这一项不存在」 (#5532) #5705 的 helper)vs 给诊断形状加
发现分诊(#4949 纪律):重启条件已触发,晋级 —— 摘
finding换pm:queue,domain:engine-core已在(落点packages/metadata-protocol)。依据:重启条件 = PR #5705(#5532)落地,已于 2026-08-06 02:18Z 合入。该 PR 的「范围外发现」段明确点名本单(
getMetaItemLayeredoverlay 裸 catch),且新 helperrethrowUnlessMetadataStoreUnprovisioned已在同文件可复用。认领方第一步是前次持有评论要求的测量:layered 视图故障时的展示失真面(谁消费三层视图、故障被画成「没有 overlay」的可见后果),测完再在「复用 helper 上报 503」与其他修向间取舍 —— 测量结论写进 PR 正文。⚠️ 同文件串行:#5706(getEffectiveLockfail-open,restore-invariant 向,其Blocked-by: #5532已随 PR #5705 合入而解除,待车道 sweep 回队)与本单同落protocol.ts,engine-core 车道派发时二者跨轮串行,建议 #5706(安全闸门)先行。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
认领:PM 循环第 1 轮(engine-core 车道,2026-08-06 接管后首轮)
会话:session_019Q7oc7ASjh8yxyS3Yz78We
分支:claude/issue-5707-layered-overlay-outage
Worktree:objectstack-issue-5707
域:domain:engine-core
文件面:packages/metadata-protocol/src/protocol.ts(getMetaItemLayered 的 overlay catch 一处)+packages/metadata-protocol测试(优先并入 #5705 同族 outage 覆盖)+.changeset/*.md(越界即停,报告说明)派发要点:按分诊晋级评论执行 —— 第一步先测量三层视图消费面;修法预裁复用
rethrowUnlessMetadataStoreUnprovisioned走 503,前提「503 不致消费面板整体空白」,前提不成立即报 needs_decision,不自行选第三态形状。同文件前序 #5706/#5532/#5264 均已合并,串行已排开。
Generated by Claude Code
复核通过,ACCEPT(engine-core 车道 PM,第 1 轮):交付于 PR #5843,CI 23 项全绿,转 ready 入合并队列。
验收要点:
- 预裁前提被测量反向坐实:担心的是「503 会不会更糟」,实测是「静默 null 本来就更糟」—— plugin-security 的
projectPermissionMutation(唯一无 try/catch 的消费点)在故障期会把权限集 UPDATE 回打包基线(customized:false被抹),无 declared body 时甚至 DELETE 行 + 注销 evaluator;503 化后零写入,且被runMutationProjector的 never-throws 契约收敛(mutation-listeners.test.ts pin 在案)。一次读故障引发破坏性写,这比 issue 自评的「展示失真」严重得多。 - PM 预扫「objectui 无直接消费」被 dev 更正:
MetadataClient.layered()有 10 个调用点,均已有错误通道,503 不引入新形态 —— 好运行的标志,更正已见 PR 正文。 - 测试并入 fix(metadata-protocol): 元数据存储读不到不再被讲成「这一项不存在」 (#5532) #5705 同族 outage 覆盖(共享
expectStoreUnavailable),6 新例含「org 读失败不再吞可读的 env 行」;反向验证方向先写后跑,3 红/3 绿吻合。 - 越界发现 MetadataManager.get() 丢弃 loadDiagnosed 的 degraded 判定:loader 读不到与「这一项没声明」在 6 个消费点上不可分辨 #5840(get() 丢 degraded 判定,修在 catch 上修不掉,单开正确)/ loadMetaFromDb 用 /no such table/i 正则判「良性首启」,其余 sys_metadata 读失败吞成 console.warn + loaded:0 —— isMissingTableError 的手抄第二份 #5841(isMissingTableError 手抄第二份)已立单并被分诊扫入队列。
- 必答项定价:保存成功的回执一律自称 "customization overlay",包括注册表声明 supportsOverlay:false 的类型(object / flow / action / seed / hook) #5265/meta overlays: a deleted overlay stays in the /meta listing though dispatch correctly 404s (#4432 residual) #5079/loadMetaFromDb object branch reads
record.packageIdfrom a snake_case row — always undefined, every object overlay registers under the 'sys_metadata' sentinel at boot #4636 均不受影响,原价保留。
Generated by Claude Code
- 预裁前提被测量反向坐实:担心的是「503 会不会更糟」,实测是「静默 null 本来就更糟」—— plugin-security 的
- added a commit that references this issue
on Oct 7, 2026
做 #5532(getMetaItem overlay 读把 outage 吞成 miss)时,在同一个文件里发现的第三处同族点。不在那单范围内(#5532 / PR #5705 的文件面限定为
getMetaItems/getMetaItem的四处 overlay 读 +getMetaItemCached终末错误),按 Prime Directive #10 单独记在这里,unassigned。标
finding:这条今天不会让用户拿到错误的判定,只会让 Studio 的三层对比视图少画一层 —— 属于展示失真而非安全或数据后果。分级请以 PM 的分诊为准,我不自评严重度。位置
packages/metadata-protocol/src/protocol.ts,getMetaItemLayered(以内容定位:注释// ── overlay layer: sys_metadata row (org-scoped wins, then env-wide) ──之后的try):现象
getMetaItemLayered是 Phase 3a 的分层读:分别返回code(artifact 基线)、overlay(per-org / env 的 sys_metadata 行)与effective。sys_metadata读失败时overlay保持null,于是:overlay报告为「这一项没有任何定制」——实际是「定制读不到」;overlayScope保持null;effective退化成code,即把 artifact 基线当成生效值呈现。Studio 的「code / overlay / effective」对比正是给作者看「我改过什么」的。故障期它会告诉作者「你什么都没改过,当前生效的就是打包件原样」——和 #5532 同一个错误结论(可用性故障被讲成「你没声明」),只是落在 diff 视图而不是 404 上。
与 #5532 的区别
#5532(PR #5705)修的是
getMetaItems/getMetaItem的四处 overlay 读;getMetaItemLayered是另一个方法、另一条读,PR #5705 刻意没有扩到它(scope = the issue)。ADR-0110 D3 的规矩相同。建议修法(与 PR #5705 对齐,不代裁决)
PR #5705 已在同文件引入
rethrowUnlessMetadataStoreUnprovisioned:isMissingTableError(表还没建 → 确实没有 overlay 行 →null是真相)良性放行,其余抛status: 503/code: SERVICE_UNAVAILABLE,驱动错误挂cause。这里复用同一个私有方法即可,一处 catch。另一种可能更贴合这个方法契约的方向:分层读返回的是诊断形状,所以也可以给
overlay增加一个「未知 / 读失败」的第三态,而不是让整个请求 503 —— 但那是新的返回形状,需要维护者拍板,别在实现时自行选。未验证:调用方(Studio 的哪个面板、有没有别的消费者)对
overlay: null的具体渲染,以及 503 化会不会让某个面板整体空白。开工时应先测量再决定上面两条哪一条。关联
#5532 / PR #5705(同文件同家族)、#5706(
getEffectiveLock的 fail-open,同家族的写侧)、ADR-0110 D3、#5108。Generated by Claude Code