Uh oh!
There was an error while loading. Please reload this page.
test(test-support): confine the spec enum-vocabulary reader to one module (#5872 class 1) - #6047
Merged
yinlianghui merged 1 commit intoAug 24, 2026
Conversation
…dule Four spec-parity suites in four packages each carried a byte-for-byte identical walk into Zod's internals to read a key's enum vocabulary (verified by normalising the schema/key/local names and hashing: one distinct form across all four). They now import one `shapeEnumOptions` from the private, never-published `@object-ui/test-support`. The shared reader is a widening of what the hand copies did: it resolves the shape through `resolvePropsShape` (all three `.shape` spellings plus the `lazySchema()` thunk), walks the wrapper chain instead of assuming a single `def.innerType` level, and reads `.options` at every level. Against the installed pin it returns the identical array in the identical order for all four (schema, key) pairs, so no verdict moves. Consolidating readers only; no schema, no type declaration and no runtime code is touched. The other reader classes the same census named (array-element unwrapping, the wrapper-key walk) are left as they are.
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 24, 2026 14:48
Uh oh!
There was an error while loading. Please reload this page.
yinlianghui
deleted the
claude/issue-5872-zod-internals-reader-confinement
branch
August 24, 2026 15:00
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 freeto 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.
Refs #5872 — reader class (1) only, the four verbatim copies. Classes (2), (3) and (4) from the card's census stay hand-copied, so this does not close the card.
What this is
packages/test-support/src/spec-tombstones.tssays ofresolvePropsShape:That was true of shape resolution and false of every other reader a spec-parity gate runs over a Zod node. This PR makes it true for one more reader class: the enum vocabulary of one key.
New module
packages/test-support/src/spec-enum-options.ts, one exportshapeEnumOptions(schema, key), and the four call sites converted onto it.Census, re-derived on the merge-base (not read off the card)
Merge-base
b0de7a85c. The card's census is from 2026-08-23; re-derived today:b0de7a85cinnerType(10 tests +core/src/actions/actionKeys.ts, a comment)Two census notes worth stating because the dispatch flagged them:
packages/types/src/__tests__/zod-mirror-parity.test.ts— the file PR fix(types): widen seven zod mirrors the renderer already implements (#5927 group A) #6032 rewrites — is not in this census at all. It does not readinnerTypeand is not one of the ~10. Nothing here goes nearpackages/types, so fix(types): widen seven zod mirrors the renderer already implements (#5927 group A) #6032's enqueued state constrained nothing in practice.packages/types/src/__tests__/gantt-view-mode-declared.test.ts:53(while (cur?._def?.innerType) cur = cur._def.innerType;) is new since the card was filed and belongs to class (4), not class (1). Untouched —packages/typesalso carries live sibling work."Verbatim" verified byte-for-byte, not by eye
Each of the four readers was extracted, the schema identifier, the member key and the local variable name normalised to
S/K/V, and the result hashed:Raw byte lengths differ only by identifier length (337 / 344 / 335 / 331). So all four are genuinely identical — no copy differs by a
?.or a default. The class the card called verbatim really is verbatim.Verdict preservation, measured
The shared reader is a widening of the hand copy in three ways: it resolves the shape through
resolvePropsShape(all three.shapespellings plus thelazySchema()thunk, where the copies read only the plain one), walks the wrapper chain instead of assuming a singledef.innerTypelevel, and reads.optionsat every level so an unwrapped enum answers too. A widening is exactly where a verdict can flip, so it was measured before anything was converted — the old reader and the candidate run side by side against the installed pin (@objectstack/spec@17.2.0,zod@4.4.3):Same arrays, same order. No verdict flipped, and no test was adjusted to keep it green — nothing needed adjusting.
Then the same suites, same invocation, before and after — counts and the test-name fingerprint, because a suite that loses one test and gains another is all-green:
c909f7b78011cad5c33dc909f7b78011cad5c33dPer file, identical both times: 8 / 5 / 10 / 8.
The only test-count movement anywhere is the new calibration suite in
test-support, declared rather than folded in: 2 files / 13 tests before, 3 files / 25 tests after — the 12 new calibration tests, with the two pre-existing suites unmoved.Confinement, falsified rather than asserted
After the change, searching the whole repo for the reader class outside
packages/test-support:A zero with a control that finds the reader where it now lives, and finds every consumer asking through the export.
Reverse verification — direction predicted before running
Prediction, written down first: break the shared reader so it reports an empty vocabulary and all four converted files must go red, each at minimum through its own
reads a non-empty enum from the spec; if only some go red the sites are not really sharing the reader.Mutation (anchor asserted unique first, 1 occurrence):
return [...options] as string[]→return [] as string[]— the quiet-permissive failure this module exists to stop. Proved on disk before reading anything: injected text count 1, removed text count 0, landing site printed (spec-enum-options.ts:104).All five, and per file:
data-table-selection-mode—reads a non-empty enum from the spec,does not accept selection modes the spec rejectsadd-record-position-spec-parity—reads a non-empty enum from the spec,gives every spec position a placement that matches its nameuser-filter-arity-spec-parity—reads a non-empty enum from the spec,does not declare control types the spec rejectstimeline-scale-spec-parity—reads a non-empty enum from the spec,declares exactly the spec scalesspec-enum-options.test.ts— all 5 wrapper fixtures + all 4 real-contract pairsExactly as predicted. Restored under
trap … EXIT INT TERM;git diff HEAD --statempty afterwards.Worth naming what the ablation also shows: in three of the four suites, the parity assertion in the "spec accepts a name we do not implement" direction stayed green on an empty vocabulary. That is the card's own argument, reproduced — an empty option set makes half of each parity gate pass over nothing, and only the non-vacuity assertion catches it.
The new dependency edge, declared
None of
@object-ui/components,@object-ui/plugin-list,@object-ui/plugin-timelinedepended on@object-ui/test-support. Each gains"@object-ui/test-support": "workspace:*"in devDependencies (the README's convention; no consumer ships it), plus thepnpm-lock.yamlupdate.node scripts/check-phantom-dependencies.mjsexit 0.@object-ui/test-supportisprivate: trueand never published, so no published surface widens.Gates
Run on
3b010122f; exit codes captured before any pipe.pnpm --filter @object-ui/test-support run type-check(tsc --noEmit)pnpm --filter @object-ui/components run type-check(tsc --noEmit && tsc -p tsconfig.test.json)pnpm --filter @object-ui/plugin-list run type-check(same two-step)pnpm --filter @object-ui/plugin-timeline run type-check(same two-step)pnpm exec vitest run packages/test-support/src packages/plugin-list/src packages/plugin-timeline/src --maxWorkers=2— 58 files, 770 testspnpm exec vitest run packages/components/src --maxWorkers=2— 183 files, 1681 testsnode scripts/check-phantom-dependencies.mjsnode scripts/check-changeset-presence.mjspnpm exec eslint .in each of the four packagesScript names are echoed in each run, so a zero-match silent pass cannot read as green. The dependency closure was built first —
pnpm --filter '@object-ui/components^...' --filter '@object-ui/plugin-list^...' --filter '@object-ui/plugin-timeline^...' build, exit 0 — so aCannot find modulereading could not be mistaken for a real failure.Changeset has empty frontmatter — this repo's "releases nothing" declaration. It is accurate: the only edits to released packages are three
devDependencieslines and four test files.Not in this PR
Per the triage fence, one reader class at a time. Left exactly as found, and why:
recordDetailsInputs.spec-parity.test.ts:83,previews/__tests__/block-config.test.ts,clientValidation.optOuts.test.ts). Not verbatim, so a shared reader has to pick a behaviour where three disagree — the flip risk this card explicitly refuses to run blind. It needs its own round with its own before/after measurement.['in','out','innerType','schema','left','right']in three files. Textually a list, not an expression; a separate reader shape.recordRelatedListInputs.spec-parity.test.ts:61-65and the newerpackages/types/src/__tests__/gantt-view-mode-declared.test.ts:53— single-site_def.innerType ?? _def.typeunwraps.packages/typesandpackages/plugin-detailboth carry live sibling work this round.Generated by Claude Code