Uh oh!
There was an error while loading. Please reload this page.
refactor(plugin-dashboard): retire FieldMeta.referenceTo, withdraw the README promise (#6597) - #6695
Merged
Merged
Conversation
WIP checkpoint before the ablation proving the new tombstone is load-bearing.
…lumn-holds interface
`ObjectDataTableColumnHolds` lost its only member (`referenceTo`, retired by the
previous commit) and eslint's `@typescript-eslint/no-empty-object-type` flags the
resulting `{}`. Kept as an `interface` (a documented extension point for a future
per-key ruling) rather than switched to `type = object`, with a scoped disable and
the reasoning inline. Also adds the changeset for the referenceTo retirement.
Claude-Session: https://claude.ai/code/session_8ca04858-ea8e-5b85-9182-de59aa49e00c
Co-authored-by: Claude <noreply@anthropic.com>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
|
os-sales
marked this pull request as ready for review
August 28, 2026 16:08
Uh oh!
There was an error while loading. Please reload this page.
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.
Fixes#6597
The measurement (measure-then-act card)
The card's rule: withdraw is the lean default when no demand is measured; enforce only
on a measured authoring story. This PR measured, and lands withdraw.
The two
referenceTopopulations, kept separate (per the card's own trap warning)referenceTosurvives legitimately elsewhere as an internal TS property name that isnot this card's subject:
DatasetRelationship.referenceTo— a resolver's output, not an authoring input.Not touched by this PR.
plugin-dashboard's ownFieldMeta.referenceTo— this card's subject: the README'sdocumented author-facing column override.
A bare grep for the identifier conflates these two populations. This PR only ever
inspected the second.
Does a real authoring story exist for a column-level reference override?
No, measured on four independent axes:
LookupCellRenderer(@object-ui/fields) resolvesits lookup target from
field.reference_to/field.reference— neverfield.referenceTo— andcomputeLookupExpand(ObjectDataTable.tsx) builds$expandfrom the OBJECT SCHEMA's field types, never from an authored column key. Thiswas already pinned by
ObjectDataTable.overrideSource-6425.test.tsx'sreferenceTo-vs-optionspositive control:options(a live override) separates twoequal-valued columns;
referenceTodoes not.RecordDetailDrawer, the only otherbuildFieldMetacaller, doesn't even offer acolumn-level override — it calls
buildFieldMetawith nooverridesat all. OnlyObjectDataTableever passed one through, and it reached nothing per (1).ObjectGrid's own relational-metapass-through (
applyRelationalMeta,packages/plugin-grid/src/ObjectGrid.tsx) copiesreference_to/reference/display_field/ etc. from the schema field defonly, at all three of its call sites — never from an authored column override. If a
column-level reference override were a real pattern anywhere in this codebase, this is
where it would show up first. It doesn't.
lookup's target away from what its schema field already says (checked
content/docs/**,examples/**, and every JSON/TS occurrence ofreferenceTooutsidethis package's own internals).
⇒ Under the maintainer's standing startup-stage rule (2026-08-27: no measured demand
retires immediately, no transition window), this selects withdraw.
Both
keyof FieldMetaseam bands (the card's fence, in full)ObjectDataTablederives two refusal bands fromkeyof FieldMeta, and both had to move:EnrichedColumn's write-side tombstones (finding(plugin-dashboard): ObjectDataTable's enrich() spreads a FieldMeta into the TableColumn[] slot, writing seven keys TableColumn does not declare #6373).referenceToleftkeyof FieldMeta, so the DERIVED tombstone band can no longer reach it (same mechanism finding(plugin-dashboard): FieldMeta.decimals is written from the schema def but read by nothing #6625hit for
decimals). A new hand-writtenObjectDataTableRetiredReferenceToTombstone(
{ referenceTo?: never }) is intersected in — the exact sibling ofObjectDataTableRetiredDecimalsTombstone.AuthoredColumnOverrides' read-side band (finding(plugin-dashboard): ObjectDataTable honours five undeclared authored column keys as field-meta overrides #6425).referenceTowas the last memberof
ObjectDataTableColumnHolds(the HELD-key interface finding(plugin-dashboard): ObjectDataTable honours five undeclared authored column keys as field-meta overrides #6425's ruling left for this cardto dispose of). It's now empty — kept as a documented extension point (an
interface,not
type = object) for a future ruling to hold a new key onto, the same role it playedfor
format/options/currencybefore finding(plugin-dashboard): ObjectDataTable honours five undeclared authored column keys as field-meta overrides #6425 declared them. The sameObjectDataTableRetiredReferenceToTombstoneis intersected into this half too.enrich()no longer readsauthored.referenceTointobuildFieldMeta'soverridesatall, and
FieldMeta.referenceTo/BuildFieldMetaParams.overrides.referenceToare gonefrom
recordFields.tsx.Ablation — prediction vs observation
Leg 1 (mutate): removing the tombstone intersection should make two
@ts-expect-errordirectives unused (TS2578).
Replaced
& ObjectDataTableRetiredReferenceToTombstonewith the old HELD shape(
& { referenceTo?: unknown }) at both of its two intersection sites inObjectDataTable.tsx. Anchored count before:grep -c ObjectDataTableRetiredReferenceToTombstone= 7;after mutation,
grep -n "ABLATION: tombstone removed"matched both edited sites andgrep -c "& ObjectDataTableRetiredReferenceToTombstone;"= 0, confirming the mutationlanded on disk.
Observed:
tsc -p tsconfig.test.jsonexited 2 —ObjectDataTable.emitBoundary-6373.test.tsx(370,5): error TS2578: Unused '@ts-expect-error' directive.and
ObjectDataTable.overrideSource-6425.test.tsx(303,5): error TS2578: Unused '@ts-expect-error' directive.— exactly the two new counter-control pins this PR adds. Matches prediction.
Leg 2 (restore): the tree should return to byte-identical HEAD.
Restore was
git checkout HEAD -- PATH(never barecheckout --, which would read fromthe polluted index) inside a
trap ... EXIT INT TERM,REPO_ROOTresolved viagit rev-parse --show-toplevelbefore mutating.Observed:
git diff HEAD --quietexited 0 (clean); re-runningtsc -p tsconfig.test.jsonafterward exited 0 with no output. Matches prediction.Behaviour is unchanged
referenceTo reaches NOTHING on this pathruntime assertion(
ObjectDataTable.overrideSource-6425.test.tsx) passes unchanged — an authoredreferenceTostill renders byte-identical to its absence, before this PR and after.decimals) prove thetombstone, not the derived band or a lingering hold, is what refuses the key at each
seam band.
packages/plugin-dashboard/src/__tests__/ObjectDataTable.emitBoundary-6373.test.tsx'sschema fixture (
owner: { type: 'lookup', ..., referenceTo: 'user' }) is retired-spellingfixture rot from before this card — updated to the spec-canonical
reference: 'user'(fixture triage: pure respelling, the field's
type: 'lookup'is what actually drivesthe render being tested, nothing in this package's pipeline ever consumed the key either
spelling).
README
Removed
referenceTofrom the "Author overrides always win" line(
packages/plugin-dashboard/README.md) and added one sentence stating the actual, measuredbehaviour: a lookup column's related-object target always comes from the schema field def,
with no column-level override.
Scope note (why this isn't a published-type removal)
FieldMeta,AuthoredColumnOverrides,EnrichedColumnandObjectDataTableColumnHoldsare absent from
dist/index.d.ts—plugin-dashboard's barrel (src/index.tsx)re-exports only the
ObjectDataTablecomponent, and the package'sexportsmap publishesonly
".". No downstream consumer can name any of these types. This is a package-internalcontract change plus a README correction, not a removal from a published type surface.
Changeset:
minor(this repo's version-alignment rule reservesmajorfor following@objectstackacross a major — see AGENTS.md 版本号策略).Out-of-scope finding filed separately
While tracing
LookupCellRenderer's actual read path, found thatObjectDataTable/RecordDetailDrawernever feedreference_to/referenceontoFieldMetaat all —so
useRefObjectSchema-driven display-name resolution andReferencedRecordLink'sdrill-through links silently never engage for any lookup cell in either widget, regardless
of this card's ruling (the gap predates it —
referenceTowas never the snake_casespelling either).
ObjectGrid'sapplyRelationalMetais the working sibling pattern.This is a behaviour change, not a retirement, and outside this card's stop-and-report
line ("enforcing must not widen behaviour beyond the documented promise") — filed as
#6694, unassigned,
findinglabel, nopm:queue(an observationfor triage to size, not a ready-to-dispatch fix).
Gate table (HEAD
3c5d330a8, merged ontoorigin/main@84b4fb69d)pnpm --filter '@object-ui/plugin-dashboard' run type-checkpnpm exec vitest run packages/plugin-dashboard/Test Files 83 passed (83)/Tests 781 passed (781)pnpm exec vitest run .../ObjectDataTable.overrideSource-6425.test.tsx .../ObjectDataTable.emitBoundary-6373.test.tsxTest Files 2 passed (2)/Tests 24 passed (24)check:control-bytesnode scripts/check-control-bytes.mjspnpm exec eslint --format json(4 touched files)origin/mainbaseline for the same 4 files (measured viaeslint --stdin), so 0 new warnings introducedcheck:doc-fencesnode scripts/check-doc-fence-languages.mjscheck:readme-exportsnode scripts/check-readme-exports.mjspackagesRead: found 13, floor is 25) because most sibling packages'dist/aren't built in this worktree (only plugin-dashboard's own dependency closure was). Unrelated to this diff: plugin-dashboard's own README raised zero findings, and CI's full build covers this gate meaningfully.pnpm changesetpresencenode scripts/check-changeset-presence.mjsnode scripts/check-changeset-no-major.mjsmajorbump declaredType-aware eslint is not enabled in this repo (
eslint.config.js'slanguageOptionssetsno
parserOptions.project), so a file-scoped eslint run is a complete judgement, not anarrowed one.
Generated by Claude Code