Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| 2026-08-18 | codex/chat-dictionary-ultimate-dictionary-ultimate | 3a8271bd7a9aa13b2a323cd29e84f294de211690 | Dictionary mode: 8 production routes, 96-entry governed catalogue, shared search/filter lib, launcher/ModeNav/universal-search/tools-catalogue integration, design-system adoption manifests | Approved for draft PR with one declared red gate — production bundle budget +10.5% (main alone is +7.8% of a 2026-08-13 baseline; this branch adds 33.9 KiB across 11 dictionary-exclusive chunks). Baseline deliberately not refreshed; decision left to review | verify:pr-local (lint, typecheck, docs/ledger guards passed); vitest 6990 passed / 2 failed, both cleared (private-access-routes passes in isolation 145/145; session-start-hook fails identically on untouched origin/main); next build compiled; check:client-bundle-secrets passed; check:bundle-budget FAIL on production bucket (documented in PR body), routes and mockups within tolerance; check:rag:fixtures 36 cases; medication interaction + lexicon checks passed; post-sync lint + typecheck exit 0 |
10 changes: 6 additions & 4 deletions docs/codebase-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Smaller top-level directories that are easy to miss:
- **PWA:** `docs/pwa.md` — install assets, privacy-first service worker/offline shell, lifecycle, security, and verification
- **Home:** `src/app/(search-app)/page.tsx` — dashboard rendered by shell
- **Dashboard:** `src/components/ClinicalDashboard.tsx` + `src/components/clinical-dashboard/`
- **Modes (13):** `src/lib/app-modes.ts` — answer, documents, services, forms, favourites, differentials, DSM-5 diagnosis, specifiers, formulation, prescribing, tools, Therapy, Factsheets
- **Modes (15):** `src/lib/app-modes.ts` — answer, documents, services, forms, favourites, differentials, DSM-5 diagnosis, specifiers, formulation, prescribing, tools, calculators, Therapy, Factsheets, Dictionary

### Product pages (`src/app/`)

Expand All @@ -77,6 +77,7 @@ Smaller top-level directories that are easy to miss:
| `/dsm`, `/dsm/search`, `/dsm/compare`, `/dsm/diagnoses/[slug]` | `src/app/(search-app)/dsm/` |
| `/documents/search`, `/source`, `/evidence`, `/[id]` | `src/app/(search-app)/documents/` |
| `/factsheets`, `/factsheets/search`, `/factsheets/[slug]` | `src/app/(search-app)/factsheets/` |
| `/dictionary`, Search, Browse, Topics, Definition, Compare, Sources | `src/app/(search-app)/dictionary/` |
| `/favourites` | `src/app/(search-app)/favourites/page.tsx` |
| `/forms`, `/forms/[slug]` | `src/app/(search-app)/forms/` |
| `/medications`, `/medications/[slug]` | `src/app/(search-app)/medications/` |
Expand Down Expand Up @@ -167,6 +168,7 @@ domain-extracted directory; imported as `@/lib/rag/rag*`). Other modules below r
| Module | Role |
| -------------------------------------------------------------------- | ------------------------------------------------------- |
| `differentials.ts`, `forms.ts`, `services.ts`, `registry-records.ts` | Shared catalogue content with optional owner overrides |
| `dictionary-data.ts`, `dictionary.ts` | Governed terminology, sources, topics, aliases, filters |
| `dsm.ts` | Local DSM diagnosis catalogue and comparison helpers |
| `formulation.ts` | Local formulation mechanism library and builder helpers |
| `clinical-safety.ts`, `demo-data.ts`, `ui-copy.ts` | Safety copy and demo mode |
Expand Down Expand Up @@ -325,12 +327,12 @@ sequenceDiagram

One shared composer (`master-search-header.tsx`) serves every mode. Placement:

