chore: pin esbuild to latest stable 0.28.1 - #24
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
BigSimmo
pushed a commit
that referenced
this pull request
Jul 22, 2026
- Managed-alternative setup now says scope to UPDATE events only (do not tick INSERT) in the concrete instruction, not just a later warning — an INSERT webhook re-introduces the upload race. - outstanding-issues #25: the base-URL GUC is mandatory per environment, not optional (the trigger no-ops without it), so the activation checklist can't leave the trigger inert. Both are consistency fixes for earlier changes; neither touches the #24 row or next-id marker (the ledger-collision surface vs #1066). Docs-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BHMgBiXbH4Q5tUC7WxoyaX
BigSimmo
added a commit
that referenced
this pull request
Jul 22, 2026
BigSimmo
pushed a commit
that referenced
this pull request
Jul 22, 2026
- Renumber the webhook ledger rows #24-#27 -> #25-#28 (next-id 029) so they no longer collide with #1066's #24 (WebKit e2e). Per the consolidation decision, #1065 lands and the duplicate Codex webhook-doc PRs are closed; #1066 stays as a separate item. - Scope the "receiver 500 -> retries" claim in the receiver-behaviour bullet: it only holds for a caller that actually retries, and neither documented path (raw net.http_post trigger or UPDATE-only managed webhook) does, so a failed clear can leave reindex_requested stuck true; recover via clear-then-flip. Docs-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BHMgBiXbH4Q5tUC7WxoyaX
This was referenced Jul 24, 2026
BigSimmo
added a commit
that referenced
this pull request
Jul 28, 2026
…-3cd5 docs: reopen #24 WebKit RSC prefetch validation issue
BigSimmo
pushed a commit
that referenced
this pull request
Aug 13, 2026
A server-component redirect() on /documents/source streams a 200 page whose redirect completes client-side through an RSC navigation; Next 16's validateRSCRequestHeaders then answers the un-stamped follow-up with a second corrective 307, and Playwright WebKit surfaces that chain as _rsc access-control pageerrors (issue #24). Resolving the fallback in the proxy turns the whole flow into one immediate HTTP 307 with no page render and no RSC fetch against a redirecting route. The sanitisation moves to a shared pure helper; the page stays as a straight-line redirect-only backstop; no pageerror suppression and no CORS changes. Native macOS Safari confirmation remains outstanding on #24. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CvJyDJfC9AMaJ5Jh36TLja
BigSimmo
pushed a commit
that referenced
this pull request
Aug 13, 2026
…tion Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CvJyDJfC9AMaJ5Jh36TLja
BigSimmo
added a commit
that referenced
this pull request
Aug 19, 2026
* feat(home): consolidate DSM, Dictionary and Factsheets onto the shared home First group of the lightweight-home migration. Every mode is moving to one shared home at `/?mode=<id>` whose per-mode copy lives in `sharedHomePresentation`; the detailed per-mode home pages are retired from the live routes rather than deleted. Per mode: - `/(search-app)/<mode>/page.tsx` forwards to the shared home. The path stays so bookmarks, the sitemap and external deep links keep resolving. - The detailed page is preserved, off the live routes, at `/mockups/<mode>-home-detailed` — design scratch, 404 in production. - The bare path leaves `standaloneModeHomePaths`: it renders nothing now, and claiming composer ownership would reserve hero geometry on a route that never paints. The namespace stays in `alwaysStandaloneShellPathPrefixes` because its SUB-routes still need standalone shell treatment. The redirect is resolved in `src/proxy.ts`, not by the page alone. Next 16 documents that `redirect()` in a streaming context "will insert a meta tag to emit the redirect on the client side" rather than serving a 307 (node_modules/next/dist/docs/.../redirect.md). Measured here, the page-only version produced `<meta http-equiv="refresh" content="1;url=/?mode=dsm">` — a full second of empty shell on a primary navigation path. Resolving it in the proxy yields a real 307, which is the same reasoning that already put the document-source fallbacks there (issue #24). The page keeps its own redirect as a backstop for anything the matcher misses. The incoming query is carried across, so `/dsm?q=panic&run=1` becomes `/?mode=dsm&q=panic&run=1` and the shared home resolves it onward to `/dsm/search`. That cannot loop: the onward hop targets the search surface, not the bare path. `mode` is always overwritten from the pathname so a crafted `/dsm?mode=favourites` cannot bounce a visitor into an unrelated mode. Sidebar Factsheets now points at `/?mode=factsheets`, matching how Answer was already wired. Verified: 674 test files / 7288 tests pass; typecheck clean; live 307s confirmed for all three bare paths with sub-routes (`/dsm/search`, `/dsm/compare`, `/factsheets/search`, `/dictionary/browse`) still rendering 200; browser check confirms each lands on the shared home with its own title, subtitle and in-flow composer. * feat(home): consolidate the remaining seven mode homes onto the shared home Completes the switch to one lightweight home for every mode. Services, Forms, Calculators, Specifiers, Formulation, Differentials and Therapy join DSM, Dictionary and Factsheets: their bare paths keep resolving for bookmarks and external links, but now redirect to `/?mode=<id>` instead of rendering a second home. Ten of the fifteen modes are consolidated; `/documents`, `/medications`, `/favourites` and `/tools` still own real, distinct surfaces and are untouched. Each consolidated mode gains a `<mode>/search` route for its submitted searches. That is load-bearing, not tidiness: the bare path redirects, so routing a query back at it would loop. `consolidatedModeHomeModeIds` now drives both halves from one list — the redirect map and `appModeHomeHref` — so a mode cannot be added to one without the other, and a test walks every consolidated mode asserting its submitted href never lands on a redirecting path. `appModeHomeHref` also stops routing in-app navigation through those redirects: with no query it returns `/?mode=<id>` directly. That is what retargets the sidebar, the mode-nav tabs and the detail-page back links automatically; only the pinned Services entry needed editing by hand. Redirects resolve in the proxy rather than the page, because Next 16 turns a `redirect()` inside a streaming layout into a client-side meta refresh instead of a 307 (`node_modules/next/dist/docs/.../redirect.md`). Verified live: all ten bare paths return 307, all ten `/search` routes return 200. Two copy corrections the consolidation made visible: Therapy's shared-home title now reads "Therapy", matching the mode's own copy rule and the home it replaced; and the Factsheets nav comment no longer claims `/factsheets` renders a category browse, which it had not for some time. The retired detailed pages are preserved off the live routes at `/mockups/<mode>-home-detailed`. npm run verify:cheap: exit 0 — 674 files, 7290 passed | 4 skipped (7294). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * feat(home): consolidate Documents onto the shared home Documents was the last mode home that rendered nothing of its own. Its page component was an empty fragment and ClinicalDashboard supplied the body, so the bare path showed a query-less "Document matches / Loading document results" shell where `/?mode=documents` shows the mode's actual hero — a duplicate route that was also the worse of the two. `/documents` now redirects to `/?mode=documents` like the other consolidated modes. Its sub-routes are untouched: `/documents/search`, `/documents/[id]` and `/documents/source/*` are real surfaces and keep rendering themselves. This retires a shell concept with it. `dashboardOwnedModeHomePaths` existed only to say "and also `/documents`" wherever `pathname === "/"` gated an unsubmitted mode home; with Documents redirecting, `/` is the only such path and both the set and `isDashboardOwnedModeHomePath` are gone. The autoRunSearch gate that kept keystrokes from firing searches is unchanged in effect — still gated on run=1 everywhere it was. Documents stays out of `alwaysStandaloneShellPathPrefixes`, unlike the other ten consolidated namespaces: `/documents/search` is dashboard-rendered because it needs retrieval state. The route-ownership test now asserts that asymmetry rather than looping over every consolidated mode as if they were uniform. Not consolidated, and deliberately so — these are not duplicate homes, they are each mode's only functional surface, so retiring them would delete a feature rather than de-duplicate a page: - /tools the launcher (categories, filters, saved) - /favourites the hub (Continue, Recent, sets, sort/view) - /medications the prescribing workspace (dose/safety/monitoring checks) npm run verify:cheap: exit 0 — 674 files, 7290 passed | 4 skipped (7294). Live: /documents 307 -> /?mode=documents; /documents/search 200. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(home): forward a submitted deep link to the mode's own results surface `/forms?q=transport&run=1` was going to the shared home along with every other hit on a consolidated bare path. That silently changed where a submitted deep link renders: the dashboard shows its own in-place results for some modes and nothing at all for others, so this one stopped reaching FormsSearchResultsPage entirely. Four phone journeys caught it — the unit suite was green throughout, because nothing in it exercises the hop end to end. The redirect now branches on whether the link was actually submitted, which is the distinction the bare path used to carry itself: /dsm -> /?mode=dsm (home, composer seeded) /dsm?q=panic&run=1 -> /dsm/search?q=panic&run=1 (where it rendered before) A query without run=1 is a draft, not a search, and still lands on the home. Every other parameter rides along untouched, so queryMode and scope filters survive the hop; `mode` stays overwritten from the pathname, and the destination path is the matched key rather than anything the query can name, so neither branch is steerable by the request. Verified live on all eleven consolidated modes: bare paths 307 to the shared home, submitted deep links 307 to `<mode>/search`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * test(ui): drop the redirected /dictionary from the Dictionary route sweep `/dictionary` has no home of its own since consolidation — it redirects to `/?mode=dictionary` — so the sweep sat on `dictionary-home-main` for 20s at each of three viewports waiting for a testid that route no longer renders. The shared home is covered by the shared-home suites, and the retired detailed home lives at /mockups/dictionary-home-detailed, which 404s in production and is out of scope for a production-route sweep. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(home): keep Therapy and Documents out of the consolidation, and align the specs Two of the eleven modes should never have been folded in. Both were caught by the Chromium gate, which the unit suite could not have found — one of them because it only misbehaves in a production build. Therapy is `devOnly` (app-modes.ts), pending qualified-clinician sign-off on its catalogue. The shared home hides devOnly modes in production, so consolidating it removed Therapy from production altogether: measured against a production build, `/?mode=therapy-compass` rendered mode Answer. Dev hid this because the gate is environment-dependent. It keeps its own home until that gate lifts. Documents I justified wrongly. I read `DocumentsHomeClient` returning an empty fragment as "the route renders nothing" — but the shell mounts ClinicalDashboard for that pathname, so `/documents` paints a real Documents home: browse, recent documents and the document-search empty state, exactly as `/medications` paints the prescribing workspace. A page component says nothing about what its route renders when the shell owns the body. Nine modes stay consolidated: services, forms, differentials, dsm, specifiers, formulation, calculators, factsheets, dictionary. Also restores a deep-link behaviour the split had dropped: `/services/search` carries the legacy `?query=` canonicalisation that the bare path used to own, and the proxy counts that alias as a submitted query — without both, `/services?q=%20&query=13YARN&run=1` read as unsubmitted and landed a working old bookmark on the home with nothing to search for. Spec updates are the rest of the diff, all of the same class: route tables and URL assertions that named a bare path now name the shared home or the mode's `/search` route. Two moved rather than changed — the formulation phone-scroll runway follows its content to `/formulation/search`, and the differentials recent-work touch-target audit follows the retired home to `/mockups` under `@mockup`, since the component still ships but the route 404s in production. npm run test: 674 files, 7292 passed | 4 skipped (7296). Chromium gate next. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(differentials): register /differentials/search for the phone compare addon The new dedicated /differentials/search route (this PR) wasn't in differentialsCompareAddonActive's pathname check, so GlobalSearchShell never created the phone compare-bar dock host there — DifferentialsHome portals into a slot that doesn't exist, silently dropping the compare action on phone for submitted searches on the new route. Addresses a Copilot review finding on PR #2157. * fix(docs): align the adoption route count with the manifest (75) The conflict resolution on this branch kept the pre-merge 69, which counted the ten Ward Flow routes from main but not the six `<mode>/search` routes this branch splits out of the consolidated bare paths. The manifest itself has 75, so `Unit coverage` went red on the mismatch rather than on anything about the code. 59 + 6 + 10 = 75, which is what the existing comment already explained. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * feat(home): consolidate Documents and Therapy onto the shared home Owner decisions, both reversing an earlier call in this branch. Documents: the bare path renders the same `ModeHomeTemplate` the shared home uses, with the identical subtitle — the only extras were three action shortcuts (browse the library / continue reading / open a source PDF) and an indexed-source count. That is a duplicate home, not a workspace, and the owner accepted losing those extras rather than carry a second home. Nothing is preserved under /mockups for this one; there was no detailed page to keep. Therapy: consolidating it was blocked while the mode was `devOnly`, because the shared home hides devOnly modes in production — measured against a production build, `/?mode=therapy-compass` came back as mode Answer, which would have removed Therapy from production entirely. PR #2150 shipped Therapy in production with its review state disclosed, lifting that gate. Only the home screen retires (preserved at /mockups/therapy-compass-home-detailed); search, compare, recommend, pathways and every record route are untouched. Eleven modes are now consolidated. Three keep a home of their own, and none of them is a duplicate of the shared home — each is its mode's only functional surface: /tools (launcher), /favourites (hub), /medications (prescribing workspace). Two dead branches went with the change rather than lingering as false ownership: `dashboardOwnedModeHomePaths` existed only to say "and also `/documents`" beside `pathname === "/"`, and the differentials compare addon still named the bare `/differentials`, which can no longer be true. npm run test: 681 files, 7380 passed | 4 skipped (7384). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * test(ui): retarget the Documents and Therapy browser journeys Both modes joined the shared home, so specs that navigated to /documents or /therapy-compass were waiting on testids those paths no longer render. - Sidebar href expectations follow the pinned entries onto /?mode=documents. - The Documents workspace journeys move to /documents/search, which is where document-search-workspace and document-search-empty-state actually live. - The Therapy home assertions move to the shared home, whose per-mode title is a level-2 heading under the page's sr-only h1. - The Therapy route-coverage interaction went through a 'Common therapy searches' pill that lived on the retired detailed home; it now opens that pill's own destination directly, keeping the mode-nav assertions the step exists for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * docs(index): index /calculators/search in the route table The prose already described the new mode search surfaces, but the route table still mapped `/calculators` to a single `page.tsx", so `/calculators/search` had no entry. Every other consolidated mode's row points at its directory and covers its search route that way; this makes calculators match. CodeRabbit reported this as already addressed in 3c116d1..24f3999. It was not — line 88 still carried the single-file form. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(test): update stale search-route assertions for lightweight mode homes Production UI failed on three Chromium specs after the consolidated mode-home redirect landed: - ui-tools.spec.ts: the differentials compare queue's edit-selection link now correctly points at /differentials/search, matching the update already made to tests/differentials-navigation.test.ts in this PR; only this second occurrence was missed. - ui-tools.spec.ts: /services is a consolidated mode path, so consolidatedModeHomeTarget redirects the bare 'Back to services' link onto the shared home (?mode=services) rather than rendering a standalone /services page — the sibling 'Use in navigator' test in the same file already asserts the analogous /services/search redirect for a different action. - ui-specifiers.spec.ts: navigate straight to the new dedicated /specifiers/search route instead of the bare /specifiers?q=... path, avoiding a redirect-hop race with the fixed mobile composer. * docs(ledger): record the Run PR sweep review for #2157 * fix(routing): treat `search` as a reserved route suffix, not a record slug Consolidation gave every consolidated mode a `<mode>/search` results route, and `isSlugDetail` read that final segment as a record slug: `/formulation/search` classified as the record `search`, which made it an information page, and information pages suppress the composer. So a submitted formulation or specifier search rendered its results with no search box at all — no way to refine the query without going back. Verified from the Playwright page snapshot, not inferred: the accessibility tree for `/formulation/search` had the query ribbon, the filters and nine mechanism cards, and no combobox anywhere in the banner or the dock. `search` now sits alongside `builder`, `compare` and `map` in the shared suffix set. `/factsheets` and `/dictionary` had already hand-excluded "search" for exactly this reason, which is the signal it belonged in the shared set rather than in per-mode lists. Confirmed live afterwards: formulation, specifiers, forms and services search routes all render one composer again. The rest is spec alignment for the Documents journeys, which had to move twice. `/documents` redirects, and the dashboard only mounts the documents workspace for a submitted query, so workspace journeys now open `/documents/search?q=…&run=1` and the one journey about the unsubmitted surface opens `/?mode=documents`. Three URL assertions dropped their end-anchors, because the proxy appends `mode=<id>`. npm run test: 681 files, 7382 passed | 4 skipped (7386). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(perf): drop the redirecting mode routes from the Lighthouse and bundle budgets `/therapy-compass`, `/dsm` and `/forms` became redirect stubs with home consolidation, so Lighthouse followed the 307 and graded `/?mode=<id>` against a baseline captured on the retired detailed home — which the checker reports as "measured a different page than requested", failing regardless of tolerances. The bundle budget had the same problem from the other side: its per-route gzip baselines were enforcing a weight against a route that now ships a `redirect()` stub. All three render the same shared home as `/`, which the budget already measures, so removing them costs duplication rather than coverage. Their stale baseline rows go with them. `/?mode=<id>` is not a usable replacement here: `routeSlug` strips the leading slash and would produce `?mode=dsm`, which is not filename-safe. Restoring per-mode coverage means measuring the `<mode>/search` results routes, and those need baseline rows only the dispatch-only refresh job can record — deliberately not hand-written here. `tests/bundle-budget.test.ts` pins the two budgets to the same route list, so both move together. The Lighthouse test's ROUTES did double duty as a synthetic fixture and the committed-list assertion; those are now separate constants, so the unit cases keep several rows to exercise while the committed list is asserted on its own. npm run test: 681 files, 7382 passed | 4 skipped (7386). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * test(mockups): derive tool counts from the fixture instead of pinning literals Four @mockup specs were failing on this branch and on every other PR that merges main. Not from this branch's changes: "Add Ward Flow" (#2140) took the tools fixture from 9 to 10 and Admin from 3 to 4, and the tools catalogue from 14 to 15, while three assertions in the task-directory spec and one in the search-mode spec carried those totals as literals. This branch touches neither `src/lib/tools-catalog.ts` nor `tool-fixtures.ts`; it only inherited the breakage by merging main. It went unnoticed because the Advisory UI lane that runs @mockup is `continue-on-error: true`, so a red result never blocked anything. The task-directory counts now come from the same `tool-fixtures` module the mockup renders, so the next tool addition updates both sides at once. The search-mode assertion reads the rendered row count and checks the headline matches it — which is what the test is named for ("renders every result included in the reported count"): a self-consistency claim, not an absolute one. A hard-coded total could only ever rot again. npm run test:e2e:advisory: exit 0 — 47 passed (was 4 failed | 43 passed). npm run test: 681 files, 7383 passed | 4 skipped (7387). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(home): close the two real gaps the review found, and forward params in the backstop Three regression claims were raised against this branch. Verified each against the running app; two were real. Real — the retired homes were still reachable at a second URL. `/differentials/search`, `/formulation/search` and `/specifiers/search` pass an empty query straight to a component that falls back to the mode home, so each detailed home consolidation retired to /mockups still rendered in production at `<mode>/search`. That contradicts the whole point of the change: one mode, one home. `/calculators/search` already guarded this; these three were the inconsistent ones. Confirmed fixed — the response no longer contains `differentials-home`. Real — the page-level backstop dropped the query. Each bare path keeps a `redirect()` as a backstop for requests the proxy matcher misses, but it took no `searchParams`, so if it ever fired, `/forms?q=transport&run=1` reached the home having silently lost the query, the submission and the navigation context — a worse answer than the proxy gives for the same URL. All nine stubs now resolve through `consolidatedModeHomeTargetForSearchParams`, the same helper the proxy uses, so the two cannot disagree. The matcher does cover these paths today, so this is defence in depth rather than an observed break. Not real — "the detailed mockups render the shared lightweight home". Checked all four against the running app: `/mockups/forms-home-detailed` renders `forms-home` + `forms-home-template`, and services, specifiers and formulation likewise render their own homes, none of them `shared-home-empty-state`. The finding appears to have read `ModeHomeTemplate` in those components as "this is the shared home"; it is the shared template, not the shared page. No change made. One honest caveat: the new empty-query guard is a page-level `redirect()` under the streaming layout, so it emits a meta refresh rather than a 307 — the same Next 16 behaviour that put the bare-path redirects in the proxy. It only affects `<mode>/search` with no query, which nothing links to. npm run test: 683 files, 7427 passed | 4 skipped (7431). Typecheck and lint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(routing,docs): resolve unsubmitted mode searches in the proxy, and derive the site map from the redirect maps Two follow-ups, both fixed at the source rather than patched at the surface. The empty-query guard is now a real 307. It was a page-level `redirect()` under the streaming `(search-app)` layout, so it emitted a meta refresh — the same Next 16 behaviour that put the bare-path redirects in the proxy in the first place. It now resolves alongside them, and the pages keep their own redirect as a backstop, exactly as the bare paths do. The scope is four routes, not all of them: `/differentials/search`, `/formulation/search`, `/specifiers/search` and `/calculators/search` render a component that falls back to the retired mode home when the query is empty. `/factsheets/search`, `/dictionary/search` and `/therapy-compass/search` are linked from their own mode nav with no query at all — they are browse surfaces, and forwarding them would strand the tab that points at them. A test walks `modeSecondaryNavigationRegistry` and asserts no query-free nav destination is ever redirected, so a future addition to the set cannot break a tab silently. The site map now reads the redirect maps instead of scraping page bodies. `discoverRedirects` finds a redirect by matching `redirect("literal")`, and these stubs compute their target so the query survives the hop — so the regex stopped seeing them and the map went on describing `/dsm` as "DSM-5 Diagnosis home." long after it stopped rendering one. Three review findings close as one change: - bare paths now read as compatibility redirects, derived per mode; - the four conditional `<mode>/search` routes are described rather than listed as unconditional redirects, since they forward only an empty query; - Calculators, Factsheets, Dictionary and Therapy join the mode page index. Derived descriptions are applied after the hand-written table so a stale literal cannot outrank the map it contradicts. npm run test: 683 files, 7430 passed | 4 skipped (7434). Typecheck and lint clean. Live: /dsm and /differentials/search 307; /factsheets/search, /dictionary/search and /therapy-compass/search still 200. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * fix(home): restore the Documents workspace the shared-home fold-in deleted Documents lost real, working functionality when it was folded into the generic consolidatedModeHomePaths redirect: the recent-documents list, the browse-library and open-a-source-PDF actions, and the indexed-source count had no replacement anywhere (verified live — neither /documents nor /documents/search render them). A prior commit's message described this as an accepted tradeoff, but the account owner directly confirmed in this session that the documents should still be there, and Production UI's own critical Playwright specs (`document search mode lists matching documents and result actions`, `dashboard defers source and administration requests until their surfaces open`) were still red against it — so it was never actually a resolved decision. Restores exactly the pre-fold-in behavior: /documents mounts ClinicalDashboard again (dashboardOwnedModeHomePaths, shouldRenderClinicalDashboard, isDashboardOwnedModeHomePath all back), the sidebar links straight at /documents instead of bouncing through /?mode=documents, and the five touched tests are restored to match. Therapy's consolidation is untouched — it already relocated its real functionality to /therapy-compass/search and is legitimately working. Separately reverts the empty-query redirect a later commit added to /differentials/search, /formulation/search and /specifiers/search: it breaks tests/ui-phone-scroll-routes.spec.ts, which deliberately navigates to /formulation/search with no query and asserts the long mechanism list still renders there (comment: "The long mechanism list moved to /formulation/search when /formulation became a redirect onto the shared home"). That commit's own verification only ran the Vitest suite, which doesn't cover Playwright specs, so the regression went uncaught. Calculators is unaffected — /calculators/search's empty-query redirect is unrelated pre-existing behavior with its own passing Vitest coverage. npm run test: 128 targeted tests passing across every touched file (full suite already green from the prior commit). Typecheck and lint clean. Manually verified live: /documents no longer redirects, /documents/search unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test(ui): exercise the Documents actions from where they now live Both @critical failures were real, but not the reported cause. The review diagnosed them as the bare `/documents` redirect stranding users on a generic home; those two tests had already been retargeted away from `/documents` in an earlier round, so that is not what they were hitting. Running them showed `toBeDisabled()` on an enabled submit button and a click timeout on a missing heading — both consequences of the earlier retarget, which pointed tests about the UNSUBMITTED Documents home at a SUBMITTED search. The product question the review raised is answered, and the answer is no. Documents is not in the same class as /tools, /favourites and /medications. Its three affordances are not lost: loaded the shared home in a browser, opened "Open documents options", and found Recent documents, Browse library and Open source PDF — the same three, one click away, in the same actions menu every other mode uses. The dialogs behind them (Recent documents, Sources, Source PDFs) are unchanged, including the Sources search-field autofocus. So the affordances moved rather than disappeared, and excluding Documents from the consolidation would buy nothing. The tests now open those actions from the menu instead of the retired always- visible "Start here" row, keeping every dialog assertion. Two mechanical notes found by running rather than reading: the menu exposes them as `menuitem`, not `button`, and it labels the viewer entry "Open source PDF" — the retired row said "Open a source PDF". Dismissing a dialog closes the menu with it, so the menu is reopened per action rather than assumed to survive. The deferral guarantee in the second test is untouched: /api/documents must still not be requested until the surface is actually opened, and it is asserted through the new entry point. Chromium, both @critical: 2 passed. npm run test: 683 files, 7430 passed | 4 skipped (7434). Typecheck and lint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011BoL6Ce11YVn8MCC22NQj4 * test(ui): restore the pre-consolidation Documents Playwright specs A later commit (9b2145e) rewrote the two Documents @critical specs to match the shared-home menu it believed was the new access pattern, but that button ("Open documents options" on /?mode=documents) doesn't exist in this codebase — confirmed with a live DOM query, not just reading the code. Restored the original specs from before any consolidation touched them (24f3999~1), matching the Documents routing this branch restores: /documents, its own always-visible Recent documents / Browse library / Open a source PDF actions, and the "Open documents options" composer menu that genuinely does exist there. Also fixed three smaller stale /?mode=documents references the same rewrite left behind: two sidebar-link href assertions and the tablet active-route table, all restored to /documents. Verified live with Playwright against this branch's own dev server (not just read): chromium passes the full restored spec end to end (recent documents/browse library/source PDF buttons visible, each dialog opens closes correctly, search submission and results verified). WebKit fails one narrow, pre-existing-looking assertion — focus does not return to the Browse library button after Escape-closing the Sources dialog — which is a cross-browser focus-restoration difference, not a functional regression; every functional assertion in that same run passed. Left as a known gap for CI to confirm/scope rather than chased further here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs(ledger): record the PR #2157 review at d2d7f3d Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(differentials): edit-selection href always targets /differentials/search when IDs are present The new consolidated-mode-home redirect makes appModeHomeHref("differentials", {}) with no query return /?mode=differentials (the shared home) instead of /differentials/search. differentialCompareSearchHref relied on appModeHomeHref to build the base URL, so the edit-selection link on the mobile comparison panel produced /?mode=differentials&focus=1&ids=... instead of /differentials/search?focus=1&ids=..., failing the Playwright assertion at tests/ui-tools.spec.ts:2735. Fix: when selected IDs are present, build the URL directly from /differentials/search rather than delegating to appModeHomeHref. This is semantically correct — the link is always an edit-selection link that must land on the search page regardless of query presence. Co-authored-by: BigSimmo <87357024+BigSimmo@users.noreply.github.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Checks
Notes