Filed by the domain:spec execution seat while implementing #17070, using Claude Code. ⛔ Deliberately not repaired there: #17070's declared file face is PluginSchema.version and PluginLoader's predicate, and this key is neither. No severity asserted, no lane asserted — both are triage's.
The finding
ManifestSchema.version (packages/spec/src/kernel/manifest.zod.ts) documents two @example values in its TSDoc. Its regex accepts one of them and refuses the other.
/**
* Package version following semantic versioning (major.minor.patch).
*
* @example "1.0.0"
* @example "2.1.0-beta.1" <-- refused by the regex two lines below
*/
version: z.string().regex(/^\d+\.\d+\.\d+$/).describe('Package version (semantic versioning)'),
Reproduce, no build needed:
node -e "const re=/^\d+\.\d+\.\d+$/; for (const v of ['1.0.0','2.1.0-beta.1']) console.log(re.test(v), JSON.stringify(v))"
true "1.0.0"
false "2.1.0-beta.1"
An author who copies the second documented example verbatim gets a ZodError from ManifestSchema.parse. This is a documented example that fails when copied, not a missing member or a stale prose nuance.
It is not an accident of the regex — the refusal is pinned
manifest.test.ts already pins the same class as invalid, deliberately:
const invalidVersions = ['1.0', '1', 'v1.0.0', '1.0.0-beta'];
So the schema, its test, and its prose sentence (major.minor.patch) all agree that prerelease suffixes are refused. The only artifact that disagrees is the @example line — which is why this reads as an editing residue in the TSDoc rather than a question about what the key should accept.
Why it is being filed rather than resolved in place
#17070 rules on PluginSchema.version and PluginLoader, and its dispatch declared a file face that does not include manifest.zod.ts. This key is also the precedent #17070 was told to copy — its TSDoc spells (major.minor.patch) explicitly instead of leaning on the word SemVer — so touching it in the same change would have edited the yardstick and the thing being measured at once.
The shape of the decision
- Delete or correct the
@example. Cheapest, and consistent with the pinned refusal: replace "2.1.0-beta.1" with a value the regex accepts. Nothing published moves.
- Widen the regex to admit prerelease/build, matching what
PluginSchema.version now accepts. ⚠️ This changes an accept set on a published schema and contradicts the existing pin, so it wants its own statement — and note the two keys are deliberately different grammars today.
- Do nothing, on the ground that one wrong example in a TSDoc costs little.
⛔ This seat does not grade which.
Adjacent
Filed by the
domain:specexecution seat while implementing #17070, using Claude Code. ⛔ Deliberately not repaired there: #17070's declared file face isPluginSchema.versionandPluginLoader's predicate, and this key is neither. No severity asserted, no lane asserted — both are triage's.The finding
ManifestSchema.version(packages/spec/src/kernel/manifest.zod.ts) documents two@examplevalues in its TSDoc. Its regex accepts one of them and refuses the other.Reproduce, no build needed:
An author who copies the second documented example verbatim gets a
ZodErrorfromManifestSchema.parse. This is a documented example that fails when copied, not a missing member or a stale prose nuance.It is not an accident of the regex — the refusal is pinned
manifest.test.tsalready pins the same class as invalid, deliberately:So the schema, its test, and its prose sentence
(major.minor.patch)all agree that prerelease suffixes are refused. The only artifact that disagrees is the@exampleline — which is why this reads as an editing residue in the TSDoc rather than a question about what the key should accept.Why it is being filed rather than resolved in place
#17070 rules on
PluginSchema.versionandPluginLoader, and its dispatch declared a file face that does not includemanifest.zod.ts. This key is also the precedent #17070 was told to copy — its TSDoc spells(major.minor.patch)explicitly instead of leaning on the word SemVer — so touching it in the same change would have edited the yardstick and the thing being measured at once.The shape of the decision
@example. Cheapest, and consistent with the pinned refusal: replace"2.1.0-beta.1"with a value the regex accepts. Nothing published moves.PluginSchema.versionnow accepts.⛔ This seat does not grade which.
Adjacent
PluginSchema.versionandisValidSemanticVersionboth call themselves SemVer but accept eight forms SemVer 2.0.0 forbids #17070 — where this was measured; that card is the mismatch between a version key's claim and its accept set, on a different key.type: "ui-plugin"that both ManifestSchema and PluginSchema refuse #16140 — a differentManifestSchemadeclaration-versus-documentation fork (type: "ui-plugin"in ADR-0026).