You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Studio Data pillar ignores its renderListView slot's refreshKey — the prop was forwarded to a component that never declared it #4549
Surfaced by the repo-wide type-check canary in #4528 (PR pending), which is the first thing ever to check ListView's call sites. Filed rather than fixed there: #4528 is a type-only card and wiring this is a behaviour change.
What was measured
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx renders the Data pillar's grid through the plugin ObjectView's renderListView slot. That slot supplies a refreshKey (declared at packages/plugin-view/src/ObjectView.tsx:207), and renderStudioGridList forwarded it straight on:
refreshKey is not a prop of ListView, and it is not a prop of anything ListView renders. ListView keeps its own refreshKeylocal state (ListView.tsx:831) and drives refetching off schema.refreshTrigger plus that state; ObjectGrid likewise keeps its own local refreshKey state and declares no such prop. The incoming value rode ListView's {...props} forward into SchemaRenderer and was dropped.
Grepping the whole repo for refreshKey?: as a prop declaration returns plugin-view/ObjectView.tsx (the slot contract), StudioDesignSurface itself, and four unrelated components — no view component in the forward chain.
It type-checked only because ListViewProps carried a [key: string]: any that erased the whole interface (#4528), so no ListView call site was checked at all.
Why it was invisible
Bumping the prop still re-renders ListView (new prop object), and the Studio grid re-renders constantly anyway because its schema is a fresh object literal on every render. So "the list looks like it updates" — it just never refetches because ofrefreshKey.
The working precedent, 300 lines away
packages/app-shell/src/views/ObjectView.tsx:1592 consumes the same slot value correctly — it folds it into React's key so the subtree remounts:
#4528's PR removes the dead prop (behaviour-preserving) and leaves a comment at the declaration pointing here. So today the Studio Data pillar has no refreshKey path at all, which is what it effectively had before — the difference is that it is now visible.
Worth deciding
Whether the Studio Data pillar needs the slot refresh at all. If it does, the key fold above is the established shape. If it does not, the slot prop can be dropped from renderStudioGridList's signature entirely. Someone who knows what user action is meant to trigger it (record create / delete / publish?) should judge, since "remount the grid" also discards scroll position, selection and in-progress inline edits — AGENTS.md #8's "refresh data, don't rebuild UI" argues against the key fold as the long-term answer even though it is what the sibling does.
CLAIM — session_017Qqyix2QcnpUC9XeYVDzx3, branch claude/issue-4549-studio-grid-refresh. Dispatching a dev agent now (#4548's canary measured app-shell clean under the ruled option B, so StudioDesignSurface is safe to take).
PM ruling (delegated decision authority; maintainer veto window open — record objections here): measure-first with a preference order, honoring AGENTS.md #8 ("refresh data, don't rebuild UI"):
First measure whether the slot value ever bumps in the Studio mount — what increments plugin-view ObjectView's refreshKey (~:207), and whether any of those triggers fire on the Studio Data pillar path. If the slot value provably never changes there, the fix is deletion: drop the dead parameter from renderStudioGridList's signature and close the card as dead code — say so with the measurement.
If it does bump: prefer ListView's existing declarative refresh input — measure schema.refreshTrigger's semantics (does a CHANGED value refetch?); if yes, pass the slot refreshKey through it. Zero new API, no remount, scroll/selection/in-progress edits survive.
Else: ListViewHandle — measure whether the imperative handle already exposes a refresh; drive it from an effect on the slot value.
Key-fold is last resort only (the sibling's shape), with the UX cost (scroll/selection/edit loss) declared — and if reached, say why 1 and 2 measured unavailable.
If a real refresh channel is measured MISSING from ListView entirely (1 and 2 both unavailable), adding one is a plugin-list API change — STOP and report rather than inventing it under this card.
Red-first: bump the slot value → the grid refetches (find called again with the same params); pre-fix nothing refetches because of it. Pins: no bump ⇒ no extra fetch; the #4528-removed dead prop stays removed; Studio Data pillar's other behaviors (including the #4558 panel gating) untouched.
Changeset: '@object-ui/app-shell' patch expected (module-local wiring); plugin-list only if a measured channel edit is unavoidable (then STOP first). Never major.
Mutual exclusion: ⛔ #4548 in flight (packages/react + consumer fixes in plugin-dashboard/plugin-report — ZERO app-shell edits per its ruling); #4305 (app-shell FLOW files — disjoint from studio-design); #4564 (types/data-objectstack); #4553-p2 (fields/gantt). StudioDesignSurface's #4558-landed panel/inspector wiring is landed context — do not disturb it.
Activity
yinlianghui commentedon Aug 13, 2026
CLAIM — session_017Qqyix2QcnpUC9XeYVDzx3, branch
claude/issue-4549-studio-grid-refresh. Dispatching a dev agent now (#4548's canary measured app-shell clean under the ruled option B, so StudioDesignSurface is safe to take).PM ruling (delegated decision authority; maintainer veto window open — record objections here): measure-first with a preference order, honoring AGENTS.md #8 ("refresh data, don't rebuild UI"):
schema.refreshTrigger's semantics (does a CHANGED value refetch?); if yes, pass the slot refreshKey through it. Zero new API, no remount, scroll/selection/in-progress edits survive.If a real refresh channel is measured MISSING from ListView entirely (1 and 2 both unavailable), adding one is a plugin-list API change — STOP and report rather than inventing it under this card.
Red-first: bump the slot value → the grid refetches (find called again with the same params); pre-fix nothing refetches because of it. Pins: no bump ⇒ no extra fetch; the #4528-removed dead prop stays removed; Studio Data pillar's other behaviors (including the #4558 panel gating) untouched.
Changeset: '@object-ui/app-shell' patch expected (module-local wiring); plugin-list only if a measured channel edit is unavoidable (then STOP first). Never major.
Mutual exclusion: ⛔ #4548 in flight (packages/react + consumer fixes in plugin-dashboard/plugin-report — ZERO app-shell edits per its ruling); #4305 (app-shell FLOW files — disjoint from studio-design); #4564 (types/data-objectstack); #4553-p2 (fields/gantt). StudioDesignSurface's #4558-landed panel/inspector wiring is landed context — do not disturb it.
Generated by Claude Code
Generated by Claude Code
fix(types): DashboardRenderer and ListView serve their declared props…
chore(app-shell): the dead slot refreshKey parameter is removed (obje…
fix(app-shell): the Studio grid's columns keep a stable identity — no…