Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9594bf7
Hide Favourites from guest mode switcher on the dashboard
cursoragent Jul 19, 2026
905f0fe
Extract dashboard shell actions to keep Favourites gate under budget
cursoragent Jul 19, 2026
23d0553
Fold Favourites access into dashboard shell actions hook
cursoragent Jul 19, 2026
2ffdbf4
Record Favourites guest-gate review in branch ledger
cursoragent Jul 19, 2026
e91b433
Black out Favourites discovery for signed-out guests
cursoragent Jul 19, 2026
618ff9e
fix: use min-h-tap on Favourites guest gate CTA
cursoragent Jul 19, 2026
02ff3f5
fix: resolve Favourites blackout lint regressions
cursoragent Jul 19, 2026
0419265
Harden Favourites guest blackout fail-closed paths
cursoragent Jul 19, 2026
5e181f1
Record final Favourites blackout review in branch ledger
cursoragent Jul 19, 2026
8755cc6
Merge remote-tracking branch 'origin/main' into cursor/hide-favourite…
cursoragent Jul 19, 2026
eab4e0f
Merge remote-tracking branch 'origin/main' into cursor/hide-favourite…
cursoragent Jul 19, 2026
80e6d32
fix: sync PR policy body for Favourites guest blackout
cursoragent Jul 19, 2026
2360059
fix: align PR policy body Supabase governance line
cursoragent Jul 19, 2026
b3cbcca
chore: retrigger PR policy after governance body sync
cursoragent Jul 19, 2026
5350142
merge: resolve PR_POLICY_BODY.md conflict with main
cursoragent Jul 19, 2026
0677763
merge: keep Favourites and PR-policy ledger rows
cursoragent Jul 19, 2026
970c319
merge: sync favourites guest-blackout with documents header redesign
cursoragent Jul 19, 2026
31192b1
test: wait for a single header#search in overlap coverage
cursoragent Jul 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -622,5 +622,7 @@ 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 | 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/hide-favourites-guest-mode-a26d (PR #934) | 23d05539320427ea3f994eaec3c2e95daa481492 | Favourites guest mode-switcher/sidebar auth gate review | No P0/P1. Primary request correctly wired: MasterSearchHeader fails closed; ClinicalDashboard and global-search-shell both pass session favouritesAccessible to mode menu + desktop/mobile showAccountLibrary; selectSearchMode/changeMode guarded; /favourites stays on-page with signup for guests. Residual P2: guest discovery still possible via composer cross-mode Favourites chips and Tools catalog Saved workflows (content remains gated on /favourites). P2 test gap: wiring tests are source-string, not MasterSearchHeader DOM. P3: header passes precomputed access as authenticated plus demoMode (redundant OR, intentional demo reopen). | Focused Vitest favourites-auth-gate + app-modes 26/26; prior verify:cheap green on branch; browser guest check: sidebar omits Your library/Favourites, /favourites shows signup gate; mode-menu automation inconclusive. No OpenAI/Supabase/hosted CI. |
| 2026-07-19 | cursor/hide-favourites-guest-mode-a26d (PR #934) | 04192653 | Final Favourites total guest-blackout review + merge readiness | No P0/P1. Fixed residual P2s: rankToolRecords now fails closed by default; mode/chip filters stop double-ORing demoMode; gated deep-link mode chrome falls back to Answer; MasterSearchHeader mode-menu DOM tests added. Guest discovery closed for mode menu, sidebar, cross-mode chips, Tools Saved, universal tools ranking, also-matches, prefetch. Intentional residual: direct /favourites signup gate; mockup routes. PR body appears overwritten by unrelated Sync PR policy content — agent posted corrective comment (403 on body edit). | Focused Vitest 37/37; verify:cheap green; verify:pr-local green (build + client-secret scan + RAG fixtures); browser guest Tools/sidebar/favourites proof earlier. No OpenAI/Supabase writes. |
| 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. |
| 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. |
86 changes: 43 additions & 43 deletions src/components/ClinicalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ import {
resolveMobileComposerReserve,
} from "@/components/clinical-dashboard/mobile-composer-reserve";
import { UniversalSearchAlsoMatches } from "@/components/clinical-dashboard/universal-search-also-matches";
import { FavouritesGuestGate } from "@/components/clinical-dashboard/favourites-guest-gate";
import { useDashboardShellActions } from "@/components/clinical-dashboard/use-dashboard-shell-actions";
import { useScrollHideReporter } from "@/components/clinical-dashboard/use-hide-on-scroll";
import { SearchCommandProvider } from "@/components/clinical-dashboard/search-command-context";
import {
Expand All @@ -110,7 +112,6 @@ import {
setupNeedsSlowRecheck,
setupRecheckPollMs,
shorterPollDelay,
sessionFavouritesAccessible,
} from "@/components/clinical-dashboard/clinical-dashboard-helpers";
import { answerRecovery, errorCopy } from "@/lib/ui-copy";
import {
Expand Down Expand Up @@ -675,7 +676,6 @@ export function ClinicalDashboard({
const [activeHash, setActiveHash] = useState("#search");
const [guideOpen, setGuideOpen] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
const [accountSetupOpen, setAccountSetupOpen] = useState(false);
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
const [sidebarCollapsed, setSidebarCollapsed] = useSidebarCollapsed();
const [documentsDrawerOpen, setDocumentsDrawerOpen] = useState(false);
Expand Down Expand Up @@ -814,6 +814,31 @@ export function ClinicalDashboard({
authUnavailableFallback: browserAuthUnavailableDemoFallback,
localNoAuthMode,
});
const sidebarIdentity = useMemo(() => deriveSidebarIdentity(auth.session?.user.email), [auth.session?.user.email]);
const {
favouritesAccessible,
accountSetupOpen,
accountSetupIntent,
closeAccountSetup,
closeTransientSurfaces: closeDashboardTransientSurfaces,
openAccountSetup,
openGuide,
closeGuide,
openSettings,
closeSettings,
openAccountProfile,
prefetchApplications,
} = useDashboardShellActions({
authenticated: auth.status === "authenticated",
demoMode: clientDemoMode,
signedIn: sidebarIdentity.signedIn,
setGuideOpen,
setSettingsOpen,
setMobileSidebarOpen,
setDocumentsDrawerOpen,
setUploadDrawerOpen,
prefetch: (href) => router.prefetch(href),
});
const answerThreadOwnerId = auth.session?.user.id ?? (clientDemoMode ? demoRecentQueryOwnerId : null);
const previousAnswerThreadOwnerIdRef = useRef(answerThreadOwnerId);
useEffect(() => {
Expand Down Expand Up @@ -888,43 +913,6 @@ export function ClinicalDashboard({
canUseDegradedLocalSearchApis ||
canUseNonProductionDemoFallback ||
canAttemptDeployedPublicSearch;
const closeDashboardTransientSurfaces = useCallback(
(except?: "guide" | "settings" | "accountSetup" | "mobileSidebar" | "documents" | "upload") => {
if (except !== "guide") setGuideOpen(false);
if (except !== "settings") setSettingsOpen(false);
if (except !== "accountSetup") setAccountSetupOpen(false);
if (except !== "mobileSidebar") setMobileSidebarOpen(false);
if (except !== "documents") setDocumentsDrawerOpen(false);
if (except !== "upload") setUploadDrawerOpen(false);
},
[],
);
const openGuide = useCallback(() => {
closeDashboardTransientSurfaces("guide");
setGuideOpen(true);
}, [closeDashboardTransientSurfaces]);
const closeGuide = useCallback(() => setGuideOpen(false), []);
const openSettings = useCallback(() => {
closeDashboardTransientSurfaces("settings");
setSettingsOpen(true);
}, [closeDashboardTransientSurfaces]);
const closeSettings = useCallback(() => setSettingsOpen(false), []);
const sidebarIdentity = useMemo(() => deriveSidebarIdentity(auth.session?.user.email), [auth.session?.user.email]);
const openAccountProfile = useCallback(() => {
if (sidebarIdentity.signedIn) {
closeDashboardTransientSurfaces("settings");
setSettingsOpen(true);
return;
}
closeDashboardTransientSurfaces("accountSetup");
setAccountSetupOpen(true);
}, [closeDashboardTransientSurfaces, sidebarIdentity.signedIn]);
const closeAccountSetup = useCallback(() => setAccountSetupOpen(false), []);
const prefetchApplications = useCallback(() => {
router.prefetch("/?mode=tools");
router.prefetch("/favourites");
router.prefetch("/differentials");
}, [router]);
const openLibraryHealthTarget = useCallback(
(target: LibraryHealthTarget) => {
if (!canUseAdministrativeApis) {
Expand Down Expand Up @@ -2482,6 +2470,10 @@ export function ClinicalDashboard({
}

function crossModeSearch(mode: AppModeId, crossQuery: string) {
if (mode === "favourites" && !favouritesAccessible) {
openAccountSetup("favourites");
return;
}
modeChangeFromUiRef.current = true;
if (mode === "differentials") clearDifferentialModeResultState();
setCommandScopes([]);
Expand Down Expand Up @@ -2763,6 +2755,10 @@ export function ClinicalDashboard({
}

function selectSearchMode(mode: AppModeId) {
if (mode === "favourites" && !favouritesAccessible) {
openAccountSetup("favourites");
return;
}
modeChangeFromUiRef.current = true;
if (mode === "differentials") clearDifferentialModeResultState();
setQuery("");
Expand Down Expand Up @@ -3476,7 +3472,7 @@ export function ClinicalDashboard({
theme={theme}
onToggleTheme={toggleTheme}
onPrefetchApplications={prefetchApplications}
showAccountLibrary={sessionFavouritesAccessible(auth.status, clientDemoMode)}
showAccountLibrary={favouritesAccessible}
/>

<div className="relative flex min-h-0 min-w-0 flex-1 flex-col md:h-full">
Expand All @@ -3493,6 +3489,8 @@ export function ClinicalDashboard({
realDataReady={canRunSearch}
onQueryChange={setQuery}
onSearchModeChange={selectSearchMode}
canAccessFavourites={favouritesAccessible}
onRequestAccountSetup={() => openAccountSetup("favourites")}
onAsk={ask}
onClearQuery={() => {
setQuery("");
Expand Down Expand Up @@ -3848,7 +3846,7 @@ export function ClinicalDashboard({
/>
) : activeModeResultKind === "tools" ? (
<ToolsHub query={query} desktopComposerSlotId={desktopHomeComposerSlotId} />
) : activeModeResultKind === "favourites" ? (
) : activeModeResultKind === "favourites" && favouritesAccessible ? (
<FavouritesHub
query={query}
demoMode={clientDemoMode}
Expand All @@ -3859,6 +3857,8 @@ export function ClinicalDashboard({
}}
desktopComposerSlotId={desktopHomeComposerSlotId}
/>
) : activeModeResultKind === "favourites" ? (
<FavouritesGuestGate onOpenAccountSetup={() => openAccountSetup("favourites")} />
) : activeModeResultKind === "documents" || activeModeResultKind === "services" ? (
searchMode === "prescribing" ? (
<MedicationPrescribingWorkspace
Expand Down Expand Up @@ -4249,7 +4249,7 @@ export function ClinicalDashboard({
onSignOut={auth.signOut}
onOpenGuide={openGuide}
/>
<AccountSetupDialog open={accountSetupOpen} onClose={closeAccountSetup} />
<AccountSetupDialog open={accountSetupOpen} onClose={closeAccountSetup} intent={accountSetupIntent} />
<ClinicalMobileSidebar
open={mobileSidebarOpen}
recentQueries={recentQueries}
Expand All @@ -4264,7 +4264,7 @@ export function ClinicalDashboard({
theme={theme}
onToggleTheme={toggleTheme}
onPrefetchApplications={prefetchApplications}
showAccountLibrary={sessionFavouritesAccessible(auth.status, clientDemoMode)}
showAccountLibrary={favouritesAccessible}
/>
</div>
</div>
Expand Down
Loading