- **Mode homes** (`/services`, `/forms`, `/favourites`, `/differentials`, `/dsm`, `/specifiers`, `/formulation`, `/factsheets`, `/therapy-compass`, `/tools`, and dashboard homes): inline in the hero via the `mode-home-composer-slot` portal, on phone and tablet+ alike. (`/applications` is a redirect to `/tools`, not a composer surface.)
- **Information (detail) pages**: catalogue/record routes under each mode (`/services/[slug]`, `/forms/[slug]`, `/medications/[slug]`, `/specifiers/[slug]`, `/formulation/[slug]`, `/factsheets/[slug]`, `/therapy-compass/[slug]`, `/dsm/diagnoses/[slug]`, …). Route detection: `src/lib/information-pages.ts` (`isInformationPage`). Shared outer chrome: `src/components/information-page-shell.tsx` (`InformationPageShell`, breadcrumbs, optional footer). Specifier/formulation mode shells re-export that primitive. Intentional opt-outs: document viewer and the differentials presentation workflow.
- **Mode homes** (`/services`, `/forms`, `/favourites`, `/differentials`, `/dsm`, `/specifiers`, `/formulation`, `/factsheets`, `/dictionary`, `/therapy-compass`, `/tools`, and dashboard homes): inline in the hero via the `mode-home-composer-slot` portal, on phone and tablet+ alike. (`/applications` is a redirect to `/tools`, not a composer surface.)
- **Information (detail) pages**: catalogue/record routes under each mode (`/services/[slug]`, `/forms/[slug]`, `/medications/[slug]`, `/specifiers/[slug]`, `/formulation/[slug]`, `/factsheets/[slug]`, `/dictionary/[slug]`, `/dictionary/topics/[slug]`, `/therapy-compass/[slug]`, `/dsm/diagnoses/[slug]`, …). Route detection: `src/lib/information-pages.ts` (`isInformationPage`). Shared outer chrome: `src/components/information-page-shell.tsx` (`InformationPageShell`, breadcrumbs, optional footer). Specifier/formulation mode shells re-export that primitive. Intentional opt-outs: document viewer and the differentials presentation workflow.
- **Result and detail views**: fixed bottom dock on phone (compact variant on submitted searches), sticky top from `sm` up.
- **Results routing**: standalone routes own their submitted searches via `?q=…&run=1` (`/services` → `ServicesNavigatorPage`, `/forms` → `FormsSearchResultsPage`, `/differentials` → `DifferentialsHome` results view, `/formulation` → local mechanism results, `/favourites` filters the command library in place). Answer, Documents, and Prescribing submitted searches render inside `ClinicalDashboard` — intentional, since they need retrieval/answer state. Bare `/?mode=<id>` always renders the shared home with that mode preselected; only a submitted deep link (`q` plus `run=1`) resolves to the mode's own search surface (proxy early-redirect still covers favourites/differentials/specifiers for those submitted aliases).
- **Intentionally composer-free routes**: `/differentials/presentations/*` and `/differentials/compare` (comparison workflow owns its chrome), `/documents/[id]` viewer (has its own in-document ask composer), `/documents/source/*` (document flow owns mobile chrome). Do not re-flag these in search-consistency audits.
- **Shared in-page navigation**: `src/components/in-page-nav/` is the default template for section navigation on any mode page (`docs/search-chrome-behaviour.md`). `in-page-nav-header.tsx` (`InPageNavHeader`) owns the header row, both sheets and the `PhoneHeaderCollapsePortal` wrapper; `page-section-index.ts` (`PageSection`, `toDocumentSections`, `sectionTargetIds`) is the declaration shape; `use-resolved-page-sections.ts` narrows a declaration to the anchors actually rendered at this breakpoint; `use-in-page-section-nav.ts` composes that with `useDocumentSectionSpy` and `jumpToDocumentSection`; `use-page-section-weights.ts` measures segment weights; `use-in-page-chrome-metrics.ts` publishes `--inpage-anchor-offset`; `in-page-nav-classes.ts` holds the shared anchor (`inPageAnchor`) and actions-sheet row classes; `in-page-section-rail.tsx` (`InPageSectionRail`) is the optional visible second rail, opted into with `rail={{ label }}` by panel-swap routes with few sections (medications only) in place of the weighted track. Anchor measurement itself is `src/components/sticky-chrome-metrics.ts` (`useStickyChromeMetrics`), shared with the document viewer's `use-document-chrome-metrics.ts`. Mounted by `differentials/differential-detail-page.tsx`, `services/service-detail-page.tsx`, `forms/form-detail-page.tsx`, `dsm/dsm-differential-considerations-page.tsx`, and — through a colocated `"use client"` nav-header sibling that owns and exports the route's section table — `specifiers/specifier-nav-header.tsx`, `formulation/formulation-nav-header.tsx`, `dsm/dsm-diagnosis-nav-header.tsx`, `factsheets/factsheet-nav-header.tsx` and `clinical-dashboard/medication-nav-header.tsx`. The sibling is mandatory for the four Server Component pages (neither `onSelectSection` nor a `LucideIcon` crosses the RSC boundary) and the convention for the rest. Two adopters swap panels instead of scrolling — `differential-detail-page.tsx` and the medication record page — so they pass explicit weights, carry no `inPageAnchor`, and use neither `useResolvedPageSections` nor the scroll spy. Every declared section is pinned against rendered DOM by `tests/in-page-nav-route-sections.dom.test.tsx` (anchors for the scrolling routes, swapped-in panels for the tab routes).
- **Shared in-page navigation**: `src/components/in-page-nav/` is the default template for section navigation on any mode page (`docs/search-chrome-behaviour.md`). `in-page-nav-header.tsx` (`InPageNavHeader`) owns the header row, both sheets and the `PhoneHeaderCollapsePortal` wrapper; `page-section-index.ts` (`PageSection`, `toDocumentSections`, `sectionTargetIds`) is the declaration shape; `use-resolved-page-sections.ts` narrows a declaration to the anchors actually rendered at this breakpoint; `use-in-page-section-nav.ts` composes that with `useDocumentSectionSpy` and `jumpToDocumentSection`; `use-page-section-weights.ts` measures segment weights; `use-in-page-chrome-metrics.ts` publishes `--inpage-anchor-offset`; `in-page-nav-classes.ts` holds the shared anchor (`inPageAnchor`) and actions-sheet row classes; `in-page-section-rail.tsx` (`InPageSectionRail`) is the optional visible second rail, opted into with `rail={{ label }}` by panel-swap routes with few sections (medications only) in place of the weighted track. Anchor measurement itself is `src/components/sticky-chrome-metrics.ts` (`useStickyChromeMetrics`), shared with the document viewer's `use-document-chrome-metrics.ts`. Mounted by `dictionary/dictionary-term-page.tsx`, Dictionary topic detail in `dictionary/dictionary-catalogue-pages.tsx`, `differentials/differential-detail-page.tsx`, `services/service-detail-page.tsx`, `forms/form-detail-page.tsx`, `dsm/dsm-differential-considerations-page.tsx`, and — through a colocated `"use client"` nav-header sibling that owns and exports the route's section table — `specifiers/specifier-nav-header.tsx`, `formulation/formulation-nav-header.tsx`, `dsm/dsm-diagnosis-nav-header.tsx`, `factsheets/factsheet-nav-header.tsx` and `clinical-dashboard/medication-nav-header.tsx`. The sibling is mandatory for the four Server Component pages (neither `onSelectSection` nor a `LucideIcon` crosses the RSC boundary) and the convention for the rest. Two adopters swap panels instead of scrolling — `differential-detail-page.tsx` and the medication record page — so they pass explicit weights, carry no `inPageAnchor`, and use neither `useResolvedPageSections` nor the scroll spy. Every declared section is pinned against rendered DOM by `tests/in-page-nav-route-sections.dom.test.tsx` (anchors for the scrolling routes, swapped-in panels for the tab routes) and focused Dictionary DOM contracts.
- **Shared secondary navigation**: `src/components/page-secondary-navigation.tsx` (`PageSecondaryNavigation`, mode destinations only). Mode destinations come from `src/lib/mode-secondary-navigation.ts` (`modeSecondaryNavigationRegistry`, no "Home" item). `GlobalSearchShell` renders it in normal flow at the top of `#main-content` for its owned namespaced modes; it self-suppresses on clean mode homes, on Therapy Compass, and on every information page — `hasLocalInformationPageNavigation` is now just `isInformationPage`, because each of those routes owns its own in-page navigation. The older shared `SecondaryNavigation` component was deleted here (`/issues #271`): its `section` kind and "On this page" pill rail went when the last six information routes moved onto `InPageNavHeader`, and the surviving `route`/`action` kinds had no production constructor left — `RegistryModeNav` renders `ModeNav`, not `SecondaryNavigation`, so the only remaining caller was its own test file, which went with it.
- **Patient context (decision support)**: the app's patient-specific surface, spanning two engines over one session-scoped profile. Store: `src/lib/patient-profile-storage.ts` (sessionStorage external store, anonymous physiology + catalogue medication slugs, cleared on tab close) behind `clinical-dashboard/patient-profile-context.tsx` (`PatientProfileProvider`, mounted for the whole shell). Engines: `src/lib/medication-patient-alerts.ts` (physiology — age/renal/hepatic/QTc/pregnancy/allergy, with an `unassessed` fail-safe) and `src/lib/medication-interactions.ts` (drug–drug, against the entered medication list). The interaction engine reads the generated `data/medication-interaction-index.json`, built by `scripts/build-medication-interaction-index.ts` (`npm run medications:interactions`, staleness-gated by `check:medication-interactions`) from the curated `src/lib/medication-interaction-lexicon.ts` — the catalogue's `Key Interactions` rows are prose, and that lexicon is what resolves their class/mechanism/non-drug terms to catalogue targets. `composeMedicationVerdict` folds both engines into the one tone a result row wears; **green is unreachable whenever either engine left something unassessed or unresolved**, degrading to a neutral "needs manual review" instead. UI: `clinical-dashboard/patient-profile-panel.tsx` (the form, including the medication picker), `medication-considerations.tsx` (both detail-page blocks and the verdict badge/edge helpers), and `patient-details-dock-action.tsx` (the phone dock pill — see the addon-slot section of `docs/search-chrome-behaviour.md`). Regulatory status is **open**: `docs/samd-classification-medication-considerations.md`.
- **Local filter fields** (sidebar "Search chats", document drawer "Find a document"/"Find a source PDF") are scoped filters, not global search; they share the `fieldControlWithIcon`/`fieldIcon` primitives.
Expand Down
8 changes: 4 additions & 4 deletions docs/design-system/ADOPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,12 @@ product exclusions; the only route-only disposition is the documented legacy doc
redirect. Shared shell/component roots carry their own explicit `shared-shell` disposition.

