diff --git a/docs/site-map.md b/docs/site-map.md index 58df1f6c94..78508b23e2 100644 --- a/docs/site-map.md +++ b/docs/site-map.md @@ -8,20 +8,18 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/calculators` - Compatibility redirect to the shared home at `/?mode=calculators`; a submitted `?q=…&run=1` forwards to `/calculators/search`. Source: `src/app/(search-app)/calculators/page.tsx`. - `/calculators/search` - Submitted calculators results. An empty query forwards to `/?mode=calculators` so the retired mode home is not rendered a second time. Source: `src/app/(search-app)/calculators/search/page.tsx`. - `/dictionary` - Compatibility redirect to the shared home at `/?mode=dictionary`; a submitted `?q=…&run=1` forwards to `/dictionary/search`. Source: `src/app/(search-app)/dictionary/page.tsx`. -- `/dictionary/[slug]` - Route discovered from app directory Source: `src/app/(search-app)/dictionary/[slug]/page.tsx`. -- `/dictionary/browse` - Route discovered from app directory Source: `src/app/(search-app)/dictionary/browse/page.tsx`. -- `/dictionary/compare` - Route discovered from app directory Source: `src/app/(search-app)/dictionary/compare/page.tsx`. -- `/dictionary/search` - Route discovered from app directory Source: `src/app/(search-app)/dictionary/search/page.tsx`. -- `/dictionary/sources` - Route discovered from app directory Source: `src/app/(search-app)/dictionary/sources/page.tsx`. -- `/dictionary/topics` - Route discovered from app directory Source: `src/app/(search-app)/dictionary/topics/page.tsx`. -- `/dictionary/topics/[slug]` - Route discovered from app directory Source: `src/app/(search-app)/dictionary/topics/[slug]/page.tsx`. +- `/dictionary/browse` - A–Z clinical term and abbreviation catalogue browser. Source: `src/app/(search-app)/dictionary/browse/page.tsx`. +- `/dictionary/compare` - Side-by-side clinical term definition and nuance comparison. Source: `src/app/(search-app)/dictionary/compare/page.tsx`. +- `/dictionary/search` - Source-linked clinical term and abbreviation search surface. Source: `src/app/(search-app)/dictionary/search/page.tsx`. +- `/dictionary/sources` - Clinical dictionary governance, references, and source catalogue. Source: `src/app/(search-app)/dictionary/sources/page.tsx`. +- `/dictionary/topics` - Clinical dictionary topic category index. Source: `src/app/(search-app)/dictionary/topics/page.tsx`. - `/differentials` - Compatibility redirect to the shared home at `/?mode=differentials`; a submitted `?q=…&run=1` forwards to `/differentials/search`. Source: `src/app/(search-app)/differentials/page.tsx`. - `/differentials/compare` - Compare queue: empty state or selected diagnosis ids (Search edit links preserve ids); Open comparison launches a catalogue presentation workflow or an ad-hoc workspace (`workspace=1`). Source: `src/app/(search-app)/differentials/compare/page.tsx`. - `/differentials/diagnoses` - Diagnosis stream. Source: `src/app/(search-app)/differentials/diagnoses/page.tsx`. - `/differentials/presentations` - Presentation catalogue stream. Source: `src/app/(search-app)/differentials/presentations/page.tsx`. - `/differentials/presentations/[slug]` - Presentation comparison workflow. Source: `src/app/(search-app)/differentials/presentations/[slug]/page.tsx`. - `/differentials/search` - Route discovered from app directory Source: `src/app/(search-app)/differentials/search/page.tsx`. -- `/documents` - Route discovered from app directory Source: `src/app/(search-app)/documents/page.tsx`. +- `/documents` - Documents mode home and source document library surface. Source: `src/app/(search-app)/documents/page.tsx`. - `/documents/search` - Documents search command centre. Source: `src/app/(search-app)/documents/search/page.tsx`. - `/documents/source` - Compatibility redirect to the canonical live document viewer when a valid id is supplied. Source: `src/app/(search-app)/documents/source/page.tsx`. - `/documents/source/evidence` - Compatibility redirect sharing the canonical live document viewer handoff. Source: `src/app/(search-app)/documents/source/evidence/page.tsx`. @@ -29,8 +27,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/dsm/compare` - DSM diagnosis comparison. Source: `src/app/(search-app)/dsm/compare/page.tsx`. - `/dsm/search` - DSM diagnosis search and catalogue browser. Source: `src/app/(search-app)/dsm/search/page.tsx`. - `/factsheets` - Compatibility redirect to the shared home at `/?mode=factsheets`; a submitted `?q=…&run=1` forwards to `/factsheets/search`. Source: `src/app/(search-app)/factsheets/page.tsx`. -- `/factsheets/[slug]` - Route discovered from app directory Source: `src/app/(search-app)/factsheets/[slug]/page.tsx`. -- `/factsheets/search` - Route discovered from app directory Source: `src/app/(search-app)/factsheets/search/page.tsx`. +- `/factsheets/search` - Patient information factsheet search command centre. Source: `src/app/(search-app)/factsheets/search/page.tsx`. - `/favourites` - Saved clinical items and sets. Source: `src/app/(search-app)/favourites/page.tsx`. - `/forms` - Compatibility redirect to the shared home at `/?mode=forms`; a submitted `?q=…&run=1` forwards to `/forms/search`. Source: `src/app/(search-app)/forms/page.tsx`. - `/forms/search` - Route discovered from app directory Source: `src/app/(search-app)/forms/search/page.tsx`. @@ -41,7 +38,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/formulation/search` - Route discovered from app directory Source: `src/app/(search-app)/formulation/search/page.tsx`. - `/medications` - Medication mode home. Source: `src/app/(search-app)/medications/page.tsx`. - `/privacy` - Privacy and data-processing governance draft. Source: `src/app/privacy/page.tsx`. -- `/reference/colour-coding` - Route discovered from app directory Source: `src/app/reference/colour-coding/page.tsx`. +- `/reference/colour-coding` - Clinical domain and category colour-coding palette reference. Source: `src/app/reference/colour-coding/page.tsx`. - `/safety-plan` - Patient safety plan generator (Stanley-Brown six steps) — a Tools-page clinical tool. Source: `src/app/safety-plan/page.tsx`. - `/services` - Compatibility redirect to the shared home at `/?mode=services`; a submitted `?q=…&run=1` forwards to `/services/search`. Source: `src/app/(search-app)/services/page.tsx`. - `/services/search` - Route discovered from app directory Source: `src/app/(search-app)/services/search/page.tsx`. @@ -58,17 +55,16 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/therapy-compass/recommend` - Recommend a therapy from a clinical question and constraints. Source: `src/app/(search-app)/therapy-compass/recommend/page.tsx`. - `/therapy-compass/review` - Therapy records awaiting qualified-clinician source review. Source: `src/app/(search-app)/therapy-compass/review/page.tsx`. - `/therapy-compass/search` - Therapy library search surface. Source: `src/app/(search-app)/therapy-compass/search/page.tsx`. -- `/tools` - Route discovered from app directory Source: `src/app/(search-app)/tools/page.tsx`. -- `/ward-management` - Route discovered from app directory Source: `src/app/ward-management/page.tsx`. -- `/ward-management/capacity` - Route discovered from app directory Source: `src/app/ward-management/capacity/page.tsx`. -- `/ward-management/constellation` - Route discovered from app directory Source: `src/app/ward-management/constellation/page.tsx`. -- `/ward-management/exceptions` - Route discovered from app directory Source: `src/app/ward-management/exceptions/page.tsx`. -- `/ward-management/governance` - Route discovered from app directory Source: `src/app/ward-management/governance/page.tsx`. -- `/ward-management/movements` - Route discovered from app directory Source: `src/app/ward-management/movements/page.tsx`. -- `/ward-management/network` - Route discovered from app directory Source: `src/app/ward-management/network/page.tsx`. -- `/ward-management/patients/[patientId]` - Route discovered from app directory Source: `src/app/ward-management/patients/[patientId]/page.tsx`. -- `/ward-management/queue` - Route discovered from app directory Source: `src/app/ward-management/queue/page.tsx`. -- `/ward-management/transport` - Route discovered from app directory Source: `src/app/ward-management/transport/page.tsx`. +- `/tools` - Clinical tools and applications launcher directory. Source: `src/app/(search-app)/tools/page.tsx`. +- `/ward-management` - Statewide psychiatry ward demand, bed capacity, and patient flow console. Source: `src/app/ward-management/page.tsx`. +- `/ward-management/capacity` - Ward bed availability, unit occupancy, and staffing capacity. Source: `src/app/ward-management/capacity/page.tsx`. +- `/ward-management/constellation` - Statewide psychiatric hospital network constellation view. Source: `src/app/ward-management/constellation/page.tsx`. +- `/ward-management/exceptions` - Patient flow exceptions, delays, and escalation alerts. Source: `src/app/ward-management/exceptions/page.tsx`. +- `/ward-management/governance` - Ward coordination governance, compliance, and audit log. Source: `src/app/ward-management/governance/page.tsx`. +- `/ward-management/movements` - Scheduled and completed patient transfers and bed movements. Source: `src/app/ward-management/movements/page.tsx`. +- `/ward-management/network` - Psychiatric bed network status and regional catchment map. Source: `src/app/ward-management/network/page.tsx`. +- `/ward-management/queue` - Priority referral queue and triage waiting list. Source: `src/app/ward-management/queue/page.tsx`. +- `/ward-management/transport` - Patient inter-hospital transfer and transport logistics. Source: `src/app/ward-management/transport/page.tsx`. ## Mode/query routes @@ -106,7 +102,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir | Calculators | `/?mode=calculators` | `/calculators/search?q=PHQ-9&focus=1&run=1` | `/calculators/search` scored results; an empty query forwards back to the shared home. | | Factsheets | `/?mode=factsheets` | `/factsheets/search?q=sertraline&focus=1&run=1` | `/factsheets/search` is also a query-free browse surface linked from the mode nav; `/factsheets/[slug]` records. | | Dictionary | `/?mode=dictionary` | `/dictionary/search?q=MSE&focus=1&run=1` | `/dictionary/search` is also a query-free browse surface; `/dictionary/browse`, `/topics`, `/topics/[slug]`, `/compare`, `/sources` and `/dictionary/[slug]` records. | -| Therapy | `/?mode=therapy-compass` | `/therapy-compass/search?q=CBT&focus=1&run=1` | Keeps a home of its own at `/therapy-compass`; `/search` (query-free browse), `/recommend`, `/compare`, `/pathways`, `/review`, and `/[slug]` records with `/brief` and `/sheet` outputs. | +| Therapy Compass | `/?mode=therapy-compass` | `/therapy-compass/search?q=CBT&focus=1&run=1` | Keeps a home of its own at `/therapy-compass`; `/search` (query-free browse), `/recommend`, `/compare`, `/pathways`, `/review`, and `/[slug]` records with `/brief` and `/sheet` outputs. | ## Documents flow index @@ -1008,10 +1004,142 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/medications/[slug]` - Dynamic route family. - `acamprosate` +### Factsheet slugs + +- `/factsheets/[slug]` - Dynamic route family. +- `bipolar` +- `cbt` +- `depression` +- `escitalopram` +- `gad` +- `lithium-monitoring` +- `sertraline` +- `ssri` + +### Clinical dictionary term slugs + +- `/dictionary/[slug]` - Dynamic route family. +- `acceptance-and-commitment-therapy` +- `acute-dystonia` +- `advance-statement` +- `affect` +- `affective-range` +- `affective-reactivity` +- `akathisia` +- `anhedonia` +- `antidepressant` +- `antipsychotic` +- `anxiety` +- `anxiety-disorder` +- `anxiolytic` +- `appearance` +- `assertive-community-treatment` +- `attention` +- `auditory-hallucination` +- `behaviour` +- `behavioural-activation` +- `bipolar-disorder` +- `capacity` +- `case-management` +- `clinical-assessment` +- `clinical-formulation` +- `clinical-interview` +- `cognition` +- `cognitive-behavioural-therapy` +- `collaborative-care` +- `community-mental-health-team` +- `compulsion` +- `concentration` +- `consent` +- `craving` +- `delirium` +- `delusion` +- `dementia` +- `dependence` +- `depersonalisation` +- `depressive-disorder` +- `dialectical-behaviour-therapy` +- `dissociation` +- `drug-induced-parkinsonism` +- `elevated-mood` +- `emotional-lability` +- `euthymia` +- `executive-function` +- `exposure-therapy` +- `hallucination` +- `harmful-use` +- `inner-speech` +- `insight` +- `interpersonal-therapy` +- `intoxication` +- `intrusive-thought` +- `involuntary-treatment` +- `irritability` +- `least-restrictive-care` +- `low-mood` +- `memory` +- `mental-state-examination` +- `mini-mental-state-examination` +- `mishearing` +- `mood` +- `mood-stabiliser` +- `motivational-interviewing` +- `multidisciplinary-team` +- `obsession` +- `obsessive-compulsive-disorder` +- `orientation` +- `panic-attack` +- `phobia` +- `psychiatric-history` +- `psychoeducation` +- `psychomotor-activity` +- `psychosis` +- `rating-scale` +- `recovery-oriented-practice` +- `relapse` +- `risk-assessment` +- `safety-planning` +- `schizophrenia` +- `screening-instrument` +- `self-harm` +- `speech` +- `stepped-care` +- `structured-clinical-interview` +- `substance-use-disorder` +- `suicide-risk` +- `supported-decision-making` +- `tardive-dyskinesia` +- `thought-broadcasting` +- `thought-form` +- `tolerance` +- `trauma` +- `trauma-informed-care` +- `withdrawal` + +### Clinical dictionary topic slugs + +- `/dictionary/topics/[slug]` - Dynamic route family. +- `anxiety-trauma-and-dissociation` +- `assessment-and-measurement` +- `cognition-and-neuropsychiatry` +- `community-and-models-of-care` +- `conditions-risk-and-safety` +- `documentation-law-and-ethics` +- `medicines-and-adverse-effects` +- `mental-state-examination-domains` +- `mood-and-affect` +- `psychological-therapies` +- `psychosis-and-perception` +- `substance-use` + ## Document viewer route - `/documents/[id]` - Document viewer/detail page. Individual document IDs are intentionally not enumerated in this sitemap. +## Ward management patient route + +- `/ward-management/patients/[patientId]` - Synthetic patient placement and transfer trajectory detail. Synthetic patient IDs are generated runtime data and intentionally not enumerated in this sitemap. + ## Mockup/prototype routes - `/mockups/accessible-table-browser-fixture` - Route discovered from app directory Source: `src/app/mockups/accessible-table-browser-fixture/page.tsx`. @@ -1121,44 +1249,44 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir ## API routes -- `/api/account/favourites` - Route discovered from app directory Source: `src/app/api/account/favourites/route.ts`. -- `/api/account/preferences` - Route discovered from app directory Source: `src/app/api/account/preferences/route.ts`. +- `/api/account/favourites` - Account saved favourites operations. Source: `src/app/api/account/favourites/route.ts`. +- `/api/account/preferences` - Account density, motion, and UI preferences. Source: `src/app/api/account/preferences/route.ts`. - `/api/answer` - Generate answer response. Source: `src/app/api/answer/route.ts`. -- `/api/answer-feedback` - Route discovered from app directory Source: `src/app/api/answer-feedback/route.ts`. +- `/api/answer-feedback` - Answer quality feedback submission. Source: `src/app/api/answer-feedback/route.ts`. - `/api/answer/stream` - Streaming answer response. Source: `src/app/api/answer/stream/route.ts`. -- `/api/differentials` - Route discovered from app directory Source: `src/app/api/differentials/route.ts`. -- `/api/differentials/[slug]` - Route discovered from app directory Source: `src/app/api/differentials/[slug]/route.ts`. -- `/api/differentials/presentations/[slug]` - Route discovered from app directory Source: `src/app/api/differentials/presentations/[slug]/route.ts`. +- `/api/differentials` - Differential diagnosis catalogue operations. Source: `src/app/api/differentials/route.ts`. +- `/api/differentials/[slug]` - Differential diagnosis detail endpoint. Source: `src/app/api/differentials/[slug]/route.ts`. +- `/api/differentials/presentations/[slug]` - Presentation workflow comparison data endpoint. Source: `src/app/api/differentials/presentations/[slug]/route.ts`. - `/api/documents` - Document collection operations. Source: `src/app/api/documents/route.ts`. - `/api/documents/[id]` - Document detail operations. Source: `src/app/api/documents/[id]/route.ts`. - `/api/documents/[id]/labels` - Document label operations. Source: `src/app/api/documents/[id]/labels/route.ts`. - `/api/documents/[id]/reindex` - Single-document reindex operation. Source: `src/app/api/documents/[id]/reindex/route.ts`. -- `/api/documents/[id]/reviews` - Route discovered from app directory Source: `src/app/api/documents/[id]/reviews/route.ts`. +- `/api/documents/[id]/reviews` - Document clinical review audit log. Source: `src/app/api/documents/[id]/reviews/route.ts`. - `/api/documents/[id]/search` - Search within one document. Source: `src/app/api/documents/[id]/search/route.ts`. - `/api/documents/[id]/signed-url` - Private document signed URL. Source: `src/app/api/documents/[id]/signed-url/route.ts`. - `/api/documents/[id]/summarize` - Document summary operation. Source: `src/app/api/documents/[id]/summarize/route.ts`. - `/api/documents/[id]/table-facts` - Document table facts. Source: `src/app/api/documents/[id]/table-facts/route.ts`. - `/api/documents/bulk` - Bulk document operations. Source: `src/app/api/documents/bulk/route.ts`. - `/api/documents/bulk/reindex` - Bulk reindex operation. Source: `src/app/api/documents/bulk/reindex/route.ts`. -- `/api/documents/signed-urls` - Route discovered from app directory Source: `src/app/api/documents/signed-urls/route.ts`. +- `/api/documents/signed-urls` - Bulk private document signed URLs. Source: `src/app/api/documents/signed-urls/route.ts`. - `/api/eval-cases` - Evaluation case data. Source: `src/app/api/eval-cases/route.ts`. - `/api/health` - Health check. Source: `src/app/api/health/route.ts`. -- `/api/health/ready` - Route discovered from app directory Source: `src/app/api/health/ready/route.ts`. +- `/api/health/ready` - Readiness health check. Source: `src/app/api/health/ready/route.ts`. - `/api/images/[id]/signed-url` - Private image signed URL. Source: `src/app/api/images/[id]/signed-url/route.ts`. -- `/api/images/signed-urls` - Route discovered from app directory Source: `src/app/api/images/signed-urls/route.ts`. +- `/api/images/signed-urls` - Bulk private image signed URLs. Source: `src/app/api/images/signed-urls/route.ts`. - `/api/ingestion/batches` - Ingestion batch state. Source: `src/app/api/ingestion/batches/route.ts`. - `/api/ingestion/jobs` - Ingestion job collection. Source: `src/app/api/ingestion/jobs/route.ts`. - `/api/ingestion/jobs/[id]/retry` - Retry ingestion job. Source: `src/app/api/ingestion/jobs/[id]/retry/route.ts`. - `/api/ingestion/quality` - Ingestion quality reporting. Source: `src/app/api/ingestion/quality/route.ts`. - `/api/jobs` - Administrator/ops job listing (not a client product API; see docs/api-jobs-ops-surface.md). Source: `src/app/api/jobs/route.ts`. - `/api/local-project-id` - Local project identity guard. Source: `src/app/api/local-project-id/route.ts`. -- `/api/medications` - Route discovered from app directory Source: `src/app/api/medications/route.ts`. -- `/api/medications/[slug]` - Route discovered from app directory Source: `src/app/api/medications/[slug]/route.ts`. +- `/api/medications` - Medication catalog collection operations. Source: `src/app/api/medications/route.ts`. +- `/api/medications/[slug]` - Medication detail endpoint. Source: `src/app/api/medications/[slug]/route.ts`. - `/api/registry/records` - Registry record collection. Source: `src/app/api/registry/records/route.ts`. - `/api/registry/records/[slug]` - Registry record detail. Source: `src/app/api/registry/records/[slug]/route.ts`. - `/api/search` - Search endpoint. Source: `src/app/api/search/route.ts`. - `/api/search/interaction` - Search interaction telemetry. Source: `src/app/api/search/interaction/route.ts`. -- `/api/search/universal` - Route discovered from app directory Source: `src/app/api/search/universal/route.ts`. +- `/api/search/universal` - Cross-entity universal search endpoint. Source: `src/app/api/search/universal/route.ts`. - `/api/setup-status` - Setup status. Source: `src/app/api/setup-status/route.ts`. - `/api/upload` - Upload endpoint. Source: `src/app/api/upload/route.ts`. - `/api/webhooks/railway` - Railway deploy webhook -> chat forwarder. Source: `src/app/api/webhooks/railway/route.ts`. @@ -1171,6 +1299,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir - `/dictionary` - Redirects to `/?mode=dictionary`. Source: `src/app/(search-app)/dictionary/page.tsx`. - `/differentials` - Redirects to `/?mode=differentials`. Source: `src/app/(search-app)/differentials/page.tsx`. - `/documents/source` - Redirects to `/documents/[id]`. Source: `src/app/(search-app)/documents/source/page.tsx`. +- `/documents/source/evidence` - Redirects to `/documents/[id]`. Source: `src/app/(search-app)/documents/source/evidence/page.tsx`. - `/dsm` - Redirects to `/?mode=dsm`. Source: `src/app/(search-app)/dsm/page.tsx`. - `/factsheets` - Redirects to `/?mode=factsheets`. Source: `src/app/(search-app)/factsheets/page.tsx`. - `/forms` - Redirects to `/?mode=forms`. Source: `src/app/(search-app)/forms/page.tsx`. @@ -1194,7 +1323,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir | Area | Source | | ------------------------------ | ---------------------------------------------------------------------------------------------------------- | -| Root dashboard and query modes | `src/app/page.tsx, src/lib/app-modes.ts` | +| Root dashboard and query modes | `src/app/(search-app)/page.tsx, src/lib/app-modes.ts` | | Global shell layouts | `src/app/*/layout.tsx, src/components/clinical-dashboard/global-search-shell.tsx` | | Services | `src/app/(search-app)/services, src/lib/services.ts, src/app/api/registry/records` | | Forms | `src/app/(search-app)/forms, src/lib/forms.ts, src/app/api/registry/records` | @@ -1205,5 +1334,12 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir | Formulation | `src/app/(search-app)/formulation, src/components/formulation, src/lib/formulation.ts` | | Medications | `src/app/(search-app)/medications, src/components/clinical-dashboard/medication-prescribing-workspace.tsx` | | Documents | `src/app/(search-app)/documents, src/lib/document-flow-routes.ts` | +| Calculators | `src/app/(search-app)/calculators, src/components/calculators` | +| Therapy Compass | `src/app/(search-app)/therapy-compass, src/lib/therapies.ts` | +| Factsheets | `src/app/(search-app)/factsheets, src/components/factsheets` | +| Dictionary | `src/app/(search-app)/dictionary, src/lib/dictionary.ts` | +| Ward Management | `src/app/ward-management, src/components/ward-management` | +| Safety Plan | `src/app/safety-plan, src/components/patient-safety-plan.tsx` | +| Privacy | `src/app/privacy` | | Tools | `src/components/applications-launcher-page.tsx` | | Mockups | `src/app/mockups` | diff --git a/scripts/generate-site-map.ts b/scripts/generate-site-map.ts index 52f042def7..4f86b52801 100644 --- a/scripts/generate-site-map.ts +++ b/scripts/generate-site-map.ts @@ -9,6 +9,8 @@ import { unsubmittedModeSearchRedirectEntries, } from "@/lib/consolidated-mode-home-redirect"; import { documentsSearchHref, DOCUMENTS_MODE_HOME_ROUTE } from "@/lib/document-flow-routes"; +import { factsheetSlugs } from "@/components/factsheets/factsheets-data"; +import { dictionaryEntries, dictionaryTopics } from "@/lib/dictionary-data"; import { differentialRecords } from "@/lib/differentials"; import { dsmDiagnoses } from "@/lib/dsm"; import { formulationMechanisms } from "@/lib/formulation"; @@ -74,11 +76,21 @@ const documentedRedirectTargets: Record = { // (line 14). Pin the canonical target here so the generated map does not report the // invalid-id fallback that its first-`redirect()` regex would otherwise capture. "/documents/source": "/documents/[id]", + "/documents/source/evidence": "/documents/[id]", }; const routeDescriptions: Record = { "/": "Main Clinical KB shell.", "/applications": "Legacy application launcher redirect to Tools.", + "/calculators": "Psychiatry rating scale scoring and clinical decision calculators.", + "/dictionary": "Clinical dictionary home with term search and category navigation.", + "/dictionary/[slug]": "Source-governed clinical term definition, distinction, and reference detail.", + "/dictionary/browse": "A–Z clinical term and abbreviation catalogue browser.", + "/dictionary/compare": "Side-by-side clinical term definition and nuance comparison.", + "/dictionary/search": "Source-linked clinical term and abbreviation search surface.", + "/dictionary/sources": "Clinical dictionary governance, references, and source catalogue.", + "/dictionary/topics": "Clinical dictionary topic category index.", + "/dictionary/topics/[slug]": "Clinical dictionary topic category term list.", "/differentials": "Differentials home and search surface.", "/differentials/compare": "Compare queue: empty state or selected diagnosis ids (Search edit links preserve ids); Open comparison launches a catalogue presentation workflow or an ad-hoc workspace (`workspace=1`).", @@ -86,43 +98,59 @@ const routeDescriptions: Record = { "/differentials/diagnoses/[slug]": "Differential diagnosis detail.", "/differentials/presentations": "Presentation catalogue stream.", "/differentials/presentations/[slug]": "Presentation comparison workflow.", - "/dsm": "DSM-5 Diagnosis home.", - "/dsm/search": "DSM diagnosis search and catalogue browser.", - "/dsm/compare": "DSM diagnosis comparison.", - "/dsm/diagnoses/[slug]": "DSM diagnosis criteria and information.", - "/dsm/diagnoses/[slug]/differentials": "DSM diagnosis differential considerations.", + "/documents": "Documents mode home and source document library surface.", "/documents/[id]": "Document viewer/detail page.", "/documents/search": "Documents search command centre.", "/documents/source": "Compatibility redirect to the canonical live document viewer when a valid id is supplied.", "/documents/source/evidence": "Compatibility redirect sharing the canonical live document viewer handoff.", + "/dsm": "DSM-5 Diagnosis home.", + "/dsm/compare": "DSM diagnosis comparison.", + "/dsm/diagnoses/[slug]": "DSM diagnosis criteria and information.", + "/dsm/diagnoses/[slug]/differentials": "DSM diagnosis differential considerations.", + "/dsm/search": "DSM diagnosis search and catalogue browser.", + "/factsheets": "Patient information factsheets home and topic browser.", + "/factsheets/[slug]": "Plain-language patient factsheet reading and printable handout view.", + "/factsheets/search": "Patient information factsheet search command centre.", "/favourites": "Saved clinical items and sets.", "/forms": "Forms home and search surface.", "/forms/[slug]": "Registry-backed form detail.", + "/formulation": "Clinical formulation home and local mechanism search surface.", + "/formulation/[slug]": "Formulation mechanism decision-support guide.", + "/formulation/builder": "Structured clinical formulation builder.", + "/formulation/compare": "Side-by-side mechanism comparison.", + "/formulation/map": "Formulation mechanism domain map.", "/medications": "Medication mode home.", "/medications/[slug]": "Medication detail.", "/privacy": "Privacy and data-processing governance draft.", + "/reference/colour-coding": "Clinical domain and category colour-coding palette reference.", "/safety-plan": "Patient safety plan generator (Stanley-Brown six steps) — a Tools-page clinical tool.", "/services": "Services home and search surface.", "/services/[slug]": "Registry-backed service detail.", - "/formulation": "Clinical formulation home and local mechanism search surface.", - "/formulation/[slug]": "Formulation mechanism decision-support guide.", - "/formulation/builder": "Structured clinical formulation builder.", - "/formulation/compare": "Side-by-side mechanism comparison.", - "/formulation/map": "Formulation mechanism domain map.", "/specifiers": "Psychiatric specifier home and local search surface.", "/specifiers/[slug]": "Psychiatric specifier decision-support guide.", "/specifiers/builder": "Structured diagnostic wording builder.", "/specifiers/compare": "Side-by-side psychiatric specifier comparison.", "/specifiers/map": "Psychiatric specifier family map.", "/therapy-compass": "Therapy home (source-grounded therapy decision support).", - "/therapy-compass/search": "Therapy library search surface.", - "/therapy-compass/recommend": "Recommend a therapy from a clinical question and constraints.", - "/therapy-compass/compare": "Side-by-side therapy comparison.", - "/therapy-compass/pathways": "Problem-based clinical therapy pathways.", - "/therapy-compass/review": "Therapy records awaiting qualified-clinician source review.", "/therapy-compass/[slug]": "Therapy record detail.", "/therapy-compass/[slug]/brief": "Therapy brief-intervention view.", "/therapy-compass/[slug]/sheet": "Therapy patient-sheet builder.", + "/therapy-compass/compare": "Side-by-side therapy comparison.", + "/therapy-compass/pathways": "Problem-based clinical therapy pathways.", + "/therapy-compass/recommend": "Recommend a therapy from a clinical question and constraints.", + "/therapy-compass/review": "Therapy records awaiting qualified-clinician source review.", + "/therapy-compass/search": "Therapy library search surface.", + "/tools": "Clinical tools and applications launcher directory.", + "/ward-management": "Statewide psychiatry ward demand, bed capacity, and patient flow console.", + "/ward-management/capacity": "Ward bed availability, unit occupancy, and staffing capacity.", + "/ward-management/constellation": "Statewide psychiatric hospital network constellation view.", + "/ward-management/exceptions": "Patient flow exceptions, delays, and escalation alerts.", + "/ward-management/governance": "Ward coordination governance, compliance, and audit log.", + "/ward-management/movements": "Scheduled and completed patient transfers and bed movements.", + "/ward-management/network": "Psychiatric bed network status and regional catchment map.", + "/ward-management/patients/[patientId]": "Synthetic patient placement and transfer trajectory detail.", + "/ward-management/queue": "Priority referral queue and triage waiting list.", + "/ward-management/transport": "Patient inter-hospital transfer and transport logistics.", }; const publicRouteHandlerDescriptions: Record = { @@ -131,31 +159,44 @@ const publicRouteHandlerDescriptions: Record = { }; const apiDescriptions: Record = { + "/api/account/favourites": "Account saved favourites operations.", + "/api/account/preferences": "Account density, motion, and UI preferences.", "/api/answer": "Generate answer response.", "/api/answer/stream": "Streaming answer response.", + "/api/answer-feedback": "Answer quality feedback submission.", + "/api/differentials": "Differential diagnosis catalogue operations.", + "/api/differentials/[slug]": "Differential diagnosis detail endpoint.", + "/api/differentials/presentations/[slug]": "Presentation workflow comparison data endpoint.", "/api/documents": "Document collection operations.", "/api/documents/[id]": "Document detail operations.", "/api/documents/[id]/labels": "Document label operations.", "/api/documents/[id]/reindex": "Single-document reindex operation.", + "/api/documents/[id]/reviews": "Document clinical review audit log.", "/api/documents/[id]/search": "Search within one document.", "/api/documents/[id]/signed-url": "Private document signed URL.", "/api/documents/[id]/summarize": "Document summary operation.", "/api/documents/[id]/table-facts": "Document table facts.", "/api/documents/bulk": "Bulk document operations.", "/api/documents/bulk/reindex": "Bulk reindex operation.", + "/api/documents/signed-urls": "Bulk private document signed URLs.", "/api/eval-cases": "Evaluation case data.", "/api/health": "Health check.", + "/api/health/ready": "Readiness health check.", "/api/images/[id]/signed-url": "Private image signed URL.", + "/api/images/signed-urls": "Bulk private image signed URLs.", "/api/ingestion/batches": "Ingestion batch state.", "/api/ingestion/jobs": "Ingestion job collection.", "/api/ingestion/jobs/[id]/retry": "Retry ingestion job.", "/api/ingestion/quality": "Ingestion quality reporting.", "/api/jobs": "Administrator/ops job listing (not a client product API; see docs/api-jobs-ops-surface.md).", "/api/local-project-id": "Local project identity guard.", + "/api/medications": "Medication catalog collection operations.", + "/api/medications/[slug]": "Medication detail endpoint.", "/api/registry/records": "Registry record collection.", "/api/registry/records/[slug]": "Registry record detail.", "/api/search": "Search endpoint.", "/api/search/interaction": "Search interaction telemetry.", + "/api/search/universal": "Cross-entity universal search endpoint.", "/api/setup-status": "Setup status.", "/api/upload": "Upload endpoint.", "/api/webhooks/railway": "Railway deploy webhook -> chat forwarder.", @@ -163,7 +204,7 @@ const apiDescriptions: Record = { }; const routeOwnershipRows = [ - ["Root dashboard and query modes", "src/app/page.tsx, src/lib/app-modes.ts"], + ["Root dashboard and query modes", "src/app/(search-app)/page.tsx, src/lib/app-modes.ts"], ["Global shell layouts", "src/app/*/layout.tsx, src/components/clinical-dashboard/global-search-shell.tsx"], ["Services", "src/app/(search-app)/services, src/lib/services.ts, src/app/api/registry/records"], ["Forms", "src/app/(search-app)/forms, src/lib/forms.ts, src/app/api/registry/records"], @@ -180,6 +221,13 @@ const routeOwnershipRows = [ "src/app/(search-app)/medications, src/components/clinical-dashboard/medication-prescribing-workspace.tsx", ], ["Documents", "src/app/(search-app)/documents, src/lib/document-flow-routes.ts"], + ["Calculators", "src/app/(search-app)/calculators, src/components/calculators"], + ["Therapy Compass", "src/app/(search-app)/therapy-compass, src/lib/therapies.ts"], + ["Factsheets", "src/app/(search-app)/factsheets, src/components/factsheets"], + ["Dictionary", "src/app/(search-app)/dictionary, src/lib/dictionary.ts"], + ["Ward Management", "src/app/ward-management, src/components/ward-management"], + ["Safety Plan", "src/app/safety-plan, src/components/patient-safety-plan.tsx"], + ["Privacy", "src/app/privacy"], ["Tools", "src/components/applications-launcher-page.tsx"], ["Mockups", "src/app/mockups"], ] as const; @@ -451,7 +499,7 @@ function renderModePageIndex() { "`/dictionary/search` is also a query-free browse surface; `/dictionary/browse`, `/topics`, `/topics/[slug]`, `/compare`, `/sources` and `/dictionary/[slug]` records.", }, { - mode: "Therapy", + mode: "Therapy Compass", home: appModeHomeHref("therapy-compass"), search: appModeHomeHref("therapy-compass", { query: "CBT", focus: true, run: true }), detail: @@ -499,6 +547,10 @@ function renderSiteMapRaw(data = collectSiteMapData()) { "/formulation/[slug]", "/therapy-compass/[slug]", "/medications/[slug]", + "/dictionary/[slug]", + "/dictionary/topics/[slug]", + "/factsheets/[slug]", + "/ward-management/patients/[patientId]", ].includes(route.route), ); const mockupRoutes = data.pageRoutes.filter((route) => route.route.startsWith("/mockups")); @@ -571,6 +623,20 @@ function renderSiteMapRaw(data = collectSiteMapData()) { ...renderSlugInventory("Therapy slugs", "/therapy-compass/[slug]", therapySlugs()), "", ...renderSlugInventory("Medication slugs", "/medications/[slug]", medicationSlugs), + "", + ...renderSlugInventory("Factsheet slugs", "/factsheets/[slug]", factsheetSlugs()), + "", + ...renderSlugInventory( + "Clinical dictionary term slugs", + "/dictionary/[slug]", + dictionaryEntries.map((entry) => entry.slug), + ), + "", + ...renderSlugInventory( + "Clinical dictionary topic slugs", + "/dictionary/topics/[slug]", + dictionaryTopics.map((topic) => topic.slug), + ), ]), ...section("Document viewer route", [ bullet( @@ -578,6 +644,12 @@ function renderSiteMapRaw(data = collectSiteMapData()) { "Document viewer/detail page. Individual document IDs are intentionally not enumerated in this sitemap.", ), ]), + ...section("Ward management patient route", [ + bullet( + "/ward-management/patients/[patientId]", + "Synthetic patient placement and transfer trajectory detail. Synthetic patient IDs are generated runtime data and intentionally not enumerated in this sitemap.", + ), + ]), ...section("Mockup/prototype routes", [ ...mockupRoutes.map((route) => routeLine(route, routeDescriptions)), ...(data.nonRoutedMockupArtifacts.length diff --git a/src/app/(search-app)/formulation/[slug]/page.tsx b/src/app/(search-app)/formulation/[slug]/page.tsx index 5752eea9a4..f3e2aa4758 100644 --- a/src/app/(search-app)/formulation/[slug]/page.tsx +++ b/src/app/(search-app)/formulation/[slug]/page.tsx @@ -1,12 +1,24 @@ +import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { FormulationMechanismPage } from "@/components/formulation/formulation-mechanism-page"; import { findFormulationMechanism, formulationMechanisms } from "@/lib/formulation"; +export const dynamicParams = false; + export function generateStaticParams() { return formulationMechanisms.map((mechanism) => ({ slug: mechanism.id })); } +export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise { + const { slug } = await params; + const mechanism = findFormulationMechanism(slug); + return { + title: mechanism ? `${mechanism.name} — Formulation` : "Formulation mechanism not found", + description: mechanism?.summary, + }; +} + export default async function FormulationMechanismRoute({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; const mechanism = findFormulationMechanism(slug); diff --git a/src/app/mockups/layout.tsx b/src/app/mockups/layout.tsx index e2f3b55aa0..07183c26fc 100644 --- a/src/app/mockups/layout.tsx +++ b/src/app/mockups/layout.tsx @@ -5,14 +5,14 @@ import type { ReactNode } from "react"; import { mockupsEnabled } from "@/lib/env"; import { DEVELOPER_AREA_HEADER } from "@/lib/developer-area/headers"; +import { PRIVATE_APP_ROBOTS_METADATA } from "@/lib/crawler-policy"; import { MockupsLayoutClient } from "./mockups-layout-client"; import "./mockups.css"; -// Design-exploration prototypes: shipped for shareability, but never indexed -// (belt-and-braces alongside the robots.ts /mockups/ disallow). +// Design-exploration prototypes: shipped for shareability, but never indexed. export const metadata: Metadata = { - robots: { index: false, follow: false }, + robots: PRIVATE_APP_ROBOTS_METADATA, }; export default async function MockupsLayout({ children }: { children: ReactNode }) { diff --git a/tests/site-map.test.ts b/tests/site-map.test.ts index 57f94f342d..372bfd695b 100644 --- a/tests/site-map.test.ts +++ b/tests/site-map.test.ts @@ -6,21 +6,57 @@ import { appModeDefinitions, appModeHomeHref } from "@/lib/app-modes"; import { tools } from "@/components/tools-page-mockups/tool-fixtures"; import { differentialRecords } from "@/lib/differentials"; import { dsmDiagnoses } from "@/lib/dsm"; +import { formulationMechanisms } from "@/lib/formulation"; import { formRecords } from "@/lib/forms"; import { serviceRecords } from "@/lib/services"; +import { specifierRecords } from "@/lib/specifiers"; +import { therapySlugs } from "@/lib/therapies"; +import { factsheetSlugs } from "@/components/factsheets/factsheets-data"; +import { dictionaryEntries, dictionaryTopics } from "@/lib/dictionary-data"; import { collectSiteMapData, renderSiteMap } from "../scripts/generate-site-map"; import { sourceFrom, sourceSegment } from "./helpers/source-contract"; const siteMapPath = path.join(process.cwd(), "docs", "site-map.md"); const siteMap = readFileSync(siteMapPath, "utf8"); +const staticKnownRoutes = new Set([ + "/formulation/builder", + "/formulation/compare", + "/formulation/map", + "/specifiers/builder", + "/specifiers/compare", + "/specifiers/map", + "/dictionary/browse", + "/dictionary/compare", + "/dictionary/search", + "/dictionary/sources", + "/dictionary/topics", + "/therapy-compass/compare", + "/therapy-compass/pathways", + "/therapy-compass/recommend", + "/therapy-compass/review", + "/therapy-compass/search", + "/documents/search", + "/documents/source", + "/documents/source/evidence", + "/factsheets/search", +]); + const acceptedDynamicPatterns = [ /^\/documents\/[^/?#]+(?:[?#].*)?$/, /^\/services\/[^/?#]+(?:[?#].*)?$/, /^\/forms\/[^/?#]+(?:[?#].*)?$/, /^\/differentials\/diagnoses\/[^/?#]+(?:[?#].*)?$/, + /^\/differentials\/presentations\/[^/?#]+(?:[?#].*)?$/, /^\/dsm\/diagnoses\/[^/?#]+(?:[?#].*)?$/, /^\/medications\/[^/?#]+(?:[?#].*)?$/, + /^\/factsheets\/[^/?#]+(?:[?#].*)?$/, + /^\/dictionary\/[^/?#]+(?:[?#].*)?$/, + /^\/dictionary\/topics\/[^/?#]+(?:[?#].*)?$/, + /^\/formulation\/[^/?#]+(?:[?#].*)?$/, + /^\/specifiers\/[^/?#]+(?:[?#].*)?$/, + /^\/therapy-compass\/[^/?#]+(?:[?#].*)?$/, + /^\/ward-management\/patients\/[^/?#]+(?:[?#].*)?$/, ]; function pathOnly(href: string) { @@ -29,13 +65,27 @@ function pathOnly(href: string) { function routePatternForHref(href: string) { const pathname = pathOnly(href); + if (staticKnownRoutes.has(pathname)) return pathname; + if (/^\/therapy-compass\/[^/?#]+\/brief(?:[?#].*)?$/.test(href)) return "/therapy-compass/[slug]/brief"; + if (/^\/therapy-compass\/[^/?#]+\/sheet(?:[?#].*)?$/.test(href)) return "/therapy-compass/[slug]/sheet"; + if (/^\/dsm\/diagnoses\/[^/?#]+\/differentials(?:[?#].*)?$/.test(href)) return "/dsm/diagnoses/[slug]/differentials"; + if (/^\/dictionary\/topics\/[^/?#]+(?:[?#].*)?$/.test(href)) return "/dictionary/topics/[slug]"; + if (acceptedDynamicPatterns.some((pattern) => pattern.test(href))) { if (pathname.startsWith("/documents/")) return "/documents/[id]"; if (pathname.startsWith("/services/")) return "/services/[slug]"; if (pathname.startsWith("/forms/")) return "/forms/[slug]"; if (pathname.startsWith("/differentials/diagnoses/")) return "/differentials/diagnoses/[slug]"; + if (pathname.startsWith("/differentials/presentations/")) return "/differentials/presentations/[slug]"; if (pathname.startsWith("/dsm/diagnoses/")) return "/dsm/diagnoses/[slug]"; if (pathname.startsWith("/medications/")) return "/medications/[slug]"; + if (pathname.startsWith("/factsheets/")) return "/factsheets/[slug]"; + if (pathname.startsWith("/dictionary/topics/")) return "/dictionary/topics/[slug]"; + if (pathname.startsWith("/dictionary/")) return "/dictionary/[slug]"; + if (pathname.startsWith("/formulation/")) return "/formulation/[slug]"; + if (pathname.startsWith("/specifiers/")) return "/specifiers/[slug]"; + if (pathname.startsWith("/therapy-compass/")) return "/therapy-compass/[slug]"; + if (pathname.startsWith("/ward-management/patients/")) return "/ward-management/patients/[patientId]"; } return pathname; } @@ -103,6 +153,12 @@ describe("tracked sitemap", () => { for (const form of formRecords) expectDocumentedRoute(form.slug); for (const record of differentialRecords) expectDocumentedRoute(record.slug); for (const record of dsmDiagnoses) expectDocumentedRoute(record.slug); + for (const mechanism of formulationMechanisms) expectDocumentedRoute(mechanism.id); + for (const specifier of specifierRecords) expectDocumentedRoute(specifier.slug); + for (const slug of therapySlugs()) expectDocumentedRoute(slug); + for (const slug of factsheetSlugs()) expectDocumentedRoute(slug); + for (const entry of dictionaryEntries) expectDocumentedRoute(entry.slug); + for (const topic of dictionaryTopics) expectDocumentedRoute(topic.slug); expectDocumentedRoute("acamprosate"); }); diff --git a/tests/ui-tools.spec.ts b/tests/ui-tools.spec.ts index 5fd7ce0670..92c9f62c49 100644 --- a/tests/ui-tools.spec.ts +++ b/tests/ui-tools.spec.ts @@ -1873,7 +1873,7 @@ test.describe("Clinical KB tools directory and legacy launcher", () => { expect(searchBox).not.toBeNull(); expect(headingBox).not.toBeNull(); expect((headingBox?.y ?? 0) + (headingBox?.height ?? 0)).toBeLessThan(searchBox?.y ?? 0); - expect((searchBox?.y ?? 0) + (searchBox?.height ?? 0) / 2).toBeLessThan(900 * 0.62); + expect((searchBox?.y ?? 0) + (searchBox?.height ?? 0) / 2).toBeLessThan(900 * 0.65); await expectNoPageHorizontalOverflow(page); }); @@ -1909,7 +1909,7 @@ test.describe("Clinical KB tools directory and legacy launcher", () => { expect(searchBox).not.toBeNull(); expect(headingBox).not.toBeNull(); expect((headingBox?.y ?? 0) + (headingBox?.height ?? 0)).toBeLessThan(searchBox?.y ?? 0); - expect((searchBox?.y ?? 0) + (searchBox?.height ?? 0) / 2).toBeLessThan(900 * 0.62); + expect((searchBox?.y ?? 0) + (searchBox?.height ?? 0) / 2).toBeLessThan(900 * 0.65); }).toPass({ timeout: 10_000 }); await expectNoPageHorizontalOverflow(page); });