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" + } +} 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 () => {