发现于 #5186(为「读接缝把故障答成空值」这一族新增闸门)实施期,由新规则在 packages/metadata-protocol 扫出;不在该单文件面内(#5186 是纯 scripts/ 闸门单,不改被扫包),故单独立卡并已作为 baseline 条目记录在 scripts/durability-read-invention.baseline.json。
现象
packages/metadata-protocol/src/protocol.ts 的 listCommits()(约 9720–9745 行,以 origin/main 为准):
/**
* List the commit timeline for a package, newest-first (ADR-0067). Returns
* [] if the commit store is unavailable. ←← JSDoc 自己就这么写
*/
async listCommits(request): Promise< …[] > {
try {
const rows = (await this.engine.find('sys_metadata_commit', { where, … })) as any[];
// … 映射 + 按 createdAt 倒序 …
return mapped;
} catch {
return [];
}
}
catch 里:没有任何日志、没有 rethrow、没有按错误类型区分。
为什么这是缺陷而不是设计
这是 ADR-0110 D3(miss 与 outage 是两个意义相反的事实,消费方不得把其中一个读成另一个)在 ADR-0067 提交时间线上的违反,与 #5108 在 DatabaseLoader 修的、#5532 在同一个文件的 getMetaItems 修的是同一形状:
- 存储读不到 → 调用方看到「这个 package 没有任何提交历史」;
- 「没有提交历史」与「有 12 次提交但库连不上」在返回值上完全一致;
- 一行日志都没有,整条链路上没有任何地方说过这次读失败了。
后果面朝向 revert:提交时间线是 revertCommit 的选择面。历史被答成空的那一刻,UI 上「无可回滚项」,而实际上有——一次故障期间的运维判断会因此做反。
同一个文件几千行之上已经有了正确形状的处方:rethrowUnlessMetadataStoreUnprovisioned()(#5532 引入),它问 isMissingTableError,良性放行、其余包成 503 上抛。listCommits 只是没走它。
修法
} catch (error) {
this.rethrowUnlessMetadataStoreUnprovisioned(error); // 良性(表未建)放行
return []; // 首启确实没有提交
}
isMissingTableError 与该 guard 在本文件里都已经在用,无新依赖。
验收
sys_metadata_commit 未 provision(首启)→ 仍返回 [],不抛、不噪;
- 驱动报连接错误 / 超时 / 权限失败 → 上抛(503 信封),调用方能把 outage 与 miss 分开;
- 更新 JSDoc:删掉「Returns [] if the commit store is unavailable」这句(它现在描述的是缺陷);
- 修好后删除
scripts/durability-read-invention.baseline.json 里的 packages/metadata-protocol/src/protocol.ts::listCommits 条目(shrink-only,条目失效即红)。
关联
#5186(新增本族闸门,本卡由它扫出)、#5532(同文件、同处方,getMetaItems)、#5108(同族,DatabaseLoader 五处读)、#5841(同文件另一处,退休手抄的 /no such table/i)、#4825 / #4728(同族)、ADR-0110 D3、ADR-0067、AGENTS.md「Absence must be loud」。
发现于 #5186(为「读接缝把故障答成空值」这一族新增闸门)实施期,由新规则在
packages/metadata-protocol扫出;不在该单文件面内(#5186 是纯scripts/闸门单,不改被扫包),故单独立卡并已作为 baseline 条目记录在scripts/durability-read-invention.baseline.json。现象
packages/metadata-protocol/src/protocol.ts的listCommits()(约 9720–9745 行,以 origin/main 为准):catch里:没有任何日志、没有 rethrow、没有按错误类型区分。为什么这是缺陷而不是设计
这是 ADR-0110 D3(miss 与 outage 是两个意义相反的事实,消费方不得把其中一个读成另一个)在 ADR-0067 提交时间线上的违反,与 #5108 在
DatabaseLoader修的、#5532 在同一个文件的getMetaItems修的是同一形状:后果面朝向 revert:提交时间线是
revertCommit的选择面。历史被答成空的那一刻,UI 上「无可回滚项」,而实际上有——一次故障期间的运维判断会因此做反。同一个文件几千行之上已经有了正确形状的处方:
rethrowUnlessMetadataStoreUnprovisioned()(#5532 引入),它问isMissingTableError,良性放行、其余包成 503 上抛。listCommits只是没走它。修法
isMissingTableError与该 guard 在本文件里都已经在用,无新依赖。验收
sys_metadata_commit未 provision(首启)→ 仍返回[],不抛、不噪;scripts/durability-read-invention.baseline.json里的packages/metadata-protocol/src/protocol.ts::listCommits条目(shrink-only,条目失效即红)。关联
#5186(新增本族闸门,本卡由它扫出)、#5532(同文件、同处方,
getMetaItems)、#5108(同族,DatabaseLoader五处读)、#5841(同文件另一处,退休手抄的/no such table/i)、#4825 / #4728(同族)、ADR-0110 D3、ADR-0067、AGENTS.md「Absence must be loud」。