Filed unassigned by the dev seat working objectui#7231 (session session_01NRRumy89BYdW9ogbcdHTho, branch claude/issue-7231-gantt-reload-stale-finally, PR #7236). Surfaced while enumerating reload()'s callers for that card. Out of scope there — that card is the finally guard alone — so it is recorded here rather than folded in.
Line numbers are on origin/main at 67dadd602 plus that branch's one-hunk change, i.e. packages/plugin-gantt/src/ObjectGantt.tsx as it reads today.
The observation
reload() has two modes. silent: true re-reads without touching loading, so GanttView stays mounted and keeps its scroll offset, collapsed groups, quick-filter state and any in-progress inline edit. Non-silent sets loading, and :1596's
if (loading) {
return placeholder;
}
returns before GanttView is rendered at all — so the whole chart unmounts and is rebuilt from scratch when the data comes back.
Every caller that re-reads an already-rendered view uses the silent mode, and deliberately so:
:1440 write-readback after a drag / resize / progress update:1484 write-readback after a dependency-link write:1585 write-readback after a delete:1753 toolbar refresh button:1820 write-readback after an inline edit in the record drawer
The one caller that does not is :712:
useEffect(() => {
reload();
}, [reload]);
It is always non-silent, and it fires on every change of reload's identity, not only on mount. reload's deps at :707 are effectiveDataSource, resource, hasInlineData, dataProvider, dataItems, schema.filter, schema.sort, objectSchema. So a host that changes schema.filter, schema.sort or the bound object on an already-rendered chart gets a full teardown and rebuild rather than a data refresh in place — the shape AGENTS.md #8's corollary ("refresh data, don't rebuild UI") rules out, reached through a conditional early return rather than through a key= bump.
Not measured
How often a host actually changes those props at runtime. The in-component QuickFilterBar filters displayTasks client-side and does not refetch, so the in-app quick filters are not this path. Whether any shipped host drives schema.filter / schema.sort / the bound object on a live chart is exactly what someone should establish before deciding this is worth changing — it is why this is filed as an observation and not as a bug.
A second thing not established: what the right shape would be. Making :712 silent on everything but the first load keeps the old rows on screen while the new query runs, which is a different lie (rows that do not match the new filter) unless it is paired with a visible busy state. That trade is a design call, not a mechanical fix.
Not this, to keep the boundaries clear
- objectui#7231 (the superseded-
finally guard) is a different fault and is already fixed on the PR above. That fix does not create or worsen this one: it changes only the two-reloads-in-flight case, and the teardown described here happens with a single reload in flight. - objectui#7210, objectui#7225 and objectui#6482 all remain open and are about which queries the gantt issues and whether they are gated or bounded. This observation is about what the component does to its own UI while a query it already decided to issue is running.
Generated by Claude Code
Filed unassigned by the dev seat working objectui#7231 (session
session_01NRRumy89BYdW9ogbcdHTho, branchclaude/issue-7231-gantt-reload-stale-finally, PR #7236). Surfaced while enumeratingreload()'s callers for that card. Out of scope there — that card is thefinallyguard alone — so it is recorded here rather than folded in.Line numbers are on
origin/mainat67dadd602plus that branch's one-hunk change, i.e.packages/plugin-gantt/src/ObjectGantt.tsxas it reads today.The observation
reload()has two modes.silent: truere-reads without touchingloading, soGanttViewstays mounted and keeps its scroll offset, collapsed groups, quick-filter state and any in-progress inline edit. Non-silent setsloading, and:1596'sreturns before
GanttViewis rendered at all — so the whole chart unmounts and is rebuilt from scratch when the data comes back.Every caller that re-reads an already-rendered view uses the silent mode, and deliberately so:
:1440write-readback after a drag / resize / progress update:1484write-readback after a dependency-link write:1585write-readback after a delete:1753toolbar refresh button:1820write-readback after an inline edit in the record drawerThe one caller that does not is
:712:It is always non-silent, and it fires on every change of
reload's identity, not only on mount.reload's deps at:707areeffectiveDataSource, resource, hasInlineData, dataProvider, dataItems, schema.filter, schema.sort, objectSchema. So a host that changesschema.filter,schema.sortor the bound object on an already-rendered chart gets a full teardown and rebuild rather than a data refresh in place — the shape AGENTS.md #8's corollary ("refresh data, don't rebuild UI") rules out, reached through a conditional early return rather than through akey=bump.Not measured
How often a host actually changes those props at runtime. The in-component
QuickFilterBarfiltersdisplayTasksclient-side and does not refetch, so the in-app quick filters are not this path. Whether any shipped host drivesschema.filter/schema.sort/ the bound object on a live chart is exactly what someone should establish before deciding this is worth changing — it is why this is filed as an observation and not as a bug.A second thing not established: what the right shape would be. Making
:712silent on everything but the first load keeps the old rows on screen while the new query runs, which is a different lie (rows that do not match the new filter) unless it is paired with a visible busy state. That trade is a design call, not a mechanical fix.Not this, to keep the boundaries clear
finallyguard) is a different fault and is already fixed on the PR above. That fix does not create or worsen this one: it changes only the two-reloads-in-flight case, and the teardown described here happens with a single reload in flight.Generated by Claude Code