refactor(react): bridgeListView maps only the five rowHeight spellings the spec admits (#4352) - #4439
Merged
Conversation
…s the spec admits (#4352) `mapDensity` carried a nine-key table while `RowHeightSchema` admits five, so `comfortable`, `spacious`, `small` and `large` were unreachable from any spec-valid list view. The parameter was widened back to `rowHeight?: string` to let them in, and the fixture asserting three of them compiled against nothing (the build tsconfig excludes tests), so four branches of renderer-side dialect read as live capability. Delete them. The parameter takes the spec's `RowHeight` honestly and the table is `Record<RowHeight, ...>`, so a row height added upstream fails the build here instead of arriving with no density. AGENTS.md #0.1 — one strict contract beats N dialects; an off-spec `rowHeight` falls through to no density and gets fixed at the producer. Empirical pre-check required by the ruling: zero authored uses of the four spellings across this repo, the objectstack example apps and the console's view metadata. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
ACCEPT — PM 复核 (session
Flipping ready + arming auto-merge. Generated by Claude Code |
yinlianghui
marked this pull request as ready for review
August 12, 2026 07:27
This was referenced Aug 12, 2026
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.
Fixes #4352
Implements the delegated ruling on #4352: delete the four
rowHeightspellingsmapDensitycarried thatRowHeightSchemadoes not admit, conditioned on the card's own empirical pre-check. AGENTS.md #0.1 — one strict contract beats N dialects.mapDensityhad a nine-key table (compact,short,comfortable,spacious,small,medium,large,tall,extra_tall) against a five-value spec enum (short | compact | medium | tall | extra_tall), socomfortable/spacious/small/largewere unreachable from any spec-valid list view. They survived because the parameter was widened back torowHeight?: stringto admit them, and the fixture asserting three of them compiled against nothing (the package's build tsconfig excludes tests). PR #4351 re-spelled the fixture; this PR takes the source half.Empirical pre-check — the ruling's stop condition, run FIRST
The ruling was conditioned on this: a LIVE authored legacy spelling means STOP (the #0.1 fix would then be metadata conversion, a different card). Result: clean — zero authored uses of any of the four.
Swept word-boundary-aware, every hit read and classified, across three repos:
rowHeightvalueobjectui@24bb2de4f—examples/,apps/(incl. console view metadata), allpackages/, every*.json/*.yml/*.yamlrowHeight/densityMode/row_heightassigned one of the four; the four words on any line mentioningrowHeight; everycomfortable/spaciousoccurrence repo-wide (75 lines, all read)objectstack@5d24f4b94—packages/spec,examples/app-showcase,examples/app-crm,packages/platform-objectsrowHeightvalue in the repouserActions.rowHeightflag or one ofcompact/short/medium/tallhotcrm@333259a(a real downstream app on@objectstack17.0.0-rc.5)src/views/lead.view.ts:182authorsrowHeight: 'medium'Classification of what the sweep did turn up, since three of the four words are common English and two of them are also the output vocabulary:
comfortable/spaciousinobjectuiis density-side —DensityMode(compact | comfortable | spacious), the three-step vocabularymapDensitymaps onto — or English prose. The only rowHeight-side occurrences in the entire repo were the four dead keys inlist-view.tsitself.small/largeappear only as unrelated component variants (examples/schema-catalog/.../components-basic-text/small.jsonauthorsvariant: "small") and prose.densityMode: 'spacious'— the legacy density alias, not arowHeight. It cannot deliver a legacy spelling into this bridge:normalizeListViewSchemafolds it throughDENSITY_MODE_TO_ROW_HEIGHT, typedRecord< DensityMode, RowHeight >, whose codomain iscompact/medium/tall. That was the one producer path worth ruling out, and it is ruled out by its type.The change
packages/react/src/spec-bridge/bridges/list-view.tsonly.The four keys are gone; the parameter takes the spec's
RowHeightinstead ofstring, so the widening dies with the branch; and the table is lifted to aRecord< RowHeight, … >const, which buys the property@object-ui/core's equivalent maps already have — a row height added upstream fails the build here instead of silently arriving with no density. A non-specrowHeightfalls through toundefined, and since the bridge writesif (density) node.density = density, the key is simply absent.Red-first (pre-fix, captured against the still-lenient branch)
The new pin was written and run before the source was touched. Exactly four red, one per spelling, each naming the density the legacy value was being rehabilitated into:
The pin routes through
SpecBridge.transformListView, whose parameter isany. That is deliberate and is the honest framing: the untyped boundary is the one a host's stored JSON actually crosses, and after this change it is the only way to get such a value in — writing it onbridgeListViewdirectly no longer type-checks, which is the static half of the same fix. A control case (rowHeight: 'gargantuan', a string in neither vocabulary) pins the fall-through itself and is green on both sides.The five spec values keep PR #4351's coverage, unchanged — no gap to extend.
Changeset grading — measured, not assumed
.changeset/mapdensity-dead-rowheight-spellings-4352.md:'@object-ui/react': minor. Nevermajor, per the version-alignment rule.The measurement that decides it, run as part of reverse verification below: the emitted
packages/react/dist/spec-bridge/bridges/list-view.d.tsis byte-identical before and after.mapDensityis module-local and never reached the published surface, andbridgeListView: BridgeFn< ListViewSpec >withListViewSpec = Partial< ListView >is untouched. So nothing published narrows in type — which is what would have made this #4403'sminor, and it does not apply.What does change is runtime output of an exported function, for a class of input: a host passing
rowHeight: 'comfortable'used to getdensity: 'comfortable'back and now gets nodensitykey. The sweep found zero such hosts in the three repos visible to me, but@object-ui/reactis published, so an out-of-tree host is not excludable — this is exactly the "behaviour change for any host still passing a legacy spelling" #4352 flagged as the separate decision. AGENTS.md's version-alignment rule is decisive for that case: objectui's own breaking changes are gradedminorwith the breaking semantics spelled out in the body, which the changeset does.patch(#4403's grading for a module-local, non-exported table) would have been defensible only if nothing observable changed, and something does.Verification (local, all green)
packages/react/— 38 files, 517 tests passed.packages/reactboth tsc commands:tsc --noEmit(exit 0) andtsc -p tsconfig.test.json(exit 0).pnpm --filter '@object-ui/react^...' build— exit 0, before any judging.eslinton both touched files — 0 errors (2 warnings, both pre-existing@typescript-eslint/no-explicit-anyonmapColumn's untouched signature at lines 22 / 28).check:control-bytes— OK, 4140 tracked text files; plus a self-scan of the touched files for the wider control-byte range: no hits.check:phantom-deps— OK, every in-scope import declared by the package that publishes it.check-changeset-presence—2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).check-changeset-no-major— OK.Reverse verification (three directions predicted before running)
Taken out with
git checkout origin/main -- FILEand put back withgit checkout HEAD -- FILE— nevergit stash.A. Revert the deletion → the new pins red. Predicted normal direction (red, not the inverted or more-diagnostics case: the assertion reads a value the deleted limb produces, not a count a gate reports). Measured, exactly four:
B. Controls green on both sides. Predicted and measured:
maps every spec rowHeight to a density(the five spec values) andleaves density unset for a rowHeight in no vocabulary at allboth pass in the reverted state — 19 of the file's 23 tests passed there, all four failures being the pins from A. A green cannot be bought by breaking the surviving mappings.C. Emitted
.d.tsidentical. Predicted identical, measured identical (diffempty) — the changeset-grading measurement above.Restored afterwards:
git statusclean,git diff HEADempty, rebuild green,packages/react/back to 38 files / 517 tests passed.Surface discipline
Touched
packages/react/src/spec-bridge/bridges/list-view.ts, its__tests__/SpecBridge.test.ts, and the changeset. Nothing inpackages/components/**,packages/plugin-chatbot/**,packages/plugin-dashboard/**, or any new sweep-gate suite.P1SpecBridge.test.tswas read and left alone: its three density cases already use spec values (short/tall/extra_tall) and stay green. No out-of-scope findings.Generated by Claude Code