Imported from crosdat/crosdat-pikin (
packages/core/src/dose/AGENTS.md). Install upstream withnpx skills add crosdat/crosdat-pikin --skill dose. Copyright stays with the author.
Drug dose calculator engine
Two engines live here, both pure-TypeScript, both deterministic, both versioned. Neither reaches for the database or the network.
Discrete-dose engine (bolus, oral, per-dose)
engine.ts-dose(input)dispatches to the rule underrules/<ruleKey>.ts; returns aDoseSuggestionwith the calculated value, range, regimen, and advisory notices.bands.ts- gestational-age × post-natal-age band resolver.pna.ts- post-natal age helper.tall-man.ts- ISMP look-alike rendering.units.ts- mg / mcg / g conversion.version.ts-CALCULATOR_VERSIONstamped on everyPlanItemsuggestion snapshot.rules/<drug>.ts- one file per drug.
Continuous-infusion engine
infusion.ts-calculateInfusionRecipe(input)returns the pump rate, delivered readback, and any advisory warnings.infusion-rules.ts- seed rules for the top NICU infusion drugs (dopamine, dobutamine, adrenaline, noradrenaline, PGE1, insulin, morphine, midazolam, fentanyl, milrinone, vasopressin, heparin, aminophylline). Each declarestargetUnit,defaultTarget, advisory band, compatible diluents, and a safety note.INFUSION_CALCULATOR_VERSION- stamp bumped on any output change.ruleOfSixMg(weightKg)- convenience preset for the classic NICU weight-scaled concentration recipe.
Design constraints (shared by both engines)
- Pure and deterministic. No
Date.now, noMath.random, no I/O. Same input todoseorcalculateInfusionRecipeyields the same output forever. - The clinician is in charge. Warnings never block persistence.
The backend service optionally treats HARD_STOP warnings as gates
on specific transitions (see e.g. TPN sign-off in
apps/backend/src/tpn/tpn.service.ts), but the record-only path forPlanItemstays open. - Never throws on plausible input. Missing weight, zero bag volume, unit mismatch - all surface as HARD_STOP warnings on the result envelope rather than exceptions.
- Versioned. Every result stamps a version string so QI can partition drift analyses by rule set.
Adding a rule
Discrete: create rules/<key>.ts exporting the rule function, add
the key to the drug catalog seed, wire into engine.ts dispatch,
add a golden vector under __golden__/<key>.json, add a test block
in apps/backend/src/common/dose-engine.spec.ts, bump
CALCULATOR_VERSION.
Infusion: add a new entry to INFUSION_RULES in infusion-rules.ts,
add a test block in
apps/backend/src/common/infusion-calculator.spec.ts, bump
INFUSION_CALCULATOR_VERSION.
Version bumps
Both CALCULATOR_VERSION and INFUSION_CALCULATOR_VERSION use
ISO-date suffixes (doseCalc/2026-06-14, infusion/2026-09-05).
Bump whenever any rule's output changes; mechanical refactors that
leave output identical do not require a bump. Same-day re-bump uses
-N suffix.
Analytics
Discrete-dose events fire from the DrugPrescriberPanel under
category Drug and DrugDose. Infusion + TPN events have their own
categories (Tpn); see packages/core/docs/analytics-events-new.md
for the full catalog.