From c61e5c10b721572b8f6d2d5b7b99b6ba6c13cb26 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 21:53:42 +0000 Subject: [PATCH 1/3] fix(therapy): restore the shared search command surface on the Therapy home MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Therapy was the only one of the 15 app modes with no entry in `searchCommandSurfaceByMode`. `UniversalSearchCommandSurface` early-returns on a null config, so Therapy silently lost four shared affordances rather than one: the phone "Try this / Tap to search" ticket, the sm+ rotating hint line, the sm+ prompt-chip row, and the entire desktop command dropdown. This affected both the shared home `/` in Therapy mode and the standalone `/therapy-compass` home. Add the missing entry, with `remoteSearchEnabled: false` — Therapy reads the local generated catalogue, and `tests/search-command-surface.test.ts` already pinned that expectation (it passed only because the config was null). Every example was run through the real scorer against the 205-record catalogue so the ticket cannot advertise a query the catalogue has no answer for. Two adjacent deviations found while auditing, both low-risk: - `/therapy-compass` was the only standalone mode home not declaring `desktopSearchPlacement: "hero"`, leaving it on a different composer code path from its twelve peers in the portal-fallback case. - The standalone home hard-coded a magnifier as its identity medallion, so the same mode showed a different glyph depending on the door. It now derives from APP_MODE_ICON, matching nav, the mode picker and the shared home. Also correct two comments that cited "therapy-compass has no entry" as load-bearing rationale; the real reason that empty state offers no example is that no `onTryExample` handler is wired, which is unchanged here. Pin whole-set coverage so no future mode can silently lose the command surface. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01W5HsA9TpWxAN6KbqFAx7GA --- .../search-results-header-band.tsx | 12 ++++++---- .../therapy-compass/screens/home-screen.tsx | 9 ++++++-- src/lib/search-command-surface.ts | 18 +++++++++++++++ src/lib/search-shell-props.ts | 2 +- tests/search-command-surface.test.ts | 23 +++++++++++++++++++ tests/search-results-header-band.dom.test.tsx | 10 ++++---- tests/search-shell-props.test.ts | 3 +++ 7 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/components/clinical-dashboard/search-results-header-band.tsx b/src/components/clinical-dashboard/search-results-header-band.tsx index 91150ecaf3..5d2ae9d0d8 100644 --- a/src/components/clinical-dashboard/search-results-header-band.tsx +++ b/src/components/clinical-dashboard/search-results-header-band.tsx @@ -869,11 +869,13 @@ export function SearchResultsEmptyState({ const filtered = appliedFilters.length > 0; const Title = headingLevel ? (`h${headingLevel}` as "h2" | "h3" | "h4" | "h5" | "h6") : "p"; // What the panel can actually offer, decided before the copy describes it. - // `searchCommandSurfaceByMode` is a `Partial>` and therapy-compass - // has no entry, so there is neither an example nor a cross-mode route there — - // yet the body said "Try an example, or jump to another mode", naming two - // controls the reader could not see. Copy that promises absent affordances is - // the same defect class as a label that does not match its handler. + // Both halves need a handler as well as data: most hosts render this panel + // without `onTryExample`/`onCrossMode` (only Services, Calculators and Forms + // wire the first), so a mode with a full `searchCommandSurfaceByMode` entry can + // still have no example and no cross-mode route to offer — yet the body said + // "Try an example, or jump to another mode", naming two controls the reader + // could not see. Copy that promises absent affordances is the same defect class + // as a label that does not match its handler. const hasExample = Boolean(config?.examples[0] && onTryExample); const hasCrossMode = crossModes.length > 0 && Boolean(onCrossMode); // Degraded outranks filtered, which outranks a plain miss. A search whose diff --git a/src/components/therapy-compass/screens/home-screen.tsx b/src/components/therapy-compass/screens/home-screen.tsx index 039ad39859..fbd4790c55 100644 --- a/src/components/therapy-compass/screens/home-screen.tsx +++ b/src/components/therapy-compass/screens/home-screen.tsx @@ -1,9 +1,10 @@ "use client"; -import { GitCompareArrows, Network, Search, Sparkles, Waypoints } from "lucide-react"; +import { GitCompareArrows, Network, Sparkles, Waypoints } from "lucide-react"; import { useRouter } from "next/navigation"; import { ModeHomeMain, ModeHomeTemplate } from "@/components/mode-home-template"; +import { appModeIcons } from "@/lib/app-mode-icons"; import { modeHomeDesktopComposerSlotId } from "@/lib/mode-home-composer"; import { therapyHrefWithSearchParams, therapyScreenHref } from "@/lib/therapy-compass-navigation"; @@ -38,7 +39,11 @@ export function HomeScreen() { testId="therapy-compass" title="Therapy" subtitle={therapyCountCopy} - icon={Search} + // The mode's identity glyph is derived from APP_MODE_ICON rather than + // chosen here, so this medallion cannot drift from the one nav, the mode + // picker and the shared home `/` all render. It was a hard-coded magnifier, + // which made the same mode show two different identities by door. + icon={appModeIcons["therapy-compass"]} actionsLabel="Therapy workflows" desktopComposerSlotId={modeHomeDesktopComposerSlotId} actions={[ diff --git a/src/lib/search-command-surface.ts b/src/lib/search-command-surface.ts index d761eff350..8b17f3ba60 100644 --- a/src/lib/search-command-surface.ts +++ b/src/lib/search-command-surface.ts @@ -178,6 +178,24 @@ const searchCommandSurfaceByMode: Partial { expect(specifiers?.crossModes).toContain("formulation"); }); + it("covers every app mode, so no mode silently loses the command surface", () => { + // `UniversalSearchCommandSurface` early-returns on a null config, which takes + // the phone "Try this" ticker, the sm+ rotating hint, the prompt-chip row and + // the whole command dropdown with it. therapy-compass shipped in exactly that + // state — the single uncovered mode — so pin the whole set rather than the + // one mode that happened to be missing. + for (const modeId of appModeIds) { + const config = searchCommandSurfaceConfig(modeId); + expect(config, `${modeId} has no search command surface config`).not.toBeNull(); + expect(config?.examples.length, `${modeId} has no examples`).toBeGreaterThan(0); + expect(config?.suggestions.length, `${modeId} has no suggestions`).toBeGreaterThan(0); + } + }); + + it("keeps therapy suggestions local to the generated catalogue", () => { + const therapy = searchCommandSurfaceConfig("therapy-compass"); + expect(therapy?.examples).toContain("trauma-focused CBT"); + expect(therapy?.crossModes).toContain("documents"); + // Therapy reads public/therapy-compass-data, not the remote index. + expect(therapy?.remoteSearchEnabled).toBe(false); + }); + it("keeps calculator suggestions local while preserving remote typeahead elsewhere", () => { expect(commandSurfaceRemoteSearchEnabled("calculators")).toBe(false); expect(commandSurfaceRemoteSearchEnabled("documents")).toBe(true); diff --git a/tests/search-results-header-band.dom.test.tsx b/tests/search-results-header-band.dom.test.tsx index 821d803000..aa14526959 100644 --- a/tests/search-results-header-band.dom.test.tsx +++ b/tests/search-results-header-band.dom.test.tsx @@ -1431,10 +1431,12 @@ describe("SearchResultsEmptyState", () => { // owns that role on every search route, and a second one made singular // `getByRole("status")` queries across the suite ambiguous. expect(screen.getByText("No matches for “unmatched therapy”")).toBeVisible(); - // `searchCommandSurfaceByMode` is a `Partial>` with no - // therapy-compass entry, so this mode has neither an example nor a - // cross-mode route. The body must not tell the reader to "try an example, or - // jump to another mode" when the panel renders no control for either. + // No `onTryExample` or `onCrossMode` handler is passed here — matching the + // real Therapy call site (therapy-compass/screens/search-screen.tsx) — so + // this panel has neither an example nor a cross-mode route to offer, even + // though the mode now carries a full `searchCommandSurfaceByMode` entry. The + // body must not tell the reader to "try an example, or jump to another mode" + // when the panel renders no control for either. expect(screen.getByText("Check the spelling, or try a broader term.")).toBeVisible(); expect(screen.queryByRole("button", { name: /^Try:/ })).toBeNull(); expect(screen.queryByRole("button", { name: /^Search in / })).toBeNull(); diff --git a/tests/search-shell-props.test.ts b/tests/search-shell-props.test.ts index 720fd702c9..1712fb8692 100644 --- a/tests/search-shell-props.test.ts +++ b/tests/search-shell-props.test.ts @@ -40,8 +40,11 @@ describe("searchShellPropsForPathname", () => { }); it("maps therapy and home fallbacks", () => { + // Therapy was the one standalone mode home not declaring the hero placement, + // which left it on a different composer code path from its twelve peers. expect(searchShellPropsForPathname("/therapy-compass/search")).toEqual({ initialMode: "therapy-compass", + desktopSearchPlacement: "hero", }); expect(searchShellPropsForPathname("/")).toEqual({ initialMode: "answer" }); }); From 0605b0e85edc9b93f03c38532231a3013710eaa4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 22:02:15 +0000 Subject: [PATCH 2/3] docs(issues): capture the cross-mode home audit findings as inbox requests Eight merge-safe inbox requests recording the deviations found while auditing the mode homes for the Therapy fix in this PR. The low-risk ones are already fixed in the preceding commit; these are the remainder, which need either an owner decision or their own visual-baseline work: - competing title systems (sharedHomePresentation vs hard-coded standalone) - three more homes overriding the canonical APP_MODE_ICON glyph - three standalone homes with no loading.tsx, invisible to the contract test - /tools phone dock suppressing the patient-identifiable-information warning - /favourites rendering two different homes for one mode - bespoke composer slots skipping the invariant-15 SSR height reservation - placeholder/heading/doc-index copy drift - suggestion data duplicated across three sources Each is an immutable request file; docs/outstanding-issues.md itself is untouched, so this cannot conflict with a concurrent ledger write. Run npm run issues:reconcile from a serialized ledger branch after this lands. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01W5HsA9TpWxAN6KbqFAx7GA --- .../61d609ea-0f7c-4934-ab71-b9a972f5a7be.json | 14 ++++++++++++++ .../6eb8b382-a129-4470-91ec-383bc580c25f.json | 14 ++++++++++++++ .../72ec8611-0294-4e33-aa36-92668ed25cd6.json | 14 ++++++++++++++ .../b10cb24d-17fa-40ca-b8bb-90eee806ea0a.json | 14 ++++++++++++++ .../c09532b5-549c-47e0-a4b7-5977435d1d0f.json | 14 ++++++++++++++ .../c196b2fd-fde1-482b-9cac-355cc2b4ee04.json | 14 ++++++++++++++ .../db8e7ade-2f04-4255-b812-29900e801e47.json | 14 ++++++++++++++ .../ef811fd9-df86-4a1f-bd5e-cd86233d251e.json | 14 ++++++++++++++ 8 files changed, 112 insertions(+) create mode 100644 docs/outstanding-issues-inbox/61d609ea-0f7c-4934-ab71-b9a972f5a7be.json create mode 100644 docs/outstanding-issues-inbox/6eb8b382-a129-4470-91ec-383bc580c25f.json create mode 100644 docs/outstanding-issues-inbox/72ec8611-0294-4e33-aa36-92668ed25cd6.json create mode 100644 docs/outstanding-issues-inbox/b10cb24d-17fa-40ca-b8bb-90eee806ea0a.json create mode 100644 docs/outstanding-issues-inbox/c09532b5-549c-47e0-a4b7-5977435d1d0f.json create mode 100644 docs/outstanding-issues-inbox/c196b2fd-fde1-482b-9cac-355cc2b4ee04.json create mode 100644 docs/outstanding-issues-inbox/db8e7ade-2f04-4255-b812-29900e801e47.json create mode 100644 docs/outstanding-issues-inbox/ef811fd9-df86-4a1f-bd5e-cd86233d251e.json diff --git a/docs/outstanding-issues-inbox/61d609ea-0f7c-4934-ab71-b9a972f5a7be.json b/docs/outstanding-issues-inbox/61d609ea-0f7c-4934-ab71-b9a972f5a7be.json new file mode 100644 index 0000000000..ec9a87fcca --- /dev/null +++ b/docs/outstanding-issues-inbox/61d609ea-0f7c-4934-ab71-b9a972f5a7be.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "61d609ea-0f7c-4934-ab71-b9a972f5a7be", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P2", + "type": "issue", + "summary": "/tools on a phone is the only mode home with no visible patient-identifiable-information warning", + "detail": "Tools is the sole route setting mobileHomeComposerPlacement: 'footer' (src/lib/search-shell-props.ts). showsComposerPrivacyNotice in master-search-header.tsx:1813 is 'usesPhoneSearchLayout ? isDesktopHomeComposer : true', so the phone footer dock suppresses both the 'Do not enter patient-identifiable information.' line and the Privacy and data processing link. The composer placement matches the documented exception in docs/search-chrome-behaviour.md row 2, but the docs do not record that the exception costs the governance copy. Needs an owner decision for a clinical product. Found during the PR #2160 cross-mode audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BE9G1GD8JBCV161HS2GQQB" + } +} diff --git a/docs/outstanding-issues-inbox/6eb8b382-a129-4470-91ec-383bc580c25f.json b/docs/outstanding-issues-inbox/6eb8b382-a129-4470-91ec-383bc580c25f.json new file mode 100644 index 0000000000..322003c69a --- /dev/null +++ b/docs/outstanding-issues-inbox/6eb8b382-a129-4470-91ec-383bc580c25f.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "6eb8b382-a129-4470-91ec-383bc580c25f", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P3", + "type": "rec", + "summary": "Mode home copy drift: three placeholder-punctuation conventions, inconsistent heading levels, and a stale docs/site-map.md mode index", + "detail": "Placeholders use ASCII '...' (answer, documents, services, forms, favourites, dsm, specifiers, formulation, prescribing, tools, calculators), Unicode '…' (therapy-compass, factsheets, dictionary), and no terminator at all on differentials ('Ask or search a presentation'). Heading level is h2 on answer/documents/prescribing and h1 elsewhere, so the Documents home has an h2 and no h1 anywhere on the page. docs/site-map.md's mode page index covers 11 modes — Therapy, Factsheets, Dictionary and Calculators have no row — and CLAUDE.md still says '13 app modes' when app-modes.ts defines 15. Pick one convention per axis and refresh the generated docs. Found during the PR #2160 cross-mode audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BEA22B97VQK5QN24JSPFCM" + } +} diff --git a/docs/outstanding-issues-inbox/72ec8611-0294-4e33-aa36-92668ed25cd6.json b/docs/outstanding-issues-inbox/72ec8611-0294-4e33-aa36-92668ed25cd6.json new file mode 100644 index 0000000000..c6b70fc88e --- /dev/null +++ b/docs/outstanding-issues-inbox/72ec8611-0294-4e33-aa36-92668ed25cd6.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "72ec8611-0294-4e33-aa36-92668ed25cd6", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P2", + "type": "issue", + "summary": "Three standalone mode homes have no loading.tsx (/medications, /calculators, /dictionary) and the contract test cannot catch it", + "detail": "All three are in standaloneModeHomePaths (src/lib/search-route-ownership.ts) and chrome invariant 18 requires ModeHomeRouteLoading, but tests/mode-home-loading-contract.test.ts enumerates only ten routes and omits these three, so the gap is invisible to CI. /documents is legitimately exempt (dashboard-owned). Fix: add the three loading.tsx files and derive the contract test's route list from standaloneModeHomePaths instead of a hand-written list. Verified by direct filesystem check during the PR #2160 audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BE9FVW6K9YGQY9G8CYM421" + } +} diff --git a/docs/outstanding-issues-inbox/b10cb24d-17fa-40ca-b8bb-90eee806ea0a.json b/docs/outstanding-issues-inbox/b10cb24d-17fa-40ca-b8bb-90eee806ea0a.json new file mode 100644 index 0000000000..5709c95179 --- /dev/null +++ b/docs/outstanding-issues-inbox/b10cb24d-17fa-40ca-b8bb-90eee806ea0a.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "b10cb24d-17fa-40ca-b8bb-90eee806ea0a", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P3", + "type": "issue", + "summary": "Tools and Favourites bespoke home composer slots skip the SSR height reservation chrome invariant 15 requires", + "detail": "ModeHomeTemplate renders its composer slot with data-composer-reserve='pending' plus min-h tokens (mode-home-template.tsx:316-320) so the hero does not shift when the portal attaches. The two bespoke homes hand-roll the slot without either: favourites-command-library-page.tsx:1426 and tools-search-results-page.tsx:353, plus favourites-hub.tsx:187. Those three get no SSR height reservation, which is the CLS that invariant 15 exists to prevent. Found during the PR #2160 cross-mode audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BEA1WHYJ3R7Y86ZGZ9FEV4" + } +} diff --git a/docs/outstanding-issues-inbox/c09532b5-549c-47e0-a4b7-5977435d1d0f.json b/docs/outstanding-issues-inbox/c09532b5-549c-47e0-a4b7-5977435d1d0f.json new file mode 100644 index 0000000000..9cc50cd38a --- /dev/null +++ b/docs/outstanding-issues-inbox/c09532b5-549c-47e0-a4b7-5977435d1d0f.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "c09532b5-549c-47e0-a4b7-5977435d1d0f", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P2", + "type": "issue", + "summary": "Mode homes: two competing title systems disagree for 8 of 13 modes (sharedHomePresentation vs hard-coded standalone titles)", + "detail": "src/lib/ui-copy.ts sharedHomePresentation drives the shared home /, while each standalone *-home-page.tsx hard-codes its own title. Its doc comment claims each entry mirrors the standalone home 'so a clinician sees the same words whichever door they came through' — untrue today: Documents/Clinical Documents, Services/Clinical Services, Forms/Clinical Forms, Differentials/Differential Diagnosis, Specifiers/Diagnostic Specifiers, Formulation/Clinical Formulation, Medication/Medication Guidance, Therapy/Therapy Compass. Either derive one list from the other or correct the comment. Found during the PR #2160 cross-mode audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BE929PTWKWE4Q142YGCRTF" + } +} diff --git a/docs/outstanding-issues-inbox/c196b2fd-fde1-482b-9cac-355cc2b4ee04.json b/docs/outstanding-issues-inbox/c196b2fd-fde1-482b-9cac-355cc2b4ee04.json new file mode 100644 index 0000000000..c2b6a6f351 --- /dev/null +++ b/docs/outstanding-issues-inbox/c196b2fd-fde1-482b-9cac-355cc2b4ee04.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "c196b2fd-fde1-482b-9cac-355cc2b4ee04", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P3", + "type": "issue", + "summary": "Three mode homes override the canonical APP_MODE_ICON glyph (services, forms, dictionary)", + "detail": "services uses Users (canonical route), forms uses FileText (canonical fileSignature — and identical to the Documents home tile), dictionary uses BookOpen (canonical bookMarked). Same class as the therapy-compass magnifier fixed in PR #2160, which now derives from appModeIcons. Each remaining one needs its own visual-baseline re-adoption, so they were left out of that PR. Found during the PR #2160 cross-mode audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BE9FPF0EKBGCMBD20EHNDF" + } +} diff --git a/docs/outstanding-issues-inbox/db8e7ade-2f04-4255-b812-29900e801e47.json b/docs/outstanding-issues-inbox/db8e7ade-2f04-4255-b812-29900e801e47.json new file mode 100644 index 0000000000..fd4966397c --- /dev/null +++ b/docs/outstanding-issues-inbox/db8e7ade-2f04-4255-b812-29900e801e47.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "db8e7ade-2f04-4255-b812-29900e801e47", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P3", + "type": "issue", + "summary": "/favourites and /?mode=favourites render visibly different homes for the same mode", + "detail": "The standalone hero lockup was deliberately deleted from favourites-command-library-page.tsx (ledger #164), but the dashboard variant FavouritesHub (src/components/clinical-dashboard/favourites-hub.tsx:179) still renders ModeHomeHero with 'Favourites / Saved notes, sources, and sets.' So the same mode looks different depending on the door. Decide which treatment is canonical and apply it to both. Found during the PR #2160 cross-mode audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BEA1Q5V0EDR4MJSWW1F5GD" + } +} diff --git a/docs/outstanding-issues-inbox/ef811fd9-df86-4a1f-bd5e-cd86233d251e.json b/docs/outstanding-issues-inbox/ef811fd9-df86-4a1f-bd5e-cd86233d251e.json new file mode 100644 index 0000000000..9faf6818e9 --- /dev/null +++ b/docs/outstanding-issues-inbox/ef811fd9-df86-4a1f-bd5e-cd86233d251e.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "ef811fd9-df86-4a1f-bd5e-cd86233d251e", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P3", + "type": "rec", + "summary": "Mode home suggestion data is duplicated across three unrelated sources", + "detail": "searchCommandSurfaceByMode examples/suggestions (src/lib/search-command-surface.ts) drive the Try this ticket, rotating hint and prompt chips; per-page pills arrays (e.g. therapy-compass/screens/home-screen.tsx:14, services-home-page.tsx) drive the mode-home pill row; src/lib/tools-catalog.ts:348 is a third. Only the first drives the ticket, so after PR #2160 the Therapy home advertises two different suggestion sets — its five pills and the three ticket examples. Reconcile to one source per mode. Found during the PR #2160 cross-mode audit.", + "source": "PR #2160 cross-mode home audit", + "issueUlid": "01M0BEA27H90Y0FDZXZY53CRKF" + } +} From 8428884709548bddeb65c16cd336d6cbdea4aecb Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 22:16:52 +0000 Subject: [PATCH 3/3] docs(issues): capture the mode-home composer reserve CLS gap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Lighthouse budget failure on this PR traced to a shared defect rather than the Therapy change alone: the mode-home composer slot reserves the composer's height but not the suggestion ticket and rotating hint that UniversalSearchCommandSurface renders above it, so the portal attaching post-hydration shifts content on every ticket-bearing mode home. Evidence from this PR's own run — mobile-dsm baseline CLS 0.0353, mobile-forms 0.088, mobile-root 0.016, while mobile-therapy-compass sat at 0.000 purely because Therapy rendered no ticket at all. Restoring it moved Therapy to 0.032, in line with its peers. Fixing the reserve would take every mode home toward zero, but it touches a shared token across all 15 homes and needs verify:phone-chrome plus Lighthouse and visual baseline re-adoption, so it is filed rather than bundled into a low-risk consistency fix. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01W5HsA9TpWxAN6KbqFAx7GA --- .../fa9f768a-9eee-4a67-96b5-ded98afbecd9.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/outstanding-issues-inbox/fa9f768a-9eee-4a67-96b5-ded98afbecd9.json diff --git a/docs/outstanding-issues-inbox/fa9f768a-9eee-4a67-96b5-ded98afbecd9.json b/docs/outstanding-issues-inbox/fa9f768a-9eee-4a67-96b5-ded98afbecd9.json new file mode 100644 index 0000000000..a3b44c5dd1 --- /dev/null +++ b/docs/outstanding-issues-inbox/fa9f768a-9eee-4a67-96b5-ded98afbecd9.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "fa9f768a-9eee-4a67-96b5-ded98afbecd9", + "createdOn": "2026-08-18", + "action": "add", + "payload": { + "pri": "P2", + "type": "issue", + "summary": "Mode-home composer reserve does not account for the suggestion ticket, so every ticket-bearing home carries a ~0.035 CLS shift", + "detail": "ModeHomeTemplate reserves the composer slot with --spacing-mode-home-composer-phone (6.625rem) / --spacing-mode-home-composer-wide (5.5rem), but the portal content is UniversalSearchCommandSurface, which renders SmartRotatingHint (phone ticket) and the sm+ rotating line/prompt-chip row ABOVE the composer inside that same slot. The reserve therefore under-accounts, and the portal attaching post-hydration shifts content — the defect class chrome invariant 15 exists to prevent. Evidence from the PR #2160 Lighthouse run: mobile-dsm baseline CLS 0.0353, mobile-forms 0.088, mobile-root 0.016, while mobile-therapy-compass was 0.000 purely because Therapy had no command-surface entry and so rendered no ticket. Restoring the ticket moved Therapy to 0.032, matching its peers. Fix: raise the reserve tokens to include the hint row height (or reserve it separately), which should take every mode home toward ~0. Touches all 15 mode homes, so it needs verify:phone-chrome plus Lighthouse and visual baseline re-adoption — deliberately not bundled into PR #2160.", + "source": "PR #2160 Lighthouse budget failure", + "issueUlid": "01M0BF075ZJVYQEMAJJ5Y2R1WF" + } +}