Skip to content

[finding] build-docs.ts silently drops the whole reference-doc section for a bare opaque-string top-level schema (~23 exports with a real .describe()) #7658

Description

@os-zhuang

Found while implementing #7513 (re-typing TenantPlanSchema from a closed enum to an opaque z.string().describe(…)).

What happens

packages/spec/scripts/build-docs.ts's generateMarkdown() decides what to render for a top-level exported schema like this:

const defs = schema.definitions || schema.$defs || {};
let mainDef = defs[schemaName];

if (!mainDef && (schema.properties || schema.enum || schema.anyOf || schema.oneOf)) {
  mainDef = schema;
}
if (!mainDef) {
  mainDef = Object.values(defs)[0];
}
if (!mainDef) return '';   // <-- silently drops the entire "## SchemaName" section

The root-detection condition only recognizes object (properties), enum, and union (anyOf/oneOf) shapes. A schema whose JSON Schema is a bare primitive{"type": "string", "description": "…"} with no enum, properties, anyOf, or oneOf — matches none of those, so mainDef stays undefined and generateMarkdown returns ''. Not just the "Allowed Values" bullets — the entire heading, including the schema's own .describe() text, disappears from the published page. The ## TypeScript Usage import list and the root content/docs/references/index.mdx table still name the export (they're driven by the export surface, not this function), so the page looks like it forgot to finish rendering an entry it just imported.

Confirmed on #7513

Before #7513, TenantPlan.json was {"type": "string", "enum": [...]}, which the schema.enum branch of the condition caught, so content/docs/references/cloud/tenant.mdx had a ## TenantPlan / ### Allowed Values section. #7513 widens it to {"type": "string", "description": "..."} (no enum) — and the whole section vanished on regeneration, taking the schema's new ownership-statement description with it. The JSON Schema itself (packages/spec/json-schema/cloud/TenantPlan.json) still carries the full description; only the rendered .mdx page silently lost it.

Scope — this is not just TenantPlan

Scanning packages/spec/json-schema/**/*.json for type ∈ {string,number,integer,boolean} with no enum/properties/anyOf/oneOf, 31 exported schemas match this shape today, 23 of them carrying a real .describe() that never reaches its reference page:

api/EventPattern, cloud/EnvironmentDriver, cloud/PackageCategory, cloud/PackageLocale,
cloud/Sha256Digest, cloud/TenantPlan, data/DriverSslToggle, data/DriverType,
kernel/OpsFilePath, shared/AppName, shared/EventName, shared/FieldName, shared/FlowName,
shared/ObjectName, shared/RoleName, shared/SnakeCaseIdentifier, shared/SystemIdentifier,
shared/ViewName, system/Locale, system/Sha256Digest, system/TraceFlags, ui/ViewItemName

(8 more have no description either way: data/CalendarDateValue, ClockTimeValue, ContextToken, ContextTokenPlaceholder, DateMacroPlaceholder, DateMacroToken, FieldNode, FileReferenceIdValue, InstantValue, ReferenceIdValue.)

Why finding, not a queued defect

Nothing breaks: check:docs compares the generated output to what's committed, so a doc that never had the section stays green — this has apparently been silently true for a while (EnvironmentDriver etc. predate #7513 and already showed the same gap before my change touched anything). No runtime path depends on the rendered docs. It's a documentation-quality gap — real .describe() text authors wrote to be read is invisible on the one page meant to show it — not a defect a user hits today. Filed unassigned/no pm:queue per the observation-class convention.

Suggested fix shape (not attempted here — out of scope for #7513)

Add an else if (mainDef.type) fallback in generateMarkdown() (packages/spec/scripts/build-docs.ts, ~line 368) that renders the description (already handled above the type-specific branches) plus a **Type:** \`line for any recognized root type that isn't object/enum/union, instead of falling through to theif (!mainDef) return ''` case. Would need a fixture pin (a bare-string schema whose description shows up on its page) so this doesn't silently regress again.


Filed while implementing #7513.
Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions