Skip to content

[裁决] duplicatePackagefailed[] 是否应在 spec 声明结构化 issues 通道 —— 它今天在 spec 里没有任何响应 schema #11017

Description

@os-elon

#10888 分出,由 PM engine 席上报。这是 packages/spec 契约变更,需要维护者裁决;在裁定前 #10888 无法派发,本席不会在它上面建任何东西。

已测量的事实(#10886 的 face 清点产出,我按内容独立核过)

#10888 要 trim saveMetaItem 的 spec-validation 422 消息(它把结构化 issues[] 的内容又用散文复述了一遍)。trim 的前置条件是 declare-then-trim:先确认每个引用这条消息的 face 都有结构化通道,再删散文。

duplicatePackagefailed[].error 是唯一载体

  • 它在 200 上作为响应数据返回,不是错误包络;
  • 数组是内联类型 {type, name, error}没有 issues
  • duplicatePackagepackages/spec/src/api/protocol.zod.ts 里出现 0 次 —— 它根本没有响应 schema

所以在它上面声明结构化通道,是比 #10895publishPackageDrafts 做的那次严格更大的工程:那次是给一个已声明的响应加字段,这次要从零建立一个门的响应契约。

⚠️ 顺带纠正一条容易被沿用的旧判断:#10895 的标题是「declare failed[].issues + seedApplied.issues」,看起来像是已经解决了这个封锁——没有,它声明的是 publishPackageDraftsfailed[],是另一个 face。

⭐ 一条会改变「声明什么」的发现:#11015

?force=true 这句补救措施被逐字引到 duplicatePackagefailed[].error 上,POST /packages/:id/duplicate 在 query 和 body 里都不接受 forceduplicatePackage 的请求类型里也没有这个字段。

也就是说:在这条消息唯一承载的那个 face 上,它承载的补救是不可执行的。 让这条消息「承重」的那个属性,恰恰在那里是坏的——这直接削弱了「不能 trim,因为消息在承重」这个论证里最强的一段。

⚠️ 所以本裁决不应只问「要不要声明」,还应先问「那个 face 上到底该说什么」。

选项

A. 给 duplicatePackage 建响应 schema,并在 failed[] 上声明 issues 之后 #10888 的 trim 可以照 declare-then-trim 正常做。代价:新建一个门的响应契约,是本轮最大的一块 spec 面;收益是这个门从「无契约」变成「有契约」,而它今天在 200 上返回的失败数据是完全未声明的。

B. 先修 #11015,再重新评估。 既然那个 face 上的补救不可执行,也许正确的动作不是「声明结构化通道以便删散文」,而是先让那句话变成真的(给端点加 force,或把这句从该 face 拿掉)。修完之后 #10888 的载体分析要重做——可能结论就变了。

C. 维持现状。 #10888 长期停在 pm:queue,422 的散文重复保留。代价是重复真实存在且修法已知,只卡在声明上;好处是零 spec 面变更。

本席建议

B 先于 A。 理由是证据顺序而非偏好:A 的全部动机是「这条消息在那个 face 上承重、所以要先给它一个结构化替身」,而 #11015 表明它在那里承载的东西本身是错的。先按一个可能不该保留的内容去设计契约,是把错误固化进 spec。B 的成本远小于 A(一个端点的入参或一句话),做完之后 A 到底还要不要做、要声明什么,都会更清楚。

⛔ C 只值得写出来以便否掉:重复是真的,修法是已知的,卡的只是声明。

相关

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions