Skip to content

fix(spec): gen:schema io:'input' fallback + disappearance ratchet — restore PageTabsProps (#2978) - #3012

Merged
os-zhuang merged 3 commits into
mainfrom
claude/gen-schema-pagetabsprops-drop-g3bp4k
Jul 16, 2026
Merged

fix(spec): gen:schema io:'input' fallback + disappearance ratchet — restore PageTabsProps (#2978)#3012
os-zhuang merged 3 commits into
mainfrom
claude/gen-schema-pagetabsprops-drop-g3bp4k

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#2978.

Problem

#2967 added an ExpressionInputSchema field (items[].visibleWhen) to PageTabsProps. That schema contains a .transform (string shorthand → {dialect, source} envelope), which zod's toJSONSchema cannot represent in the default output mode, so build-schemas.tssilently skipped it. json-schema/ui/PageTabsProps.json disappeared, and the next full gen:docs run would have deleted the published PageTabsProps section from content/docs/references/ui/component.mdx.

It turned out to be a whole class, not a one-off: 150 schemas (ObjectSchema, FieldSchema, FlowSchema, PageSchema, ActionSchema, …) were already transform-blocked and absent from json-schema/ — delivered but not declared.

Fix (packages/spec/scripts/build-schemas.ts)

  1. io: 'input' fallback — when output-mode conversion fails on a transform, retry with io: 'input'. These JSON Schemas describe what authors write, and the input side of a transform pipe is plain data, so it is representable. For PageTabsProps.visibleWhen this emits the correct authoring shape: anyOf: [string (CEL shorthand), expression envelope]. Rescued schemas carry an x-io: "input" marker (author-time shape: parse-time transforms/defaults not applied). Result: 1849 schemas generated (150 as input shape); only 18 truly unrepresentable ones (function/Date/BigInt/custom) remain skipped.

  2. Disappearance ratchetjson-schema/ is a gitignored build artifact, so a new committed packages/spec/json-schema.manifest.json records every schema key ever emitted (mirrors the spec-liveness ratchet pattern). A key present in the manifest but not emitted by a build now fails gen:schema loudly with remediation steps; deliberate retirements must remove the key in the same PR. New schemas are auto-appended (commit the manifest change). Silent skip is now reserved for types that have never been representable — exactly the boundary gen:schema silently drops PageTabsProps since #2967 — references regen would delete real docs #2978 asked for.

  3. build-docs.ts pipe escaping — rescued schemas surfaced descriptions containing literal |, which split GFM table cells (the type column already escaped pipes; the description column didn't). Descriptions in property tables are now escaped.

Docs regen (content/docs/references/)

Full gen:docs over the fixed output (the regen that was unsafe before this fix):

  • PageTabsProps keeps its section — the regression the issue predicted is gone;
  • the 150 rescued contracts gain reference sections (4 new pages: automation/control-flow, integration/connector-auth, integration/mapping, shared/mapping);
  • previously-broken table rows with raw pipes are re-emitted escaped.

Verification

  • pnpm --filter @objectstack/spec gen:schemaGenerated: 1849 (150 as input shape), json-schema/ui/PageTabsProps.json present with anyOf authoring shape for visibleWhen;
  • ratchet tested: adding a ghost key to the manifest fails the build with exit 1 and a pointed error message; re-runs are idempotent (no manifest churn);
  • pnpm --filter @objectstack/spec gen:openapi unaffected;
  • pnpm docs:build compiles all regenerated MDX.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Fn6qMKtJeVbs2KzouWDHhB


Generated by Claude Code

claude added 2 commits July 16, 2026 04:42
…hemas (#2978)
PageTabsProps vanished from json-schema/ when #2967 added an
ExpressionInputSchema (.transform) field — zod's toJSONSchema cannot
represent transforms in the default output mode, and build-schemas.ts
silently skipped it, so the next gen:docs run would have deleted the
published PageTabsProps reference section.
Two-part fix:
1. io:'input' fallback — when output-mode conversion fails on a
transform, retry with io:'input'. These JSON Schemas describe what
authors WRITE, and the input side of a transform pipe is plain data,
so it is representable (for PageTabsProps.visibleWhen it emits the
correct `anyOf: [string, expression envelope]` authoring shape).
Rescued schemas are marked `x-io: "input"`. This restores
PageTabsProps and 149 other transform-blocked public contracts
(ObjectSchema, FieldSchema, FlowSchema, PageSchema, ActionSchema, …);
only 18 truly unrepresentable schemas (function/Date/BigInt/custom)
remain skipped.
2. Disappearance ratchet — json-schema/ is gitignored, so the committed
json-schema.manifest.json records every schema key ever emitted.
A key present in the manifest but absent from a build now fails
gen:schema loudly with remediation steps; deliberate retirements must
remove the key in the same PR. Silent skip remains only for types
that have never been representable.
Also escape literal `|` in the description cell of generated property
tables (build-docs.ts) — rescued schemas surfaced descriptions with
pipes that split GFM table rows.
Closes#2978
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fn6qMKtJeVbs2KzouWDHhB
gen:docs over the post-fix json-schema/ output. PageTabsProps keeps its
section (now including the visibleWhen items shape from #2967), and the
149 schemas rescued by the io:'input' fallback gain reference sections —
previously delivered-but-undeclared contracts (Prime Directive #10).
Existing table rows with literal pipes in descriptions are re-emitted
with GFM escaping.
Verified: `pnpm docs:build` compiles all regenerated MDX.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fn6qMKtJeVbs2KzouWDHhB
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specCanceledCanceledJul 16, 2026 5:08am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tooling labels Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

97 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/cli.mdx(via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/permissions/authorization.mdx(via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Comment threadpackages/spec/scripts/build-docs.ts Fixed
Comment threadpackages/spec/scripts/build-schemas.ts Fixed
- build-schemas.ts: read the ratchet manifest directly and treat ENOENT
as first-run bootstrap instead of existsSync-then-read (TOCTOU).
- build-docs.ts: escape backslashes before pipes in table-cell
descriptions — an existing `\|` would otherwise decay into an escaped
backslash followed by a live pipe, splitting the GFM cell.
No output changes: regenerated json-schema/ and references/ are
byte-identical.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fn6qMKtJeVbs2KzouWDHhB
@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 04:50
@os-zhuang
os-zhuang merged commit c435e29 into mainJul 16, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/gen-schema-pagetabsprops-drop-g3bp4k branch July 16, 2026 05:09
os-zhuang pushed a commit that referenced this pull request Jul 16, 2026
Conflict resolution: content/docs/references/ui/view.mdx (auto-generated)
regenerated via gen:docs on the merged tree; api-surface.json auto-merge
verified identical to regenerated output; json-schema.manifest.json
(disappearance ratchet, #3012, new on main) picks up +ui/FormButtonConfig.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Ue47V8zZ5QhcYMPiRQDA7
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xltooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gen:schema silently drops PageTabsProps since #2967 — references regen would delete real docs

3 participants

@os-zhuang@github-advanced-security@claude