⏹ Blocked-by: #17534 — RELEASED 2026-09-21T00:18Z. ⭐ The line named the card; the condition the hold actually rested on was the PR. The ruling's Execution clause reads 「Serial behind PR #18319 (holds packages/spec/src/kernel/manifest.zod.ts)」, and PR #18319 merged 2026-09-21T00:08:02Z as 097d2685 on origin/main (read twice). Card #17534 is still open and still pm:dispatched — that is a half-state on its card, ⛔ not a live block on this one. ⛔ Leaving the line pointing at an open card would recreate the exact body-vs-state contradiction this card was parked to fix.
@objectstack/spec carries four different grammars for "the version of a package", and the
strictest of them refuses a string that its own sibling advertises as an example.
All four measured on bdea10a185d422ef1f9022e210b87d19882055ee (the commit objectstack-ai/cloud
pins today) via the contents API, 2026-09-17T15:29Z:
| carrier |
regex |
prerelease |
case |
ManifestSchema.version — packages/spec/src/kernel/manifest.zod.ts:322 |
^\d+\.\d+\.\d+$ |
none at all |
— |
PluginSchema.version — packages/spec/src/kernel/plugin.zod.ts:212 |
^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ |
yes |
upper and lower |
PackageVersionSchema.version — packages/spec/src/marketplace/package-version.zod.ts:144-146 |
^\d+\.\d+\.\d+(-[a-z0-9.-]+)?(\+[a-z0-9.-]+)?$ |
yes |
lower only |
PackageManifestSchema.version — same file, :80 |
no regex — bare z.string() |
unconstrained |
unconstrained |
The declared-contract violation, quoted
PackageVersionSchema.version's own JSDoc, verbatim at that commit:
/** Semantic version string (e.g. 1.2.3, 2.0.0-beta.1). */
ManifestSchema.version's regex is ^\d+\.\d+\.\d+$ ⇒ it refuses 2.0.0-beta.1, the very
string the sibling schema documents as an example of the same concept. That is class (b): a declared
contract contradicted by an enforced one, with the contract text quoted above.
⚠️ PackageManifestSchema.version at :80 is the one nobody has named yet — it is a bare
z.string(), so it constrains nothing at all. A downstream that trusts "spec validated it" gets
no validation from this carrier.
Honest limit on severity — ⛔ do not grade this from the table alone
What is measured here is the schema disagreement. What is NOT measured is whether any live path
judges a real bundle's manifest.version with ManifestSchema — if none does, this is a latent
trap rather than a today-defect, and the grading should say so. Whoever triages this should answer
that question first; it decides the class as much as the table does.
Where this came from
Found while implementing objectstack-ai/cloud#2305 (PR objectstack-ai/cloud#2320), which had to
pick one of these grammars for the cloud package-publish route. It picked
PackageVersionSchema.version deliberately, because that accept set is a strict SUBSET of
PluginSchema.version — the one the runtime plugin loader parses with — so nothing that gets past
the publish gate can fail the runtime parse. That choice is sound whatever happens to this card;
⛔ this card is not a blocker for it.
One consequence worth stating for whoever fixes this: cloud's publish route now refuses a
semver-valid prerelease with an uppercase identifier (1.0.0-Beta.1) that the runtime loader
would have accepted. That is a deliberate, safe-direction narrowing today; if this card converges
the grammars, that fringe disappears with it.
查重词
semver grammar divergence spec · ManifestSchema.version regex · PackageVersionSchema.version ·
PluginSchema version prerelease case · package version schema four spellings
os-decision-facets
- ① 项目长远合理性:A 让被强制的语法等于仓里已公开宣称的那句话,缩小特例与契约增生(10 载体 → 3 声明);B/C 把假声明搬到另一个载体上,增生不减。
- ② 实际业务拉动:有实测 —— git tag 483/7611 与
packages/spec/CHANGELOG.md 版本标题 8/170 是预发布,而描述包的那个键表达不出预发布;反向零拉动 —— 退化形态(01.1.1 / 1.0.0-0123 / 1.0.0-alpha..1 / 1.0.0+.)在 examples/** 与 packages/apps/** 里零生产者(亮控:同模式全树 43)。
- ③ 防 AI 犯错:A 是唯一让「AI 的直觉」与「被强制的语法」一致的选项;B 永不拒绝作者,代价是把
1.0.0-alpha..1 这类无法排序的串永久册封进已发布面 —— 静默容忍胜过响亮拒绝的反面。
- ④ 创业阶段不扩散:第一阶段(10 → 3 个被引用声明)即本轴一步;本轮新发现的三个「已发布但无人解析」载体证明,语法写成字面量时载体数会自己长。
Prior rulings read: version grammar,semver,manifest.version,prerelease → 1 hits; ADR-0087 D1
⚠️ 那条 ADR 读过了,它不答本卡:ADR-0087 D1 是协议握手(PROTOCOL_VERSION、engines.protocol 的检查与结构化拒绝),命中只是 :106 上的 semver 一词;它⛔ 没有裁定包清单 version 键在十个载体上的文法。⇒ 本卡仍是决策卡,⛔ 不是执行卡。(判据出自 check-prior-rulings.mjs 的警告「Read the decision before presenting the card」—— 本席读了。)
推荐:A(SemVer 2.0.0)。自检:只看①选 A;②③④ 是否翻转:② 不翻(两侧都支持 A:有预发布拉动、退化形态零拉动)· ③ 不翻(A 是唯一直觉=强制的选项)· ④ 不翻(第一阶段本身就是不扩散)。⇒ 四棱同向 A。
置信缺口:objectstack-ai/cloud 未挂载 ⇒ 它的 publish 路由接受集在 A/B/C 下都会动而本轮无法读;且四套文法的判读取自正则字面量而非运行期 Zod 判决(刻意不建构,避开陈旧 dist)。
Generated by Claude Code
⏹
Blocked-by: #17534— RELEASED 2026-09-21T00:18Z. ⭐ The line named the card; the condition the hold actually rested on was the PR. The ruling's Execution clause reads 「Serial behind PR #18319 (holdspackages/spec/src/kernel/manifest.zod.ts)」, and PR #18319 merged 2026-09-21T00:08:02Z as097d2685onorigin/main(read twice). Card #17534 is still open and stillpm:dispatched— that is a half-state on its card, ⛔ not a live block on this one. ⛔ Leaving the line pointing at an open card would recreate the exact body-vs-state contradiction this card was parked to fix.@objectstack/speccarries four different grammars for "the version of a package", and thestrictest of them refuses a string that its own sibling advertises as an example.
All four measured on
bdea10a185d422ef1f9022e210b87d19882055ee(the commitobjectstack-ai/cloudpins today) via the contents API, 2026-09-17T15:29Z:
ManifestSchema.version—packages/spec/src/kernel/manifest.zod.ts:322^\d+\.\d+\.\d+$PluginSchema.version—packages/spec/src/kernel/plugin.zod.ts:212^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$PackageVersionSchema.version—packages/spec/src/marketplace/package-version.zod.ts:144-146^\d+\.\d+\.\d+(-[a-z0-9.-]+)?(\+[a-z0-9.-]+)?$PackageManifestSchema.version— same file,:80z.string()The declared-contract violation, quoted
PackageVersionSchema.version's own JSDoc, verbatim at that commit:ManifestSchema.version's regex is^\d+\.\d+\.\d+$⇒ it refuses2.0.0-beta.1, the verystring the sibling schema documents as an example of the same concept. That is class (b): a declared
contract contradicted by an enforced one, with the contract text quoted above.
PackageManifestSchema.versionat:80is the one nobody has named yet — it is a barez.string(), so it constrains nothing at all. A downstream that trusts "spec validated it" getsno validation from this carrier.
Honest limit on severity — ⛔ do not grade this from the table alone
What is measured here is the schema disagreement. What is NOT measured is whether any live path
judges a real bundle's
manifest.versionwithManifestSchema— if none does, this is a latenttrap rather than a today-defect, and the grading should say so. Whoever triages this should answer
that question first; it decides the class as much as the table does.
Where this came from
Found while implementing
objectstack-ai/cloud#2305(PRobjectstack-ai/cloud#2320), which had topick one of these grammars for the cloud package-publish route. It picked
PackageVersionSchema.versiondeliberately, because that accept set is a strict SUBSET ofPluginSchema.version— the one the runtime plugin loader parses with — so nothing that gets pastthe publish gate can fail the runtime parse. That choice is sound whatever happens to this card;
⛔ this card is not a blocker for it.
One consequence worth stating for whoever fixes this: cloud's publish route now refuses a
semver-valid prerelease with an uppercase identifier (
1.0.0-Beta.1) that the runtime loaderwould have accepted. That is a deliberate, safe-direction narrowing today; if this card converges
the grammars, that fringe disappears with it.
查重词
semver grammar divergence spec·ManifestSchema.version regex·PackageVersionSchema.version·PluginSchema version prerelease case·package version schema four spellingsos-decision-facets
packages/spec/CHANGELOG.md版本标题 8/170 是预发布,而描述包的那个键表达不出预发布;反向零拉动 —— 退化形态(01.1.1/1.0.0-0123/1.0.0-alpha..1/1.0.0+.)在examples/**与packages/apps/**里零生产者(亮控:同模式全树 43)。1.0.0-alpha..1这类无法排序的串永久册封进已发布面 —— 静默容忍胜过响亮拒绝的反面。Prior rulings read: version grammar,semver,manifest.version,prerelease → 1 hits; ADR-0087 D1
PROTOCOL_VERSION、engines.protocol的检查与结构化拒绝),命中只是:106上的semver一词;它⛔ 没有裁定包清单version键在十个载体上的文法。⇒ 本卡仍是决策卡,⛔ 不是执行卡。(判据出自check-prior-rulings.mjs的警告「Read the decision before presenting the card」—— 本席读了。)推荐:A(SemVer 2.0.0)。自检:只看①选 A;②③④ 是否翻转:② 不翻(两侧都支持 A:有预发布拉动、退化形态零拉动)· ③ 不翻(A 是唯一直觉=强制的选项)· ④ 不翻(第一阶段本身就是不扩散)。⇒ 四棱同向 A。
置信缺口:
objectstack-ai/cloud未挂载 ⇒ 它的 publish 路由接受集在 A/B/C 下都会动而本轮无法读;且四套文法的判读取自正则字面量而非运行期 Zod 判决(刻意不建构,避开陈旧dist)。Generated by Claude Code