From cd84c08a8965e6666432a97532070cf34736f53a Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 22 Aug 2026 22:16:28 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat(medications):=20clinical=20sign-off=20?= =?UTF-8?q?of=20the=20interaction=20lexicon=20=E2=80=94=20three=20terms=20?= =?UTF-8?q?narrowed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ledger #1YPV51. All 37 catalogue terms were expanded to their resolved drug lists and reviewed against the text of the rows each fires on. 34 confirmed; 3 narrowed, each the same shape as the loperamide over-match — a class token matching drugs the interaction rows plainly do not mean. antihistamines: every row is additive ANTICHOLINERGIC burden, and one says "sedating antihistamines" in its own words. Cetirizine, fexofenadine and loratadine resolved into it anyway, so benzatropine + loratadine produced a CRITICAL "anticholinergic toxidrome ... risk of toxic megacolon" alert and oxybutynin + cetirizine "frank delirium and bowel impaction". The three second-generation agents are denied; cyclizine, promethazine, alimemazine and diphenhydramine stay. corticosteroids: every row is a systemic effect — insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia. The four purely topical glucocorticoids are denied. Inhaled agents are deliberately KEPT: the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids, and fludrocortisone stays as a mineralocorticoid that raises BSL and drives hypokalaemia. oral-contraceptives: the rows are enzyme inducers destroying the COMBINED pill. Depot medroxyprogesterone is the method a woman is switched TO on an inducer, and its own catalogue row already carries the nuance the generic term flattened — inducers "accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this." It is removed from the term; its own row still fires. That row is what makes the removal safe, and there is a test pinning it. Also: the report generator hardcoded "**Status: UNREVIEWED.**", so the day a clinician filled in the sign-off the document contradicted itself in its own first sentence. The status line is now derived from the recorded sign-off, on the same read in both the write and --check paths, and says explicitly that the sign-off covers only the mappings as they stood on that date. Measured: 23 medications changed, removals only, nothing added anywhere, all 328 medications intact, resolved/unresolved unchanged at 392/133. Each of the three changes was mutation-tested — reverted, observed to fail 3/4/1 tests, restored. Co-Authored-By: Claude Opus 5 --- data/medication-interaction-index.json | 82 ++++------------- data/outstanding-issues-snapshot.json | 14 ++- docs/medication-interaction-lexicon-review.md | 89 ++++++++++++++++--- .../4df11bb5-3d3a-46bc-bf82-3be1bed87663.json | 14 +++ .../a4a993d4-2326-4150-b9df-1ccf4f5433a3.json | 11 +++ scripts/build-medication-lexicon-report.ts | 48 +++++++--- src/lib/medication-interaction-lexicon.ts | 41 ++++++++- tests/medication-interactions.test.ts | 78 ++++++++++++++++ 8 files changed, 283 insertions(+), 94 deletions(-) create mode 100644 docs/outstanding-issues-inbox/4df11bb5-3d3a-46bc-bf82-3be1bed87663.json create mode 100644 docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json diff --git a/data/medication-interaction-index.json b/data/medication-interaction-index.json index 093049e620..4fa6096a5d 100644 --- a/data/medication-interaction-index.json +++ b/data/medication-interaction-index.json @@ -2859,7 +2859,6 @@ "fosfomycin", "gentamicin", "levonorgestrel", - "medroxyprogesterone", "meropenem", "metronidazole", "minocycline", @@ -2889,17 +2888,14 @@ "counterparties": [ "atenolol", "beclometasone", - "betamethasone", "bisoprolol", "budesonide", "carvedilol", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "labetalol", "methylprednisolone", "metoprolol", @@ -2907,8 +2903,7 @@ "prednisolone", "prednisone", "propranolol", - "sotalol", - "triamcinolone" + "sotalol" ], "termIds": ["beta-blockers", "corticosteroids"], "resolved": true, @@ -2948,17 +2943,14 @@ "counterparties": [ "atenolol", "beclometasone", - "betamethasone", "bisoprolol", "budesonide", "carvedilol", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "labetalol", "methylprednisolone", "metoprolol", @@ -2966,8 +2958,7 @@ "prednisolone", "prednisone", "propranolol", - "sotalol", - "triamcinolone" + "sotalol" ], "termIds": ["beta-blockers", "corticosteroids"], "resolved": true, @@ -2985,17 +2976,14 @@ "counterparties": [ "atenolol", "beclometasone", - "betamethasone", "bisoprolol", "budesonide", "carvedilol", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "labetalol", "methylprednisolone", "metoprolol", @@ -3003,8 +2991,7 @@ "prednisolone", "prednisone", "propranolol", - "sotalol", - "triamcinolone" + "sotalol" ], "termIds": ["beta-blockers", "corticosteroids"], "resolved": true, @@ -3038,20 +3025,16 @@ "severity": "high", "counterparties": [ "beclometasone", - "betamethasone", "budesonide", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "methylprednisolone", "mometasone", "prednisolone", - "prednisone", - "triamcinolone" + "prednisone" ], "termIds": ["corticosteroids"], "resolved": true, @@ -3069,17 +3052,14 @@ "counterparties": [ "atenolol", "beclometasone", - "betamethasone", "bisoprolol", "budesonide", "carvedilol", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "labetalol", "methylprednisolone", "metoprolol", @@ -3087,8 +3067,7 @@ "prednisolone", "prednisone", "propranolol", - "sotalol", - "triamcinolone" + "sotalol" ], "termIds": ["beta-blockers", "corticosteroids"], "resolved": true, @@ -3106,17 +3085,14 @@ "counterparties": [ "atenolol", "beclometasone", - "betamethasone", "bisoprolol", "budesonide", "carvedilol", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "labetalol", "methylprednisolone", "metoprolol", @@ -3124,8 +3100,7 @@ "prednisolone", "prednisone", "propranolol", - "sotalol", - "triamcinolone" + "sotalol" ], "termIds": ["beta-blockers", "corticosteroids"], "resolved": true, @@ -3143,17 +3118,14 @@ "counterparties": [ "atenolol", "beclometasone", - "betamethasone", "bisoprolol", "budesonide", "carvedilol", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "labetalol", "methylprednisolone", "metoprolol", @@ -3161,8 +3133,7 @@ "prednisolone", "prednisone", "propranolol", - "sotalol", - "triamcinolone" + "sotalol" ], "termIds": ["beta-blockers", "corticosteroids"], "resolved": true, @@ -4021,7 +3992,6 @@ "benzatropine", "brexpiprazole", "cariprazine", - "cetirizine", "chlorpromazine", "clomipramine", "clozapine", @@ -4029,13 +3999,11 @@ "diphenhydramine", "dosulepin", "doxepin", - "fexofenadine", "flupentixol-decanoate", "haloperidol-decanoate", "hyoscine-hydrobromide", "imipramine", "levomepromazine", - "loratadine", "lurasidone", "nortriptyline", "olanzapine-pamoate-lai", @@ -4167,7 +4135,7 @@ "rowKey": "Pharmacokinetic", "rowIndex": 0, "severity": "critical", - "counterparties": ["ethinylestradiol", "levonorgestrel", "medroxyprogesterone"], + "counterparties": ["ethinylestradiol", "levonorgestrel"], "termIds": ["oral-contraceptives"], "resolved": true, "note": "CRITICAL — Flushes EVERYTHING out. Any oral medication (e.g., blood pressure pills, oral contraceptives) taken within 2-3 hours of the prep will be flushed out completely unabsorbed." @@ -4660,7 +4628,7 @@ "rowKey": "Pharmacodynamic", "rowIndex": 0, "severity": "high", - "counterparties": ["ethinylestradiol", "levonorgestrel", "medroxyprogesterone"], + "counterparties": ["ethinylestradiol", "levonorgestrel"], "termIds": ["oral-contraceptives"], "resolved": true, "note": "HIGH — Combined Oral Contraceptive Pill (COCP). Using TXA and estrogen together synergistically increases the risk of a fatal DVT or PE." @@ -5187,17 +5155,14 @@ "counterparties": [ "aspirin", "beclometasone", - "betamethasone", "budesonide", "celecoxib", "ciclesonide", - "clobetasol", "dexamethasone", "diclofenac", "fludrocortisone", "fluticasone", "hydrocortisone", - "hydrocortisone-1", "ibuprofen", "ketorolac", "meloxicam", @@ -5206,8 +5171,7 @@ "naproxen", "parecoxib", "prednisolone", - "prednisone", - "triamcinolone" + "prednisone" ], "termIds": ["corticosteroids", "nsaids"], "resolved": true, @@ -6196,7 +6160,7 @@ "rowKey": "Endocrine", "rowIndex": 0, "severity": "critical", - "counterparties": ["copper", "ethinylestradiol", "levonorgestrel", "medroxyprogesterone"], + "counterparties": ["copper", "ethinylestradiol", "levonorgestrel"], "termIds": ["oral-contraceptives"], "resolved": true, "note": "CRITICAL — Strong inducer of **CYP3A4**. It rapidly destroys the estrogen/progesterone in the Combined Oral Contraceptive Pill. Women MUST use alternative non-hormonal contraception (Copper IUD) while on the drug and for 1 month after stopping." @@ -6342,7 +6306,6 @@ "ethinylestradiol", "heparin-iv-sc", "levonorgestrel", - "medroxyprogesterone", "quetiapine", "rivaroxaban", "roxithromycin", @@ -6427,7 +6390,7 @@ "rowKey": "Endocrine", "rowIndex": 2, "severity": "high", - "counterparties": ["ethinylestradiol", "levonorgestrel", "medroxyprogesterone"], + "counterparties": ["ethinylestradiol", "levonorgestrel"], "termIds": ["oral-contraceptives"], "resolved": true, "note": "HIGH — The combined oral contraceptive pill (COCP) halves lamotrigine blood levels. If the woman stops the pill for the placebo week, lamotrigine levels spike, causing acute neurotoxicity (ataxia/double vision)." @@ -6452,7 +6415,6 @@ "ethinylestradiol", "heparin-iv-sc", "levonorgestrel", - "medroxyprogesterone", "rivaroxaban", "ticagrelor", "warfarin-anticoagulant", @@ -6482,7 +6444,6 @@ "ethinylestradiol", "heparin-iv-sc", "levonorgestrel", - "medroxyprogesterone", "quetiapine", "rivaroxaban", "ticagrelor", @@ -6570,7 +6531,7 @@ "rowKey": "Endocrine", "rowIndex": 0, "severity": "high", - "counterparties": ["ethinylestradiol", "levonorgestrel", "medroxyprogesterone"], + "counterparties": ["ethinylestradiol", "levonorgestrel"], "termIds": ["oral-contraceptives"], "resolved": true, "note": "HIGH — Doses > 200mg/day induce CYP3A4, accelerating the clearance of oral contraceptives (OCPs), rendering them ineffective and leading to unplanned pregnancies." @@ -7172,18 +7133,15 @@ "counterparties": [ "alimemazine", "amitriptyline", - "cetirizine", "clomipramine", "clozapine", "cyclizine", "diphenhydramine", "dosulepin", "doxepin", - "fexofenadine", "hyoscine-butylbromide", "hyoscine-hydrobromide", "imipramine", - "loratadine", "nortriptyline", "orphenadrine", "oxybutynin", @@ -8657,7 +8615,7 @@ "rowKey": "Endocrine", "rowIndex": 0, "severity": "critical", - "counterparties": ["ethinylestradiol", "levonorgestrel", "medroxyprogesterone"], + "counterparties": ["ethinylestradiol", "levonorgestrel"], "termIds": ["oral-contraceptives"], "resolved": true, "note": "CRITICAL — Weak inducer of CYP3A4, but strong enough to completely destroy the efficacy of oral contraceptives (OCPs), causing unplanned pregnancy. Must use IUD or barrier." @@ -9085,22 +9043,18 @@ "severity": "high", "counterparties": [ "beclometasone", - "betamethasone", "budesonide", "ciclesonide", - "clobetasol", "dexamethasone", "fludrocortisone", "fluticasone", "hydrochlorothiazide", "hydrocortisone", - "hydrocortisone-1", "indapamide", "methylprednisolone", "mometasone", "prednisolone", - "prednisone", - "triamcinolone" + "prednisone" ], "termIds": ["corticosteroids", "thiazide-diuretics"], "resolved": true, @@ -9125,7 +9079,6 @@ "benzatropine", "brexpiprazole", "cariprazine", - "cetirizine", "chlorpromazine", "clomipramine", "clozapine", @@ -9133,14 +9086,12 @@ "diphenhydramine", "dosulepin", "doxepin", - "fexofenadine", "flupentixol-decanoate", "haloperidol-decanoate", "hyoscine-butylbromide", "hyoscine-hydrobromide", "imipramine", "levomepromazine", - "loratadine", "lurasidone", "nortriptyline", "olanzapine-pamoate-lai", @@ -9367,7 +9318,6 @@ "benzatropine", "brexpiprazole", "cariprazine", - "cetirizine", "chlorpromazine", "clomipramine", "clozapine", @@ -9375,14 +9325,12 @@ "diphenhydramine", "dosulepin", "doxepin", - "fexofenadine", "flupentixol-decanoate", "haloperidol-decanoate", "hyoscine-butylbromide", "hyoscine-hydrobromide", "imipramine", "levomepromazine", - "loratadine", "lurasidone", "nortriptyline", "olanzapine-pamoate-lai", diff --git a/data/outstanding-issues-snapshot.json b/data/outstanding-issues-snapshot.json index b35932a907..199bd9e59b 100644 --- a/data/outstanding-issues-snapshot.json +++ b/data/outstanding-issues-snapshot.json @@ -10,7 +10,7 @@ "p2": 43, "p3": 33, "queued": 11, - "pending": 32, + "pending": 34, "resolved": 359 }, "queue": [ @@ -913,6 +913,12 @@ "summary": "#P5542X: Resolved 2026-08-21: clinical-risk classification includes mode gating, therapy reachability, review/policy/content library surfaces, with explicit app-modes and therapies self-tests.", "created_at": "2026-08-21" }, + { + "request_id": "4df11bb5-3d3a-46bc-bf82-3be1bed87663", + "action": "add", + "summary": "Common cardiovascular drugs are absent from the medication catalogue, so patients taking them get silence rather than an interaction check", + "created_at": "2026-08-22" + }, { "request_id": "4f754fec-20c4-4ca8-8e07-0d948089eaf1", "action": "done", @@ -979,6 +985,12 @@ "summary": "Cancel request 3552c196-bf4f-49c8-a39b-28f8876d8caf: Duplicate done request created by overlapping command completion; retain 4bc642e9-5fba-4b43-90e8-407fe2c11408.", "created_at": "2026-08-21" }, + { + "request_id": "a4a993d4-2326-4150-b9df-1ccf4f5433a3", + "action": "done", + "summary": "#1YPV51: Resolved 2026-08-22 by the Repository Lead's sign-off, recorded in docs/medication-interaction-lexicon-review.md. All 37 catalogue terms were expanded to their resolved drug lists and reviewed alongside the text of the rows each fires on. 34 were confirmed correct; 3 were narrowed. (1) antihistamines: every row is about additive ANTICHOLINERGIC burden -- one says 'sedating antihistamines' in its own words -- yet cetirizine, fexofenadine and loratadine resolved into it, so benzatropine + loratadine produced a CRITICAL 'anticholinergic toxidrome ... toxic megacolon' alert and oxybutynin + cetirizine 'frank delirium and bowel impaction'; the three second-generation agents are now denied. (2) corticosteroids: every row is a systemic effect (insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia), so the four purely topical glucocorticoids are denied; inhaled agents are deliberately kept because the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids. (3) oral-contraceptives: the rows are about enzyme inducers destroying the COMBINED pill, and depot medroxyprogesterone is the method a woman is switched TO on an inducer -- its own catalogue row already states inducers 'accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this', so the generic term was flattening a nuance the catalogue records correctly; it is removed from the term and its own row still fires. Two classification questions answered: moclobemide correctly excluded from maois (reversible inhibition does not carry the tyramine/washout risks the rows describe), atomoxetine correctly classed SNRI. Measured: 23 medications changed, removals only, nothing added, all 328 medications intact, resolved/unresolved unchanged at 392/133; each change mutation-tested. HOW IT WAS DONE, stated because this row exists over an earlier closure that claimed a review that had not happened: an assistant analysis proposed a verdict per term with its evidence, and the Repository Lead read and accepted them. It is a reviewed-and-accepted sign-off, NOT an independent re-derivation from primary sources, and must not be described as one. NOT resolved by this: acei resolves to perindopril alone, arbs to candesartan alone, statins to atorvastatin and rosuvastatin -- ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely, so a patient on one produces silence rather than safety. That is a catalogue coverage gap, recorded in the sign-off, and is not fixable in the lexicon.", + "created_at": "2026-08-22" + }, { "request_id": "afaa753b-41ae-4bee-8c63-89c649cdcfd5", "action": "done", diff --git a/docs/medication-interaction-lexicon-review.md b/docs/medication-interaction-lexicon-review.md index e81edebed3..a1adfb109d 100644 --- a/docs/medication-interaction-lexicon-review.md +++ b/docs/medication-interaction-lexicon-review.md @@ -1,6 +1,6 @@ # Medication interaction lexicon — clinical review sheet -**Status: UNREVIEWED.** No clinician has checked these mappings. Record sign-off at the bottom. +**Status: reviewed 2026-08-22** — see the sign-off at the bottom. That sign-off covers the mappings as they stood on that date only. Any lexicon change made since is NOT covered by it: re-check every term the change touches, and say so in the sign-off. Generated by `npm run medications:lexicon-report` from `src/lib/medication-interaction-lexicon.ts`. Do not hand-edit — fix the lexicon and regenerate. `npm run check:medication-lexicon-report` fails when @@ -42,9 +42,9 @@ CRITICAL or HIGH. Start at the top — the table is sorted by severe usage. | `antacids` | antacids, antacid | 16 | 14 | **2** — Calcium carbonate, Magnesium oxide | | `antihypertensives` | antihypertensives, antihypertensive | 14 | 14 | **17** — Amlodipine, Atenolol, Bisoprolol, Candesartan, Carvedilol, Diltiazem, Eplerenone, Felodipine, Frusemide, Hydrochlorothiazide, Indapamide, Labetalol, Metoprolol, Nifedipine XR, Perindopril, Spironolactone, Verapamil | | `macrolides` | macrolides, macrolide | 13 | 12 | **4** — Azithromycin, Clarithromycin, Erythromycin, Roxithromycin | -| `oral-contraceptives` | oral contraceptives, oral contraceptive, combined oral contraceptive pill, cocp, ocps, ocp | 10 | 9 | **3** — Ethinylestradiol, Levonorgestrel, Medroxyprogesterone | +| `oral-contraceptives` | oral contraceptives, oral contraceptive, combined oral contraceptive pill, cocp, ocps, ocp | 10 | 9 | **2** — Ethinylestradiol, Levonorgestrel | | `calcium-channel-blockers` | calcium channel blockers, calcium channel blocker, ccbs, ccb, non-dhp ccbs, dhp calcium channel blockers | 9 | 9 | **5** — Amlodipine, Diltiazem, Felodipine, Nifedipine XR, Verapamil | -| `corticosteroids` | corticosteroids, corticosteroid, steroids, steroid | 9 | 9 | **15** — Beclometasone, Betamethasone, Budesonide, Ciclesonide, Clobetasol, Dexamethasone, Fludrocortisone, Fluticasone, Hydrocortisone, Hydrocortisone 1%, Methylprednisolone, Mometasone, Prednisolone, Prednisone, Triamcinolone | +| `corticosteroids` | corticosteroids, corticosteroid, steroids, steroid | 9 | 9 | **11** — Beclometasone, Budesonide, Ciclesonide, Dexamethasone, Fludrocortisone, Fluticasone, Hydrocortisone, Methylprednisolone, Mometasone, Prednisolone, Prednisone | | `lithium` | lithium, lithium carbonate | 9 | 9 | **1** — Lithium carbonate (IR/SR) | | `thiazide-diuretics` | thiazide diuretics, thiazides, thiazide | 9 | 9 | **2** — Hydrochlorothiazide, Indapamide | | `ppis` | ppis, ppi, proton pump inhibitors | 8 | 8 | **2** — Esomeprazole, Pantoprazole | @@ -53,7 +53,7 @@ CRITICAL or HIGH. Start at the top — the table is sorted by severe usage. | `fluoroquinolones` | fluoroquinolones, fluoroquinolone, quinolones | 5 | 5 | **3** — Ciprofloxacin, Moxifloxacin, Norfloxacin | | `loop-diuretics` | loop diuretics, loop diuretic | 5 | 5 | **1** — Frusemide | | `antibiotics` | antibiotics, antibiotic, oral antibiotics, broad-spectrum antibiotics | 5 | 3 | **34** — Amikacin, Amoxicillin, Amoxicillin/clavulanate, Azithromycin, Aztreonam, Benzathine benzylpenicillin, Cefazolin, Cefepime, Ceftriaxone, Cefuroxime, Cephalexin, Ciprofloxacin, Clarithromycin, Clindamycin, Co-trimoxazole, Colistin, Dicloxacillin, Doxycycline, Ertapenem, Erythromycin, Flucloxacillin, Fosfomycin, Gentamicin, Meropenem, Metronidazole, Minocycline, Moxifloxacin, Nitrofurantoin, Norfloxacin, Phenoxymethylpenicillin, Piperacillin/tazobactam, Roxithromycin, Trimethoprim, Vancomycin | -| `antihistamines` | antihistamines, antihistamine | 4 | 3 | **7** — Alimemazine, Cetirizine, Cyclizine, Diphenhydramine, Fexofenadine, Loratadine, Promethazine | +| `antihistamines` | antihistamines, antihistamine | 4 | 3 | **4** — Alimemazine, Cyclizine, Diphenhydramine, Promethazine | | `penicillins` | penicillins, penicillin | 4 | 3 | **7** — Amoxicillin, Amoxicillin/clavulanate, Benzathine benzylpenicillin, Dicloxacillin, Flucloxacillin, Phenoxymethylpenicillin, Piperacillin/tazobactam | | `snris` | snris, snri | 4 | 3 | **5** — Atomoxetine, Desvenlafaxine, Duloxetine, Tramadol IR, Venlafaxine XR | | `antiplatelets` | antiplatelets, antiplatelet | 3 | 3 | **4** — Aspirin, Clopidogrel, Dipyridamole, Ticagrelor | @@ -76,6 +76,13 @@ Drugs a selector would otherwise have swept in. Each is a clinical claim worth c | `opioids` | Naloxone | class `Antidote`, subclass `Opioid Antagonist` | | `opioids` | Loperamide | class `Antidiarrhoeal`, subclass `Peripheral Opioid Agonist` | | `anticoagulants` | Aspirin | class `Anticoagulant`, subclass `Antiplatelet / NSAID` | +| `antihistamines` | Cetirizine | class `Allergy`, subclass `H1 Antihistamine (2nd Gen)` | +| `antihistamines` | Fexofenadine | class `Allergy`, subclass `H1 Antihistamine (2nd Gen)` | +| `antihistamines` | Loratadine | class `Allergy`, subclass `H1 Antihistamine (2nd Gen)` | +| `corticosteroids` | Betamethasone | class `Steroid`, subclass `Topical Glucocorticoid` | +| `corticosteroids` | Clobetasol | class `Steroid`, subclass `Topical Glucocorticoid` | +| `corticosteroids` | Hydrocortisone 1% | class `Steroid`, subclass `Topical Glucocorticoid` | +| `corticosteroids` | Triamcinolone | class `Steroid`, subclass `Topical Glucocorticoid` | ## Terms that resolve to no catalogue drug @@ -113,7 +120,7 @@ the class cannot be enumerated, and holds the medication at grey rather than gre ## What this tool can never warn about -**20 of the catalogue's 328 medications sit outside both ends of every resolved +**26 of the catalogue's 328 medications sit outside both ends of every resolved interaction row.** Entering one of them produces no alert — not because the combination was checked and found clear, but because no machine-resolved edge in the corpus includes that drug. On screen those outcomes look the same, so this list is the honest boundary of the feature. @@ -125,7 +132,9 @@ interaction row or making an existing row machine-resolvable, with clinical revi | ------------ | ----------- | -------------------------------------------------------------------------------- | | Aperient | 5 | Docusate sodium, Glycerol suppository, Ispaghula husk, Movicol/Macrogol, Osmolax | | Antidiabetic | 4 | Dulaglutide, Linagliptin, Semaglutide, Sitagliptin | +| Steroid | 4 | Betamethasone, Clobetasol, Hydrocortisone 1%, Triamcinolone | | Vitamin | 3 | Riboflavin, Thiamine, Vitamin A | +| Allergy | 2 | Cetirizine, Loratadine | | Antifungal | 2 | Clotrimazole, Nystatin | | Urology | 2 | Dutasteride, Finasteride | | Antiviral | 1 | Oseltamivir | @@ -144,12 +153,70 @@ Checks that ran and found nothing: ## Sign-off -| Field | Value | -| ---------------------- | ------------------ | -| Reviewer (name + role) | _not yet reviewed_ | -| Date | _not yet reviewed_ | -| Outcome | _not yet reviewed_ | -| Corrections raised | _not yet reviewed_ | +| Field | Value | +| ---------------------- | --------------------------------------------------------------------------------------------------------- | +| Reviewer (name + role) | Repository Lead | +| Date | 2026-08-22 | +| Outcome | All 37 catalogue terms reviewed. 34 confirmed correct as they stood; 3 corrected (below). Ledger #1YPV51. | +| Corrections raised | 3 accepted and applied; 2 classification questions answered; 1 coverage limit recorded, see below. | + +### What was corrected, and why + +1. **`antihistamines` was too broad.** Every row it fires on describes additive + _anticholinergic_ burden — one says "sedating antihistamines" in its own words — yet the term + also resolved to cetirizine, fexofenadine and loratadine. Benzatropine plus loratadine was + producing a CRITICAL "anticholinergic toxidrome … risk of toxic megacolon" alert, and oxybutynin + plus cetirizine "frank delirium and bowel impaction". The three second-generation agents are now + excluded. Cyclizine, promethazine, alimemazine and diphenhydramine are retained: all four are + genuinely anticholinergic and are what the rows mean. +2. **`corticosteroids` was too broad.** Every row is a systemic effect — five are insulin + resistance and raised BSL, one tendon rupture with ciprofloxacin, one additive hypokalaemia. The + four purely topical agents (betamethasone, clobetasol, hydrocortisone 1%, triamcinolone) are now + excluded; a steroid cream does not increase insulin requirements. Inhaled agents are + **deliberately retained**, because the hypokalaemia row concerns a formoterol inhaler and names + high-dose corticosteroids, and high-dose inhaled steroids do carry systemic effects. + Beclometasone and mometasone ("topical/inhaled") are retained on the same reasoning, and + fludrocortisone is retained as a mineralocorticoid that raises BSL and drives hypokalaemia. +3. **`oral-contraceptives` was too broad.** Almost every row is an enzyme inducer destroying the + _combined_ pill. Depot medroxyprogesterone is the method a woman is switched **to** when she is + on an inducer, so warning that it will fail argues against the option that still works. It is now + excluded; ethinylestradiol and levonorgestrel are retained. + +Measured effect: 23 medications changed, removals only, nothing added anywhere, all 328 catalogue +medications intact, and resolved/unresolved row counts unchanged at 392 / 133. + +### Classification questions answered + +- **Moclobemide is correctly excluded from `maois`.** The MAOI rows concern irreversible + inhibition — tyramine-driven hypertensive crisis and the washout interval — which a reversible + inhibitor does not carry. Its serotonergic risk is covered separately. +- **Atomoxetine is correctly classified `SNRI`.** It is a noradrenaline reuptake inhibitor and the + SNRI rows that fire on it concern noradrenergic and serotonergic load, which apply. + +### Recorded limits this sign-off does NOT resolve + +`acei` resolves to perindopril alone, `arbs` to candesartan alone, and `statins` to atorvastatin and +rosuvastatin. Ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue +entirely, so a patient taking one of them produces **silence, not safety**. That is a catalogue +coverage gap rather than a mapping fault, and it is not fixable in this file. The same caveat applies +to the 20 medications listed under "What this tool can never warn about" above. + +### How this review was conducted + +Stated plainly, because this row exists (`#1YPV51`) precisely because an earlier closure claimed a +review that had not happened. What took place on 2026-08-22: every one of the 37 terms was expanded +to its resolved drug list and put to the Repository Lead, together with the text of the interaction +rows each term fires on. An assistant analysis proposed a verdict per term — 34 accept, 3 narrow — +with the evidence for each, and identified the classification questions. The Repository Lead read +those and accepted them. So this is a reviewed-and-accepted sign-off, not an independent +re-derivation from the primary sources, and it should not be described as one. + +### Scope of this sign-off + +It covers the 37 catalogue-term mappings as they stood on 2026-08-22. It is **not** a review of the +interaction wording, which is verbatim from the source catalogue, nor of the `external`, `nonDrug` or +`mechanism` terms, which resolve to no catalogue drug and therefore raise no alert. Any later change +to the lexicon falls outside it and must be re-checked. Until this is filled in, treat every interaction alert as unvalidated mapping over source-backed text. The wording shown to the clinician is always verbatim from the catalogue; what is unreviewed is _which diff --git a/docs/outstanding-issues-inbox/4df11bb5-3d3a-46bc-bf82-3be1bed87663.json b/docs/outstanding-issues-inbox/4df11bb5-3d3a-46bc-bf82-3be1bed87663.json new file mode 100644 index 0000000000..bbbfa480db --- /dev/null +++ b/docs/outstanding-issues-inbox/4df11bb5-3d3a-46bc-bf82-3be1bed87663.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "4df11bb5-3d3a-46bc-bf82-3be1bed87663", + "createdOn": "2026-08-22", + "action": "add", + "payload": { + "pri": "P2", + "type": "issue", + "summary": "Common cardiovascular drugs are absent from the medication catalogue, so patients taking them get silence rather than an interaction check", + "detail": "SPLIT OUT 2026-08-22 from the #1YPV51 clinical sign-off, which recorded this as the one finding the lexicon review could NOT fix. The interaction terms acei, arbs and statins resolve to one or two drugs each -- acei to Perindopril alone, arbs to Candesartan alone, statins to Atorvastatin and Rosuvastatin -- not because the mapping is wrong but because ramipril, lisinopril, irbesartan and simvastatin are not in data/medications-snapshot.json at all. Simvastatin is the notable one: it has the largest CYP3A4 interaction profile of the statins and is entirely unrepresented. CONSEQUENCE, and it is the dangerous shape: a clinician entering a patient on ramipril sees no alert, and on screen that is indistinguishable from 'checked and clear'. The sign-off sheet's 'What this tool can never warn about' section already names the same failure mode for the 20 catalogue medications that sit outside every resolved interaction row; this is that boundary reached from the other side -- the drug is not in the catalogue at all. NEXT: decide whether the catalogue should be widened to the common ACE inhibitors, ARBs and statins prescribed in Australian practice, which is a clinical-content decision about source coverage rather than a code change, and needs the same source-backed review any catalogue addition needs. STOP: do not 'fix' this by loosening the lexicon terms -- the terms are correct; the drugs are missing. Related: #1YPV51 (the sign-off recording this), and the corpus-coverage limit documented in docs/medication-interaction-lexicon-review.md.", + "source": "docs/medication-interaction-lexicon-review.md sign-off 2026-08-22; data/medications-snapshot.json; clinical review session 2026-08-22", + "issueUlid": "01M0MX15KK4AM8Z0TXNDG8EGEE" + } +} diff --git a/docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json b/docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json new file mode 100644 index 0000000000..8728890bd3 --- /dev/null +++ b/docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "a4a993d4-2326-4150-b9df-1ccf4f5433a3", + "createdOn": "2026-08-22", + "action": "done", + "payload": { + "id": "#1YPV51", + "outcome": "Resolved 2026-08-22 by the Repository Lead's sign-off, recorded in docs/medication-interaction-lexicon-review.md. All 37 catalogue terms were expanded to their resolved drug lists and reviewed alongside the text of the rows each fires on. 34 were confirmed correct; 3 were narrowed. (1) antihistamines: every row is about additive ANTICHOLINERGIC burden -- one says 'sedating antihistamines' in its own words -- yet cetirizine, fexofenadine and loratadine resolved into it, so benzatropine + loratadine produced a CRITICAL 'anticholinergic toxidrome ... toxic megacolon' alert and oxybutynin + cetirizine 'frank delirium and bowel impaction'; the three second-generation agents are now denied. (2) corticosteroids: every row is a systemic effect (insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia), so the four purely topical glucocorticoids are denied; inhaled agents are deliberately kept because the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids. (3) oral-contraceptives: the rows are about enzyme inducers destroying the COMBINED pill, and depot medroxyprogesterone is the method a woman is switched TO on an inducer -- its own catalogue row already states inducers 'accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this', so the generic term was flattening a nuance the catalogue records correctly; it is removed from the term and its own row still fires. Two classification questions answered: moclobemide correctly excluded from maois (reversible inhibition does not carry the tyramine/washout risks the rows describe), atomoxetine correctly classed SNRI. Measured: 23 medications changed, removals only, nothing added, all 328 medications intact, resolved/unresolved unchanged at 392/133; each change mutation-tested. HOW IT WAS DONE, stated because this row exists over an earlier closure that claimed a review that had not happened: an assistant analysis proposed a verdict per term with its evidence, and the Repository Lead read and accepted them. It is a reviewed-and-accepted sign-off, NOT an independent re-derivation from primary sources, and must not be described as one. NOT resolved by this: acei resolves to perindopril alone, arbs to candesartan alone, statins to atorvastatin and rosuvastatin -- ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely, so a patient on one produces silence rather than safety. That is a catalogue coverage gap, recorded in the sign-off, and is not fixable in the lexicon.", + "baseRowFingerprint": "474e5feba5b3f5d8fc1cd5230994a22d6d9c642c22498922e2b286f6b43b75b4" + } +} diff --git a/scripts/build-medication-lexicon-report.ts b/scripts/build-medication-lexicon-report.ts index fd26c7cafd..d1b74b9c2a 100644 --- a/scripts/build-medication-lexicon-report.ts +++ b/scripts/build-medication-lexicon-report.ts @@ -83,10 +83,23 @@ async function main(): Promise { } } + // The status line has to be derived, not hardcoded. It previously always read + // UNREVIEWED, so the day a clinician filled in the sign-off block the document + // contradicted itself in its own first sentence — and the sign-off is the half + // a reader is less likely to scroll to. Both the write path and `--check` build + // it from the same read, or the check would report a stale artefact forever. + const recordedSignOff = readSignOff(path.resolve(process.cwd(), OUTPUT_PATH)); + const lines: string[] = []; lines.push("# Medication interaction lexicon — clinical review sheet"); lines.push(""); - lines.push("**Status: UNREVIEWED.** No clinician has checked these mappings. Record sign-off at the bottom."); + lines.push( + recordedSignOff.date + ? `**Status: reviewed ${recordedSignOff.date}** — see the sign-off at the bottom. That sign-off covers the ` + + "mappings as they stood on that date only. Any lexicon change made since is NOT covered by it: re-check " + + "every term the change touches, and say so in the sign-off." + : "**Status: UNREVIEWED.** No clinician has checked these mappings. Record sign-off at the bottom.", + ); lines.push(""); lines.push( "Generated by `npm run medications:lexicon-report` from `src/lib/medication-interaction-lexicon.ts`.", @@ -263,23 +276,34 @@ async function main(): Promise { return; } - // Preserve any sign-off already recorded by a human. - let existingSignOff = ""; - try { - const current = readFileSync(outputPath, "utf8"); - const marker = current.indexOf("## Sign-off"); - if (marker >= 0 && !current.includes("_not yet reviewed_")) existingSignOff = current.slice(marker); - } catch { - existingSignOff = ""; - } - - const output = existingSignOff ? `${beforeSignOff(rendered)}${existingSignOff}` : rendered; + const output = recordedSignOff.block ? `${beforeSignOff(rendered)}${recordedSignOff.block}` : rendered; writeFileSync(outputPath, output); console.log( `[lexicon-report] wrote ${OUTPUT_PATH}: ${catalogueTerms.length} catalogue terms, ${flags.length} flagged.`, ); } +/** + * Read a sign-off a human has already recorded, if there is one. + * + * A block still containing `_not yet reviewed_` is a placeholder, not a + * sign-off, and is treated as absent — that is what keeps a half-filled table + * from flipping the document's status line to "reviewed". + */ +function readSignOff(outputPath: string): { block: string; date: string } { + let current = ""; + try { + current = readFileSync(outputPath, "utf8"); + } catch { + return { block: "", date: "" }; + } + const marker = current.indexOf("## Sign-off"); + if (marker < 0 || current.includes("_not yet reviewed_")) return { block: "", date: "" }; + const block = current.slice(marker); + const date = block.match(/\|\s*Date\s*\|\s*(\d{4}-\d{2}-\d{2})\s*\|/)?.[1] ?? ""; + return { block, date }; +} + function beforeSignOff(value: string): string { const marker = value.indexOf("## Sign-off"); return marker >= 0 ? value.slice(0, marker) : value; diff --git a/src/lib/medication-interaction-lexicon.ts b/src/lib/medication-interaction-lexicon.ts index 06f5d62e06..455eb894e7 100644 --- a/src/lib/medication-interaction-lexicon.ts +++ b/src/lib/medication-interaction-lexicon.ts @@ -180,16 +180,44 @@ const CATALOGUE_TERMS: LexiconTerm[] = [ select: { subclassIncludes: ["Anticholinergic"] }, }, { + // Every row this term fires on is about additive ANTICHOLINERGIC burden, not + // about histamine blockade — one says so in its own words: "if given with + // TCAs, sedating antihistamines, or antipsychotics". The second-generation + // agents are denied because they carry essentially no anticholinergic + // activity, and the catalogue labels them as such ("H1 Antihistamine (2nd + // Gen)"). Before this, benzatropine + loratadine produced a CRITICAL + // "anticholinergic toxidrome ... risk of toxic megacolon" alert and + // oxybutynin + cetirizine produced "frank delirium and bowel impaction". + // + // Cyclizine, promethazine, alimemazine and diphenhydramine stay: all four + // are genuinely anticholinergic and are what the rows mean. + // Clinical review 2026-08-22 (ledger #1YPV51). id: "antihistamines", surfaces: ["antihistamines", "antihistamine"], kind: "catalogue", - select: { subclassIncludes: ["Antihistamine"] }, + select: { subclassIncludes: ["Antihistamine"], denySlugs: ["cetirizine", "fexofenadine", "loratadine"] }, }, { + // Every row is a SYSTEMIC effect: five are insulin resistance and raised + // BSL, one is tendon rupture with ciprofloxacin, one is additive + // hypokalaemia. A steroid cream does not massively increase insulin + // requirements, so the four purely topical agents are denied — the + // catalogue marks them "Topical Glucocorticoid". + // + // Inhaled agents are deliberately KEPT. The hypokalaemia row is about a + // formoterol inhaler and names "high-dose corticosteroids", and high-dose + // inhaled steroids do carry systemic effects. Beclometasone and mometasone + // are catalogued "Topical/Inhaled" and are kept on the same reasoning. + // Fludrocortisone is a mineralocorticoid and is kept: it raises BSL and + // drives hypokalaemia, which is exactly what these rows describe. + // Clinical review 2026-08-22 (ledger #1YPV51). id: "corticosteroids", surfaces: ["corticosteroids", "corticosteroid", "steroids", "steroid"], kind: "catalogue", - select: { classes: ["Steroid"] }, + select: { + classes: ["Steroid"], + denySlugs: ["betamethasone", "clobetasol", "hydrocortisone-1", "triamcinolone"], + }, }, { // Not a class — a name alias, and the most consequential one in the file. @@ -252,10 +280,17 @@ const CATALOGUE_TERMS: LexiconTerm[] = [ }, }, { + // Almost every row is an enzyme inducer destroying the COMBINED pill — + // carbamazepine, St John's wort, topiramate above 200 mg — plus one about + // estrogen and VTE risk with tranexamic acid. Depot medroxyprogesterone is + // the method a woman is switched TO when she is on an inducer, so warning + // that it will fail does not merely cry wolf: it argues against the option + // that still works. Removed on clinical review 2026-08-22 (ledger #1YPV51). + // Levonorgestrel is kept: implant and pill formulations are inducer-affected. id: "oral-contraceptives", surfaces: ["oral contraceptives", "oral contraceptive", "combined oral contraceptive pill", "cocp", "ocps", "ocp"], kind: "catalogue", - select: { slugs: ["ethinylestradiol", "levonorgestrel", "medroxyprogesterone"] }, + select: { slugs: ["ethinylestradiol", "levonorgestrel"] }, }, { id: "fibrates", diff --git a/tests/medication-interactions.test.ts b/tests/medication-interactions.test.ts index c6c82f4d48..fadb45d099 100644 --- a/tests/medication-interactions.test.ts +++ b/tests/medication-interactions.test.ts @@ -266,3 +266,81 @@ describe("loperamide over-match: the other directions", () => { expect(result.interactions.length).toBeGreaterThan(0); }); }); + +describe("clinical review 2026-08-22: three terms narrowed (ledger #1YPV51)", () => { + // Each of the three corrections has the same shape as the loperamide fix — a + // class token matching drugs the interaction rows plainly do not mean — so each + // needs a guard in BOTH directions: the false alert is gone, and the true alert + // the term exists for still fires. + + describe("antihistamines: anticholinergic burden, not histamine blockade", () => { + it.each(["cetirizine", "fexofenadine", "loratadine"])( + "no longer fires the anticholinergic toxidrome alert for %s", + (slug) => { + const result = evaluateMedicationInteractions("benzatropine", [slug]); + expect(result.interactions.some((item) => item.counterpartySlug === slug)).toBe(false); + }, + ); + + it.each(["promethazine", "diphenhydramine", "alimemazine", "cyclizine"])( + "still fires for %s, which is genuinely anticholinergic", + (slug) => { + const result = evaluateMedicationInteractions("benzatropine", [slug]); + expect(result.interactions.some((item) => item.counterpartySlug === slug)).toBe(true); + }, + ); + + it("still fires on oxybutynin, the other critical anticholinergic row", () => { + const result = evaluateMedicationInteractions("oxybutynin", ["promethazine"]); + expect(result.interactions.some((item) => item.counterpartySlug === "promethazine")).toBe(true); + }); + }); + + describe("corticosteroids: systemic effects only", () => { + it.each(["betamethasone", "clobetasol", "hydrocortisone-1", "triamcinolone"])( + "no longer claims topical %s raises insulin requirements", + (slug) => { + const result = evaluateMedicationInteractions("insulin-glargine", [slug]); + expect(result.interactions.some((item) => item.counterpartySlug === slug)).toBe(false); + }, + ); + + it.each(["prednisolone", "dexamethasone", "fludrocortisone"])("still fires for systemic %s", (slug) => { + const result = evaluateMedicationInteractions("insulin-glargine", [slug]); + expect(result.interactions.some((item) => item.counterpartySlug === slug)).toBe(true); + }); + + it.each(["budesonide", "ciclesonide", "fluticasone", "beclometasone", "mometasone"])( + "deliberately keeps inhaled %s, which the hypokalaemia row is about", + (slug) => { + const result = evaluateMedicationInteractions("formoterol", [slug]); + expect(result.interactions.some((item) => item.counterpartySlug === slug)).toBe(true); + }, + ); + }); + + describe("oral contraceptives: the combined pill", () => { + it("no longer sweeps depot medroxyprogesterone into the generic inducer alerts", () => { + // Topiramate's row is one of the "inducer destroys the OCP, use alternative + // contraception" rows. Medroxyprogesterone reached it only through the + // oral-contraceptives term, so removing it from that term removes the alert. + const result = evaluateMedicationInteractions("topiramate", ["medroxyprogesterone"]); + expect(result.interactions.some((item) => item.counterpartySlug === "medroxyprogesterone")).toBe(false); + }); + + it("keeps medroxyprogesterone's OWN inducer row, which is the accurate one", () => { + // The catalogue already states the nuance the generic term flattened: + // inducers "accelerate the clearance of the oral tablets, but the massive + // 150mg IM depot is generally resistant to clinically failing from this." + // That row must survive — losing it would be the dangerous over-correction, + // and keeping it is why removing the generic alert is safe. + const result = evaluateMedicationInteractions("medroxyprogesterone", ["carbamazepine"]); + expect(result.interactions.some((item) => item.counterpartySlug === "carbamazepine")).toBe(true); + }); + + it.each(["ethinylestradiol", "levonorgestrel"])("still warns about %s", (slug) => { + const result = evaluateMedicationInteractions("carbamazepine", [slug]); + expect(result.interactions.some((item) => item.counterpartySlug === slug)).toBe(true); + }); + }); +}); From 05c532c44801613bdb5292e85099eb347d613314 Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 22 Aug 2026 22:35:08 +0800 Subject: [PATCH 2/5] fix(ledger): resolve the #1YPV51 collision and record an evidence-driven reversal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two pending mutations targeted #1YPV51 — yesterday's partial-progress update from the loperamide fix, which explicitly instructed that the row not be closed without owner confirmation, and today's closure now that the confirmation exists. Both are cancelled with reasons and the closure is reissued carrying yesterday's history, because requests are immutable and combining them means replacing rather than editing. The reason this matters beyond bookkeeping: yesterday's record listed "splitting antihistamines by sedation" as a proposal made and WITHDRAWN. Today that withdrawal was reversed and the split applied. The reversal is evidence-driven, not a change of mind, and the closure says so: the original withdrawal reasoned only that splitting would stop the term meaning "antihistamines" — it never examined what the interaction rows say. They say "sedating antihistamines" and describe an anticholinergic toxidrome, which the second-generation agents cannot cause. The other three withdrawals from that day still stand, and the record now distinguishes the two cases. Co-Authored-By: Claude Opus 5 --- data/outstanding-issues-snapshot.json | 20 ++++++++++++++++++- .../414e60a0-f441-4cbb-9996-9dce4f22583e.json | 10 ++++++++++ .../4aed85d0-2bed-4c39-9560-6d5ab2bada19.json | 11 ++++++++++ .../6a16ed64-3b63-4977-8a2b-8c50c6b16877.json | 10 ++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json create mode 100644 docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json create mode 100644 docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json diff --git a/data/outstanding-issues-snapshot.json b/data/outstanding-issues-snapshot.json index 9e1c746bbc..c6b38cda69 100644 --- a/data/outstanding-issues-snapshot.json +++ b/data/outstanding-issues-snapshot.json @@ -10,7 +10,7 @@ "p2": 43, "p3": 33, "queued": 11, - "pending": 43, + "pending": 46, "resolved": 359 }, "queue": [ @@ -901,6 +901,12 @@ "summary": "#G4M3DV: Resolved 2026-08-21: verify:pr-local detects an active Clinical KB dev server before its build and prints the stop/clear/rerun remedy while preserving fail-closed build behavior.", "created_at": "2026-08-21" }, + { + "request_id": "414e60a0-f441-4cbb-9996-9dce4f22583e", + "action": "cancel", + "summary": "Cancel request 296db779-44cb-4817-9592-3ebf22aca38b: Superseded by the clinical sign-off of 2026-08-22. This request recorded PARTIAL PROGRESS and instructed that the row not be closed without explicit owner confirmation that the review was actually carried out. That confirmation has now been given and the review has happened, so the row closes; its content is carried into the closure rather than discarded. Note in particular that one of the four proposals this request recorded as WITHDRAWN -- splitting antihistamines by sedation -- was reversed on 2026-08-22 and applied, and the reversal was evidence-driven rather than a change of mind: the original withdrawal reasoned only that the term selects the antihistamine subclass so splitting it would stop the term meaning antihistamines, which never examined what the rows say. Reading them settled it: all four rows describe additive ANTICHOLINERGIC burden and one names sedating antihistamines explicitly, so the second-generation agents were producing a CRITICAL anticholinergic-toxidrome alert they cannot cause. The other three withdrawals still stand.", + "created_at": "2026-08-22" + }, { "request_id": "453dc608-a999-4789-9792-35431b805245", "action": "done", @@ -913,6 +919,12 @@ "summary": "#EP1BQS: Resolved 2026-08-21: the RAG programme handover now points implementing sessions back to the canonical ledger and requires a duplicate-implementation check when provider reads are authorised.", "created_at": "2026-08-21" }, + { + "request_id": "4aed85d0-2bed-4c39-9560-6d5ab2bada19", + "action": "done", + "summary": "#1YPV51: Resolved 2026-08-22 by the Repository Lead's sign-off, recorded in the Sign-off block of docs/medication-interaction-lexicon-review.md. All 37 catalogue terms were expanded to their resolved drug lists and reviewed alongside the text of the rows each term fires on: 34 confirmed correct as they stood, 3 narrowed. (1) ANTIHISTAMINES: all four rows describe additive ANTICHOLINERGIC burden and one names 'sedating antihistamines' in its own words, yet cetirizine, fexofenadine and loratadine resolved into the term -- benzatropine + loratadine produced a CRITICAL 'anticholinergic toxidrome ... risk of toxic megacolon' alert and oxybutynin + cetirizine 'frank delirium and bowel impaction'. The three second-generation agents are denied; cyclizine, promethazine, alimemazine and diphenhydramine are kept. (2) CORTICOSTEROIDS: every row is a systemic effect (insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia), so the four purely topical glucocorticoids are denied; inhaled agents are deliberately kept because the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids, and fludrocortisone is kept as a mineralocorticoid that raises BSL and drives hypokalaemia. (3) ORAL-CONTRACEPTIVES: the rows concern enzyme inducers destroying the COMBINED pill, and depot medroxyprogesterone is the method a woman is switched TO on an inducer; its own catalogue row already states inducers 'accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this', so the generic term was flattening a nuance the catalogue records correctly. It is removed from the term and its own row still fires, pinned by a test. Two classification questions answered: moclobemide correctly excluded from maois (the rows concern irreversible inhibition -- tyramine crisis and washout -- which a reversible inhibitor does not carry), atomoxetine correctly classed SNRI. Measured: 23 medications changed, removals only, nothing added anywhere, all 328 medications intact, resolved/unresolved unchanged at 392/133. Each change was mutation-tested: reverted, observed to fail 3/4/1 tests, restored. Also fixed: the report generator hardcoded 'Status: UNREVIEWED', so the document would have contradicted itself in its first sentence the moment the sign-off was filled in; the status line is now derived from the recorded sign-off on the same read in both the write and --check paths. HISTORY CARRIED FROM CANCELLED REQUEST 296db779 (2026-08-21, partial progress): loperamide was resolving as an opioid because the selector matches the substring 'Opioid' and the catalogue classifies it 'Peripheral Opioid Agonist'; it is deny-listed alongside naltrexone and naloxone. Four further changes were proposed and withdrawn that day -- adding moclobemide to maois, removing atomoxetine from snris, folding the Z-drugs into benzodiazepines, and splitting antihistamines by sedation. THREE OF THOSE WITHDRAWALS STILL STAND. The fourth was REVERSED on 2026-08-22 and applied: the original withdrawal reasoned only that splitting would stop the term meaning 'antihistamines', which never examined what the rows say; reading them settled it. Recorded so the reversal is visible as evidence-driven rather than a change of mind. HOW THIS REVIEW WAS DONE, stated because this row exists over an earlier closure that claimed a review that had not happened: an assistant analysis proposed a verdict per term with its evidence, and the Repository Lead read and accepted them. It is a reviewed-and-accepted sign-off, NOT an independent re-derivation from primary sources, and must not be described as one. NOT RESOLVED BY THIS, and filed as its own row: acei resolves to perindopril alone, arbs to candesartan alone, statins to atorvastatin and rosuvastatin, because ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely -- a patient on one of them produces silence rather than safety, which on screen is indistinguishable from a clear check.", + "created_at": "2026-08-22" + }, { "request_id": "4bc642e9-5fba-4b43-90e8-407fe2c11408", "action": "done", @@ -961,6 +973,12 @@ "summary": "#G4M3DV: Resolved 2026-08-21: verify:pr-local detects an active Clinical KB dev server before its build and prints the stop/clear/rerun remedy while preserving fail-closed build behavior.", "created_at": "2026-08-21" }, + { + "request_id": "6a16ed64-3b63-4977-8a2b-8c50c6b16877", + "action": "cancel", + "summary": "Cancel request a4a993d4-2326-4150-b9df-1ccf4f5433a3: Reissued as one closure carrying the history from cancelled request 296db779 -- the loperamide fix, the four proposals withdrawn on 2026-08-21, and the fact that one of those withdrawals was later reversed on better evidence. Requests are immutable, so combining them means replacing rather than editing.", + "created_at": "2026-08-22" + }, { "request_id": "725bdcac-1dd2-45dd-bb99-2901797f9ade", "action": "done", diff --git a/docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json b/docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json new file mode 100644 index 0000000000..afef993c05 --- /dev/null +++ b/docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json @@ -0,0 +1,10 @@ +{ + "version": 2, + "id": "414e60a0-f441-4cbb-9996-9dce4f22583e", + "createdOn": "2026-08-22", + "action": "cancel", + "payload": { + "requestId": "296db779-44cb-4817-9592-3ebf22aca38b", + "reason": "Superseded by the clinical sign-off of 2026-08-22. This request recorded PARTIAL PROGRESS and instructed that the row not be closed without explicit owner confirmation that the review was actually carried out. That confirmation has now been given and the review has happened, so the row closes; its content is carried into the closure rather than discarded. Note in particular that one of the four proposals this request recorded as WITHDRAWN -- splitting antihistamines by sedation -- was reversed on 2026-08-22 and applied, and the reversal was evidence-driven rather than a change of mind: the original withdrawal reasoned only that the term selects the antihistamine subclass so splitting it would stop the term meaning antihistamines, which never examined what the rows say. Reading them settled it: all four rows describe additive ANTICHOLINERGIC burden and one names sedating antihistamines explicitly, so the second-generation agents were producing a CRITICAL anticholinergic-toxidrome alert they cannot cause. The other three withdrawals still stand." + } +} diff --git a/docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json b/docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json new file mode 100644 index 0000000000..1b9763d440 --- /dev/null +++ b/docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "id": "4aed85d0-2bed-4c39-9560-6d5ab2bada19", + "createdOn": "2026-08-22", + "action": "done", + "payload": { + "id": "#1YPV51", + "outcome": "Resolved 2026-08-22 by the Repository Lead's sign-off, recorded in the Sign-off block of docs/medication-interaction-lexicon-review.md. All 37 catalogue terms were expanded to their resolved drug lists and reviewed alongside the text of the rows each term fires on: 34 confirmed correct as they stood, 3 narrowed. (1) ANTIHISTAMINES: all four rows describe additive ANTICHOLINERGIC burden and one names 'sedating antihistamines' in its own words, yet cetirizine, fexofenadine and loratadine resolved into the term -- benzatropine + loratadine produced a CRITICAL 'anticholinergic toxidrome ... risk of toxic megacolon' alert and oxybutynin + cetirizine 'frank delirium and bowel impaction'. The three second-generation agents are denied; cyclizine, promethazine, alimemazine and diphenhydramine are kept. (2) CORTICOSTEROIDS: every row is a systemic effect (insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia), so the four purely topical glucocorticoids are denied; inhaled agents are deliberately kept because the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids, and fludrocortisone is kept as a mineralocorticoid that raises BSL and drives hypokalaemia. (3) ORAL-CONTRACEPTIVES: the rows concern enzyme inducers destroying the COMBINED pill, and depot medroxyprogesterone is the method a woman is switched TO on an inducer; its own catalogue row already states inducers 'accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this', so the generic term was flattening a nuance the catalogue records correctly. It is removed from the term and its own row still fires, pinned by a test. Two classification questions answered: moclobemide correctly excluded from maois (the rows concern irreversible inhibition -- tyramine crisis and washout -- which a reversible inhibitor does not carry), atomoxetine correctly classed SNRI. Measured: 23 medications changed, removals only, nothing added anywhere, all 328 medications intact, resolved/unresolved unchanged at 392/133. Each change was mutation-tested: reverted, observed to fail 3/4/1 tests, restored. Also fixed: the report generator hardcoded 'Status: UNREVIEWED', so the document would have contradicted itself in its first sentence the moment the sign-off was filled in; the status line is now derived from the recorded sign-off on the same read in both the write and --check paths. HISTORY CARRIED FROM CANCELLED REQUEST 296db779 (2026-08-21, partial progress): loperamide was resolving as an opioid because the selector matches the substring 'Opioid' and the catalogue classifies it 'Peripheral Opioid Agonist'; it is deny-listed alongside naltrexone and naloxone. Four further changes were proposed and withdrawn that day -- adding moclobemide to maois, removing atomoxetine from snris, folding the Z-drugs into benzodiazepines, and splitting antihistamines by sedation. THREE OF THOSE WITHDRAWALS STILL STAND. The fourth was REVERSED on 2026-08-22 and applied: the original withdrawal reasoned only that splitting would stop the term meaning 'antihistamines', which never examined what the rows say; reading them settled it. Recorded so the reversal is visible as evidence-driven rather than a change of mind. HOW THIS REVIEW WAS DONE, stated because this row exists over an earlier closure that claimed a review that had not happened: an assistant analysis proposed a verdict per term with its evidence, and the Repository Lead read and accepted them. It is a reviewed-and-accepted sign-off, NOT an independent re-derivation from primary sources, and must not be described as one. NOT RESOLVED BY THIS, and filed as its own row: acei resolves to perindopril alone, arbs to candesartan alone, statins to atorvastatin and rosuvastatin, because ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely -- a patient on one of them produces silence rather than safety, which on screen is indistinguishable from a clear check.", + "baseRowFingerprint": "474e5feba5b3f5d8fc1cd5230994a22d6d9c642c22498922e2b286f6b43b75b4" + } +} diff --git a/docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json b/docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json new file mode 100644 index 0000000000..f774e4dd83 --- /dev/null +++ b/docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json @@ -0,0 +1,10 @@ +{ + "version": 2, + "id": "6a16ed64-3b63-4977-8a2b-8c50c6b16877", + "createdOn": "2026-08-22", + "action": "cancel", + "payload": { + "requestId": "a4a993d4-2326-4150-b9df-1ccf4f5433a3", + "reason": "Reissued as one closure carrying the history from cancelled request 296db779 -- the loperamide fix, the four proposals withdrawn on 2026-08-21, and the fact that one of those withdrawals was later reversed on better evidence. Requests are immutable, so combining them means replacing rather than editing." + } +} From 7703188efea5a58a1cd9c4d62fc57fb26ca1fca7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 22 Aug 2026 16:27:28 +0000 Subject: [PATCH 3/5] fix(ledger): refresh #1YPV51 inbox fingerprints after main reconciliation Remove stale cancel/duplicate inbox requests that targeted requests already applied on main (#2294). Update the done request baseRowFingerprint so docs:check-links can replay the batch offline. Co-authored-by: BigSimmo --- .../414e60a0-f441-4cbb-9996-9dce4f22583e.json | 10 ---------- .../4aed85d0-2bed-4c39-9560-6d5ab2bada19.json | 2 +- .../6a16ed64-3b63-4977-8a2b-8c50c6b16877.json | 10 ---------- .../a4a993d4-2326-4150-b9df-1ccf4f5433a3.json | 11 ----------- 4 files changed, 1 insertion(+), 32 deletions(-) delete mode 100644 docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json delete mode 100644 docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json delete mode 100644 docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json diff --git a/docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json b/docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json deleted file mode 100644 index afef993c05..0000000000 --- a/docs/outstanding-issues-inbox/414e60a0-f441-4cbb-9996-9dce4f22583e.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "version": 2, - "id": "414e60a0-f441-4cbb-9996-9dce4f22583e", - "createdOn": "2026-08-22", - "action": "cancel", - "payload": { - "requestId": "296db779-44cb-4817-9592-3ebf22aca38b", - "reason": "Superseded by the clinical sign-off of 2026-08-22. This request recorded PARTIAL PROGRESS and instructed that the row not be closed without explicit owner confirmation that the review was actually carried out. That confirmation has now been given and the review has happened, so the row closes; its content is carried into the closure rather than discarded. Note in particular that one of the four proposals this request recorded as WITHDRAWN -- splitting antihistamines by sedation -- was reversed on 2026-08-22 and applied, and the reversal was evidence-driven rather than a change of mind: the original withdrawal reasoned only that the term selects the antihistamine subclass so splitting it would stop the term meaning antihistamines, which never examined what the rows say. Reading them settled it: all four rows describe additive ANTICHOLINERGIC burden and one names sedating antihistamines explicitly, so the second-generation agents were producing a CRITICAL anticholinergic-toxidrome alert they cannot cause. The other three withdrawals still stand." - } -} diff --git a/docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json b/docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json index 1b9763d440..53cb581232 100644 --- a/docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json +++ b/docs/outstanding-issues-inbox/4aed85d0-2bed-4c39-9560-6d5ab2bada19.json @@ -6,6 +6,6 @@ "payload": { "id": "#1YPV51", "outcome": "Resolved 2026-08-22 by the Repository Lead's sign-off, recorded in the Sign-off block of docs/medication-interaction-lexicon-review.md. All 37 catalogue terms were expanded to their resolved drug lists and reviewed alongside the text of the rows each term fires on: 34 confirmed correct as they stood, 3 narrowed. (1) ANTIHISTAMINES: all four rows describe additive ANTICHOLINERGIC burden and one names 'sedating antihistamines' in its own words, yet cetirizine, fexofenadine and loratadine resolved into the term -- benzatropine + loratadine produced a CRITICAL 'anticholinergic toxidrome ... risk of toxic megacolon' alert and oxybutynin + cetirizine 'frank delirium and bowel impaction'. The three second-generation agents are denied; cyclizine, promethazine, alimemazine and diphenhydramine are kept. (2) CORTICOSTEROIDS: every row is a systemic effect (insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia), so the four purely topical glucocorticoids are denied; inhaled agents are deliberately kept because the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids, and fludrocortisone is kept as a mineralocorticoid that raises BSL and drives hypokalaemia. (3) ORAL-CONTRACEPTIVES: the rows concern enzyme inducers destroying the COMBINED pill, and depot medroxyprogesterone is the method a woman is switched TO on an inducer; its own catalogue row already states inducers 'accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this', so the generic term was flattening a nuance the catalogue records correctly. It is removed from the term and its own row still fires, pinned by a test. Two classification questions answered: moclobemide correctly excluded from maois (the rows concern irreversible inhibition -- tyramine crisis and washout -- which a reversible inhibitor does not carry), atomoxetine correctly classed SNRI. Measured: 23 medications changed, removals only, nothing added anywhere, all 328 medications intact, resolved/unresolved unchanged at 392/133. Each change was mutation-tested: reverted, observed to fail 3/4/1 tests, restored. Also fixed: the report generator hardcoded 'Status: UNREVIEWED', so the document would have contradicted itself in its first sentence the moment the sign-off was filled in; the status line is now derived from the recorded sign-off on the same read in both the write and --check paths. HISTORY CARRIED FROM CANCELLED REQUEST 296db779 (2026-08-21, partial progress): loperamide was resolving as an opioid because the selector matches the substring 'Opioid' and the catalogue classifies it 'Peripheral Opioid Agonist'; it is deny-listed alongside naltrexone and naloxone. Four further changes were proposed and withdrawn that day -- adding moclobemide to maois, removing atomoxetine from snris, folding the Z-drugs into benzodiazepines, and splitting antihistamines by sedation. THREE OF THOSE WITHDRAWALS STILL STAND. The fourth was REVERSED on 2026-08-22 and applied: the original withdrawal reasoned only that splitting would stop the term meaning 'antihistamines', which never examined what the rows say; reading them settled it. Recorded so the reversal is visible as evidence-driven rather than a change of mind. HOW THIS REVIEW WAS DONE, stated because this row exists over an earlier closure that claimed a review that had not happened: an assistant analysis proposed a verdict per term with its evidence, and the Repository Lead read and accepted them. It is a reviewed-and-accepted sign-off, NOT an independent re-derivation from primary sources, and must not be described as one. NOT RESOLVED BY THIS, and filed as its own row: acei resolves to perindopril alone, arbs to candesartan alone, statins to atorvastatin and rosuvastatin, because ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely -- a patient on one of them produces silence rather than safety, which on screen is indistinguishable from a clear check.", - "baseRowFingerprint": "474e5feba5b3f5d8fc1cd5230994a22d6d9c642c22498922e2b286f6b43b75b4" + "baseRowFingerprint": "4392b4bd458745dcb4fc01dec4cd1e0bce616d3c3180f93d2521d3cd45390239" } } diff --git a/docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json b/docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json deleted file mode 100644 index f774e4dd83..0000000000 --- a/docs/outstanding-issues-inbox/6a16ed64-3b63-4977-8a2b-8c50c6b16877.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "version": 2, - "id": "6a16ed64-3b63-4977-8a2b-8c50c6b16877", - "createdOn": "2026-08-22", - "action": "cancel", - "payload": { - "requestId": "a4a993d4-2326-4150-b9df-1ccf4f5433a3", - "reason": "Reissued as one closure carrying the history from cancelled request 296db779 -- the loperamide fix, the four proposals withdrawn on 2026-08-21, and the fact that one of those withdrawals was later reversed on better evidence. Requests are immutable, so combining them means replacing rather than editing." - } -} diff --git a/docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json b/docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json deleted file mode 100644 index 8728890bd3..0000000000 --- a/docs/outstanding-issues-inbox/a4a993d4-2326-4150-b9df-1ccf4f5433a3.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": 2, - "id": "a4a993d4-2326-4150-b9df-1ccf4f5433a3", - "createdOn": "2026-08-22", - "action": "done", - "payload": { - "id": "#1YPV51", - "outcome": "Resolved 2026-08-22 by the Repository Lead's sign-off, recorded in docs/medication-interaction-lexicon-review.md. All 37 catalogue terms were expanded to their resolved drug lists and reviewed alongside the text of the rows each fires on. 34 were confirmed correct; 3 were narrowed. (1) antihistamines: every row is about additive ANTICHOLINERGIC burden -- one says 'sedating antihistamines' in its own words -- yet cetirizine, fexofenadine and loratadine resolved into it, so benzatropine + loratadine produced a CRITICAL 'anticholinergic toxidrome ... toxic megacolon' alert and oxybutynin + cetirizine 'frank delirium and bowel impaction'; the three second-generation agents are now denied. (2) corticosteroids: every row is a systemic effect (insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia), so the four purely topical glucocorticoids are denied; inhaled agents are deliberately kept because the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids. (3) oral-contraceptives: the rows are about enzyme inducers destroying the COMBINED pill, and depot medroxyprogesterone is the method a woman is switched TO on an inducer -- its own catalogue row already states inducers 'accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this', so the generic term was flattening a nuance the catalogue records correctly; it is removed from the term and its own row still fires. Two classification questions answered: moclobemide correctly excluded from maois (reversible inhibition does not carry the tyramine/washout risks the rows describe), atomoxetine correctly classed SNRI. Measured: 23 medications changed, removals only, nothing added, all 328 medications intact, resolved/unresolved unchanged at 392/133; each change mutation-tested. HOW IT WAS DONE, stated because this row exists over an earlier closure that claimed a review that had not happened: an assistant analysis proposed a verdict per term with its evidence, and the Repository Lead read and accepted them. It is a reviewed-and-accepted sign-off, NOT an independent re-derivation from primary sources, and must not be described as one. NOT resolved by this: acei resolves to perindopril alone, arbs to candesartan alone, statins to atorvastatin and rosuvastatin -- ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely, so a patient on one produces silence rather than safety. That is a catalogue coverage gap, recorded in the sign-off, and is not fixable in the lexicon.", - "baseRowFingerprint": "474e5feba5b3f5d8fc1cd5230994a22d6d9c642c22498922e2b286f6b43b75b4" - } -} From 55f3a47fa4f46f118270fa12284636a2ac77f5af Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 22 Aug 2026 16:31:03 +0000 Subject: [PATCH 4/5] chore(snapshot): regenerate outstanding-issues snapshot after inbox cleanup Co-authored-by: BigSimmo --- data/outstanding-issues-snapshot.json | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/data/outstanding-issues-snapshot.json b/data/outstanding-issues-snapshot.json index 07d89383ec..28070d4278 100644 --- a/data/outstanding-issues-snapshot.json +++ b/data/outstanding-issues-snapshot.json @@ -1,8 +1,8 @@ { "version": "outstanding-issues-snapshot-v1", "ledger_revision": { - "sha": "2327bd9624d788a7b9ecb61eee494f1acd9a1997", - "committed_at": "2026-08-22T06:11:46+00:00" + "sha": "9a382a0504632186bab075b53633cb69a6f92446", + "committed_at": "2026-08-22T15:25:05+00:00" }, "counts": { "open": 66, @@ -10,7 +10,7 @@ "p2": 36, "p3": 29, "queued": 10, - "pending": 5, + "pending": 2, "resolved": 375 }, "queue": [ @@ -722,12 +722,6 @@ } ], "pending": [ - { - "request_id": "414e60a0-f441-4cbb-9996-9dce4f22583e", - "action": "cancel", - "summary": "Cancel request 296db779-44cb-4817-9592-3ebf22aca38b: Superseded by the clinical sign-off of 2026-08-22. This request recorded PARTIAL PROGRESS and instructed that the row not be closed without explicit owner confirmation that the review was actually carried out. That confirmation has now been given and the review has happened, so the row closes; its content is carried into the closure rather than discarded. Note in particular that one of the four proposals this request recorded as WITHDRAWN -- splitting antihistamines by sedation -- was reversed on 2026-08-22 and applied, and the reversal was evidence-driven rather than a change of mind: the original withdrawal reasoned only that the term selects the antihistamine subclass so splitting it would stop the term meaning antihistamines, which never examined what the rows say. Reading them settled it: all four rows describe additive ANTICHOLINERGIC burden and one names sedating antihistamines explicitly, so the second-generation agents were producing a CRITICAL anticholinergic-toxidrome alert they cannot cause. The other three withdrawals still stand.", - "created_at": "2026-08-22" - }, { "request_id": "4aed85d0-2bed-4c39-9560-6d5ab2bada19", "action": "done", @@ -739,18 +733,6 @@ "action": "add", "summary": "Common cardiovascular drugs are absent from the medication catalogue, so patients taking them get silence rather than an interaction check", "created_at": "2026-08-22" - }, - { - "request_id": "6a16ed64-3b63-4977-8a2b-8c50c6b16877", - "action": "cancel", - "summary": "Cancel request a4a993d4-2326-4150-b9df-1ccf4f5433a3: Reissued as one closure carrying the history from cancelled request 296db779 -- the loperamide fix, the four proposals withdrawn on 2026-08-21, and the fact that one of those withdrawals was later reversed on better evidence. Requests are immutable, so combining them means replacing rather than editing.", - "created_at": "2026-08-22" - }, - { - "request_id": "a4a993d4-2326-4150-b9df-1ccf4f5433a3", - "action": "done", - "summary": "#1YPV51: Resolved 2026-08-22 by the Repository Lead's sign-off, recorded in docs/medication-interaction-lexicon-review.md. All 37 catalogue terms were expanded to their resolved drug lists and reviewed alongside the text of the rows each fires on. 34 were confirmed correct; 3 were narrowed. (1) antihistamines: every row is about additive ANTICHOLINERGIC burden -- one says 'sedating antihistamines' in its own words -- yet cetirizine, fexofenadine and loratadine resolved into it, so benzatropine + loratadine produced a CRITICAL 'anticholinergic toxidrome ... toxic megacolon' alert and oxybutynin + cetirizine 'frank delirium and bowel impaction'; the three second-generation agents are now denied. (2) corticosteroids: every row is a systemic effect (insulin resistance x5, tendon rupture with ciprofloxacin, additive hypokalaemia), so the four purely topical glucocorticoids are denied; inhaled agents are deliberately kept because the hypokalaemia row concerns a formoterol inhaler and names high-dose corticosteroids. (3) oral-contraceptives: the rows are about enzyme inducers destroying the COMBINED pill, and depot medroxyprogesterone is the method a woman is switched TO on an inducer -- its own catalogue row already states inducers 'accelerate the clearance of the oral tablets, but the massive 150mg IM depot is generally resistant to clinically failing from this', so the generic term was flattening a nuance the catalogue records correctly; it is removed from the term and its own row still fires. Two classification questions answered: moclobemide correctly excluded from maois (reversible inhibition does not carry the tyramine/washout risks the rows describe), atomoxetine correctly classed SNRI. Measured: 23 medications changed, removals only, nothing added, all 328 medications intact, resolved/unresolved unchanged at 392/133; each change mutation-tested. HOW IT WAS DONE, stated because this row exists over an earlier closure that claimed a review that had not happened: an assistant analysis proposed a verdict per term with its evidence, and the Repository Lead read and accepted them. It is a reviewed-and-accepted sign-off, NOT an independent re-derivation from primary sources, and must not be described as one. NOT resolved by this: acei resolves to perindopril alone, arbs to candesartan alone, statins to atorvastatin and rosuvastatin -- ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely, so a patient on one produces silence rather than safety. That is a catalogue coverage gap, recorded in the sign-off, and is not fixable in the lexicon.", - "created_at": "2026-08-22" } ] } From 84d338b7b68d938b71b046e32ac743e2ed24772f Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sun, 23 Aug 2026 00:49:55 +0800 Subject: [PATCH 5/5] fix(medications): name the six drugs this review made unreachable, and stop the signed report telling readers it is unreviewed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two findings from review, both real. The sign-off said the catalogue-coverage caveat applied to 20 medications; the generated table above it says 26. The count rose *because of this review*, and a bare number understated it — so the six are now named: betamethasone, clobetasol, hydrocortisone 1%, triamcinolone, cetirizine and loratadine reach no resolved interaction row at all. That is the intended result, since the alerts they used to fire were the false ones removed here, but it has to be said out loud: on screen "no applicable interaction" and "this drug reaches no row" look identical, and a clinician checking clobetasol against insulin is now told nothing where before they were told something wrong. The trailing paragraph of the sign-off block still read "Until this is filled in, treat every interaction alert as unvalidated" — directly beneath a completed sign-off. Reworded to state what the sign-off covers and its date boundary. Note on the second finding's diagnosis: it proposed suppressing the disclaimer in the generator when a sign-off exists. The generator is already correct — it emits that sentence *after* the `## Sign-off` heading, so `beforeSignOff(rendered)` never carries it into a signed report. It survived only because the hand-written sign-off block copied it verbatim, which is where it is fixed. Co-Authored-By: Claude Opus 5 --- data/outstanding-issues-snapshot.json | 10 ++++++++-- docs/medication-interaction-lexicon-review.md | 17 +++++++++++++---- .../aca88c5d-9fd4-4e6b-8e0b-e4d789e1d46c.json | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 docs/outstanding-issues-inbox/aca88c5d-9fd4-4e6b-8e0b-e4d789e1d46c.json diff --git a/data/outstanding-issues-snapshot.json b/data/outstanding-issues-snapshot.json index 28070d4278..814374a3c2 100644 --- a/data/outstanding-issues-snapshot.json +++ b/data/outstanding-issues-snapshot.json @@ -2,7 +2,7 @@ "version": "outstanding-issues-snapshot-v1", "ledger_revision": { "sha": "9a382a0504632186bab075b53633cb69a6f92446", - "committed_at": "2026-08-22T15:25:05+00:00" + "committed_at": "2026-08-22T15:25:05Z" }, "counts": { "open": 66, @@ -10,7 +10,7 @@ "p2": 36, "p3": 29, "queued": 10, - "pending": 2, + "pending": 3, "resolved": 375 }, "queue": [ @@ -733,6 +733,12 @@ "action": "add", "summary": "Common cardiovascular drugs are absent from the medication catalogue, so patients taking them get silence rather than an interaction check", "created_at": "2026-08-22" + }, + { + "request_id": "aca88c5d-9fd4-4e6b-8e0b-e4d789e1d46c", + "action": "add", + "summary": "The pre-push ledger guard uses the previous branch tip as its baseline, so it false-positives after a branch merges main", + "created_at": "2026-08-22" } ] } diff --git a/docs/medication-interaction-lexicon-review.md b/docs/medication-interaction-lexicon-review.md index a1adfb109d..4b55a200f9 100644 --- a/docs/medication-interaction-lexicon-review.md +++ b/docs/medication-interaction-lexicon-review.md @@ -199,7 +199,15 @@ medications intact, and resolved/unresolved row counts unchanged at 392 / 133. rosuvastatin. Ramipril, lisinopril, irbesartan and simvastatin are absent from the catalogue entirely, so a patient taking one of them produces **silence, not safety**. That is a catalogue coverage gap rather than a mapping fault, and it is not fixable in this file. The same caveat applies -to the 20 medications listed under "What this tool can never warn about" above. +to the 26 medications listed under "What this tool can never warn about" above. + +**That count rose from 20 to 26 because of this review, and the six are named here rather than left +in a total.** Betamethasone, clobetasol, hydrocortisone 1%, triamcinolone, cetirizine and loratadine +now sit outside every resolved interaction row, so entering one of them produces no alert at all. +That is the intended result — the alerts they used to fire were the false ones this review removed — +but the consequence must be stated plainly, because on screen "no applicable interaction was found" +and "this drug reaches no interaction row" look identical. A clinician checking clobetasol against a +patient's insulin is now told nothing, where before they were told something wrong. ### How this review was conducted @@ -218,6 +226,7 @@ interaction wording, which is verbatim from the source catalogue, nor of the `ex `mechanism` terms, which resolve to no catalogue drug and therefore raise no alert. Any later change to the lexicon falls outside it and must be re-checked. -Until this is filled in, treat every interaction alert as unvalidated mapping over source-backed text. -The wording shown to the clinician is always verbatim from the catalogue; what is unreviewed is _which -drugs a phrase was taken to mean_. +The mappings above were reviewed on the date recorded in this block. The wording shown to the +clinician is always verbatim from the catalogue; what this sign-off covers is _which drugs a phrase +was taken to mean_, as of that date and no later. Treat any term changed since as unvalidated until +this block is updated. diff --git a/docs/outstanding-issues-inbox/aca88c5d-9fd4-4e6b-8e0b-e4d789e1d46c.json b/docs/outstanding-issues-inbox/aca88c5d-9fd4-4e6b-8e0b-e4d789e1d46c.json new file mode 100644 index 0000000000..3b2912b463 --- /dev/null +++ b/docs/outstanding-issues-inbox/aca88c5d-9fd4-4e6b-8e0b-e4d789e1d46c.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "id": "aca88c5d-9fd4-4e6b-8e0b-e4d789e1d46c", + "createdOn": "2026-08-22", + "action": "add", + "payload": { + "pri": "P2", + "type": "issue", + "summary": "The pre-push ledger guard uses the previous branch tip as its baseline, so it false-positives after a branch merges main", + "detail": "OBSERVED 2026-08-22/23 on branch claude/lexicon-clinical-signoff (PR #2298). SYMPTOM: git push refused by scripts/guard-push.mjs with 'docs/outstanding-issues-inbox/applied/.json was introduced without moving the identical pending request from the base' and 'reconciliation moved only part of the base inbox', for applied records the branch never touched. CAUSE: the pre-push guard diffs against the PREVIOUSLY PUSHED BRANCH TIP; scripts/check-ledger-write-discipline.mjs diffs against the base branch. When a reconcile lands on main and the branch merges main, main's applied/ records enter the diff relative to the old branch tip and look like a partial reconciliation done on the branch. EVIDENCE, all three checked: the named applied records exist on origin/main; git diff origin/main...HEAD -- docs/outstanding-issues.md was EMPTY, so the branch's canonical ledger was byte-identical to main's; and git log --diff-filter=A named commit 9a382a050 'chore(ledger): reconcile 43 queued inbox requests (#2294)' as their origin. Running the gate with the correct base -- node scripts/check-ledger-write-discipline.mjs --base origin/main --head -- PASSED on the same trees throughout. SECOND SYMPTOM FROM THE SAME CAUSE: the guard also refuses the deletion of a branch-local inbox request that has been pushed but never merged. Editing or deleting such a request is LEGITIMATE -- immutability binds requests present in the base, and the gate confirms this by passing -- but the guard sees it as mutating a published record. This wasted a cycle: the deletion was reverted as if it had been a mistake, then a Cursor autofix agent performed the identical deletion on the same branch and the gate passed. CONSEQUENCE: SKIP_LEDGER_WRITE_GUARD=1 becomes routine on ordinary branches, which is how a guard stops being read -- and this guard exists to make an accidental ledger rewrite impossible. NEXT: give the pre-push guard the same baseline the gate uses (merge base with the upstream default branch), and add a regression test for the exact shape: branch, reconcile on main, merge main into branch, assert the guard passes; plus a second for deleting a pushed-but-unmerged branch-local request. STOP: do not relax what the guard checks -- the baseline is wrong, not the rule.", + "source": "PR #2298 push attempts 2026-08-22/23; scripts/guard-push.mjs; scripts/check-ledger-write-discipline.mjs; commits 9a382a050 (#2294) and 7703188ef", + "issueUlid": "01M0N5DZ42RSD9EJEATKSXEHQX" + } +}