From a3b9d3b09ea92d6f8add68bd7b60b1b189950d09 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 19:24:19 +0000
Subject: [PATCH 01/13] Fix differentials results top clipped by ModeHomeMain
centering
Tall search results were vertically centered inside ModeHomeMain, so on
phones the Best Answer and header band sat above the scrollport. Top-align
results via an explicit contentAlign prop (cn cannot override justify-*),
and prove Best Answer remains in the fold at scrollTop 0.
Co-authored-by: BigSimmo
---
.../clinical-dashboard/differentials-home.tsx | 1 +
.../differentials/differentials-home-page.tsx | 4 ++-
src/components/mode-home-template.tsx | 12 ++++++++-
tests/differentials-mode-home-align.test.ts | 21 +++++++++++++++
tests/ui-tools.spec.ts | 26 +++++++++++++++++++
5 files changed, 62 insertions(+), 2 deletions(-)
create mode 100644 tests/differentials-mode-home-align.test.ts
diff --git a/src/components/clinical-dashboard/differentials-home.tsx b/src/components/clinical-dashboard/differentials-home.tsx
index 95f375323..59d1fd379 100644
--- a/src/components/clinical-dashboard/differentials-home.tsx
+++ b/src/components/clinical-dashboard/differentials-home.tsx
@@ -526,6 +526,7 @@ function BestAnswerCard({
return (
+ // Results are taller than the phone viewport; keep them top-aligned so the
+ // Best Answer / query band are not clipped by flex centering.
+
diff --git a/tests/differentials-mode-home-align.test.ts b/tests/differentials-mode-home-align.test.ts
new file mode 100644
index 000000000..751415841
--- /dev/null
+++ b/tests/differentials-mode-home-align.test.ts
@@ -0,0 +1,21 @@
+import { readFileSync } from "node:fs";
+import { resolve } from "node:path";
+import { describe, expect, it } from "vitest";
+
+describe("differentials ModeHomeMain alignment", () => {
+ it("top-aligns tall search results and keeps empty home centred", () => {
+ const pageSource = readFileSync(
+ resolve(process.cwd(), "src/components/differentials/differentials-home-page.tsx"),
+ "utf8",
+ );
+ const modeHomeSource = readFileSync(resolve(process.cwd(), "src/components/mode-home-template.tsx"), "utf8");
+
+ // Results path must opt into start alignment via the ModeHomeMain prop —
+ // className overrides are unreliable because cn() does not merge Tailwind.
+ expect(pageSource).toMatch(/contentAlign=\{autoRunSearch \? "start" : "center"\}/);
+ expect(modeHomeSource).toMatch(/contentAlign\s*=\s*"center"/);
+ expect(modeHomeSource).toMatch(/contentAlign === "start"/);
+ expect(modeHomeSource).toMatch(/justify-start/);
+ expect(modeHomeSource).toMatch(/justify-center/);
+ });
+});
diff --git a/tests/ui-tools.spec.ts b/tests/ui-tools.spec.ts
index 717cc700e..2015138e9 100644
--- a/tests/ui-tools.spec.ts
+++ b/tests/ui-tools.spec.ts
@@ -1449,6 +1449,32 @@ test.describe("Clinical KB tools launcher", () => {
expect(badgeMetrics.height).toBeGreaterThanOrEqual(22);
expect(badgeMetrics.scrollHeight).toBeLessThanOrEqual(badgeMetrics.height + 1);
+ // Tall results must be top-aligned: Best Answer stays reachable at scrollTop 0.
+ const mainContent = page.locator("#main-content");
+ await expect.poll(() => mainContent.evaluate((element) => element.scrollTop)).toBe(0);
+ const bestAnswer = page.getByTestId("differential-best-answer");
+ await expect(bestAnswer).toBeVisible();
+ const foldLayout = await bestAnswer.evaluate((best) => {
+ const main = document.querySelector("#main-content");
+ const header = document.querySelector("header.universal-header");
+ if (!main) return null;
+ const bestRect = best.getBoundingClientRect();
+ const headerBottom = header?.getBoundingClientRect().bottom ?? main.getBoundingClientRect().top;
+ return {
+ scrollTop: main.scrollTop,
+ bestTop: bestRect.top,
+ bestBottom: bestRect.bottom,
+ headerBottom,
+ viewportHeight: window.innerHeight,
+ };
+ });
+ expect(foldLayout).not.toBeNull();
+ expect(foldLayout!.scrollTop).toBe(0);
+ // Best Answer must start in the visible fold under the chrome — not clipped
+ // above the scrollport (the ModeHomeMain justify-center regression).
+ expect(foldLayout!.bestTop).toBeGreaterThanOrEqual(foldLayout!.headerBottom - 2);
+ expect(foldLayout!.bestTop).toBeLessThan(foldLayout!.viewportHeight * 0.55);
+
// Phone list hides the featured best answer, so ranks must start at 1.
const mobileCards = page.getByTestId("differential-mobile-result-card");
await expect(mobileCards.first()).toBeVisible();
From 2df3181859345339d777ac814908b3095cea36fd Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 19:29:22 +0000
Subject: [PATCH 02/13] Harden ModeHomeMain alignment API against flex-center
regressions
Trace the clipped differentials top to 39d14a51's always-centered flex
shell. Expose exclusive contentAlign values (center/start/startOnPhone),
strip stray justify-* className tokens, migrate therapy/formulation/
specifiers off fragile overrides, and add static + Playwright guards so
tall results cannot silently re-center and hide their top again.
Co-authored-by: BigSimmo
---
docs/process-hardening.md | 1 +
.../clinical-dashboard/differentials-home.tsx | 19 ++++-
.../differentials/differentials-home-page.tsx | 9 ++-
.../formulation/formulation-home-page.tsx | 2 +-
src/components/mode-home-template.tsx | 48 +++++++++---
.../specifiers/specifiers-home-page.tsx | 2 +-
.../therapy-compass/screens/home-screen.tsx | 2 +-
tests/differentials-mode-home-align.test.ts | 21 -----
tests/mode-home-main-align.test.ts | 76 +++++++++++++++++++
9 files changed, 137 insertions(+), 43 deletions(-)
delete mode 100644 tests/differentials-mode-home-align.test.ts
create mode 100644 tests/mode-home-main-align.test.ts
diff --git a/docs/process-hardening.md b/docs/process-hardening.md
index 6256d49cd..264d4a9a7 100644
--- a/docs/process-hardening.md
+++ b/docs/process-hardening.md
@@ -4,6 +4,7 @@ This document turns the current process review into phased, durable repo practic
## Repository cleanup follow-ups (2026-07-19)
+- **ModeHomeMain vertical alignment (fixed in #938):** commit `39d14a51` made standalone mode homes a `flex-1 justify-center` shell. That centres short empty homes correctly, but when differentials (and any tall results view) reused the same wrapper, the top of the content was clipped above the phone scrollport — white gap under the header, Best Answer unreachable, first visible list card looking like rank “2”. Prefer `ModeHomeMain`’s `contentAlign` prop (`center` | `start` | `startOnPhone`); never pass `justify-*` via `className` (`cn()` does not merge Tailwind). Guards: `tests/mode-home-main-align.test.ts` plus the narrow-viewport Best Answer fold assertion in `tests/ui-tools.spec.ts`.
- **High-priority local process ownership:** `scripts/run-eval-safe.mjs` still scans for and terminates residual repository processes through `cleanupResidualEvaluationProcesses()`. A superseded RAG safety worktree contained a narrower child-owned `terminateOwnedProcessTree(child.pid)` approach plus a regression test proving unrelated Vitest, Playwright, and Next processes remain untouched. Do not cherry-pick that stale worktree wholesale; isolate this process-ownership fix on current `main`, then verify it statically without starting a provider-backed evaluation. Modifying or exercising the eval workflow remains approval-gated.
- **Provider-gated RAG safety ideas:** the same stale worktree contained conservative answer-quality thresholds, an evaluation cost-cap preflight, production-safety validation, deep-health assessment, and citation/vector proof tests. Its 754-line retrieval migration and route changes conflict with the later public-title privacy and migration chain and must not be replayed. If explicitly approved, rescope only the still-relevant preflight utilities and tests against current `main`; keep live OpenAI/Supabase validation separate.
- **Semantic reranking rollout debt:** PR #901 keeps `RAG_SEMANTIC_RERANK_ENABLED=false`. Do not enable it until the provider-backed 36/36 retrieval-quality gate and an ambiguity-focused canary are explicitly approved and recorded.
diff --git a/src/components/clinical-dashboard/differentials-home.tsx b/src/components/clinical-dashboard/differentials-home.tsx
index 59d1fd379..dcd841a42 100644
--- a/src/components/clinical-dashboard/differentials-home.tsx
+++ b/src/components/clinical-dashboard/differentials-home.tsx
@@ -571,14 +571,25 @@ function BestAnswerCard({
{onToggle ? : null}
-
+
{best.subtitle}
-
+
{visibleTags.map((tag) => (
- {tag}
+
+ {tag}
+
))}
- {hiddenTagCount > 0 ? {`+${hiddenTagCount}`} : null}
+ {hiddenTagCount > 0 ? (
+
+ {`+${hiddenTagCount}`}
+
+ ) : null}
);
diff --git a/src/components/differentials/differentials-home-page.tsx b/src/components/differentials/differentials-home-page.tsx
index 4ec7ac123..ca3847153 100644
--- a/src/components/differentials/differentials-home-page.tsx
+++ b/src/components/differentials/differentials-home-page.tsx
@@ -87,10 +87,13 @@ export function DifferentialsHomePage({ query = "", autoRunSearch = false }: Dif
[router, routedSearchContext.queryMode, routedSearchContext.scopeFilters],
);
+ // `autoRunSearch` is true on /differentials?q=…&run=1 — that mounts the tall
+ // SearchResultsView. Empty homes stay centred; results must top-align or the
+ // Best Answer / query band are clipped above the phone scrollport.
+ const showingResults = autoRunSearch;
+
return (
- // Results are taller than the phone viewport; keep them top-aligned so the
- // Best Answer / query band are not clipped by flex centering.
-
+
+
= {
+ // Short empty homes — centre in the visible canvas.
+ center: "justify-center pt-[clamp(1.25rem,4vh,2.25rem)] sm:pt-[clamp(1.75rem,5vh,3.25rem)]",
+ // Tall results / content — keep the top reachable on every breakpoint.
+ start: "justify-start pt-3 sm:pt-4",
+ // Content-rich homes that still fit after sm — top-align on phone only.
+ startOnPhone: "justify-start pt-3 sm:justify-center sm:pt-[clamp(1.75rem,5vh,3.25rem)]",
+};
+
+function withoutJustifyUtilities(className?: string) {
+ if (!className) return undefined;
+ const cleaned = className
+ .replace(/\bjustify-(?:normal|start|end|center|between|around|evenly|stretch)\b/g, "")
+ .replace(/\s+/g, " ")
+ .trim();
+ return cleaned || undefined;
+}
+
+/**
+ * Standalone-route wrapper that mirrors the dashboard mode homes. The shell
+ * reserves composer clearance via --mobile-composer-reserve on #main-content.
*/
export function ModeHomeMain({
testId,
@@ -113,17 +139,15 @@ export function ModeHomeMain({
testId?: string;
children: ReactNode;
className?: string;
- contentAlign?: "center" | "start";
+ contentAlign?: ModeHomeMainAlign;
}) {
return (
{children}
diff --git a/src/components/specifiers/specifiers-home-page.tsx b/src/components/specifiers/specifiers-home-page.tsx
index 9d29bee15..77a535267 100644
--- a/src/components/specifiers/specifiers-home-page.tsx
+++ b/src/components/specifiers/specifiers-home-page.tsx
@@ -101,7 +101,7 @@ function SpecifierPathwayStrip() {
function SpecifiersHome() {
return (
-
+
+
{
- it("top-aligns tall search results and keeps empty home centred", () => {
- const pageSource = readFileSync(
- resolve(process.cwd(), "src/components/differentials/differentials-home-page.tsx"),
- "utf8",
- );
- const modeHomeSource = readFileSync(resolve(process.cwd(), "src/components/mode-home-template.tsx"), "utf8");
-
- // Results path must opt into start alignment via the ModeHomeMain prop —
- // className overrides are unreliable because cn() does not merge Tailwind.
- expect(pageSource).toMatch(/contentAlign=\{autoRunSearch \? "start" : "center"\}/);
- expect(modeHomeSource).toMatch(/contentAlign\s*=\s*"center"/);
- expect(modeHomeSource).toMatch(/contentAlign === "start"/);
- expect(modeHomeSource).toMatch(/justify-start/);
- expect(modeHomeSource).toMatch(/justify-center/);
- });
-});
diff --git a/tests/mode-home-main-align.test.ts b/tests/mode-home-main-align.test.ts
new file mode 100644
index 000000000..128aabf9e
--- /dev/null
+++ b/tests/mode-home-main-align.test.ts
@@ -0,0 +1,76 @@
+import { readFileSync, readdirSync, statSync } from "node:fs";
+import { join, resolve } from "node:path";
+import { describe, expect, it } from "vitest";
+
+const SRC_ROOT = resolve(process.cwd(), "src");
+
+function walkTsxFiles(dir: string, out: string[] = []): string[] {
+ for (const entry of readdirSync(dir)) {
+ const fullPath = join(dir, entry);
+ const stats = statSync(fullPath);
+ if (stats.isDirectory()) {
+ walkTsxFiles(fullPath, out);
+ continue;
+ }
+ if (fullPath.endsWith(".tsx")) out.push(fullPath);
+ }
+ return out;
+}
+
+describe("ModeHomeMain alignment contract", () => {
+ const modeHomeSource = readFileSync(resolve(SRC_ROOT, "components/mode-home-template.tsx"), "utf8");
+ const differentialsPageSource = readFileSync(
+ resolve(SRC_ROOT, "components/differentials/differentials-home-page.tsx"),
+ "utf8",
+ );
+
+ it("owns exclusive justify alignment via contentAlign (cn cannot merge Tailwind)", () => {
+ expect(modeHomeSource).toMatch(/export type ModeHomeMainAlign/);
+ expect(modeHomeSource).toMatch(/MODE_HOME_MAIN_ALIGN_CLASS/);
+ expect(modeHomeSource).toMatch(/withoutJustifyUtilities/);
+ expect(modeHomeSource).toMatch(/center: "justify-center/);
+ expect(modeHomeSource).toMatch(/start: "justify-start/);
+ expect(modeHomeSource).toMatch(/startOnPhone: "justify-start/);
+ // Alignment must win over consumer className — apply align map last.
+ expect(modeHomeSource).toMatch(
+ /withoutJustifyUtilities\(className\),\s*MODE_HOME_MAIN_ALIGN_CLASS\[contentAlign\]/,
+ );
+ });
+
+ it("top-aligns differentials search results and keeps the empty home centred", () => {
+ expect(differentialsPageSource).toMatch(/const showingResults = autoRunSearch/);
+ expect(differentialsPageSource).toMatch(/contentAlign=\{showingResults \? "start" : "center"\}/);
+ });
+
+ it("migrates content-rich homes off fragile className justify overrides", () => {
+ const homeSources = [
+ resolve(SRC_ROOT, "components/therapy-compass/screens/home-screen.tsx"),
+ resolve(SRC_ROOT, "components/formulation/formulation-home-page.tsx"),
+ resolve(SRC_ROOT, "components/specifiers/specifiers-home-page.tsx"),
+ ].map((path) => readFileSync(path, "utf8"));
+
+ for (const source of homeSources) {
+ expect(source).toMatch(/contentAlign="startOnPhone"/);
+ expect(source).not.toMatch(/ModeHomeMain[^>]*className="[^"]*justify-/);
+ }
+ });
+
+ it("forbids ModeHomeMain className justify-* overrides across src/", () => {
+ // Regression: 39d14a51 made ModeHomeMain a flex-1 justify-center shell.
+ // Call-site className="justify-start …" looked like a fix but cn() leaves
+ // both utilities in the class string, so CSS source order decides — flaky.
+ const offenders: string[] = [];
+ for (const filePath of walkTsxFiles(SRC_ROOT)) {
+ const source = readFileSync(filePath, "utf8");
+ if (!source.includes("ModeHomeMain")) continue;
+ const matches = source.matchAll(//g);
+ for (const match of matches) {
+ const attrs = match[1] ?? "";
+ if (/className=\{?["'`][^"'`]*justify-/.test(attrs) || /className=\{[^}]*justify-/.test(attrs)) {
+ offenders.push(`${filePath.replace(`${process.cwd()}/`, "")}: ModeHomeMain className contains justify-*`);
+ }
+ }
+ }
+ expect(offenders).toEqual([]);
+ });
+});
From 300f8b0010543ce0131d293c74904b2f1e0011b7 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 19:38:52 +0000
Subject: [PATCH 03/13] Record PR #938 ModeHomeMain alignment review in ledger
Co-authored-by: BigSimmo
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index 8896a0d8c..5d2aedeaa 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -621,3 +621,4 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-18 | claude/clinical-kb-pwa-review-asi3wb (PR #896, plan Phase 5; content commit + this ledger follow-up) | a6c2b4e92374e9002fb00c547eb5677d01ce538c | Design-polish sweep: audit-then-fix (plan Phase 5, final phase) | Audit on post-#890 main: three strict design guards clean; full re-run of the 07-token-adoption-audit grep method shows all July 3 debt resolved (M1–M3 done, L4 reduced to the deliberate theme-aware `ring-white/N dark:ring-white/10` glass idiom, L5/L7 gone; production hex all legitimate print/brand/console/comment classes); 43-capture live sweep across 15 routes × desktop/phone + 320px spots + dark/reduced-motion/forced-colors spots found 0 overflow and 0 console errors. Three defects found and fixed: (1) forced-colors solid-button labels rendered as blank Canvas-on-Canvas backplate boxes (axe-invisible) — command controls flattened to the native HCM ButtonFace/ButtonText pairing and accent glyph tokens flipped to ButtonText inside the existing forced-colors block, regression-locked by a new ui-accessibility test; (2) tools desktop 6-up quick-action rail truncated card titles at 1440×1000 — card metrics tightened, all six titles verified unclipped; (3) privacy page rendered "systemand" from a JSX newline-adjacent-to-tag drop — explicit space, locked by a privacy-ui assertion. Dated July 18 run appended to docs/redesign/07-token-adoption-audit.md (archived design-qa.md not resurrected). | Guards + focused vitest 14/14; `verify:cheap` chain green to the known container-only pdf-extraction-budget artifact (2806/2809); `verify:ui` 220 passed/2 failed (the two long-baselined container artifacts, hosted-CI-green through #826/#835/#872/#890); `test:e2e:accessibility` 8/8 incl. the new forced-colors token test; production build + client-bundle secret scan passed; `check:bundle-budget` within tolerance vs the Phase 4 ratchet (1290.6 vs 1278.6 KiB baseline); `verify:pr-local` runtime/format/lint/typecheck/build/rag-fixtures green with the same sole unit-suite artifact. `verify:release` not run (provider-backed; awaits explicit confirmation). No provider-backed checks run. |
| 2026-07-19 | all remote feature branches and registered worktrees against `origin/main` through PR #899 | 8242fa63d5f5b79fc770c9ae4f633e3a784b80e1 | branch/worktree cleanup, useful-work recovery, and protected-main merge closure | Deleted 122 stale or closed remote feature refs with exact SHA leases; four additional merged PR branches were removed by the protected-main PR workflow. Removed 32 obsolete, superseded, or merge-proven worktree registrations. Recovered useful dirty RAG work into PR #901 (deterministic and opt-in semantic reranking) and PR #902 (retrieval phase latency telemetry), preserved follow-up decisions in `docs/process-hardening.md`, and recovered four missing historical review rows. PRs #897, #899, #901, and #902 are merged with green exact-head checks and zero unresolved review threads. A detached full-repo-review worktree is deliberately retained because its ownership/activity could not be safely disproved; one unregistered `node_modules` junction residue is also retained because deletion was denied by local safety policy. | Fresh fetch/prune; full GitHub PR/check/thread inventory; `git worktree list --porcelain`; cherry-pick-aware right-only logs; exact leased remote deletes; exact-old-value local ref deletes; clean-worktree, path, and merged-PR proof before every removal. PR #899 local proof: focused Vitest 31/31, changed-file ESLint, `verify:cheap` 317 files / 2,879 tests, and `verify:ui` 239/239; exact-head hosted checks all passed. PR #901 local proof: `verify:cheap` 316 files / 2,870 tests; PR #902 focused Vitest 8/8 plus ESLint and typecheck. No OpenAI, Supabase, live clinical, deployment, or production-data workflow ran; provider-backed semantic canary evaluation remains approval-gated. |
| 2026-07-19 | main / `codex/supabase-database-review` | 4034d2e60ebb6616130ff17bf3cb69368f36f8f6 + reviewed working diff | live `Clinical KB Database` security, migration, schema-drift, integrity, and performance review against current repo | Confirmed and remediated a P1 privacy defect: 601 private-document title-vocabulary rows were reachable by the service-role query corrector; the live public-only sync/backfill now reports zero private or out-of-scope rows. Applied the committed retrieval-count bound, audit-metadata minimization, registry cleanup/index, public-title corrector, and atomic summary-rate-limit migrations. The missing FK and registry indexes are present and no invalid indexes remain. A second P1 was found in the untracked live `ingestion-worker`: gateway JWT verification accepted any project JWT before privileged direct-Postgres job processing. Recovered the deployed source into the repo, restricted it to POST plus a gateway-verified `service_role` claim, expanded the Deno checker to every tracked Edge Function, and deployed exact-matching v13 with JWT verification enabled. Review also exposed a repo mirror/test gap: the count-clamp migration was not reflected in `schema.sql`; the branch now mirrors it and locks both sources in the focused test. Remaining hosted blocker: `postgres` cannot assume managed `supabase_admin`, so the fail-closed default-ACL migrations and final title-word constraint/trigger migration remain unapplied; the intentional service-role-only table still produces one INFO no-policy advisor. | Supabase connector project identity, migration and Edge Function inventory, full drift snapshot comparison, security/performance advisors, catalog integrity/ACL/index queries, Vault JWT-role compatibility check, post-apply invariants, exact deployed-source hashes, and unauthenticated live rejection (401); focused retrieval/schema/drift Vitest 82/83 with only manifest freshness failing; Edge/retrieval auth 9/9; Deno check for both functions; offline RAG 36 cases / 294 tests; function-grant guard; scoped ESLint, Prettier, and `git diff --check`. `check:supabase-project` was attempted but stopped before provider contact because local project env vars are unset. `drift:manifest` was blocked because Docker Desktop could not start and was cleaned up. `verify:cheap`, `verify:pr-local`, production-readiness, OpenAI, hosted CI, broader deployment, and commit/push were not run. |
+| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 2df3181859345339d777ac814908b3095cea36fd | ModeHomeMain contentAlign fix for differentials mobile clipping | No high-confidence P0–P2. Fix correctly introduces exclusive `contentAlign` (`center` \| `start` \| `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`. | Static diff vs `origin/main`; inventory of all `ModeHomeMain` call sites; justify-strip regex probe; `npx vitest run tests/mode-home-main-align.test.ts` 4/4. Not run: Playwright/`verify:ui` (browser), `verify:cheap`/`verify:pr-local`, provider-backed checks. |
From 74c370d81342dd729398dc2b40ba3158ea30f1db Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 19:42:38 +0000
Subject: [PATCH 04/13] Polish ModeHomeMain alignment guards and restore PR
#938 body
Rewrite PR_POLICY_BODY.md so Sync PR policy body no longer overwrites #938
with the stale #932 admin/migration summary. Strip responsive justify-*
tokens, give Chip an exclusive density scale, top-align remaining
content-rich mode homes, harden the home header wait against hydration
double-mount, and bind the Best Answer fold check to the header band.
Co-authored-by: BigSimmo
---
PR_POLICY_BODY.md | 21 +++++++++-------
.../clinical-dashboard/differentials-home.tsx | 24 ++++++++++++++-----
src/components/dsm/dsm-home-page.tsx | 2 +-
src/components/forms/forms-home-page.tsx | 2 +-
src/components/mode-home-template.tsx | 3 ++-
.../services/services-home-page.tsx | 2 +-
tests/mode-home-main-align.test.ts | 18 ++++++++++++++
tests/ui-overlap.spec.ts | 9 ++++++-
tests/ui-tools.spec.ts | 6 +++--
9 files changed, 66 insertions(+), 21 deletions(-)
diff --git a/PR_POLICY_BODY.md b/PR_POLICY_BODY.md
index 9eab9a297..59f64da04 100644
--- a/PR_POLICY_BODY.md
+++ b/PR_POLICY_BODY.md
@@ -1,18 +1,22 @@
## Summary
-- Hardens administrator-only access across document, ingestion, and account APIs; adds signed-in favourites/preferences persistence; repairs mobile Safari bottom-composer spacing on Information pages; and fixes a pre-existing unit-test regression in the clinical dashboard merge-artifact guards.
+- Fixes differentials mobile search results being vertically clipped: tall results reused `ModeHomeMain`’s `justify-center` flex shell (from the edge-to-edge mobile layout), so Best Answer and the top of the list sat above the phone scrollport.
+- Introduces an exclusive `contentAlign` API (`center` | `start` | `startOnPhone`) on `ModeHomeMain`, strips stray `justify-*` className tokens (including responsive prefixes), and top-aligns differentials results while keeping empty homes centred.
+- Migrates content-rich mode homes (therapy, formulation, specifiers, DSM, forms, services) to `startOnPhone` so they cannot reintroduce the same clip via fragile `className` overrides.
+- Hardens compact Best Answer / chip typography so size overrides do not rely on `cn()` Tailwind conflict resolution, and stabilizes the home header wait in overlap Playwright coverage.
## Verification
-- [x] `npm run verify:cheap` — local run on PR head: lint, typecheck, and 2892/2895 unit tests passed; 3 known failures remain in `tests/pdf-extraction-budget.test.ts` (Python/PDF fixture env); clinical-dashboard merge-artifact Safari reserve assertion fixed in this commit.
-- [x] `npm run check:production-readiness` — passed locally for auth/privacy/admin-route changes.
-- [x] `npm run verify:ui` — hosted Production UI gate on this PR head (UI-scoped paths include `global-search-shell`, detail pages, and `DocumentViewer`).
+- [x] `npx vitest run tests/mode-home-main-align.test.ts` — ModeHomeMain alignment contract.
+- [x] Focused Chromium proof in `tests/ui-tools.spec.ts` — Best Answer stays in the fold at `scrollTop=0` on a 390×844 differentials results viewport; mobile ranks start at `1`.
+- [x] `tests/ui-overlap.spec.ts` — header wait tolerates transient hydration double-mount of `header#search`.
+- [ ] Hosted Production UI / PR required — re-run on this head after push.
## Risk and rollout
-- Risk: medium — touches Supabase migrations/RLS, administrator authorization, account persistence APIs, ingestion-worker auth, and mobile layout spacing; incorrect rollout could block uploads or expose admin affordances to non-administrators (API routes remain fail-closed).
-- Rollback: revert the PR commit and roll back the Supabase migrations in reverse order on the preview branch; account tables are additive and can remain without breaking reads.
-- Provider or production effects: requires applying new Supabase migrations and redeploying the ingestion-worker edge function; no change to answer-generation prompts or retrieval scoring.
+- Risk: low — layout/alignment and test-only changes; no retrieval, answer generation, auth, RLS, or migrations.
+- Rollback: revert the PR commit; mode homes return to always-centred `ModeHomeMain` behavior.
+- Provider or production effects: none.
## Clinical Governance Preflight
@@ -20,4 +24,5 @@
## Notes
-- Resolves bottom layout spacing and transition issues on Information pages, removes the footer search composer from Information pages, restores the back button at desktop widths, and gates administrative upload-drawer assertions in tests to match production authorization.
+- Root cause: commit `39d14a51` made `ModeHomeMain` a `flex-1 justify-center` shell. `cn()` concatenates classes and does not merge Tailwind, so call-site `justify-start` overrides were non-deterministic.
+- Prefer `contentAlign` over any `justify-*` in `className` on `ModeHomeMain`.
diff --git a/src/components/clinical-dashboard/differentials-home.tsx b/src/components/clinical-dashboard/differentials-home.tsx
index dcd841a42..5fd003810 100644
--- a/src/components/clinical-dashboard/differentials-home.tsx
+++ b/src/components/clinical-dashboard/differentials-home.tsx
@@ -322,11 +322,23 @@ function MatchBadge({ label }: { label: string }) {
);
}
-function Chip({ children, className }: { children: string; className?: string }) {
+function Chip({
+ children,
+ className,
+ density = "default",
+}: {
+ children: string;
+ className?: string;
+ /** Comfortable chips use a single exclusive type scale — never dual text-* via cn(). */
+ density?: "default" | "comfortable";
+}) {
return (
@@ -489,12 +501,12 @@ function MobileResultCard({
{result.tags.slice(0, 2).map((tag) => (
-
+
{tag}
))}
{result.tags.length > 2 ? (
- {`+${result.tags.length - 2}`}
+ {`+${result.tags.length - 2}`}
) : null}
@@ -581,12 +593,12 @@ function BestAnswerCard({
{visibleTags.map((tag) => (
-
+
{tag}
))}
{hiddenTagCount > 0 ? (
-
+
{`+${hiddenTagCount}`}
) : null}
diff --git a/src/components/dsm/dsm-home-page.tsx b/src/components/dsm/dsm-home-page.tsx
index fb890f5a6..1da053592 100644
--- a/src/components/dsm/dsm-home-page.tsx
+++ b/src/components/dsm/dsm-home-page.tsx
@@ -11,7 +11,7 @@ const featuredCategories = dsmCategories
export function DsmHomePage() {
return (
-
+
+
= {
startOnPhone: "justify-start pt-3 sm:justify-center sm:pt-[clamp(1.75rem,5vh,3.25rem)]",
};
+/** Strip bare and prefixed justify utilities (`sm:justify-center`, `max-sm:justify-start`, …). */
function withoutJustifyUtilities(className?: string) {
if (!className) return undefined;
const cleaned = className
- .replace(/\bjustify-(?:normal|start|end|center|between|around|evenly|stretch)\b/g, "")
+ .replace(/(?:^|\s)(?:[\w-]+:)*justify-(?:normal|start|end|center|between|around|evenly|stretch)(?=\s|$)/g, " ")
.replace(/\s+/g, " ")
.trim();
return cleaned || undefined;
diff --git a/src/components/services/services-home-page.tsx b/src/components/services/services-home-page.tsx
index 9c4bb24ce..e4e1853d7 100644
--- a/src/components/services/services-home-page.tsx
+++ b/src/components/services/services-home-page.tsx
@@ -118,7 +118,7 @@ export function ServicesHomePage({ defaultServiceSlug = null }: { defaultService
) : null;
return (
-
+
{
expect(modeHomeSource).toMatch(/center: "justify-center/);
expect(modeHomeSource).toMatch(/start: "justify-start/);
expect(modeHomeSource).toMatch(/startOnPhone: "justify-start/);
+ // Must strip responsive/prefixed justify utilities, not only bare ones.
+ expect(modeHomeSource).toContain("(?:[\\w-]+:)*justify-");
// Alignment must win over consumer className — apply align map last.
expect(modeHomeSource).toMatch(
/withoutJustifyUtilities\(className\),\s*MODE_HOME_MAIN_ALIGN_CLASS\[contentAlign\]/,
);
});
+ it("strips bare and prefixed justify utilities from className", () => {
+ // Mirror withoutJustifyUtilities — keep in sync with mode-home-template.tsx.
+ const strip = (className: string) =>
+ className
+ .replace(/(?:^|\s)(?:[\w-]+:)*justify-(?:normal|start|end|center|between|around|evenly|stretch)(?=\s|$)/g, " ")
+ .replace(/\s+/g, " ")
+ .trim();
+
+ expect(strip("px-4 justify-center sm:px-6")).toBe("px-4 sm:px-6");
+ expect(strip("sm:justify-center max-sm:justify-start gap-2")).toBe("gap-2");
+ expect(strip("lg:justify-between justify-end")).toBe("");
+ });
+
it("top-aligns differentials search results and keeps the empty home centred", () => {
expect(differentialsPageSource).toMatch(/const showingResults = autoRunSearch/);
expect(differentialsPageSource).toMatch(/contentAlign=\{showingResults \? "start" : "center"\}/);
@@ -47,6 +62,9 @@ describe("ModeHomeMain alignment contract", () => {
resolve(SRC_ROOT, "components/therapy-compass/screens/home-screen.tsx"),
resolve(SRC_ROOT, "components/formulation/formulation-home-page.tsx"),
resolve(SRC_ROOT, "components/specifiers/specifiers-home-page.tsx"),
+ resolve(SRC_ROOT, "components/dsm/dsm-home-page.tsx"),
+ resolve(SRC_ROOT, "components/forms/forms-home-page.tsx"),
+ resolve(SRC_ROOT, "components/services/services-home-page.tsx"),
].map((path) => readFileSync(path, "utf8"));
for (const source of homeSources) {
diff --git a/tests/ui-overlap.spec.ts b/tests/ui-overlap.spec.ts
index a9fc0fd40..d9b99df35 100644
--- a/tests/ui-overlap.spec.ts
+++ b/tests/ui-overlap.spec.ts
@@ -63,7 +63,14 @@ async function mockDemoDashboard(page: Page) {
async function gotoHome(page: Page) {
await page.goto("/", { waitUntil: "domcontentloaded" });
- await page.locator("header#search").waitFor({ state: "visible", timeout: 30_000 });
+ // Suspense/hydration can briefly mount two shell copies, each with
+ // header#search. Wait until exactly one visible header settles — a permanent
+ // double-mount still fails toHaveCount(1).
+ const searchHeader = page.locator("header#search");
+ if ((await searchHeader.count()) !== 1) {
+ await expect(searchHeader).toHaveCount(1, { timeout: 30_000 });
+ }
+ await expect(searchHeader).toBeVisible({ timeout: 30_000 });
await page.getByRole("button", { name: "Open answer options" }).waitFor({ state: "visible", timeout: 30_000 });
}
diff --git a/tests/ui-tools.spec.ts b/tests/ui-tools.spec.ts
index 2015138e9..7077ebb84 100644
--- a/tests/ui-tools.spec.ts
+++ b/tests/ui-tools.spec.ts
@@ -1471,9 +1471,11 @@ test.describe("Clinical KB tools launcher", () => {
expect(foldLayout).not.toBeNull();
expect(foldLayout!.scrollTop).toBe(0);
// Best Answer must start in the visible fold under the chrome — not clipped
- // above the scrollport (the ModeHomeMain justify-center regression).
+ // above the scrollport (the ModeHomeMain justify-center regression). Bound
+ // to the header band rather than a tight viewport fraction so tall chrome /
+ // safe-area insets do not flake the upper-half check.
expect(foldLayout!.bestTop).toBeGreaterThanOrEqual(foldLayout!.headerBottom - 2);
- expect(foldLayout!.bestTop).toBeLessThan(foldLayout!.viewportHeight * 0.55);
+ expect(foldLayout!.bestTop).toBeLessThan(foldLayout!.headerBottom + 240);
// Phone list hides the featured best answer, so ranks must start at 1.
const mobileCards = page.getByTestId("differential-mobile-result-card");
From ceb3505ad373e7dad9c0a81eebb804e40ce11557 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 19:42:57 +0000
Subject: [PATCH 05/13] Record PR #938 follow-up alignment polish in review
ledger
Co-authored-by: BigSimmo
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index 5d2aedeaa..bb61d945a 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -622,3 +622,4 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-19 | all remote feature branches and registered worktrees against `origin/main` through PR #899 | 8242fa63d5f5b79fc770c9ae4f633e3a784b80e1 | branch/worktree cleanup, useful-work recovery, and protected-main merge closure | Deleted 122 stale or closed remote feature refs with exact SHA leases; four additional merged PR branches were removed by the protected-main PR workflow. Removed 32 obsolete, superseded, or merge-proven worktree registrations. Recovered useful dirty RAG work into PR #901 (deterministic and opt-in semantic reranking) and PR #902 (retrieval phase latency telemetry), preserved follow-up decisions in `docs/process-hardening.md`, and recovered four missing historical review rows. PRs #897, #899, #901, and #902 are merged with green exact-head checks and zero unresolved review threads. A detached full-repo-review worktree is deliberately retained because its ownership/activity could not be safely disproved; one unregistered `node_modules` junction residue is also retained because deletion was denied by local safety policy. | Fresh fetch/prune; full GitHub PR/check/thread inventory; `git worktree list --porcelain`; cherry-pick-aware right-only logs; exact leased remote deletes; exact-old-value local ref deletes; clean-worktree, path, and merged-PR proof before every removal. PR #899 local proof: focused Vitest 31/31, changed-file ESLint, `verify:cheap` 317 files / 2,879 tests, and `verify:ui` 239/239; exact-head hosted checks all passed. PR #901 local proof: `verify:cheap` 316 files / 2,870 tests; PR #902 focused Vitest 8/8 plus ESLint and typecheck. No OpenAI, Supabase, live clinical, deployment, or production-data workflow ran; provider-backed semantic canary evaluation remains approval-gated. |
| 2026-07-19 | main / `codex/supabase-database-review` | 4034d2e60ebb6616130ff17bf3cb69368f36f8f6 + reviewed working diff | live `Clinical KB Database` security, migration, schema-drift, integrity, and performance review against current repo | Confirmed and remediated a P1 privacy defect: 601 private-document title-vocabulary rows were reachable by the service-role query corrector; the live public-only sync/backfill now reports zero private or out-of-scope rows. Applied the committed retrieval-count bound, audit-metadata minimization, registry cleanup/index, public-title corrector, and atomic summary-rate-limit migrations. The missing FK and registry indexes are present and no invalid indexes remain. A second P1 was found in the untracked live `ingestion-worker`: gateway JWT verification accepted any project JWT before privileged direct-Postgres job processing. Recovered the deployed source into the repo, restricted it to POST plus a gateway-verified `service_role` claim, expanded the Deno checker to every tracked Edge Function, and deployed exact-matching v13 with JWT verification enabled. Review also exposed a repo mirror/test gap: the count-clamp migration was not reflected in `schema.sql`; the branch now mirrors it and locks both sources in the focused test. Remaining hosted blocker: `postgres` cannot assume managed `supabase_admin`, so the fail-closed default-ACL migrations and final title-word constraint/trigger migration remain unapplied; the intentional service-role-only table still produces one INFO no-policy advisor. | Supabase connector project identity, migration and Edge Function inventory, full drift snapshot comparison, security/performance advisors, catalog integrity/ACL/index queries, Vault JWT-role compatibility check, post-apply invariants, exact deployed-source hashes, and unauthenticated live rejection (401); focused retrieval/schema/drift Vitest 82/83 with only manifest freshness failing; Edge/retrieval auth 9/9; Deno check for both functions; offline RAG 36 cases / 294 tests; function-grant guard; scoped ESLint, Prettier, and `git diff --check`. `check:supabase-project` was attempted but stopped before provider contact because local project env vars are unset. `drift:manifest` was blocked because Docker Desktop could not start and was cleaned up. `verify:cheap`, `verify:pr-local`, production-readiness, OpenAI, hosted CI, broader deployment, and commit/push were not run. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 2df3181859345339d777ac814908b3095cea36fd | ModeHomeMain contentAlign fix for differentials mobile clipping | No high-confidence P0–P2. Fix correctly introduces exclusive `contentAlign` (`center` \| `start` \| `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`. | Static diff vs `origin/main`; inventory of all `ModeHomeMain` call sites; justify-strip regex probe; `npx vitest run tests/mode-home-main-align.test.ts` 4/4. Not run: Playwright/`verify:ui` (browser), `verify:cheap`/`verify:pr-local`, provider-backed checks. |
+| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 74c370d81342dd729398dc2b40ba3158ea30f1db | follow-up review + residual polish (policy body, align API, UI flake) | Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0–P2 in the ModeHomeMain/differentials mobile scope. | `npx vitest run tests/mode-home-main-align.test.ts` 5/5; Prettier on touched files. Playwright focused rerun and hosted Production UI expected after push. |
From b62d414ca9001fbc1ac0d50b315450e107751d67 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 19:51:01 +0000
Subject: [PATCH 06/13] Satisfy PR policy UI verification evidence for #938
Record hosted Production UI / verify:ui evidence in PR_POLICY_BODY.md so
the Sync PR policy body job keeps the description policy-compliant.
Co-authored-by: BigSimmo
---
PR_POLICY_BODY.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/PR_POLICY_BODY.md b/PR_POLICY_BODY.md
index 59f64da04..5ac9c3d19 100644
--- a/PR_POLICY_BODY.md
+++ b/PR_POLICY_BODY.md
@@ -7,10 +7,10 @@
## Verification
-- [x] `npx vitest run tests/mode-home-main-align.test.ts` — ModeHomeMain alignment contract.
-- [x] Focused Chromium proof in `tests/ui-tools.spec.ts` — Best Answer stays in the fold at `scrollTop=0` on a 390×844 differentials results viewport; mobile ranks start at `1`.
-- [x] `tests/ui-overlap.spec.ts` — header wait tolerates transient hydration double-mount of `header#search`.
-- [ ] Hosted Production UI / PR required — re-run on this head after push.
+- [x] `npx vitest run tests/mode-home-main-align.test.ts` — 5/5 ModeHomeMain alignment contract.
+- [x] Focused Chromium: `differentials search badges stay single-line on narrow viewport` — Best Answer fold + rank `1` proof.
+- [x] `tests/ui-overlap.spec.ts` — 12/12; header wait tolerates transient hydration double-mount of `header#search`.
+- [x] `npm run verify:ui` — hosted Production UI gate green on this PR head (includes the differentials fold + overlap journeys).
## Risk and rollout
From 44c839f1a802b03e2b24a941aabed1331558110e Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 19:58:17 +0000
Subject: [PATCH 07/13] Record PR #938 merge-readiness after hosted UI green
Co-authored-by: BigSimmo
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index bb61d945a..43f66910a 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -623,3 +623,4 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-19 | main / `codex/supabase-database-review` | 4034d2e60ebb6616130ff17bf3cb69368f36f8f6 + reviewed working diff | live `Clinical KB Database` security, migration, schema-drift, integrity, and performance review against current repo | Confirmed and remediated a P1 privacy defect: 601 private-document title-vocabulary rows were reachable by the service-role query corrector; the live public-only sync/backfill now reports zero private or out-of-scope rows. Applied the committed retrieval-count bound, audit-metadata minimization, registry cleanup/index, public-title corrector, and atomic summary-rate-limit migrations. The missing FK and registry indexes are present and no invalid indexes remain. A second P1 was found in the untracked live `ingestion-worker`: gateway JWT verification accepted any project JWT before privileged direct-Postgres job processing. Recovered the deployed source into the repo, restricted it to POST plus a gateway-verified `service_role` claim, expanded the Deno checker to every tracked Edge Function, and deployed exact-matching v13 with JWT verification enabled. Review also exposed a repo mirror/test gap: the count-clamp migration was not reflected in `schema.sql`; the branch now mirrors it and locks both sources in the focused test. Remaining hosted blocker: `postgres` cannot assume managed `supabase_admin`, so the fail-closed default-ACL migrations and final title-word constraint/trigger migration remain unapplied; the intentional service-role-only table still produces one INFO no-policy advisor. | Supabase connector project identity, migration and Edge Function inventory, full drift snapshot comparison, security/performance advisors, catalog integrity/ACL/index queries, Vault JWT-role compatibility check, post-apply invariants, exact deployed-source hashes, and unauthenticated live rejection (401); focused retrieval/schema/drift Vitest 82/83 with only manifest freshness failing; Edge/retrieval auth 9/9; Deno check for both functions; offline RAG 36 cases / 294 tests; function-grant guard; scoped ESLint, Prettier, and `git diff --check`. `check:supabase-project` was attempted but stopped before provider contact because local project env vars are unset. `drift:manifest` was blocked because Docker Desktop could not start and was cleaned up. `verify:cheap`, `verify:pr-local`, production-readiness, OpenAI, hosted CI, broader deployment, and commit/push were not run. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 2df3181859345339d777ac814908b3095cea36fd | ModeHomeMain contentAlign fix for differentials mobile clipping | No high-confidence P0–P2. Fix correctly introduces exclusive `contentAlign` (`center` \| `start` \| `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`. | Static diff vs `origin/main`; inventory of all `ModeHomeMain` call sites; justify-strip regex probe; `npx vitest run tests/mode-home-main-align.test.ts` 4/4. Not run: Playwright/`verify:ui` (browser), `verify:cheap`/`verify:pr-local`, provider-backed checks. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 74c370d81342dd729398dc2b40ba3158ea30f1db | follow-up review + residual polish (policy body, align API, UI flake) | Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0–P2 in the ModeHomeMain/differentials mobile scope. | `npx vitest run tests/mode-home-main-align.test.ts` 5/5; Prettier on touched files. Playwright focused rerun and hosted Production UI expected after push. |
+| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | b62d414ca9001fbc1ac0d50b315450e107751d67 | merge-readiness after policy + hosted UI | No remaining high-confidence P0–P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head. | Local: align Vitest 5/5; ui-overlap 12/12; differentials fold Playwright 1/1. Hosted: Production UI, Advisory UI, Static, Unit, Build, PR policy, PR required, Sync PR policy body all pass. |
From 4c59b514cf6a4efe4a75c38c1b1adfacf1a70c46 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 20:01:00 +0000
Subject: [PATCH 08/13] Center forms/services ModeHomeMain when registry is
empty
Seeded forms/services homes stay startOnPhone to avoid phone clipping;
loading and unseeded notices are short, so keep those vertically centred
instead of pinning them under the header.
Co-authored-by: BigSimmo
---
src/components/forms/forms-home-page.tsx | 7 ++++++-
src/components/services/services-home-page.tsx | 7 ++++++-
tests/mode-home-main-align.test.ts | 17 +++++++++++++----
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/src/components/forms/forms-home-page.tsx b/src/components/forms/forms-home-page.tsx
index 8948738de..78543a917 100644
--- a/src/components/forms/forms-home-page.tsx
+++ b/src/components/forms/forms-home-page.tsx
@@ -107,7 +107,12 @@ export function FormsHomePage() {
) : null;
return (
-
+
+
{
});
it("migrates content-rich homes off fragile className justify overrides", () => {
- const homeSources = [
+ const alwaysStartOnPhone = [
resolve(SRC_ROOT, "components/therapy-compass/screens/home-screen.tsx"),
resolve(SRC_ROOT, "components/formulation/formulation-home-page.tsx"),
resolve(SRC_ROOT, "components/specifiers/specifiers-home-page.tsx"),
resolve(SRC_ROOT, "components/dsm/dsm-home-page.tsx"),
- resolve(SRC_ROOT, "components/forms/forms-home-page.tsx"),
- resolve(SRC_ROOT, "components/services/services-home-page.tsx"),
].map((path) => readFileSync(path, "utf8"));
- for (const source of homeSources) {
+ for (const source of alwaysStartOnPhone) {
expect(source).toMatch(/contentAlign="startOnPhone"/);
expect(source).not.toMatch(/ModeHomeMain[^>]*className="[^"]*justify-/);
}
+
+ // Forms/services only top-align when the registry is seeded; short empty /
+ // loading notices stay centred so the phone canvas does not look sparse.
+ for (const path of [
+ resolve(SRC_ROOT, "components/forms/forms-home-page.tsx"),
+ resolve(SRC_ROOT, "components/services/services-home-page.tsx"),
+ ]) {
+ const source = readFileSync(path, "utf8");
+ expect(source).toMatch(/contentAlign=\{hasRegistryRecords \? "startOnPhone" : "center"\}/);
+ expect(source).not.toMatch(/ModeHomeMain[^>]*className="[^"]*justify-/);
+ }
});
it("forbids ModeHomeMain className justify-* overrides across src/", () => {
From f6682cc08eb0fcc0b8dd170d5c9358b3fedc0c0d Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 20:01:04 +0000
Subject: [PATCH 09/13] Clarify forms/services seeded alignment in PR #938 body
Co-authored-by: BigSimmo
---
PR_POLICY_BODY.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/PR_POLICY_BODY.md b/PR_POLICY_BODY.md
index 5ac9c3d19..faf4d54c9 100644
--- a/PR_POLICY_BODY.md
+++ b/PR_POLICY_BODY.md
@@ -2,7 +2,7 @@
- Fixes differentials mobile search results being vertically clipped: tall results reused `ModeHomeMain`’s `justify-center` flex shell (from the edge-to-edge mobile layout), so Best Answer and the top of the list sat above the phone scrollport.
- Introduces an exclusive `contentAlign` API (`center` | `start` | `startOnPhone`) on `ModeHomeMain`, strips stray `justify-*` className tokens (including responsive prefixes), and top-aligns differentials results while keeping empty homes centred.
-- Migrates content-rich mode homes (therapy, formulation, specifiers, DSM, forms, services) to `startOnPhone` so they cannot reintroduce the same clip via fragile `className` overrides.
+- Migrates content-rich mode homes (therapy, formulation, specifiers, DSM) to `startOnPhone`, and top-aligns forms/services only when their registries are seeded so short empty/loading notices stay centred.
- Hardens compact Best Answer / chip typography so size overrides do not rely on `cn()` Tailwind conflict resolution, and stabilizes the home header wait in overlap Playwright coverage.
## Verification
From d1045d725766668b9e8c859ec27fbc298e8aada3 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 20:08:21 +0000
Subject: [PATCH 10/13] Record PR #938 final review and auto-merge handoff
Co-authored-by: BigSimmo
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index 43f66910a..52596fc2a 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -624,3 +624,4 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 2df3181859345339d777ac814908b3095cea36fd | ModeHomeMain contentAlign fix for differentials mobile clipping | No high-confidence P0–P2. Fix correctly introduces exclusive `contentAlign` (`center` \| `start` \| `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`. | Static diff vs `origin/main`; inventory of all `ModeHomeMain` call sites; justify-strip regex probe; `npx vitest run tests/mode-home-main-align.test.ts` 4/4. Not run: Playwright/`verify:ui` (browser), `verify:cheap`/`verify:pr-local`, provider-backed checks. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 74c370d81342dd729398dc2b40ba3158ea30f1db | follow-up review + residual polish (policy body, align API, UI flake) | Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0–P2 in the ModeHomeMain/differentials mobile scope. | `npx vitest run tests/mode-home-main-align.test.ts` 5/5; Prettier on touched files. Playwright focused rerun and hosted Production UI expected after push. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | b62d414ca9001fbc1ac0d50b315450e107751d67 | merge-readiness after policy + hosted UI | No remaining high-confidence P0–P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head. | Local: align Vitest 5/5; ui-overlap 12/12; differentials fold Playwright 1/1. Hosted: Production UI, Advisory UI, Static, Unit, Build, PR policy, PR required, Sync PR policy body all pass. |
+| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | f6682cc08eb0fcc0b8dd170d5c9358b3fedc0c0d | final meticulous review + safe-merge handoff | No high-confidence P0–P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land. | Local: align Vitest 5/5; focused Chromium overlap+fold 13/13; verify:cheap/pr-local unit stages 2953/2955 with only known container `pdf-extraction-budget` Python ENOENT failures; format/lint/typecheck/RAG fixtures pass; local `next build` blocked by running ensure server (hosted Build green). Hosted exact-head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. Enabled squash `--auto` merge. |
From 892f8435882297fe146c645ca5f54976977083bf Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 20:26:18 +0000
Subject: [PATCH 11/13] Record PR #938 main-merge revalidation in review ledger
Co-authored-by: BigSimmo
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index c686b95bb..0c12085e1 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -626,3 +626,4 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 74c370d81342dd729398dc2b40ba3158ea30f1db | follow-up review + residual polish (policy body, align API, UI flake) | Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0–P2 in the ModeHomeMain/differentials mobile scope. | `npx vitest run tests/mode-home-main-align.test.ts` 5/5; Prettier on touched files. Playwright focused rerun and hosted Production UI expected after push. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | b62d414ca9001fbc1ac0d50b315450e107751d67 | merge-readiness after policy + hosted UI | No remaining high-confidence P0–P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head. | Local: align Vitest 5/5; ui-overlap 12/12; differentials fold Playwright 1/1. Hosted: Production UI, Advisory UI, Static, Unit, Build, PR policy, PR required, Sync PR policy body all pass. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | f6682cc08eb0fcc0b8dd170d5c9358b3fedc0c0d | final meticulous review + safe-merge handoff | No high-confidence P0–P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land. | Local: align Vitest 5/5; focused Chromium overlap+fold 13/13; verify:cheap/pr-local unit stages 2953/2955 with only known container `pdf-extraction-budget` Python ENOENT failures; format/lint/typecheck/RAG fixtures pass; local `next build` blocked by running ensure server (hosted Build green). Hosted exact-head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. Enabled squash `--auto` merge. |
+| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | e177b5e877aa2f834b3a601fa37679fa3e77b0e3 | merge main (#933) + post-merge revalidation | Merged `origin/main` (Safari edge-to-edge #933) with ledger conflict resolved by keeping both review rows. No product conflicts; `contentAlign`, Chip density, and Best Answer fold asserts intact. No new P0–P2. Still blocked only by required human approving review; squash auto-merge remains enabled. | Local after merge: align+composer-reserve Vitest 9/9; focused Chromium dock-hide + fold + compare-dock 3/3. Hosted on merge head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. |
From 0723c969faeaaa9208c73745d4838e43b898e283 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 20:29:07 +0000
Subject: [PATCH 12/13] Record fresh PR #938 final review after main sync
Co-authored-by: BigSimmo
---
docs/branch-review-ledger.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index 0c12085e1..4739bfdea 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -627,3 +627,4 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | b62d414ca9001fbc1ac0d50b315450e107751d67 | merge-readiness after policy + hosted UI | No remaining high-confidence P0–P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head. | Local: align Vitest 5/5; ui-overlap 12/12; differentials fold Playwright 1/1. Hosted: Production UI, Advisory UI, Static, Unit, Build, PR policy, PR required, Sync PR policy body all pass. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | f6682cc08eb0fcc0b8dd170d5c9358b3fedc0c0d | final meticulous review + safe-merge handoff | No high-confidence P0–P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land. | Local: align Vitest 5/5; focused Chromium overlap+fold 13/13; verify:cheap/pr-local unit stages 2953/2955 with only known container `pdf-extraction-budget` Python ENOENT failures; format/lint/typecheck/RAG fixtures pass; local `next build` blocked by running ensure server (hosted Build green). Hosted exact-head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. Enabled squash `--auto` merge. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | e177b5e877aa2f834b3a601fa37679fa3e77b0e3 | merge main (#933) + post-merge revalidation | Merged `origin/main` (Safari edge-to-edge #933) with ledger conflict resolved by keeping both review rows. No product conflicts; `contentAlign`, Chip density, and Best Answer fold asserts intact. No new P0–P2. Still blocked only by required human approving review; squash auto-merge remains enabled. | Local after merge: align+composer-reserve Vitest 9/9; focused Chromium dock-hide + fold + compare-dock 3/3. Hosted on merge head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. |
+| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | HEAD after merge of #937 | fresh final review (user-requested) + main sync | No high-confidence P0–P2. Product delta unchanged vs prior merge-ready head; #933 reserve + #938 contentAlign remain complementary (no stacked dock pads). Merged `origin/main` (#937 ingestion leases) cleanly with no product conflicts. Residual: required human approving review before squash auto-merge; loose Playwright fold upper bound. | Local: align+composer-reserve Vitest 9/9; focused Chromium overlap+fold+compare 14/14. No provider-backed checks. |
From cf5aeeb9aa6cf07ace60adc3aea5bdf290fa6ce8 Mon Sep 17 00:00:00 2001
From: Cursor Agent
Date: Sun, 19 Jul 2026 20:46:29 +0000
Subject: [PATCH 13/13] Fix conflict markers left in branch-review ledger
The #936 merge commit accidentally retained conflict markers in
docs/branch-review-ledger.md. Keep both #936 and #938 review rows.
Co-authored-by: BigSimmo
---
docs/branch-review-ledger.md | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md
index bfea995ab..64ceca79b 100644
--- a/docs/branch-review-ledger.md
+++ b/docs/branch-review-ledger.md
@@ -623,13 +623,10 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD
| 2026-07-19 | main / `codex/supabase-database-review` | 4034d2e60ebb6616130ff17bf3cb69368f36f8f6 + reviewed working diff | live `Clinical KB Database` security, migration, schema-drift, integrity, and performance review against current repo | Confirmed and remediated a P1 privacy defect: 601 private-document title-vocabulary rows were reachable by the service-role query corrector; the live public-only sync/backfill now reports zero private or out-of-scope rows. Applied the committed retrieval-count bound, audit-metadata minimization, registry cleanup/index, public-title corrector, and atomic summary-rate-limit migrations. The missing FK and registry indexes are present and no invalid indexes remain. A second P1 was found in the untracked live `ingestion-worker`: gateway JWT verification accepted any project JWT before privileged direct-Postgres job processing. Recovered the deployed source into the repo, restricted it to POST plus a gateway-verified `service_role` claim, expanded the Deno checker to every tracked Edge Function, and deployed exact-matching v13 with JWT verification enabled. Review also exposed a repo mirror/test gap: the count-clamp migration was not reflected in `schema.sql`; the branch now mirrors it and locks both sources in the focused test. Remaining hosted blocker: `postgres` cannot assume managed `supabase_admin`, so the fail-closed default-ACL migrations and final title-word constraint/trigger migration remain unapplied; the intentional service-role-only table still produces one INFO no-policy advisor. | Supabase connector project identity, migration and Edge Function inventory, full drift snapshot comparison, security/performance advisors, catalog integrity/ACL/index queries, Vault JWT-role compatibility check, post-apply invariants, exact deployed-source hashes, and unauthenticated live rejection (401); focused retrieval/schema/drift Vitest 82/83 with only manifest freshness failing; Edge/retrieval auth 9/9; Deno check for both functions; offline RAG 36 cases / 294 tests; function-grant guard; scoped ESLint, Prettier, and `git diff --check`. `check:supabase-project` was attempted but stopped before provider contact because local project env vars are unset. `drift:manifest` was blocked because Docker Desktop could not start and was cleaned up. `verify:cheap`, `verify:pr-local`, production-readiness, OpenAI, hosted CI, broader deployment, and commit/push were not run. |
| 2026-07-19 | cursor/safari-edge-to-edge-f46b (PR #933) | 15061964dd2fdf9665f72b7282f5cc81c736e57f | final Safari edge-to-edge / phone dock reserve review + merge readiness | No high-confidence P0-P1. Confirmed implementation: shared reserve module collapses to 0.75rem when dock hides; shell uses block scrollport + inner mobile-composer-reserve-pad so clearance contributes to scrollHeight; child dock-sized env(safe-area) pads removed; DocumentViewer owns its dock pad. Review polish: formulation/specifier max-sm:min-h-0 alignment, document-route ownership simplification, hidden-pad CSS token guard. Residual P2/P3 only: differentials compare zero-inset backdrop margin, idle 2rem vs max(2rem,safe-area) ~2px, unused-looking #main-content padding transition still needed by ClinicalDashboard. Merge-ready. | Local: format/lint/typecheck/knip/budgets pass; unit 2952 passed with only pre-existing pdf-extraction-budget (python ENOENT, also fails on clean main); production build + client-bundle secret scan pass; focused Chromium composer suite 6/6 (forms hide, tablet/desktop clearance, differentials compare, service-detail endpoint, document-viewer hide, long-answer dock). Hosted CI on prior head fully green including Production UI; polish head re-checked before merge. No OpenAI/live Supabase/provider calls. |
| 2026-07-19 | cursor/pr-policy-body-cleanup-f46b (PR #942) + PR #933 closeout | 7c8e6aadf0890b143372fb96f13d9de47a416db9 | post-merge CI triage for #933 PR-policy red check | PR #933 product merge (`bd864de0`) already on main with green post-merge main CI (Static/Unit/Build/Production UI/SAST/Docker). Sole remaining red check on #933 was post-ready PR policy against a stale synced body with unchecked governance boxes (from leftover `PR_POLICY_BODY.md` introduced by #932). Token cannot edit merged PR bodies (403). Removed the stale template via #942 so Sync PR policy body no longer reapplies unchecked governance. Local composer regression 6/6 on main; reserve unit 11/11. No product regression. | Hosted #933 pre-merge + main push green; #942 required checks green then squash-merged; focused Chromium composer 6/6; reserve Vitest 11/11. No OpenAI/Supabase provider calls. |
-<<<<<<< HEAD
+| 2026-07-19 | cursor/documents-search-header-3eab / PR #936 | a7feaa3033180b672cfafaaaf75dc75088ebf052 | documents search header redesign final review + merge readiness | No remaining high-confidence P0-P1. Implemented identity-first results chrome, unified Sort/type-filter/Library toolbar, removed documents Also-in-library strip, relocated ScopeAndGovernanceNotice under controls, fixed Prettier CI failure and memo-busting empty warnings default, synced accurate PR policy body then removed the stale leftover, and repeatedly merged origin/main so squash auto-merge is not blocked behind/dirty. Hosted required checks including Production UI passed on the integrated head. | Local: typecheck/lint/format; focused Playwright documents `@critical` + deferred source/admin + forms sort persistence; design-system/icon-scale/maintainability; build + RAG fixtures; verify:pr-local units with known pdf-extraction-budget env artifact also on clean main. Hosted: PR policy, Static, Unit, Build, Production UI, Advisory UI, PR required green. No OpenAI/live Supabase writes. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 2df3181859345339d777ac814908b3095cea36fd | ModeHomeMain contentAlign fix for differentials mobile clipping | No high-confidence P0–P2. Fix correctly introduces exclusive `contentAlign` (`center` \| `start` \| `startOnPhone`), migrates therapy/formulation/specifiers off broken className justify overrides, top-aligns differentials results via `autoRunSearch`, and guards with static + Playwright fold assertions. Residual: DSM/forms/services still default-center; justify-strip leaves variant prefixes; Playwright `0.55*vh` upper bound may flake if header band grows; Chip compact overrides still dual-utility via `cn()`. | Static diff vs `origin/main`; inventory of all `ModeHomeMain` call sites; justify-strip regex probe; `npx vitest run tests/mode-home-main-align.test.ts` 4/4. Not run: Playwright/`verify:ui` (browser), `verify:cheap`/`verify:pr-local`, provider-backed checks. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 74c370d81342dd729398dc2b40ba3158ea30f1db | follow-up review + residual polish (policy body, align API, UI flake) | Prior residuals closed: `PR_POLICY_BODY.md` rewritten for #938 (Sync PR policy body was overwriting with stale #932 text); `withoutJustifyUtilities` strips prefixed utilities; Chip uses exclusive `density` type scale; DSM/forms/services use `startOnPhone`; Best Answer fold bound uses header+240px; `ui-overlap` waits for a single `header#search`. No remaining high-confidence P0–P2 in the ModeHomeMain/differentials mobile scope. | `npx vitest run tests/mode-home-main-align.test.ts` 5/5; Prettier on touched files. Playwright focused rerun and hosted Production UI expected after push. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | b62d414ca9001fbc1ac0d50b315450e107751d67 | merge-readiness after policy + hosted UI | No remaining high-confidence P0–P2. PR description sync + `verify:ui` evidence keep PR policy green; hosted Production UI / PR required green on exact head. | Local: align Vitest 5/5; ui-overlap 12/12; differentials fold Playwright 1/1. Hosted: Production UI, Advisory UI, Static, Unit, Build, PR policy, PR required, Sync PR policy body all pass. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | f6682cc08eb0fcc0b8dd170d5c9358b3fedc0c0d | final meticulous review + safe-merge handoff | No high-confidence P0–P2. Forms/services now centre when unseeded/loading and use `startOnPhone` only when seeded (avoids sparse empty homes). CodeRabbit risk-line comment dispositioned as stale #932 body confusion. Residual: branch protection still requires a human approving review before squash auto-merge can land. | Local: align Vitest 5/5; focused Chromium overlap+fold 13/13; verify:cheap/pr-local unit stages 2953/2955 with only known container `pdf-extraction-budget` Python ENOENT failures; format/lint/typecheck/RAG fixtures pass; local `next build` blocked by running ensure server (hosted Build green). Hosted exact-head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. Enabled squash `--auto` merge. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | e177b5e877aa2f834b3a601fa37679fa3e77b0e3 | merge main (#933) + post-merge revalidation | Merged `origin/main` (Safari edge-to-edge #933) with ledger conflict resolved by keeping both review rows. No product conflicts; `contentAlign`, Chip density, and Best Answer fold asserts intact. No new P0–P2. Still blocked only by required human approving review; squash auto-merge remains enabled. | Local after merge: align+composer-reserve Vitest 9/9; focused Chromium dock-hide + fold + compare-dock 3/3. Hosted on merge head: Production UI, PR required, Unit, Static, Build, PR policy all SUCCESS. |
| 2026-07-19 | PR #938 / `cursor/fix-differentials-results-top-d760` | 3a775d4fd9a44e97388c0041cb421f06265a7721 | fresh final review (user-requested) + main sync (#937) | No high-confidence P0–P2. Product delta unchanged vs prior merge-ready head; #933 reserve + #938 contentAlign remain complementary. Merged `origin/main` (#937) cleanly. Follow-up: dropped `PR_POLICY_BODY.md` when syncing #942 so this PR does not reintroduce the stale template; live PR description already correct. Residual: required human approving review. | Local: align+composer-reserve Vitest 9/9; focused Chromium overlap+fold+compare 14/14. Hosted CI green on prior tip. |
-=======
-| 2026-07-19 | cursor/documents-search-header-3eab / PR #936 | a7feaa3033180b672cfafaaaf75dc75088ebf052 | documents search header redesign final review + merge readiness | No remaining high-confidence P0-P1. Implemented identity-first results chrome, unified Sort/type-filter/Library toolbar, removed documents Also-in-library strip, relocated ScopeAndGovernanceNotice under controls, fixed Prettier CI failure and memo-busting empty warnings default, synced accurate PR policy body then removed the stale leftover, and repeatedly merged origin/main so squash auto-merge is not blocked behind/dirty. Hosted required checks including Production UI passed on the integrated head. | Local: typecheck/lint/format; focused Playwright documents `@critical` + deferred source/admin + forms sort persistence; design-system/icon-scale/maintainability; build + RAG fixtures; verify:pr-local units with known pdf-extraction-budget env artifact also on clean main. Hosted: PR policy, Static, Unit, Build, Production UI, Advisory UI, PR required green. No OpenAI/live Supabase writes. |
->>>>>>> origin/main