Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
de7e4ae
Rebrand the sidebar lockup to PsychSift and re-cut it as a header band
claude Sep 4, 2026
392b7c8
Finish the PsychSift rename and guard the retired name
claude Sep 4, 2026
62e067c
Merge remote-tracking branch 'origin/main' into claude/clinical-guide…
claude Sep 4, 2026
093ff75
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
48edb3c
Settle the Sources page-root locators before asserting on them
claude Sep 4, 2026
5e403e8
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
66e6e90
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
aff60bc
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
c5230ff
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
c00a3f5
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
bb4f611
docs(issues): log CaringContactsShell testid-duplication root cause (P2)
claude Sep 4, 2026
39d877b
Merge branch 'claude/clinical-guide-redesign-ir5zcj' of origin into c…
claude Sep 4, 2026
14c71b7
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
061bba2
Settle both workspace landmarks, not just the rail, before measuring
claude Sep 4, 2026
14a4251
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
a90e369
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
7c56cf0
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
5f195fd
Merge branch 'main' into claude/clinical-guide-redesign-ir5zcj
BigSimmo Sep 4, 2026
89c4735
Wait for the mode menu's autofocus before taking focus off it
claude Sep 4, 2026
ac1de9c
Merge branch 'claude/clinical-guide-redesign-ir5zcj' of https://githu…
claude Sep 4, 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: 1 addition & 1 deletion docs/design-system/ADOPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ manifest remains `baseline: not-committed`, and no Playwright snapshot PNG is an
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| forms | `FormField` is mounted by `TextField`/`Select`; required labels carry a text marker and optional labels remain unmarked. | `tests/ui-v2-form-field.dom.test.tsx` |
| headers/catalogues | Shared mode status notices now delegate to DS `EmptyState`; therapy loading/empty wrappers delegate to `LoadingPanel`/`EmptyState`; differential and favourites chip wrappers delegate to DS `Chip` while retaining their surface-specific density/tone mapping. | `tests/design-system-target-evidence.test.ts`, `tests/mode-home-status-notice.dom.test.tsx` |
| overlays | `Sheet` portals to `OverlayRoot`'s modal host by default. Settings, the mobile Clinical Guide sidebar, and the three answer-review sheets use that default; none opts out with `portal={false}`. | `tests/sheet.dom.test.tsx`, `tests/design-system-target-evidence.test.ts` |
| overlays | `Sheet` portals to `OverlayRoot`'s modal host by default. Settings, the mobile PsychSift sidebar, and the three answer-review sheets use that default; none opts out with `portal={false}`. | `tests/sheet.dom.test.tsx`, `tests/design-system-target-evidence.test.ts` |
| answer | The three product copy paths share the payload builder described in §2.6; answer-review overlays retain their existing content, dismissal, and focus-return props while using the portal default. | `tests/answer-copy-payload.test.ts`, `tests/answer-clipboard-product-path.dom.test.tsx` |
| cross-mode links | `responsive-compact` deliberately mounts a phone chip rail and an `md+` card rail so SSR and hydration agree. CSS makes only one rail visible/in the accessibility tree; selectors and analytics must target the variant rail, while `cross-mode-links-rail` remains the phone-only contract. | `tests/design-system-target-evidence.test.ts`, focused `tests/ui-smoke.spec.ts` CrossModeLinks journeys |

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": 2,
"id": "4a148cf3-eae0-41f6-8b0a-61f4f318ca99",
"createdOn": "2026-09-04",
"action": "add",
"payload": {
"pri": "P2",
"type": "issue",
"summary": "Fourth occurrence of the shared-shell testid duplication race, now with a mechanism: CaringContactsShell's streamed/placed duplicate is only partly guarded",
"detail": "PR #2600 (claude/clinical-guide-redesign-ir5zcj), CI run 33868074584 job 101007656433 (Production UI shard 2): tests/ui-caring-contacts-workspace.spec.ts:1992 failed with 'strict mode violation: getByTestId(caring-contacts-phone-dock) resolved to 2 elements', identical markup, one via .first() one via the role/name locator. NOT PR #2600's fault: its diff (public/llms.txt, src/lib/brand.ts, ClinicalSidebar.tsx, master-search-header.tsx, ClinicalDashboard.tsx, calculators/mockups, globals.css, and matching tests) touches nothing under src/app/caring-contacts/** or src/components/caring-contacts/**. Source check: data-testid=caring-contacts-phone-dock has exactly one render site, shell.tsx:492 (nav aria-label Phone workspace) -- no second render path exists. STRONGER EVIDENCE THAN THE PRIOR TWO OCCURRENCES (service-actions-trigger on PR #2536/ui-tools.spec.ts, sources-topics-main on PR #2591/ui-sources.spec.ts:88, neither root-caused): this test file already documents and partially guards the exact mechanism. openWorkspace() (ui-caring-contacts-workspace.spec.ts:315-334) navigates with waitUntil:'load' then has a settle-wait comment: 'React streams the segment under loading.tsx's Suspense boundary into a hidden holder before moving it into place, so a production page sampled too early carries a second, inert copy of the whole shell. Settle on exactly one before measuring anything' -- followed by awaiting getByTestId('caring-contacts-rail') to reach count 1. Every /caring-contacts/* route dynamic-imports CaringContactsShell via next/dynamic (confirmed in page.tsx, patients/page.tsx, team/page.tsx, templates/page.tsx, schedule/page.tsx, reports/page.tsx, guidance/page.tsx, patients/[patientId]/page.tsx, templates/[pathwayId]/page.tsx), which is exactly the next/dynamic-under-Suspense shape session 2026-09-02's inbox note (id 5ad9c07e, re caring-contacts-guidance on PR #2536) hypothesized but did not verify. HYPOTHESIS, STILL NOT LIVE-VERIFIED: the settle-wait only polls caring-contacts-rail to count 1; it does not also wait for caring-contacts-phone-dock (or other shell-internal testids) to settle. Rail and dock are siblings inside the same streamed shell subtree, so Playwright's retrying assertion can resolve rail to 1 at a moment when dock, reconciled on a different tick, is still doubled -- which would explain a failure at line 1992 despite the openWorkspace() guard having already passed for that same navigation. Could not reproduce live in this session: this sandbox's egress policy returns 403 for cdn.playwright.dev (confirmed via the proxy README and status endpoint), so the Playwright chromium install command could not fetch the pinned v1234 build and no Playwright browser run was possible here -- this is a policy denial, not something to route around, so it was reported rather than retried. NEXT STEP for whoever picks this up: with a working browser, extend openWorkspace()'s settle-wait to also poll getByTestId('caring-contacts-phone-dock') for count 1 (mirroring the existing rail wait) before any per-width assertion, or generalize the wait to every shell-internal landmark the test suite queries; then re-run tests/ui-caring-contacts-workspace.spec.ts several times under load to confirm the race clears. If confirmed, the same generalized settle-wait likely explains the caring-contacts-guidance occurrence (PR #2536) and is worth checking against sources-topics-main and service-actions-trigger too, since both of those pages may have their own dynamic-import/Suspense-streamed shells with no equivalent settle-wait at all.",
"source": "session investigating PR #2600 CI failure, 2026-09-04",
"issueUlid": "01M1P80XNDNHGFXRGQQD670Y90"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": 2,
"id": "c0a4e200-1363-47c3-8d8b-41ec25165ba3",
"createdOn": "2026-09-04",
"action": "add",
"payload": {
"pri": "P2",
"type": "issue",
"summary": "Fourth occurrence of the shared-shell testid duplication race, now with a mechanism: CaringContactsShell's streamed/placed duplicate is only partly guarded",
"detail": "PR #2600 (claude/clinical-guide-redesign-ir5zcj), CI run 33868074584 job 101007656433 (Production UI shard 2): tests/ui-caring-contacts-workspace.spec.ts:1992 failed with 'strict mode violation: getByTestId(caring-contacts-phone-dock) resolved to 2 elements', identical markup, one via .first() one via the role/name locator. NOT PR #2600's fault: its diff (public/llms.txt, src/lib/brand.ts, ClinicalSidebar.tsx, master-search-header.tsx, ClinicalDashboard.tsx, calculators/mockups, globals.css, and matching tests) touches nothing under src/app/caring-contacts/** or src/components/caring-contacts/**. Source check: data-testid=caring-contacts-phone-dock has exactly one render site, shell.tsx:492 (nav aria-label Phone workspace) -- no second render path exists. STRONGER EVIDENCE THAN THE PRIOR TWO OCCURRENCES (service-actions-trigger on PR #2536/ui-tools.spec.ts, sources-topics-main on PR #2591/ui-sources.spec.ts:88, neither root-caused): this test file already documents and partially guards the exact mechanism. openWorkspace() (ui-caring-contacts-workspace.spec.ts:315-334) navigates with waitUntil:'load' then has a settle-wait comment: 'React streams the segment under loading.tsx's Suspense boundary into a hidden holder before moving it into place, so a production page sampled too early carries a second, inert copy of the whole shell. Settle on exactly one before measuring anything' -- followed by await expect(page.getByTestId('caring-contacts-rail')).toHaveCount(1). Every /caring-contacts/* route dynamic-imports CaringContactsShell via next/dynamic (confirmed in page.tsx, patients/page.tsx, team/page.tsx, templates/page.tsx, schedule/page.tsx, reports/page.tsx, guidance/page.tsx, patients/[patientId]/page.tsx, templates/[pathwayId]/page.tsx), which is exactly the next/dynamic-under-Suspense shape session 2026-09-02's inbox note (id 5ad9c07e, re caring-contacts-guidance on PR #2536) hypothesized but did not verify. HYPOTHESIS, STILL NOT LIVE-VERIFIED: the settle-wait only polls caring-contacts-rail to count 1; it does not also wait for caring-contacts-phone-dock (or other shell-internal testids) to settle. Rail and dock are siblings inside the same streamed shell subtree, so Playwright's retrying assertion can resolve rail to 1 at a moment when dock -- reconciled on a different tick -- is still doubled, which would explain a failure at line 1992 despite the openWorkspace() guard having already passed for that same navigation. Could not reproduce live in this session: this sandbox's egress policy returns 403 for cdn.playwright.dev (confirmed via /root/.ccr/README.md and the proxy status endpoint), so Downloading Chrome for Testing 151.0.7922.34 (playwright chromium v1234)\u001b[2m from https://cdn.playwright.dev/builds/cft/151.0.7922.34/linux64/chrome-linux64.zip\u001b[22m\nDownloading Chrome for Testing 151.0.7922.34 (playwright chromium v1234)\u001b[2m from https://cdn.playwright.dev/builds/cft/151.0.7922.34/linux64/chrome-linux64.zip\u001b[22m\nDownloading Chrome for Testing 151.0.7922.34 (playwright chromium v1234)\u001b[2m from https://cdn.playwright.dev/builds/cft/151.0.7922.34/linux64/chrome-linux64.zip\u001b[22m\nDownloading Chrome for Testing 151.0.7922.34 (playwright chromium v1234)\u001b[2m from https://cdn.playwright.dev/builds/cft/151.0.7922.34/linux64/chrome-linux64.zip\u001b[22m\nDownloading Chrome for Testing 151.0.7922.34 (playwright chromium v1234)\u001b[2m from https://cdn.playwright.dev/builds/cft/151.0.7922.34/linux64/chrome-linux64.zip\u001b[22m\nFailed to install browsers\nError: Failed to download Chrome for Testing 151.0.7922.34 (playwright chromium v1234), caused by\nError: Download failure, code=1\n at ChildProcess.<anonymous> (/home/user/Database/.claude/worktrees/agent-ac8e1da0ad4ee5edc/node_modules/playwright-core/lib/coreBundle.js:32015:32)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:295:12) cannot fetch the pinned v1234 build and no Playwright browser run was possible here -- this is a policy denial, not something to route around, so it was reported rather than retried. NEXT STEP for whoever picks this up: with a working browser, extend openWorkspace()'s settle-wait to also poll getByTestId('caring-contacts-phone-dock').toHaveCount(1) (mirroring the existing rail wait) before any per-width assertion, or generalize the wait to every shell-internal landmark the test suite queries; then re-run tests/ui-caring-contacts-workspace.spec.ts several times under load to confirm the race clears. If confirmed, the same generalized settle-wait likely explains the caring-contacts-guidance occurrence (PR #2536) and is worth checking against sources-topics-main and service-actions-trigger too, since both of those pages may have their own dynamic()/Suspense-streamed shells with no equivalent settle-wait at all.",
"source": "session investigating PR #2600 CI failure, 2026-09-04",
"issueUlid": "01M1P7ZFYE4PRD7VCEWSV0V6Z3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": 2,
"id": "d562a529-9b05-42a4-93b5-651ddffe4a98",
"createdOn": "2026-09-04",
"action": "cancel",
"payload": {
"requestId": "c0a4e200-1363-47c3-8d8b-41ec25165ba3",
"reason": "authoring error: unescaped backticks in --detail triggered bash command substitution, embedding stray shell output into the payload; re-filed cleanly"
}
}
4 changes: 2 additions & 2 deletions public/llms.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Clinical Guide
PsychSift

Purpose: Clinical Guide is a local clinical knowledge-base interface for searching indexed source documents, reviewing evidence, and drafting source-backed clinical answers.
Purpose: PsychSift is a local clinical knowledge-base interface for searching indexed source documents, reviewing evidence, and drafting source-backed clinical answers.

Agent / codebase orientation: docs/codebase-index.md (module map, APIs, Supabase, worker). Route index: docs/site-map.md.

Expand Down
11 changes: 11 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,15 @@
--brand-mark: var(--clinical-accent);
--brand-mark-emphasis: var(--clinical-accent-strong);
--brand-mark-contrast: var(--clinical-accent-contrast);
/* Corner wash behind the brand lockup in the sidebar and phone drawer header.
Per-theme rather than an alias, because the two themes need opposite
mixes to land on the same *read* — a whisper of brand at the top-left that
dissolves before it reaches the close control. In light, --clinical-accent-soft
(#eff5fc) is within a hair of the white panel and simply disappears, so the
wash is cut from the accent itself at a low percentage. In dark, the soft
step is already a deep blue against a near-black panel and carries on its
own; cutting from the accent there would put a bright haze over the mark. */
--brand-band-wash: color-mix(in oklab, var(--clinical-accent) 13%, transparent);
/* Tinted filter-count pill on the results band — quieter than a solid disc. */
--search-band-badge-bg: color-mix(in oklab, var(--clinical-accent) 16%, transparent);

Expand Down Expand Up @@ -751,6 +760,8 @@
--clinical-accent-soft: var(--primary-soft);
--clinical-accent-border: #235a7d;
--clinical-accent-contrast: #082e4d;
/* See the light definition: dark takes the soft step, not a cut of the accent. */
--brand-band-wash: color-mix(in oklab, var(--clinical-accent-soft) 88%, transparent);
--search-band-badge-bg: color-mix(in oklab, var(--clinical-accent) 16%, transparent);

--clinical-chat-sand: #2d2418;
Expand Down
2 changes: 1 addition & 1 deletion src/app/mockups/mode-dropdown/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function HeaderMockup({ expanded = false, compact = false }: { expanded?: boolea
<button
type="button"
className="grid h-11 w-11 shrink-0 place-items-center rounded-full text-[color:var(--text-muted)] transition hover:bg-[color:var(--surface-subtle)] hover:text-[color:var(--text)] lg:hidden"
aria-label="Open Clinical Guide menu"
aria-label="Open PsychSift menu"
>
<Menu className="h-5 w-5" />
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ClinicalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3418,7 +3418,7 @@ function ClinicalDashboardContent({
: "mb-0",
)}
>
<h1 className="sr-only">Clinical Guide</h1>
<h1 className="sr-only">PsychSift</h1>
{privateScopeStatus === "unavailable" ? (
// Lives inside <main> (not as a header sibling): in the answer view
// the header is absolute, so a sibling alert would reflow to the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ export function CalculatorSearchHome({
<div className="grid justify-items-center gap-2 rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-subtle)] p-6 text-center">
<p className="text-sm font-bold text-[color:var(--text-heading)]">No calculator matches that.</p>
<p className="text-sm-minus font-medium text-[color:var(--text-muted)]">
Try a symptom (“hopeless”, “drinking”) or ask Clinical Guide below.
Try a symptom (“hopeless”, “drinking”) or ask PsychSift below.
</p>
</div>
) : null}
Expand Down
2 changes: 1 addition & 1 deletion src/components/calculators/search-detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ export function CalculatorSearchHome({
<div className="grid justify-items-center gap-2 rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-subtle)] p-6 text-center">
<p className="text-sm font-bold text-[color:var(--text-heading)]">No calculator matches that.</p>
<p className="text-sm-minus font-medium text-[color:var(--text-muted)]">
Try a symptom (“hopeless”, “drinking”) or ask Clinical Guide below.
Try a symptom (“hopeless”, “drinking”) or ask PsychSift below.
</p>
</div>
) : null}
Expand Down
Loading
Loading