From fb3757925d169bf43a7c2a1231e3b68890405814 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 21 Aug 2026 19:15:16 +0000 Subject: [PATCH 1/2] docs(issues): record that the five Windows test failures do not reproduce on Linux A full `npm run test` on a clean Windows workstation at cdfcbaccd exited 1 with four files and five tests failed. None of them reproduce here. On Linux at HEAD all five pass individually, and a full `GATE_RECEIPTS=off npm run test` is green: 696 files / 7770 tests passed, 4 skipped, exit 0. The document-viewer pair also passed three consecutive runs under 3x CPU oversubscription, so ordinary load does not reproduce it either. None of the four test files, nor their subjects, changed between cdfcbaccd and HEAD, so the Linux green applies to the reported SHA and the three intervening commits did not quietly fix these. The record keeps the classification open rather than closing it. Items 3-5 are timing shapes and are plausibly load-induced. Items 1 and 2 are deterministic state assertions, so a Windows-only failure there is a real Windows-only defect and must not be written off as environmental; closing them out needs the actual assertion text from that machine. It also captures the leads found by reading: the migration-role guard grades untracked files and hashes on-disk bytes, and the document-viewer `flushIdle()` helper is structurally fragile because the render-ahead effect never schedules an idle callback when the canvas budget resolves to one. `tests/flake-ledger.json` is explicitly Playwright-only, so none of these five Vitest failures are eligible for quarantine there. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01JEzkroXdtL9kYo8rW5eZh2 --- .../67bf71cf-25cb-40d9-a8a2-bbf993bf6b29.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/outstanding-issues-inbox/67bf71cf-25cb-40d9-a8a2-bbf993bf6b29.json diff --git a/docs/outstanding-issues-inbox/67bf71cf-25cb-40d9-a8a2-bbf993bf6b29.json b/docs/outstanding-issues-inbox/67bf71cf-25cb-40d9-a8a2-bbf993bf6b29.json new file mode 100644 index 0000000000..d2ef868bf8 --- /dev/null +++ b/docs/outstanding-issues-inbox/67bf71cf-25cb-40d9-a8a2-bbf993bf6b29.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "67bf71cf-25cb-40d9-a8a2-bbf993bf6b29", + "createdOn": "2026-08-21", + "action": "add", + "payload": { + "pri": "P2", + "type": "issue", + "summary": "Five npm run test failures reported on Windows at cdfcbaccd do not reproduce on Linux; full suite is green, and none are eligible for the Playwright-only flake ledger", + "detail": "Reported on a clean Windows workstation (D:\\Repos\\Database, main at cdfcbaccd, empty working tree): npm run test exited 1 with 4 files / 5 tests failed (tests/codex-cloud-setup.test.ts 'writes managed shell policy behaviorally and preserves unrelated Codex config'; tests/hosted-migration-role-guard.test.ts 'accepts the current repository state'; tests/http-readiness.test.ts 'honours the overall deadline when every response remains open'; tests/document-viewer-page-virtualization.dom.test.tsx 'reads exactly one page ahead and one behind, and only once idle' and 'collapses render-ahead to the reader's page alone when one canvas costs the whole budget', both failing at flushIdle() line 80 on await waitFor(() => expect(idleCallbacks.length).toBeGreaterThan(0))). VERIFIED ON LINUX at HEAD 1155041: all five pass individually, and a full GATE_RECEIPTS=off npm run test is green (696 files / 7770 tests passed, 4 skipped, exit 0, 196s). The document-viewer pair also passed 3/3 consecutive runs under 3x CPU oversubscription (12 spinners on 4 cores), so ordinary load does not reproduce it. git diff cdfcbaccd..1155041 shows none of the four test files, nor their subjects (scripts/check-hosted-migration-role.mjs, scripts/setup-codex-cloud.sh, supabase/**, src/components/document-viewer/**), changed between the reported SHA and HEAD, so the Linux green applies to cdfcbaccd itself and the three intervening commits did not fix these. CONCLUSION SO FAR: no genuine breakage on main is detectable from Linux; the failures are specific to that Windows workstation. NOT YET CLASSIFIED: whether each is environmental noise or a real Windows-only defect. Items 3-5 are timing shapes and are plausibly load-induced (the reported run took 601s vs 196s here). Items 1 and 2 are NOT timing shapes - they are deterministic state assertions - so a Windows-only failure there is a real Windows-only defect in either the test's Windows handling or the guard itself, and should not be dismissed as environmental. Needed to close this out: the actual assertion text from the Windows run (npx vitest run tests/hosted-migration-role-guard.test.ts tests/codex-cloud-setup.test.ts on that machine). CONCRETE LEADS: (a) hosted-migration-role-guard's validateRepository() calls repositoryEntries(), which runs git ls-files --cached --others --exclude-standard, so it grades UNTRACKED non-ignored files too - any stray file under scripts/, supabase/migrations/, .github/workflows/, or the guarded exact paths whose name or content matches the reserved role flips this test red, as would a nested git worktree directory under the repo root (readFileSync on a directory entry throws EISDIR); it also SHA-256s the on-disk bytes of supabase/migrations/20260713102000_revoke_supabase_admin_default_privileges.sql, so CRLF in the working tree would break it, though .gitattributes '* text=auto eol=lf' should prevent that and the bytes hash correctly here. (b) codex-cloud-setup's failing case shells out to Git Bash (C:\\Program Files\\Git\\bin\\bash.exe) with msys drive-letter path translation and asserts idempotency across two setup runs; only 1 of that file's 39 tests failed, so it is not a systemic bash/path breakage. (c) The document-viewer pair's shared failure point is structurally fragile independent of load: flushIdle() waits for requestIdleCallback to have been scheduled, but the viewer's render-ahead effect (src/components/document-viewer/pdf-canvas-viewer.tsx:781-792) returns early WITHOUT scheduling whenever liveCanvasLimit <= 1, and resolveLiveCanvasWindow returns 1 whenever perCanvasPixels is 0 - which is what jsdom's zero-width layout measurement yields before the ResizeObserver-driven contentWidth lands. The test's cancelIdleCallback stub is a no-op, so idleCallbacks only ever accumulates callbacks from earlier effect runs; if the first effect run measures a zero-width canvas, no callback is ever pushed and flushIdle times out at waitFor's 1000ms default regardless of machine speed. FLAKE POLICY DOES NOT APPLY: tests/flake-ledger.json is explicitly Playwright-only ('Only reproduced @quarantine Playwright tests belong here', entries need an exact spec+title and a @quarantine tag), and all five failures are Vitest. None of these can be quarantined there; they must be diagnosed or fixed. Also note the previously known local-Windows failures (tests/session-start-hook.test.ts, worker-observability) PASSED in the reported run, so any note calling those the known environmental set is stale.", + "source": "Session investigation on Linux cloud container at HEAD 1155041; full-suite log /tmp scratchpad fulltest.log; reported Windows run at cdfcbaccd", + "issueUlid": "01M0JVX4NP97J5B4FG2V62GNJZ" + } +} From 8a1ab1574f1c681158bc0e601ce5a7029cb40ce4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 21 Aug 2026 19:20:23 +0000 Subject: [PATCH 2/2] test(document-viewer): name the cause when render-ahead is never scheduled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both reported document-viewer failures land on the same line: `flushIdle()` waiting for `idleCallbacks.length` to exceed zero. All `waitFor` can say there is "expected 0 to be greater than 0", which reads as a slow machine and is usually not one. The viewer schedules a render-ahead idle callback only while `liveCanvasLimit > 1`, and `resolveLiveCanvasWindow` collapses that to 1 whenever `perCanvasPixels` is 0 — which is what jsdom's zero-width layout measurement yields before `contentWidth` lands. The test's `cancelIdleCallback` stub is a no-op, so `idleCallbacks` only ever accumulates callbacks from earlier effect runs. If the first run measures a zero-width canvas, none is ever pushed and no amount of waiting produces one. So the timeout now throws with the budget explanation and the observable state at that moment: slot count, rendered count, observer count. A run that mounted and rastered the reader's page but scheduled nothing is now distinguishable from one that was merely slow. Assertions are unchanged; this only replaces an opaque timeout with a named failure. Verified both ways: the file still passes 9/9, and forcing the stub to drop callbacks produces "8 page slot(s), 1 rendered, 1 intersection observer(s)". Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01JEzkroXdtL9kYo8rW5eZh2 --- ...nt-viewer-page-virtualization.dom.test.tsx | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/document-viewer-page-virtualization.dom.test.tsx b/tests/document-viewer-page-virtualization.dom.test.tsx index 616aae13a3..790f4a94e3 100644 --- a/tests/document-viewer-page-virtualization.dom.test.tsx +++ b/tests/document-viewer-page-virtualization.dom.test.tsx @@ -77,7 +77,28 @@ let animationFrameCallbacks = new Map(); let nextAnimationFrame = 1; async function flushIdle() { - await waitFor(() => expect(idleCallbacks.length).toBeGreaterThan(0)); + try { + await waitFor(() => expect(idleCallbacks.length).toBeGreaterThan(0)); + } catch (cause) { + // `waitFor` alone reports "expected 0 to be greater than 0", which reads as + // a slow machine and is usually not one. The viewer schedules render-ahead + // ONLY when `liveCanvasLimit > 1`, and `resolveLiveCanvasWindow` collapses + // that to 1 whenever `perCanvasPixels` is 0 — which is exactly what jsdom's + // zero-width layout measurement yields before `contentWidth` lands. In that + // case no callback is ever scheduled and no amount of waiting produces one, + // so say which of the two happened instead of timing out opaquely. + const slots = screen.queryAllByTestId("pdf-page-slot"); + throw new Error( + "No render-ahead idle callback was scheduled within the waitFor window. " + + "The viewer schedules one only while the canvas budget allows more than one live " + + "canvas; a zero-width measurement collapses that budget to the reader's page alone " + + "and skips scheduling entirely. Observed at timeout: " + + `${slots.length} page slot(s), ` + + `${slots.filter((slot) => slot.getAttribute("data-rendered") === "true").length} rendered, ` + + `${observers.length} intersection observer(s).`, + { cause }, + ); + } const pending = idleCallbacks; idleCallbacks = []; await act(async () => {