import type { CheckSourceId } from './sources.js';
/**
* CHK-5 DRAFT clinician wording, apart from rules.ts so no sign-off hash changes: each rule's approved `clinical` and `why`
* restated as facts, never instructions (clinician-guard.ts). {a} {b} medicines, {result} result and date, {threshold},
* {age}, {allergy}, {reaction}; " Basis: ..." is added from the sources. Every entry needs the clinical lead's sign-off.
*/
export interface ClinicianWordingEntry {
title?: string;
why: string;
/** For a lab rule that applies with no matching medicine (a dangerous potassium on its own). */
whyAlone?: string;
/** Sources the explanation states, when not the rule's own. */
basis?: CheckSourceId[];
review: 'draft';
}
const draft = 'draft' as const;
const ix = (why: string): ClinicianWordingEntry => ({ why, review: draft });
export const INTERACTION_WORDING: Record<string, ClinicianWordingEntry> = {
'vka-nsaid': ix('{a} (vitamin K antagonist) with {b} (NSAID): additive bleeding risk, including gastrointestinal bleeding.'),
'doac-nsaid': ix('{a} (direct oral anticoagulant) with {b} (NSAID): increased bleeding risk.'),
'vka-aspirin-dose-unknown': ix('{a} (vitamin K antagonist) with {b} at a dose that is not recorded. An antiplatelet dose may be intended; analgesic doses add NSAID gastrointestinal bleeding risk.'),
'doac-aspirin-dose-unknown': ix('{a} (direct oral anticoagulant) with {b} at a dose that is not recorded. An antiplatelet dose may be intended; analgesic doses add NSAID gastrointestinal bleeding risk.'),
'anticoagulant-antiplatelet': ix('{a} (vitamin K antagonist) with {b} (antiplatelet): increased bleeding risk. The combination is sometimes intended; its indication and duration are not recorded here.'),
'doac-antiplatelet': ix('{a} (direct oral anticoagulant) with {b} (antiplatelet): increased bleeding risk. The combination is sometimes intended; its indication and duration are not recorded here.'),
'vka-metronidazole': ix('{b} inhibits the metabolism of {a} (CYP2C9), which can raise the INR markedly.'),
'vka-cotrimoxazole': ix('{b} (co-trimoxazole) potentiates {a}, which can raise the INR.'),
'vka-azole': ix('{b} (azole antifungal) inhibits the metabolism of {a}, which can raise the INR.'),
'vka-fluoroquinolone': ix('{b} (fluoroquinolone) may raise the INR with {a}, as reported in some people.'),
'vka-macrolide': ix('{b} (macrolide or strong CYP3A4 inhibitor) may raise the INR with {a}.'),
'vka-inducer': ix('{b} (enzyme inducer) reduces the effect of {a}, so the INR may fall.'),
'vka-amiodarone': ix('{b} potentiates {a}, often over several weeks, which raises the INR.'),
'nsaid-nsaid': ix('{a} and {b} are both NSAIDs: a duplicate class, with added gastrointestinal and renal toxicity.'),
'ssri-nsaid': ix('{a} (SSRI) with {b} (NSAID): increased upper gastrointestinal bleeding risk.'),
'ssri-anticoagulant': ix('{a} (SSRI) with {b} (vitamin K antagonist): increased bleeding risk.'),
'herbal-bleeding-anticoagulant': ix('Case reports describe potentiated anticoagulation with {a} at supplement doses alongside {b}.'),
'herbal-bleeding-doac': ix('{a} with {b} (direct oral anticoagulant): an additive antiplatelet effect is expected from how the herb acts. No DOAC label covers it.'),
'st-johns-wort-anticoagulant': ix('{a} induces CYP enzymes and reduces the effect of {b}.'),
'st-johns-wort-ssri': ix('{a} with {b} (SSRI): risk of serotonin toxicity.'),
'acei-arb': ix('{a} (ACE inhibitor) with {b} (ARB): dual renin-angiotensin blockade, with a risk of hyperkalaemia and acute kidney injury.'),
'raas-k-sparing': ix('{a} (ACE inhibitor) with {b} (potassium-sparing diuretic): risk of hyperkalaemia.'),
'arb-k-sparing': ix('{a} (ARB) with {b} (potassium-sparing diuretic): risk of hyperkalaemia.'),
'raas-potassium': ix('{a} (ACE inhibitor) with {b} (potassium supplement): risk of hyperkalaemia.'),
'arb-potassium': ix('{a} (ARB) with {b} (potassium supplement): risk of hyperkalaemia.'),
'nsaid-acei': ix('{a} (NSAID) with {b} (ACE inhibitor): reduced antihypertensive effect and a risk of acute kidney injury, higher with a diuretic.'),
'nsaid-arb': ix('{a} (NSAID) with {b} (ARB): reduced antihypertensive effect and a risk of acute kidney injury, higher with a diuretic.'),
'simvastatin-strong-cyp3a4': ix('{b} (strong CYP3A4 inhibitor) raises {a} exposure. The simvastatin label lists the combination as contraindicated because of the risk of rhabdomyolysis.'),
'atorvastatin-strong-cyp3a4': ix('{b} (strong CYP3A4 inhibitor) raises {a} exposure, with a risk of myopathy. The atorvastatin label sets dose limits with these inhibitors.'),
'simvastatin-amiodarone': ix('{b} raises {a} exposure. The simvastatin label limits simvastatin to 20 mg a day with amiodarone.'),
'digoxin-macrolide': ix('{b} (clarithromycin or erythromycin) raises {a} levels through P-glycoprotein, with a risk of toxicity.'),
'digoxin-amiodarone': ix('{b} raises {a} levels, with a risk of toxicity.'),
'pde5-nitrate': ix('{a} (PDE5 inhibitor) with {b} (nitrate): contraindicated in the label because of severe hypotension.'),
'opioid-benzodiazepine': ix('{a} (opioid) with {b} (benzodiazepine): FDA boxed warning for profound sedation and respiratory depression.'),
'tramadol-ssri': ix('{a} with {b} (SSRI): risk of serotonin syndrome and a lower seizure threshold.'),
'tramadol-tca': ix('{a} with {b} (tricyclic antidepressant): serotonergic and seizure risk.'),
'methotrexate-trimethoprim': ix('{b} (trimethoprim or co-trimoxazole) with {a}: risk of bone marrow suppression.'),
'methotrexate-nsaid': ix('{b} (NSAID) reduces {a} clearance; the risk is higher with higher methotrexate doses.'),
'allopurinol-azathioprine': ix('{a} inhibits xanthine oxidase, which raises {b} exposure. The azathioprine label sets a dose of about a quarter of the usual dose with allopurinol.'),
'lithium-nsaid': ix('{b} (NSAID) reduces {a} clearance and can raise lithium levels.'),
'lithium-acei': ix('{b} (ACE inhibitor) can raise {a} levels.'),
'lithium-arb': ix('{b} (ARB) can raise {a} levels.'),
'lithium-thiazide': ix('{b} (thiazide) reduces {a} clearance and can raise lithium levels.'),
'sulfonylurea-cotrimoxazole': ix('{b} may potentiate {a} (sulfonylurea): risk of hypoglycaemia.'),
'sulfonylurea-fluconazole': ix('{b} inhibits the metabolism of {a} (sulfonylurea): risk of hypoglycaemia.'),
'clopidogrel-omeprazole': ix('{b} inhibits CYP2C19 activation of {a}. The clopidogrel label warns against this combination.'),
'clopidogrel-esomeprazole': ix('{b} inhibits CYP2C19 activation of {a}. The clopidogrel label warns against this combination.'),
'dolutegravir-rifampicin': ix('{b} induces dolutegravir metabolism and lowers {a} exposure. The dolutegravir label gives 50 mg twice daily with rifampicin.'),
'dolutegravir-cations': ix('{b} (polyvalent cation) chelates {a} and reduces its absorption. The label sets dolutegravir 2 hours before or 6 hours after, and allows iron or calcium together with food.'),
'lumefantrine-efavirenz': ix('{b} (CYP3A4 inducer) lowers artemether, dihydroartemisinin and lumefantrine exposure in {a}, with a risk of treatment failure.'),
'apixaban-strong-inducer': ix('{b} (combined P-gp and strong CYP3A4 inducer) markedly lowers {a} exposure. The apixaban label warns against the combination.'),
'apixaban-st-johns-wort': ix('{b} (combined P-gp and strong CYP3A4 inducer) lowers {a} exposure. The apixaban label warns against the combination.'),
'rivaroxaban-strong-inducer': ix('{b} (combined P-gp and strong CYP3A4 inducer) markedly lowers {a} exposure. The rivaroxaban label warns against the combination.'),
'rivaroxaban-st-johns-wort': ix('{b} (combined P-gp and strong CYP3A4 inducer) lowers {a} exposure. The rivaroxaban label warns against the combination.'),
'lumefantrine-strong-inducer': ix('{b} (strong CYP3A4 inducer) with {a}: contraindicated in the artemether-lumefantrine label because of loss of efficacy.'),
'lumefantrine-st-johns-wort': ix('{b} (CYP3A4 inducer) with {a}: contraindicated in the artemether-lumefantrine label because of loss of efficacy.'),
'amodiaquine-efavirenz': ix('{a} with {b}: marked hepatotoxicity reported. The WHO malaria guidelines list efavirenz as a reason not to use artesunate-amodiaquine.'),
'dolutegravir-phenytoin': ix('{b} (UGT1A1 and CYP3A inducer) lowers {a} exposure. The dolutegravir label warns against the combination.'),
'dolutegravir-st-johns-wort': ix('{b} lowers {a} exposure. The dolutegravir label warns against the combination.'),
'dolutegravir-carbamazepine': ix('{b} lowers {a} exposure. The dolutegravir label gives 50 mg twice daily with carbamazepine.'),
'nevirapine-rifampicin': ix('{b} lowers {a} exposure (AUC about 58% lower). The nevirapine label warns against the combination.'),
'simvastatin-amlodipine': ix('With {b}, the simvastatin label limits {a} to 20 mg a day because of the risk of myopathy. This applies when the simvastatin dose is above 20 mg or not recorded.'),
'digoxin-loop-diuretic': ix('{b} (loop diuretic) can cause hypokalaemia and hypomagnesaemia, which increase the risk of {a} toxicity.'),
'digoxin-thiazide': ix('{b} (thiazide) can cause hypokalaemia, which increases the risk of {a} toxicity.'),
'corticosteroid-nsaid': ix('{a} (corticosteroid) with {b} (NSAID): increased risk of gastrointestinal ulceration and bleeding.'),
'fluoroquinolone-cations': ix('{b} (polyvalent cation) chelates {a} and reduces its absorption. The labels set a gap of 2 hours before or 6 hours after.'),
'levothyroxine-cations': ix('{b} (iron, calcium or antacid) reduces {a} absorption. The label sets a gap of about 4 hours.'),
};
/** Allergy rules: the class each one covers, for "{a} contains {ingredients}, in the {class} class". */
export const ALLERGY_CLASS_WORDS: Record<string, string> = {
'allergy-penicillin': 'penicillin',
'allergy-sulfa': 'sulfonamide antibiotic',
'allergy-nsaid': 'NSAID (including aspirin)',
'allergy-cephalosporin': 'cephalosporin',
'allergy-opioid': 'opioid',
};
/** {subject} is "Amoxicillin is" or "Augmentin contains amoxicillin,": the medicine as recorded, with its matching ingredients when the name differs. */
export const ALLERGY_WORDING = {
title: '{a} and a recorded {allergy} allergy',
ingredient: '{subject} named in the recorded {allergy} allergy{reaction}.',
class: '{subject} in the {class} class, the same class as the recorded {allergy} allergy{reaction}.',
cross: '{subject} a cephalosporin. A {allergy} allergy is recorded{reaction}. Cross-reactivity between penicillins and cephalosporins is reported '
+ 'in a small number of people with a penicillin allergy.',
review: draft,
} as const;
export const OLDER_WORDING: Record<string, ClinicianWordingEntry> = {
'older-long-acting-sulfonylurea': ix('{a} at {age}: long-acting sulfonylureas (glyburide, glimepiride) are listed as potentially inappropriate in older adults '
+ 'in the 2023 Beers Criteria and STOPP/START version 3, because of prolonged hypoglycaemia.'),
'older-first-gen-antihistamine': ix('{a} at {age}: first-generation antihistamines are listed as potentially inappropriate in older adults in the 2023 Beers '
+ 'Criteria, as strongly anticholinergic.'),
'older-benzodiazepine': ix('{a} at {age}: benzodiazepines are listed as potentially inappropriate in older adults in the 2023 Beers Criteria (cognitive '
+ 'impairment, falls, fractures). Abrupt withdrawal carries its own risks.'),
'older-tca': ix('{a} at {age}: tricyclic antidepressants such as amitriptyline are listed as potentially inappropriate in older adults in the 2023 Beers '
+ 'Criteria, as highly anticholinergic and sedating.'),
'older-regular-nsaid': ix('{a} at {age}: regular NSAID use is listed as potentially inappropriate in older adults in the 2023 Beers Criteria and STOPP/START '
+ 'version 3, unless alternatives have failed and a gastroprotective agent is used.'),
};
export const CHILD_WORDING: Record<string, ClinicianWordingEntry> = {
'child-aspirin-under-16': ix('{a} at {age}. The MHRA and NHS state aspirin is not for children under 16 unless specifically indicated (for example '
+ 'Kawasaki disease), because of the risk of Reye\'s syndrome.'),
'child-codeine-under-12': ix('{a} at {age}. The MHRA (2013, 2015) and EMA restrict codeine under 12: unpredictable CYP2D6 conversion to morphine '
+ 'and respiratory depression.'),
'child-tramadol-under-12': ix('{a} at {age}. The tramadol label (FDA 2017) lists it as contraindicated under 12: ultra-rapid metabolism and '
+ 'respiratory depression.'),
'child-promethazine-under-2': ix('{a} at {age}. The promethazine label boxed warning lists it as contraindicated under 2: fatal respiratory depression.'),
'child-cough-cold-promethazine-under-6': ix('{a} at {age}: a cough and cold product with an antihistamine (promethazine). The MHRA (2009) states these '
+ 'products are not for children under 6.'),
'child-night-nurse-under-16': ix('{a} at {age}. Its patient leaflet states it is not for children under 16 (paracetamol, promethazine, dextromethorphan).'),
};
const lab = (why: string, extra: Partial<ClinicianWordingEntry> = {}): ClinicianWordingEntry => ({ why, review: draft, ...extra });
export const LAB_WORDING: Record<string, ClinicianWordingEntry> = {
'lab-metformin-egfr-30': lab('{result} is below 30, the level at which the metformin label (UK SmPC, sections 4.2 and 4.3) lists metformin as contraindicated.',
{ basis: ['smpc-metformin'] }),
'lab-metformin-egfr-45': lab('{result} is in the range where the metformin label (UK SmPC, section 4.2) limits the total daily dose to 1,000 mg (GFR 30 to 44 mL/min).',
{ basis: ['smpc-metformin'] }),
'lab-inr-8': lab('{result} on {a}, a vitamin K antagonist. An INR of 8 or more carries a high risk of serious bleeding.'),
'lab-inr-5': lab('{result} on {a}, a vitamin K antagonist. An INR of 5 or more is well above any usual target range.'),
'lab-inr-high-nsaid': lab('{result} on {a} is above the target of {threshold}, with {b}, an NSAID, also recorded: added bleeding risk.'),
'lab-inr-4-5': lab('{result} on {a}, a vitamin K antagonist. An INR of 4.5 or more is above any usual target range.'),
'lab-inr-high': lab('{result} on {a} is above the target of {threshold}.'),
'lab-potassium-very-high': lab('{result} on {a}, which can raise potassium. NICE CKS (hyperkalaemia) places 6.5 mmol/L or more in the range for emergency assessment.',
{ whyAlone: '{result}. NICE CKS (hyperkalaemia) places 6.5 mmol/L or more in the range for emergency assessment.' }),
'lab-potassium-high': lab('{result} on {a}, which can raise potassium. NICE CKS (hyperkalaemia) places 6.0 to 6.4 mmol/L in the range for same-day assessment.',
{ whyAlone: '{result}. NICE CKS (hyperkalaemia) places 6.0 to 6.4 mmol/L in the range for same-day assessment.' }),
'lab-potassium-raised': lab('{result} on {a}, which can raise potassium. NICE CKS (hyperkalaemia) places 5.5 to 5.9 mmol/L in the range for review and a repeat test.'),
};
/** Tests to ask about: "{test} · needed with {medicines}" (FND-7) and why. */
export const MONITORING_WORDING: Record<string, ClinicianWordingEntry> = {
'monitor-warfarin-inr': ix('The INR shows the effect of a vitamin K antagonist. The cited sources give testing at least every 12 weeks when stable.'),
'monitor-metformin-kidneys': ix('Renal function sets the metformin dose limits in the label. This rule looks for a result at least once a year.'),
'monitor-metformin-b12': ix('Long-term metformin can lower vitamin B12. This rule sets no interval.'),
'monitor-diabetes-hba1c': ix('HbA1c shows average glucose over the previous months. This rule looks for a result every 3 to 6 months.'),
'monitor-acei-kidneys-potassium': ix('ACE inhibitors can change renal function and potassium. This rule looks for a result at the start, after each new dose, and at least yearly.'),
'monitor-arb-kidneys-potassium': ix('ARBs can change renal function and potassium. This rule looks for a result at the start, after each new dose, and at least yearly.'),
'monitor-spironolactone-potassium': ix('Potassium-sparing diuretics can raise potassium. This rule looks for a result about every 6 months.'),
'monitor-bp-home': ix('Home blood pressure readings show the response to a calcium channel blocker. This rule looks for a reading about monthly.'),
'monitor-statin-lipids': ix('A lipid profile shows the response to a statin. This rule looks for a result about 3 months after starting, then yearly.'),
'monitor-lithium-level': ix('Lithium needs regular levels, with renal and thyroid tests. This rule sets no interval.'),
'monitor-methotrexate-bloods': ix('Methotrexate needs regular blood count, liver and renal tests. This rule sets no interval.'),
'monitor-levothyroxine-tsh': ix('TSH shows whether the levothyroxine dose matches need. This rule looks for a result about yearly.'),
};
/** Findings written in engine code (signoff.ts ENGINE_CODED_RULES). */
export const ENGINE_WORDING = {
'dose-max': { title: '{a}: daily amount above the label maximum', why: 'As entered, {a} gives {amounts}.', review: draft },
duplicate: { title: '{ingredient} in more than one medicine', why: '{medicines} each contain {ingredient}{total}.', review: draft },
'paracetamol-lower-maximum': { title: 'Paracetamol near the adult daily maximum',
why: 'About {total} mg of paracetamol a day, {reason}. This rule marks 3,000 to 4,000 mg a day in adults under 50 kg or aged 75 and over, where a lower daily maximum may apply.',
review: draft },
} as const;