feat(lint-meta): schema-enum-field-consistency — keep the generated API client precise#306
Merged
Merged
Conversation
…PI client precise A fixed-value TypeBox field (typed t.Union([t.Literal(...)]) in any schema in a *.schemas.ts file) must be typed the SAME way in every schema in that file — never widened to t.String(), typically in the response schema. Why it's a gate error: the response schema becomes the OpenAPI spec, which generate:api turns into the UI's typed client — the single source of truth for the UI's API types. A status field that's an enum on input but t.String() on the response makes the generated client type it `string`; the UI (expecting the enum) then can't reconcile the two, and a weak model "fixes" the clash by reverting/stubbing the feature instead of tightening the schema. Observed live: a TaskFlow build oscillated near-green for 82 cycles and parked, because task status/priority were t.Union([t.Literal…]) on create/update but t.String() on TaskResponse. This rule fails the build on that drift so the model must fix the schema (define the enum once, reuse it everywhere), not delete its UI. Text-based (whitespace-collapsed), matching the other source-text rules; scoped to src/**/*.schemas.ts so fixtures/tests aren't linted. Pure analyzer (inconsistentEnumFields) unit-tested; RULES.md regenerated; no violations on the current API source.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A new
lint:metarule (schema-enum-field-consistency, source-text category): a fixed-value TypeBox field — one typedt.Union([t.Literal(...)])in any schema in a*.schemas.tsfile — must be typed the same way in every schema in that file. Widening it tot.String()(typically in the response schema) fails the gate.Why (real failure it prevents)
The response schema becomes the OpenAPI spec, which
generate:apiturns into the UI's typed client — the single source of truth for the UI's API types. Ifstatusist.Union([t.Literal("todo"),…])on create/update butt.String()on the response, the generated client types the responsestatusasstring. The UI (which expects the enum) can't reconcilestringwith"todo"|"doing"|"done".Observed on a live autonomous build: a TaskFlow feature had exactly this drift (
status/priorityenums on input,t.String()onTaskResponse). The type clash sent the builder into near-green oscillation — it reached 1 error, misread the clash as "spec not regenerated", reverted its UI to stubs, and thrashed for 82 cycles before parking. This rule turns that silent drift into a clear, actionable gate error so the fix is "tighten the schema" (define the enum once, reuse it everywhere), never "delete the UI".How
t.Union([t.String(), t.Null()])(a nullable string) is deliberately not treated as an enum field.src/**/*.schemas.tsso fixtures/tests aren't linted.inconsistentEnumFields(src)unit-tested (drift, clean-via-shared-enum, nullable-string-not-flagged, path-filter).RULES.mdregenerated. No violations on the current API source.bun run checkgreen; 116/116 lint-meta tests pass.