Filed unassigned by the domain:ui execution seat while working #7828 (PR #7892). Not fixed there on purpose: that card's file surface is two test fixtures, and its ruling is explicitly Clause-② = no — no runtime code.
Duplicate check run before filing, with a control that fires: a repo-scoped listing of all 400 open issues, grepped locally (/search/* answers 403 for this seat). The control returned on-topic hits — #7232 (ObjectGantt's schema-resolution exits that never settle), #7233, #7237, and #7429 ($expand ungated at seven buildExpandFields sites, timeline among them) — so the absence of a match is a reading rather than a broken query. #7429 is the neighbouring but distinct concern: it is about the FLS gate on the expand set, not about when the record query fires.
The observation
ObjectTimeline is the one record view that never took objectui#6482 / objectui#7225's settled-schema gate. It still carries the pre-#7225 shape:
packages/plugin-timeline/src/ObjectTimeline.tsx:176 — a local useState for the object definition, not the shared useSettledSchema;
packages/plugin-timeline/src/ObjectTimeline.tsx:254 — objectDef is in the record-fetch effect's dependency array, so the effect runs once with the definition unresolved and again once it lands.
That is exactly the shape objectui#7225 ask 2 removed from ObjectGantt, whose own code comment describes the cost it was removing: "2 find calls and 1 getObjectSchema per load", and, whenever the metadata read is the slower of the two, "the user sees the full THREE-STEP PAINT — raw foreign-key ids, back to the loading placeholder, then the expanded rows". ObjectCalendar took the same gate at objectui#6453.
Measured, not inferred
Instrumented mock renderer counting writes per single mount, getObjectSchema held by a fixed delay, all three components in one vitest run (this is the trace PR #7892 produced while establishing that the two sibling fixtures do not paint twice):
| component |
hold |
paints when the arity predicate goes green |
paints total |
late writes |
ObjectTimeline |
+25ms |
1 |
4 |
3 |
ObjectTimeline |
unperturbed |
1 |
1 |
0 |
ObjectCalendar |
+0 / +25 / +100ms |
1 |
1 |
0 |
ObjectGantt |
+0 / +25 / +100ms |
1 |
1 |
0 |
The two gated components' first paint arrives only after the metadata read — their measured paint time tracks the hold (calendar 34ms at +25, 104ms at +100; gantt 31ms and 114ms) — and nothing follows it. ObjectTimeline paints at 15ms under a 25ms hold, i.e. before the metadata lands, and then writes three more times.
The container settles the two reads together by default, which is why the unperturbed row shows nothing and why this is invisible in ordinary local runs. A real backend with a cold MetadataCache is the profile objectui#6482's per-component standard names as the one where gating pays.
Why it is worth recording
It is the last unconverted member of a set that was deliberately converged: ObjectKanban, ObjectView, ObjectCalendar and ObjectTree were named in objectui#6482, ObjectGantt was ask 2 of objectui#7225. ObjectTimeline was in neither list, and nothing marks it as a deliberate exclusion.
Second-order, and the reason the measurement exists at all: this double paint is precisely what made objectui#7466's ladder fixture intermittently red, and it is why the timeline fixture needs harness guards that its two siblings — measured, in PR #7892 — do not need for any reason of their own.
⚠️ Not claimed here: that any user has reported this, or that the expand set is wrong. The $expand gap at this site is #7429's, and this card does not overlap it.
Back-links: #7828 / PR #7892 (where the trace was produced) · objectui#7225 (the shared hook and the gantt gate) · objectui#6453 (the calendar gate) · objectui#6482 (the ruling) · #7466 (the fixture failure this behaviour caused).
Generated by Claude Code
Filed unassigned by the
domain:uiexecution seat while working #7828 (PR #7892). Not fixed there on purpose: that card's file surface is two test fixtures, and its ruling is explicitlyClause-② = no— no runtime code.Duplicate check run before filing, with a control that fires: a repo-scoped listing of all 400 open issues, grepped locally (
/search/*answers 403 for this seat). The control returned on-topic hits — #7232 (ObjectGantt's schema-resolution exits that never settle), #7233, #7237, and #7429 ($expandungated at sevenbuildExpandFieldssites, timeline among them) — so the absence of a match is a reading rather than a broken query. #7429 is the neighbouring but distinct concern: it is about the FLS gate on the expand set, not about when the record query fires.The observation
ObjectTimelineis the one record view that never took objectui#6482 / objectui#7225's settled-schema gate. It still carries the pre-#7225 shape:packages/plugin-timeline/src/ObjectTimeline.tsx:176— a localuseStatefor the object definition, not the shareduseSettledSchema;packages/plugin-timeline/src/ObjectTimeline.tsx:254—objectDefis in the record-fetch effect's dependency array, so the effect runs once with the definition unresolved and again once it lands.That is exactly the shape objectui#7225 ask 2 removed from
ObjectGantt, whose own code comment describes the cost it was removing: "2findcalls and 1getObjectSchemaper load", and, whenever the metadata read is the slower of the two, "the user sees the full THREE-STEP PAINT — raw foreign-key ids, back to the loading placeholder, then the expanded rows".ObjectCalendartook the same gate at objectui#6453.Measured, not inferred
Instrumented mock renderer counting writes per single mount,
getObjectSchemaheld by a fixed delay, all three components in one vitest run (this is the trace PR #7892 produced while establishing that the two sibling fixtures do not paint twice):ObjectTimelineObjectTimelineObjectCalendarObjectGanttThe two gated components' first paint arrives only after the metadata read — their measured paint time tracks the hold (calendar 34ms at +25, 104ms at +100; gantt 31ms and 114ms) — and nothing follows it.
ObjectTimelinepaints at 15ms under a 25ms hold, i.e. before the metadata lands, and then writes three more times.The container settles the two reads together by default, which is why the unperturbed row shows nothing and why this is invisible in ordinary local runs. A real backend with a cold
MetadataCacheis the profile objectui#6482's per-component standard names as the one where gating pays.Why it is worth recording
It is the last unconverted member of a set that was deliberately converged:
ObjectKanban,ObjectView,ObjectCalendarandObjectTreewere named in objectui#6482,ObjectGanttwas ask 2 of objectui#7225.ObjectTimelinewas in neither list, and nothing marks it as a deliberate exclusion.Second-order, and the reason the measurement exists at all: this double paint is precisely what made objectui#7466's ladder fixture intermittently red, and it is why the timeline fixture needs harness guards that its two siblings — measured, in PR #7892 — do not need for any reason of their own.
$expandgap at this site is #7429's, and this card does not overlap it.Back-links: #7828 / PR #7892 (where the trace was produced) · objectui#7225 (the shared hook and the gantt gate) · objectui#6453 (the calendar gate) · objectui#6482 (the ruling) · #7466 (the fixture failure this behaviour caused).
Generated by Claude Code