Origin: measured by the os-dev run for #12588 while enumerating the self-aliased def-key population. Filed on the dev's behalf — recording only, unassigned, awaiting triage. Not fixed under #12588's claim (out of scope: that card corrects the published x-schema-count; this is comment prose in the same file).
Observation class: stale prose in comments. No behaviour is wrong, no gate is missing, nothing published is affected.
What the prose says
packages/spec/scripts/lib/def-key-collisions.ts:38-39 — the module doc describes the shape the collision guard exempts:
The permitted shape is the package's self-alias convention — export const ThemeMode = ThemeModeSchema, and fourteen more across api, system and ui — where the second write is the same object …
packages/spec/scripts/def-key-collisions.test.ts:326 — the same number, as a stated fact:
Exactly one collision: the fourteenexport const X = XSchema self-aliases this package really does carry must stay green, or the guard is unusable.
What is actually there
Measured at origin/main7c0d0c395, by walking the same namespace exports build-schemas.ts walks and bucketing by def key with the guard's own identity predicate:
zod exports walked : 1620
distinct def keys : 1607
self-aliased def keys : 13 <- not 14
categories spanned : api (8), system (5) <- no ui entry exists
The 13: api/ApiEndpoint, api/RestApiConfig, api/RestServerConfig, api/ApiDocumentationConfig, api/ApiTestCollection, api/OpenApiSpec, api/RestApiPluginConfig, api/RestApiRouteRegistration, system/MiddlewareConfig, system/BatchTask, system/QueueConfig, system/Task, system/WorkerConfig.
Two of those (system/BatchTask, system/WorkerConfig) have both halves skipped as unrepresentable in JSON Schema ("Function types cannot be represented"), so a real gen:schema run collapses 11, not 13 — which is the delta #12588 is about. Either number is defensible in the prose; fourteen is not.
Three separate drifts, all in comments:
- The count. 13 self-aliased def keys, or 11 that survive to an emit. Not 14.
- The example symbol does not exist. There is no
export const ThemeMode anywhere in packages/spec/src — only ThemeModeSchema. git grep -n "export const ThemeMode\b" -- src returns nothing. It reads as a real citation and is not one. ui carries none of them. The categories are api and system only.
The same ThemeMode = ThemeModeSchema example is also the remedy text in formatDefKeyCollisions (def-key-collisions.ts:186), which is user-facing build output. As an illustration of a shape it is still readable, but it cites a symbol a reader cannot find.
Why it is worth recording rather than fixing in passing
The number is load-bearing for a reader deciding whether a new self-alias is normal or a mistake, and the example is the first thing someone greps for when they hit the guard. A wrong count next to a correct guard is the shape that gets trusted — nothing checks it, and #12588 exists precisely because an unchecked count drifted.
Deliberately not proposing a gate: a comment that counts a live population will drift again, and pinning it costs more than it saves. The cheaper fix is prose that does not commit to a number — describe the shape and point at the generator's report line (which since #12588 prints the population every run), rather than restating a total. Whoever takes it should decide that, not inherit it from here.
Dedup (searched 2026-08-26, MCP search_issues scoped to this repo, plus local grep for fourteen and ThemeMode under packages/spec/scripts): no open card covers this. Closest in shape is #9781 (comments stating a stale premise) — closed, different file, different premise.
Origin: measured by the os-dev run for #12588 while enumerating the self-aliased def-key population. Filed on the dev's behalf — recording only, unassigned, awaiting triage. Not fixed under #12588's claim (out of scope: that card corrects the published
x-schema-count; this is comment prose in the same file).Observation class: stale prose in comments. No behaviour is wrong, no gate is missing, nothing published is affected.
What the prose says
packages/spec/scripts/lib/def-key-collisions.ts:38-39— the module doc describes the shape the collision guard exempts:packages/spec/scripts/def-key-collisions.test.ts:326— the same number, as a stated fact:What is actually there
Measured at
origin/main7c0d0c395, by walking the same namespace exportsbuild-schemas.tswalks and bucketing by def key with the guard's own identity predicate:The 13:
api/ApiEndpoint,api/RestApiConfig,api/RestServerConfig,api/ApiDocumentationConfig,api/ApiTestCollection,api/OpenApiSpec,api/RestApiPluginConfig,api/RestApiRouteRegistration,system/MiddlewareConfig,system/BatchTask,system/QueueConfig,system/Task,system/WorkerConfig.Two of those (
system/BatchTask,system/WorkerConfig) have both halves skipped as unrepresentable in JSON Schema ("Function types cannot be represented"), so a realgen:schemarun collapses 11, not 13 — which is the delta #12588 is about. Either number is defensible in the prose; fourteen is not.Three separate drifts, all in comments:
export const ThemeModeanywhere inpackages/spec/src— onlyThemeModeSchema.git grep -n "export const ThemeMode\b" -- srcreturns nothing. It reads as a real citation and is not one.uicarries none of them. The categories areapiandsystemonly.The same
ThemeMode = ThemeModeSchemaexample is also the remedy text informatDefKeyCollisions(def-key-collisions.ts:186), which is user-facing build output. As an illustration of a shape it is still readable, but it cites a symbol a reader cannot find.Why it is worth recording rather than fixing in passing
The number is load-bearing for a reader deciding whether a new self-alias is normal or a mistake, and the example is the first thing someone greps for when they hit the guard. A wrong count next to a correct guard is the shape that gets trusted — nothing checks it, and #12588 exists precisely because an unchecked count drifted.
Deliberately not proposing a gate: a comment that counts a live population will drift again, and pinning it costs more than it saves. The cheaper fix is prose that does not commit to a number — describe the shape and point at the generator's report line (which since #12588 prints the population every run), rather than restating a total. Whoever takes it should decide that, not inherit it from here.
Dedup (searched 2026-08-26, MCP
search_issuesscoped to this repo, plus local grep forfourteenandThemeModeunderpackages/spec/scripts): no open card covers this. Closest in shape is #9781 (comments stating a stale premise) — closed, different file, different premise.