Filed by the os-dev seat working #7007 (session session_013hfmP9hoMd3dJwTh85J4yB), out of a measurement taken there. #7007 is scoped to ONE site and its card fences a rewrite, so this is filed rather than folded into that PR.
The shape
RelatedList fetches the related object's schema in its own effect (RelatedList.tsx:430) and derives sort/cell verdicts from it (withheldFromServerSort, the lookup cell renderers). A test that settles only the FETCH chain — waitFor(columnSortable('name') === true), or waitFor(h.schema?.type === 'data-table') — and then reads a SCHEMA-derived value is reading one promise resolution too early. With no schema in state the predicate falls through to isUnmaterializedFieldType(undefined), i.e. false, and the refusal under test has not happened yet.
These blocks are green today only because the schema effect is declared before the fetch effect and both mocks resolve on the same microtask. Nothing pins that ordering. 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).
The measurement — a census, with its bound stated
Timing FACT mutated inside the component and nothing else: the schema fetch deferred by 50ms, so it lands after the fetch chain instead of alongside it.
new Promise((r) => setTimeout(r, 50)).then(() => dataSource.getObjectSchema(api)).then(setObjectSchema)
Whole package run, pnpm exec vitest run packages/plugin-detail/:
- unmutated:
Test Files 118 passed (118), Tests 1089 passed (1089) - with the deferral:
Test Files 4 failed | 114 passed (118), Tests 17 failed | 1072 passed (1089)
The four:
| file | failing sites |
|---|
RelatedList.sortabilitySignal.test.tsx | :199 :213 :222 :229 :240 :250 :258 :303 :318 :329 :338 :351 |
RelatedList.lookupCellLink.test.tsx | :117 :128 :137 |
RelatedList.headerSort.test.tsx | :178 |
RelatedList.relationalSort.test.tsx | :111 |
The mutation was proved on disk before the run (anchor count 1 to 0, marker count 0 to 1, git diff --numstat = 1 1), and restored from HEAD after with a blob-hash comparison.
⭐ Hot control, and the reason this reading is not just "a delay breaks tests":RelatedList.unmaterializedSort.test.tsx — the file #7007 is about, with its #7007 fix applied — stays GREEN under this same deferral, while its unfixed spelling goes red under a weaker perturbation (the mock delayed rather than the call). So the probe distinguishes gated from ungated blocks rather than flagging everything that touches a schema.
Bound on what this proves
It proves the STRUCTURAL dependency: the assertion reads a value from a chain the block never settles. It does NOT prove these four have flaked in the merge queue. The queue is where #6959's ejections were measured; nobody has yet correlated a queue failure to these sites.
Suggested remedy, not a rewrite
The same one #7007 landed, per file: KEEP the existing gate — it is what proves the view committed with rows at all, and is what keeps a queryBy…).toBeNull() read non-vacuous — and ADD a second gate that settles the getObjectSchema chain. ⛔ Not expect(getObjectSchema).toHaveBeenCalled(): a mock call is issued one resolution before its value reaches state, which is the trap #6959 recorded. ⛔ Do not skip, quarantine or widen a timeout.
Each file needs its own judgement about which of its assertions ride the schema chain — sites listed above are the measured set, not a guess.
Dedupe bound, stated rather than implied
Both search channels were down for this seat: REST /search/issues answered 403, and MCP search_issues answered API rate limit already exceeded. The dedupe actually performed is a title-level scan over all 273 open issues pulled through the REST list endpoint, matched against relatedlist|settle|gate|chain|flak|race|racing|plugin-detail. No match. That bound does not cover a card that mentions these sites only in its body. If this duplicates something, close it against the original — the miss is this seat's.
Related: #7007 (the single-site card this came out of), #6959 and #6953 (the ejection precedent and the gate-substitution trap).
Generated by Claude Code
Filed by the
os-devseat working #7007 (sessionsession_013hfmP9hoMd3dJwTh85J4yB), out of a measurement taken there. #7007 is scoped to ONE site and its card fences a rewrite, so this is filed rather than folded into that PR.The shape
RelatedListfetches the related object's schema in its own effect (RelatedList.tsx:430) and derives sort/cell verdicts from it (withheldFromServerSort, the lookup cell renderers). A test that settles only the FETCH chain —waitFor(columnSortable('name') === true), orwaitFor(h.schema?.type === 'data-table')— and then reads a SCHEMA-derived value is reading one promise resolution too early. With no schema in state the predicate falls through toisUnmaterializedFieldType(undefined), i.e.false, and the refusal under test has not happened yet.These blocks are green today only because the schema effect is declared before the fetch effect and both mocks resolve on the same microtask. Nothing pins that ordering. 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).
The measurement — a census, with its bound stated
Timing FACT mutated inside the component and nothing else: the schema fetch deferred by 50ms, so it lands after the fetch chain instead of alongside it.
Whole package run,
pnpm exec vitest run packages/plugin-detail/:Test Files 118 passed (118),Tests 1089 passed (1089)Test Files 4 failed | 114 passed (118),Tests 17 failed | 1072 passed (1089)The four:
RelatedList.sortabilitySignal.test.tsx:199 :213 :222 :229 :240 :250 :258 :303 :318 :329 :338 :351RelatedList.lookupCellLink.test.tsx:117 :128 :137RelatedList.headerSort.test.tsx:178RelatedList.relationalSort.test.tsx:111The mutation was proved on disk before the run (anchor count 1 to 0, marker count 0 to 1,
git diff --numstat=1 1), and restored fromHEADafter with a blob-hash comparison.⭐ Hot control, and the reason this reading is not just "a delay breaks tests":
RelatedList.unmaterializedSort.test.tsx— the file #7007 is about, with its #7007 fix applied — stays GREEN under this same deferral, while its unfixed spelling goes red under a weaker perturbation (the mock delayed rather than the call). So the probe distinguishes gated from ungated blocks rather than flagging everything that touches a schema.Bound on what this proves
It proves the STRUCTURAL dependency: the assertion reads a value from a chain the block never settles. It does NOT prove these four have flaked in the merge queue. The queue is where #6959's ejections were measured; nobody has yet correlated a queue failure to these sites.
Suggested remedy, not a rewrite
The same one #7007 landed, per file: KEEP the existing gate — it is what proves the view committed with rows at all, and is what keeps a
queryBy…).toBeNull()read non-vacuous — and ADD a second gate that settles thegetObjectSchemachain. ⛔ Notexpect(getObjectSchema).toHaveBeenCalled(): a mock call is issued one resolution before its value reaches state, which is the trap #6959 recorded. ⛔ Do not skip, quarantine or widen a timeout.Each file needs its own judgement about which of its assertions ride the schema chain — sites listed above are the measured set, not a guess.
Dedupe bound, stated rather than implied
Both search channels were down for this seat: REST
/search/issuesanswered403, and MCPsearch_issuesansweredAPI rate limit already exceeded. The dedupe actually performed is a title-level scan over all 273 open issues pulled through the REST list endpoint, matched againstrelatedlist|settle|gate|chain|flak|race|racing|plugin-detail. No match. That bound does not cover a card that mentions these sites only in its body. If this duplicates something, close it against the original — the miss is this seat's.Related: #7007 (the single-site card this came out of), #6959 and #6953 (the ejection precedent and the gate-substitution trap).
Generated by Claude Code