Skip to content
Merged
1 change: 1 addition & 0 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,3 +568,4 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-17 | codex/pwa-privacy-safe-20260717 | 35fa8c929d44a9bd84b3f7f2b795354d3b6dae02 | privacy-safe PWA shell and merge-readiness review | No remaining high-confidence product defect in the changed scope. The pre-push browser gate found and fixed one P2 test defect: cleanup referenced `PWA_CACHE_PREFIX` without passing it into the browser context, and the cold installability flow now has a focused 120-second budget. The worker caches only the generic offline page and allow-listed public shell assets; navigations, APIs, auth, queries, documents, uploads, signed URLs, range requests, and cross-origin traffic remain network-only. | Current-main integration; focused Vitest 81/81; full uncached ESLint; TypeScript; scoped Prettier and diff checks; production Webpack build generated 1,043 pages and the client-bundle secret scan passed; full Vitest produced 2,506 passes plus six contention timeouts, with all affected files passing 24/24 serially; focused Chromium PWA 2/2. No Supabase/OpenAI/live-provider checks run. |
| 2026-07-17 | codex/historical-branch-cleanup-20260717 | e36ac0c6628264c7ed6c494a597a62d0214b68f6 | branch-cleanup and historical-content recovery | Completed the pending historical cleanup: deleted 55 exact-SHA remote refs and 20 redundant local refs, removed nine clean merged worktrees, preserved every dirty, active, open-PR, or patch-unique worktree, and recovered the still-useful governance incident runbook from `codex/domain-1-governance-remediation`. Historical code changes were either tied to merged PRs or reviewed as superseded by current implementations; open PRs #699, #700, #702, and #704 remain protected. | Fresh `git fetch --prune`; GitHub PR inventory and exact commit-to-merged-PR associations; exact remote SHA rechecks before deletion; cherry-pick-aware logs; two-dot tree and branch-only-file review; Codex task-to-worktree cross-check; focused documentation validation recorded in the cleanup PR. No OpenAI, Supabase, production-data, or live clinical workflow was run. |
| 2026-07-17 | PR #704 / codex/scroll-geometry-stability-20260717 | 35e74ddbd61bacc5b34f06efbd58091f092665fd | nested scroll-source review follow-up | Confirmed the outside-diff CodeRabbit finding: the standalone shell shared one intent history across main and descendant scroll containers, so a switch from a deep main offset to a near-zero nested offset could falsely reveal chrome. Scroll metrics now identify their source, source changes rebase direction and travel while preserving visibility, and unit/UI regressions cover the switch. No unresolved actionable review finding remains. | Focused Vitest 9/9; TypeScript; scoped ESLint; Prettier; `git diff --check`. Exact-head hosted CI and UI remain required after push. No Supabase/OpenAI/live-provider checks run. |
| 2026-07-17 | codex/scrolling-cleanup-20260717 | ff77cd06c + latest origin/main sync | cross-page scrolling and interaction stability review | Fixed two confirmed P2 defects: desktop action-popup placement performed synchronous geometry work for every captured scroll event, and submitted differential searches with zero document matches fell back to the home state. Placement is now coalesced per animation frame with passive scroll listeners, and submitted empty-evidence results remain visible. Hardened three popup/navigation browser helpers that reproduced hydration timing failures. No other high-confidence defect remains in the scoped diff. | Scroll-focused Chromium 28/28; final affected Chromium 5/5; source regressions 2/2; scoped ESLint; Prettier; TypeScript and production build passed before the final upstream-only sync; `git diff --check`. The aggregate local Vitest/UI runs were affected by concurrent-worktree resource contention, so exact-head hosted CI remains required before merge. No Supabase/OpenAI/live-provider checks run. |
27 changes: 19 additions & 8 deletions src/components/clinical-dashboard/mode-action-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -620,16 +620,27 @@ export function ModeActionPopup({
useEffect(() => {
if (!open || useSheet) return;

let placementFrame: number | null = null;
const schedulePlacementUpdate = () => {
if (placementFrame !== null) return;
placementFrame = window.requestAnimationFrame(() => {
placementFrame = null;
updatePlacement();
});
};
const scrollOptions: AddEventListenerOptions = { capture: true, passive: true };

updatePlacement();
window.addEventListener("resize", updatePlacement);
window.addEventListener("scroll", updatePlacement, true);
window.visualViewport?.addEventListener("resize", updatePlacement);
window.visualViewport?.addEventListener("scroll", updatePlacement);
window.addEventListener("resize", schedulePlacementUpdate);
window.addEventListener("scroll", schedulePlacementUpdate, scrollOptions);
window.visualViewport?.addEventListener("resize", schedulePlacementUpdate);
window.visualViewport?.addEventListener("scroll", schedulePlacementUpdate, { passive: true });
return () => {
window.removeEventListener("resize", updatePlacement);
window.removeEventListener("scroll", updatePlacement, true);
window.visualViewport?.removeEventListener("resize", updatePlacement);
window.visualViewport?.removeEventListener("scroll", updatePlacement);
if (placementFrame !== null) window.cancelAnimationFrame(placementFrame);
window.removeEventListener("resize", schedulePlacementUpdate);
window.removeEventListener("scroll", schedulePlacementUpdate, scrollOptions);
window.visualViewport?.removeEventListener("resize", schedulePlacementUpdate);
window.visualViewport?.removeEventListener("scroll", schedulePlacementUpdate);
};
}, [open, updatePlacement, useSheet]);

Expand Down
1 change: 1 addition & 0 deletions src/components/differentials/differentials-home-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export function DifferentialsHomePage({ query = "", autoRunSearch = false }: Dif
<DifferentialsHome
query={query}
loading={loading}
searchSubmitted={autoRunSearch}
documentMatches={documentMatches}
evidenceQuery={evidenceQuery}
desktopComposerSlotId={modeHomeDesktopComposerSlotId}
Expand Down
34 changes: 34 additions & 0 deletions tests/ui-smoke.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,40 @@ test.describe("Clinical KB UI smoke coverage", () => {
await expectNoPageHorizontalOverflow(page);
});

test("desktop mode action placement coalesces scroll updates per frame", async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 900 });
await mockPrivateUnauthenticatedApi(page);
await gotoApp(page, "/");
await waitForDemoDashboardReady(page);

const trigger = page.getByRole("button", { name: "Open answer options" });
await trigger.evaluate((element) => {
const originalGetBoundingClientRect = element.getBoundingClientRect.bind(element);
element.dataset.placementReadCount = "0";
element.getBoundingClientRect = () => {
element.dataset.placementReadCount = String(Number(element.dataset.placementReadCount ?? "0") + 1);
return originalGetBoundingClientRect();
};
});

await openDailyActions(page, "Open answer options");
await page.evaluate(() => new Promise<void>((resolve) => requestAnimationFrame(() => resolve())));
await trigger.evaluate((element) => {
element.dataset.placementReadCount = "0";
});

const placementReads = await page.evaluate(async () => {
for (let index = 0; index < 20; index += 1) {
window.dispatchEvent(new Event("scroll"));
}
await new Promise<void>((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
const triggerElement = document.querySelector<HTMLElement>('button[aria-label="Open answer options"]');
return Number(triggerElement?.dataset.placementReadCount ?? "0");
});

expect(placementReads).toBeLessThanOrEqual(1);
});

test("demo answer flow reaches a source-backed answer @critical", async ({ browserName, page }) => {
await page.setViewportSize({ width: 390, height: 820 });
await mockDemoApi(page);
Expand Down
22 changes: 6 additions & 16 deletions tests/ui-tools.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1370,22 +1370,8 @@ test.describe("Clinical KB tools launcher", () => {
results: [],
visualEvidence: [],
relatedDocuments: [],
documentMatches: [
{
document_id: "11111111-1111-4111-8111-111111111111",
title: "Acute confusion differential guide",
file_name: "acute-confusion-differentials.pdf",
labels: [],
summarySnippet: "Reviewed acute confusion differential guidance.",
bestPages: [1],
bestChunkIds: ["chunk-acute-confusion"],
imageCount: 0,
tableCount: 0,
matchReason: "Matched indexed passage",
score: 0.93,
},
],
relevance: { verdict: "strong", score: 0.93, directSourceCount: 1, weakSourceCount: 0 },
documentMatches: [],
relevance: { verdict: "weak", score: 0, directSourceCount: 0, weakSourceCount: 0 },
smartPanel: {},
telemetry: { query_class: "differential_compare", retrieval_strategy: "text_fast_path" },
scope: { queryMode: "compare_guidance" },
Expand All @@ -1401,7 +1387,11 @@ test.describe("Clinical KB tools launcher", () => {
const submit = page.locator('button[aria-label="Search differential presentations"]:visible');
await input.fill("acute confusion");
await expect(submit).toBeEnabled();
const searchResponse = page.waitForResponse(
(response) => response.url().includes("/api/search") && response.request().method() === "POST",
);
await submit.click();
await searchResponse;

const compareAction = page.getByTestId("differentials-compare-selected-mobile");
const dock = page.locator("form.answer-footer-search-dock");
Expand Down