Filed by the domain:ui execution-seat PM (session session_01EMrWaQw3XS5DxTHxp4yRyC) from a live CI red, not from a census.
The observation
Test (shard 2/4) failed on PR #7577, head 681053908:
FAIL packages/plugin-detail/src/__tests__/RelatedList.serverpagination.test.tsx
> RelatedList — server-windowed pagination (#2711) > pages forward and back by refetching with a new $skip
AssertionError: expected [ { id: 'c5', name: 'Row 5' }, …(4) ] to have a length of 2 but got 5
at RelatedList.serverpagination.test.tsx:118:27
Tests 1 failed | 8124 passed (8125)
⭐ This is #7075's family, in a file #7076 did not reach
#7075 measured exactly this shape — "a test that settles only the FETCH chain … and then reads a SCHEMA-derived value is reading one promise resolution too early" — and PR #7076 repaired the four files it named:
RelatedList.sortabilitySignal · RelatedList.lookupCellLink · RelatedList.headerSort · RelatedList.relationalSort
RelatedList.serverpagination.test.tsx is not among them, and the reason is structural rather than an oversight: #7075's census used one specific mutation — deferring getObjectSchema by 50ms — which probes the schema chain. This site rides the pagination refetch chain instead, so that probe could not have flagged it. The census was sound for the question it asked; its bound just did not cover this one.
The defect, read from the source
RelatedList.serverpagination.test.tsx:114-119:
fireEvent.click(nextButton());
await screen.findByText('Page 3 of 3'); // gates on the LABEL only
expect(h.schema.data).toHaveLength(2); // reads the REFETCHED data
⭐ The same test settles the chain one step earlier and then stops doing it. Its page-2 step is gated:
fireEvent.click(nextButton());
await waitFor(() => {
expect(ds.find).toHaveBeenCalledWith('contact', { $filter: …, $top: 5, $skip: 5 });
});
await screen.findByText('Page 2 of 3');
The page-3 step drops that waitFor. The label is driven by pagination state and commits before the refetched rows reach h.schema.data, so the assertion samples the previous page — which is why the received value is 5, the page size, and not some arbitrary number.
⛔ The obvious patch is the trap this repo already recorded
The reflex fix is to copy the page-2 gate — waitFor(() => expect(ds.find).toHaveBeenCalledWith(…, { $skip: 10 })). Do not. #7075 names it:
⛔ Not expect(getObjectSchema).toHaveBeenCalled(): a mock call is issued one resolution before its value reaches state, which is the trap #6959 recorded.
A toHaveBeenCalledWith gate settles the call, not the value. It would make this site flake less often and fail identically, which is worse than the current honest red. ⚠️ Note this also means the page-2 gate above is not the model to copy — it is the same shape, one step luckier.
Suggested repair, in #7075's own words
Keep the existing gate (it proves the view committed with rows at all, and keeps any queryBy…toBeNull() read non-vacuous) and add a gate that settles the chain the assertion actually reads — here, the value itself:
await screen.findByText('Page 3 of 3');
await waitFor(() => expect(h.schema.data).toHaveLength(2));
expect(nextButton().disabled).toBe(true);
That does not weaken the assertion: if the data never reaches length 2, waitFor times out and the test still fails. ⛔ Do not skip, quarantine or widen a timeout. ⛔ Do not "fix" it by relaxing the expected length.
⚠️ Whoever takes this should re-run #7075's census with a mutation that probes the pagination refetch chain, not just the schema chain — this file was invisible to the original probe, and there is no reason to believe it is the only one. The four repaired files are the measured set of that probe, not of the class.
Operational cost, measured elsewhere
#7075 records why this matters beyond one red: "A flaky RED in the merge queue ejects unrelated PRs (#6959 measured two ejections in fifteen minutes, one PR failing and passing on byte-identical content)." Three PRs are in the queue as this is filed.
Not fixed on the PR that surfaced it
#7577's diff is five files, all in packages/types — a zod const rename plus a deprecated alias. Measured: StylePropsSchema has zero occurrences in packages/plugin-detail, packages/react or packages/components, with BaseSchema as the lit control in the same query shape returning 30 files across those roots. The diff cannot reach this test. Fixing it there would widen a contract-review PR with an unrelated test repair.
Filed unassigned.
Filed by the
domain:uiexecution-seat PM (sessionsession_01EMrWaQw3XS5DxTHxp4yRyC) from a live CI red, not from a census.The observation
Test (shard 2/4)failed on PR #7577, head681053908:⭐ This is #7075's family, in a file #7076 did not reach
#7075 measured exactly this shape — "a test that settles only the FETCH chain … and then reads a SCHEMA-derived value is reading one promise resolution too early" — and PR #7076 repaired the four files it named:
RelatedList.sortabilitySignal·RelatedList.lookupCellLink·RelatedList.headerSort·RelatedList.relationalSortRelatedList.serverpagination.test.tsxis not among them, and the reason is structural rather than an oversight: #7075's census used one specific mutation — deferringgetObjectSchemaby 50ms — which probes the schema chain. This site rides the pagination refetch chain instead, so that probe could not have flagged it. The census was sound for the question it asked; its bound just did not cover this one.The defect, read from the source
RelatedList.serverpagination.test.tsx:114-119:⭐ The same test settles the chain one step earlier and then stops doing it. Its page-2 step is gated:
The page-3 step drops that
waitFor. The label is driven by pagination state and commits before the refetched rows reachh.schema.data, so the assertion samples the previous page — which is why the received value is 5, the page size, and not some arbitrary number.⛔ The obvious patch is the trap this repo already recorded
The reflex fix is to copy the page-2 gate —
waitFor(() => expect(ds.find).toHaveBeenCalledWith(…, { $skip: 10 })). Do not. #7075 names it:A⚠️ Note this also means the page-2 gate above is not the model to copy — it is the same shape, one step luckier.
toHaveBeenCalledWithgate settles the call, not the value. It would make this site flake less often and fail identically, which is worse than the current honest red.Suggested repair, in #7075's own words
Keep the existing gate (it proves the view committed with rows at all, and keeps any
queryBy…toBeNull()read non-vacuous) and add a gate that settles the chain the assertion actually reads — here, the value itself:That does not weaken the assertion: if the data never reaches length 2,
waitFortimes out and the test still fails. ⛔ Do not skip, quarantine or widen a timeout. ⛔ Do not "fix" it by relaxing the expected length.Operational cost, measured elsewhere
#7075 records why this matters beyond one red: "A flaky RED in the merge queue ejects unrelated PRs (#6959 measured two ejections in fifteen minutes, one PR failing and passing on byte-identical content)." Three PRs are in the queue as this is filed.
Not fixed on the PR that surfaced it
#7577's diff is five files, all in
packages/types— a zod const rename plus a deprecated alias. Measured:StylePropsSchemahas zero occurrences inpackages/plugin-detail,packages/reactorpackages/components, withBaseSchemaas the lit control in the same query shape returning 30 files across those roots. The diff cannot reach this test. Fixing it there would widen a contract-review PR with an unrelated test repair.Filed unassigned.