chore(sweep): retire four zero-consumer declared surfaces — dead-surface deletions batch 3 (#4328) - #4366
Merged
Conversation
Dead-surface deletions batch 3. Every member was re-measured at this branch point (7e4f0e5) and each is removed rather than left as an authoring surface whose values nothing reads. - core: delete the second `mergeViewsIntoObjects` and its `export *` (#3775). Zero in-repo consumers; the live copy is MetadataProvider's, untouched. - data-objectstack: delete the five `views:{object}` invalidations (#3778). No read path populates that key — `listViews` is uncached — so all five were permanent no-ops. Pinned alongside the two keys that do have readers. - types: remove `RoleDefinition.permissions` (#4288). Grants live in `ObjectPermissionConfig.roles`; the field was required and read by nothing, so five fixtures across three packages declared an empty array for it. - react: remove `RecordContextValue.loading` / `error` and their memo dep-list wiring (#3773). Zero producers, zero consumers. The new pin ties the dep list to `keyof RecordContextValue` at compile time and at runtime, so neither a half-wired new key nor a resurrected dead one can land silently. 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
|
yinlianghui
marked this pull request as ready for review
August 11, 2026 22:18
This was referenced Aug 11, 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 #3775
Fixes #3778
Fixes #4288
Fixes #3773
Fixes #4328
Dead-surface deletions batch 3. One claim, one PR, one
Fixesline per member. All four members ship: every premise was re-measured at this branch point (7e4f0e530, not the triage refs — main moved ~150 PRs on 2026-08-11), and none had drifted.7e4f0e530export *lineviews:{object};listViewsis uncachedgit diff --statis 13 files: 4 member rows + 2 pins + 1 changeset. Nothing else.Member 1 — #3775: the second
mergeViewsIntoObjectsin@object-ui/coreEvidence (
git grep -n "mergeViewsIntoObjects" -- packages apps examples, at7e4f0e530, excludingdist/node_modules): every hit outside the deleted file is app-shell's own live copy, its tests, or prose.git grep -n "merge-views-into-objects"returns exactly one line: the barrel re-export atpackages/core/src/index.ts:34. Both are gone; app-shell's copy — the one atMetadataProvider.tsx:697— is untouched.Member 2 — #3778: five invalidations of a key nothing populates
The triage anchors still held line-for-line at this branch point (
:3022,:3183,:3243,:3274,:3291), so no re-anchoring was needed.Evidence.
git grep -n 'views:'overpackages apps examplesreturns those fiveinvalidate` lines and nothing else — no producer anywhere in the repo. Every cache key the adapter actually reads back:view-overrides:{objectName}listViewOverridesview:{objectName}:{viewId}getViewview:{objectName}:{viewId}updateViewConfig(invalidation)app:{appId}getApppage:{pageId}getPage{category}:{name}No
views:prefix among them, and the file has nometadataCache.set/primeat all.listViewsfetchesclient.meta.getItems('view')directly with nometadataCache.getwrapper — genuinely uncached, and left that way. Whether it should be cached is a separate card, not this sweep.Pin (
packages/data-objectstack/src/viewCacheInvalidation.pin.test.ts, 6 cases):listViewsstill hits the transport on every call and consults no cache key (behaviour unchanged — this deletion changes no request count); the surviving invalidations still name exactly the keys with readers (updateViewConfig→ both,updateViewdraft + published → thegetViewkey,deleteView→ thegetViewkey); and no write path names aviews:key.createViewis asserted as "noviews:key" rather than "no invalidation at all", deliberately — see the finding below.Member 3 — #4288:
RoleDefinition.permissionsremoved, not demotedEvidence.
git grep -n "\.permissions"overpackages apps examplesat7e4f0e530: the only hits on aRoleDefinitionare three test comments documenting the dormancy. Every other hit is a different type (d.permissionsin AgentPreview,contract.permissions,version.permissions,counts.permissions). The four consumers ofRoleDefinition[]—evaluator.ts:18,resolveRolesat:92,store.ts:34,PermissionProvider.tsx:22— readnameandinheritsonly.The member card offered removal or demotion to optional. Removal, on all three axes:
ObjectPermissionConfig.roles, keyed by object. There is no producer either: five fixtures across three packages independently omitted the field until PR fix(permissions): type-check its tests (#4040 tranche 1) #4287 gave thempermissions: [], and every case still asserted what its author meant, because no code path was ever going to look.permissions: []to one fixture turnspnpm --filter @object-ui/permissions type-checkred witherror TS2353: Object literal may only specify known properties, and 'permissions' does not exist in type 'RoleDefinition'. A lenient optional key is exactly where AI-authored metadata errors hide.RoleDefinition's doc comment now records where grants live and that the second home was retired, so the next author does not re-declare it.Blast radius (the PM rider — this row's, not scope creep): the
permissions: []fixture convention from #4287, followed by #4326/#4338, becomes an excess-property error. Seven fixture lines in five files are cleaned, and the three comments that explained the empty array are rewritten to say where grants actually come from.Changeset shape. No
majorconflict arises: AGENTS.md §版本号策略 rules that objectui's own breaking changes are markedminorwith the breaking semantics spelled out in the body, the major being reserved for tracking@objectstack. That is what this changeset does, so there was nothing to escalate.Member 4 — #3773:
RecordContextValue.loading/errorEvidence. Zero producers: the two mount points pass neither —
RecordDetailView.tsx:2054passesobjectName / recordId / data / objectSchema / dataSource / embedded / refresh / headerSystemActions / isFavorite / onToggleFavorite, andPagePreview.tsx:192a subset.git grep -n -A 12 "RecordContextProvider"filtered toloading|erroracrosspackages appsreturns no prop on any provider, in source or tests. Zero consumers:git grep -n "ctx\.loading\|ctx\.error\|recordCtx\.loading\|recordCtx\.error"returns one hit,MetadataProvider.tsx:730— the Metadata context, a different context object, exactly as the triage comment said. Only the memo dep list named the two keys.Pin (
packages/react/src/context/__tests__/RecordContext.valueShape.pin.test.tsx). The provider spreads its props and hands consumers a memoized object, which makes the dep list a hand-maintained mirror of the interface — the drift that let these two keys sit in it for months. The pin joins both halves: a compile-time assertion that its key list is exactlykeyof RecordContextValue(checked bytsconfig.test.json, which this package'stype-checkchains), and a runtime sweep proving each listed key really re-memoizes. A new key cannot land half-wired, and a retired one cannot come back silently.Reverse verification
Deletions are proved by the zero-consumer greps above plus a green ladder; where a deletion could silently change behaviour, the direction was predicted before running it and each came back red as predicted (fix taken out with
git checkout/ edit-then-restore, nevergit stash):permissions: []on one role fixturestore.test.ts(17,36): error TS2353: … 'permissions' does not exist in type 'RoleDefinition'loading?: booleanre-added toRecordContextValueRecordContext.valueShape.pin.test.tsx(65,3): error TS2344: Type 'false' does not satisfy the constraint 'true'value.isFavoritedropped from the memo dep list× re-memoizes when isFavorite changes—expected {…} not to be {…}views:{object}invalidation restored indeleteViewexpected [ 'views:account', 'view:account:v1' ] to deeply equal [ 'view:account:v1' ]andexpected [ 'views:account' ] to deeply equal []Verification
Downstream sweeps run honestly — these deletions sit upstream of most of the repo, so the type gate was run repo-wide rather than scoped.
The repo-root vitest form is the one AGENTS.md §测试纪律 mandates; heavy phases ran under the shared verification lock.
Out of scope, filed as their own cards
view-overrides:{object}is only invalidated by updateViewConfig — createView / updateView / deleteView leave the batch map stale for the 5-minute TTL #4363 —view-overrides:{object}is invalidated byupdateViewConfigonly;createView/updateView/deleteViewleave the batch map stale for the 5-minute TTL, andloadViewOverridestreats a resolved map as authoritative (by design, data-objectstack 的 listViewOverrides 读的是meta/{对象名}(把对象名当 metadata type),写却落在type='view'—— 两边键空间不相交,已保存的视图个性化永远读不回来 #3774), so the per-view fallback cannot mask it. Pre-existing and untouched here — which is why the pin above asserts "noviews:key" forcreateViewinstead of freezing "invalidates nothing".ObjectLevelPermissionhas no consumer left onceRoleDefinition.permissionsis retired — a published type nothing references #4364 (finding) —ObjectLevelPermission, and transitivelyPermissionCondition, have no structural referent left once member 3 lands. Recorded rather than ridden along: retiring two more published types is its own row.Generated by Claude Code