Registered public components: 54
Declared product roots: 59
Declared product roots: 67
Roots with a literal `.ckb-v2` opt-in: 1
Roots inheriting `.ckb-v2` from the global `<html>`: 58
Roots inheriting `.ckb-v2` from the global `<html>`: 66
Production surfaces observed under v2: 14/14
Dynamic `ckb-v2` constructions: 0
Declared production page routes: 51/51
Declared production page routes: 59/59

Source observation and contract declaration are independent. A literal `ckb-v2` on the global `<html>` makes every production surface inherit v2, but it does not approve that adoption.
The Proof column summarizes each surface's dark, forced-colours, 320px, print and browser declarations; exact statuses and evidence paths live in the manifest.
Expand All @@ -375,7 +375,7 @@ Observed v2 under a compatibility declaration fails closed. A declared v2 shell
| Surface | Disposition | Routes | Roots | Declared shell | Observed shell (mount) | Proof | Baseline |
| ---------------------------------- | --------------- | -----: | ----: | -------------- | -------------------------- | -------------- | -------------- |
| `root-shell-and-settings` | shared-shell | 3 | 6 | v2 | v2 (inherited-global-root) | passed | not-committed |
| `catalogues-forms-and-info` | owned | 13 | 13 | v2 | v2 (inherited-global-root) | passed | not-committed |
| `catalogues-forms-and-info` | owned | 21 | 21 | v2 | v2 (inherited-global-root) | passed | not-committed |
| `differentials` | owned | 6 | 6 | v2 | v2 (inherited-global-root) | passed | not-committed |
| `formulation` | owned | 5 | 5 | v2 | v2 (inherited-global-root) | passed | not-committed |
| `specifiers` | owned | 5 | 5 | v2 | v2 (inherited-global-root) | passed | not-committed |
Expand Down
4 changes: 2 additions & 2 deletions docs/design-system/COMPONENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ This generated snapshot is a local source-derived inventory. It does not assert
| `IconButton` | controls | yes | yes | inherited-global-root | yes | no | 2 |
| `InlineNotice` | feedback | yes | yes | inherited-global-root | yes | no | 7 |
| `LinkAction` | controls | yes | yes | no | yes | no | 0 |
| `LoadingPanel` | feedback | yes | yes | inherited-global-root | yes | no | 7 |
| `LoadingPanel` | feedback | yes | yes | inherited-global-root | yes | no | 11 |
| `MissingValue` | feedback | yes | yes | inherited-global-root | yes | no | 3 |
| `OverlayRoot` | layout | yes | yes | inherited-global-root | yes | no | 1 |
| `PageHeader` | layout | yes | yes | inherited-global-root | yes | no | 2 |
Expand All @@ -1001,7 +1001,7 @@ This generated snapshot is a local source-derived inventory. It does not assert
| `SearchField` | controls | yes | yes | no | yes | no | 0 |
| `SegmentedControl` | controls | yes | yes | inherited-global-root | yes | no | 8 |
| `Select` | controls | yes | yes | inherited-global-root | yes | no | 2 |
| `Sheet` | layout | yes | yes | inherited-global-root | yes | no | 24 |
| `Sheet` | layout | yes | yes | inherited-global-root | yes | no | 25 |
| `Skeleton` | feedback | yes | yes | inherited-global-root | yes | no | 6 |
| `SourceDesignationBadge` | source | yes | yes | inherited-global-root | yes | no | 4 |
| `SourceProvenance` | source | yes | yes | inherited-global-root | yes | no | 1 |
Expand Down
Loading
Loading