medirulekit

the problem · Eroom's law

Moore's law, spelled backwards. Since the 1950s, the number of new medicines a billion research dollars buys has halved roughly every nine years — a hundredfold fall, over the same decades in which everything else in technology got cheaper.

Scannell et al., Nature Reviews Drug Discovery, 2012
where the money goes

The most expensive part is the clinical trial — the slow, human years where an idea meets real patients. And every trial is governed by a single document: the protocol, hundreds of pages of prose deciding who may enter, what gets measured, and what counts as an answer.

the page that decides

Buried in that stack are the entry rules. Get them wrong and the trial screens the wrong people, amendments follow at half a million dollars each, and the mistake surfaces only after the money is spent.

keep scrolling — this is where the story starts

scroll

medirulekit

A trial's entry rules live in a PDF. You cannot run a PDF, so the mistakes turn up after the money is spent. rulekit rewrites the rules as code you can test.

The plain-language tour. No code needed, about six minutes, and it builds as it goes, so read it in order. There is an engineers' edition of the same story; the last section links to it.

PROTOCOL v3.0 · SECTION 5.2 the entry rules, as law SAME RULES, RUNNABLE age 18 or older: pass kidney score 30 or more: fail no clashing medicine: don't know three answers, on purpose
The whole thing in one picture. A paragraph nobody can run becomes a set of checks a machine can run, and the machine is allowed to say "I don't know" instead of guessing.
scroll, about six minutes, best in order

01the clinical side

The rules read like law. Law does not run.

A clinical trial tests a new medicine on volunteers. Its eligibility criteriathe rules for who may join decide who gets the experimental drug and who is turned away for their own safety.

Those criteria are written in statute language: "participants are required to have", "must be excluded if". It sounds exact the way a law sounds exact, and it works the way a law works, through whoever happens to be applying it. The protocolthe trial's rulebook document is the statute book. There is no court attached. Every screener at every hospital rules on it alone, and a wrong ruling can hurt somebody.

So five teams copy the law into whatever tool they use, and each copy is a reading, not the law. Below is one rule about eGFRa standard kidney score: the trial wants a score of 30 or better. Watch what happens to that number.

the protocol · the statute itself "…participants are required to have an eGFR of at least 30 at the time of screening…"
screening spreadsheet kidney_min  30  ✓
nurse's paper checklist ☐ kidney score over 30
database query WHERE egfr > 30
site training slides "kidney function above 30-ish is fine"
draft of the next version requirement raised to at least 40
The documents here are made up. The failure is not. "At least 30" quietly becomes "over 30", so a patient who scores exactly 30 is admitted by the statute and thrown out by the database query. Five readings of one law now exist, none of them binding, and nobody can say which one is current.

Sooner or later the drift, or a flaw in the rules themselves, forces an amendmenta formal mid-trial rule change. The word is borrowed from law for a reason: this is changing the statute mid-trial. It looks like a page turning. It is re-printing, re-training, regulator re-approval, and sometimes re-consenting every volunteer at every hospital in the trial.

protocol v3.1 · after the amendment
includeeGFR at least 30
includeage 18 or older
excludepregnancy
excludeeGFR below 45 at screeningadded
The amendment, performed. Version 3.1 is the same page with one new exclusion row on it. Hold on to that row; it comes back in chapter 02. Researchers at Tufts University priced out what one page turn costs.
$0K

median direct cost of one substantial amendment in Phase IIthe mid-stage test

Tufts CSDD

$0K

median direct cost in Phase IIIthe large late-stage test

Tufts CSDD

~0%

of substantial amendments judged avoidable

Tufts CSDD

Source: Tufts Center for the Study of Drug Development, on the cost of protocol amendments.

Half a million dollars is a house, spent on changing a paragraph. Nearly half of those changes were avoidable, so the industry keeps buying houses it never needed. If you can test the rules, you find the flaw while it is still cheap to fix.

chapter 02 · the engine

the statute stops here. what follows is a file you can run.

02the engine

Write the rule once, in a form a machine can run

rulekit keeps each entry rule as a few lines of structured text. The protocol's original sentence sits right next to the logic, in the same file, so anyone can hold one up against the other. The next scene performs the translation on the statute's own words, one word at a time.

the engine · the whole trick, once

Watch one sentence compile

the difference between a statute and working code, in four moves

the protocol · section 5.2

“…participants are required to have an eGFR of at least 30 at the time of screening…”

1- id: egfr-min
2 kind: inclusion
3 verbatim: "eGFR at least 30 mL/min/1.73m²"
4 when: { fact: egfr, op: gte, value: 30 }
step 1 · one line of statuteThe sentence as the protocol states it. Precise-sounding words, nothing attached that could run them. Scroll.
step 2 · three words carry the lawA measurement, a direction, a threshold. The rest of the sentence is grammar. The engine only needs those three.
step 3 · the words take their posts"eGFR" becomes the fact to look up. "at least" becomes gte, greater than or equal. "30" stays 30. Each word lands in a slot a machine can read, and the pale ghosts above mark where they came from.
step 4 · the sentence never leavesThe original wording rides along in the verbatim line, one line above the logic, permanently attached. The statute and its working translation live in the same file, so any reader can hold one against the other.
line 3 · the original wordsverbatim is the protocol's exact sentence, copied in and never touched again. Ask whether the logic matches the rulebook and the rulebook's own words are right there, one line up.
line 4 · the runnable meaningwhen is that same sentence turned into logic: egfr must be gte (greater than or equal to) 30. A machine can run this line. A person can still read it.
who writes itA person writes this file and a person reviews it. No AI translates the protocol on its own. When a rule will not fit the language, it stays as plain text and gets labelled that way, rather than quietly disappearing.

One file holds every rule, and every edit to it is tracked the way code changes are tracked. That alone kills the five drifting readings: there is one binding text again, and this one runs. The three ideas that follow are what you get once the law is a file.

the engine · idea one

Three answers, not two

yes, no, and "I don't know", and the third one is the whole point

one synthetic patient · what the chart contains age: 63  ·  heart pump strength: 38  ·  kidney score: missing
step 1 · a normal chartReal patient charts are full of holes. This one has an age and a heart measurement but no kidney score, and the trial has a kidney-safety rule with nothing to check it against. Scroll.
most screening softwareA yes-or-no program has nowhere to put "we don't know". The missing kidney score gets read as "no problem", and the patient sails past a safety rule that nobody ever checked. Nobody notices either, because a rule that was skipped looks exactly like a rule that passed.
rulekitThe missing score comes back as don't know, a real answer rather than an error. That don't-know carries up through every rule built on it, so the patient's overall result reads "undetermined" and the chart lands in the pile that means a human has to read this one.
counted as a yes?
don't know refused
the rule that never bendsThe system never turns a don't-know into a yes. There is no code path that does it. A patient counts as eligible only when every rule actually passes on confirmed facts, and one confirmed "no" settles the case on its own.

02the engine · idea two

It finds contradictions before anyone enrolls

Once the rules are logic, a checker can lay them out on a number line and prove when two of them collide. Here is the collision planted in the project's teaching example, drawn slowly.

rule 1 to get in

"eGFR at least 30" … kidney score must be 30 or more to join.

rule 2 to be kept out · the row the page turn added, by a different author

"eGFR below 45 at screening" … anyone under 45 is turned away.

[30, 45) 0 30 45 60 90 kidney score rule 1 lets in: 30 and up rule 2 turns away: under 45
two clauses, pages apartEach rule makes sense on its own. One admits decent kidney function, the other protects people with fragile kidneys. Different authors, different sections of the same statute, and no court ever read the two side by side. Scroll.
rule 1, drawn"At least 30" becomes a bar on the number line: everything from 30 upward. Only patients inside the bar can join.
rule 2, drawn"Below 45" becomes a second bar: everything under 45 gets turned away. Now look at where the two bars sit on top of each other.
the collisionOne rule needs a kidney score of at least 30. The other rejects anything under 45. So everyone between 30 and 45 is admitted by one clause and barred by the other. The checker proves that for every possible patient, then fails the build the way a broken test fails software, before a single volunteer is screened. The honest limit: when the checker cannot prove a clash, it says nothing rather than guessing. Keep scrolling to walk the same ground.

the same collision, walked

the floor is the statute. seven patients cross it. where the two clauses disagree there is no floor, and one patient, scoring exactly 30, is left hanging from the edge.

02the engine · idea three

Every number comes from one calculation

A patient's verdict is computed exactly once. The printed report and the visual app both read that one result, so two screens can never show different counts.

one patient confirmed facts only synthetic, like all of them one calculation the engine · same input, same answer, always verdict printed report 7 screen fail of 10 visual app 7 screen fail of 10
The dot next to a patient's name and the totals on every screen come from that one verdict. There is no second copy of the math to drift. It sounds obvious. The build story near the end shows what it looked like back when it was not true.

chapter 03 · the AI part

a machine starts reading the notes. it still does not decide.

03the AI part

The AI reads. It never decides.

The hard part of screening is that the facts are buried in doctors' notes, written for other doctors. rulekit lets an AI read a note and suggest facts. Every suggestion has to carry the exact quote it came from, and a person approves it or throws it out.

The scene below runs on a note somebody wrote by hand for this page. The suggested fact is an NYHA classa heart-failure severity grade, and the number beside it is a confidencethe AI's own certainty guess, which only decides what gets reviewed first.

How one fact gets from a note into the engine

every document, patient and clinician here is synthetic

LAKESHORE GENERAL (FICTIONAL) · HEART ULTRASOUND REPORT
patient SYN-042 · study date 2026-03-12 · synthetic: true

CLINICAL CORRELATION
She reports marked limitation of physical activity, comfortable at rest, with breathlessness on climbing a single flight of stairs; symptoms consistent with NYHA class III heart failure. She was hospitalized for decompensated heart failure in November 2025.

nyha_class = III suggestedapproved 0.94 suggested by the AI
quote: "symptoms consistent with NYHA class III heart failure" · found word-for-word in the note above
Approve Edit value Reject a person clicks this, with the quote in front of them
quote check
kidney score = 280.88
quote: "renal function is severely impaired"
rejected
that sentence appears nowhere in the note
step 1 · the raw materialThis is what screening data actually looks like: a paragraph one clinician wrote for another. The fact the trial needs, the severity grade, is sitting in the middle of a sentence. Scroll, and watch the AI dig it out.
a suggestion, with its receiptThe AI proposes a fact and highlights the exact sentence it read it from. The quote is the receipt. A reviewer can check the suggestion against the note in a few seconds, without having to trust the AI at all.
approved, and only now visibleThe click writes the reviewer's name and a timestamp next to the fact. Until that click, the engine cannot see the suggestion at all. The AI has no wire to the decision.
and when the AI makes something upIf the quote is not in the source document word for word, the software throws the suggestion out before any person lays eyes on it. A fact that cannot show its receipt does not exist here. That setup, where the clinician can see the evidence and check it themselves, is what the FDA looks for in a tool that assists rather than decides.

chapter 04 · what exists

ten synthetic charts arriving. seven fail a rule, three need a human, none get in. the funnel below counts the same ten.

04what exists

It runs today

Not a slide deck. It is a public code repository that runs on a laptop: no account, no cloud, nothing leaves the machine.

0

automated tests, all passing, re-run on every change (green CIchecks that run on every change)

2

trial rule packs. One was built from the published entry criteria of COMMANDER HF, a real heart-failure trial (registry id NCT01877915): 12 criteria, 8 of them turned into runnable rules, the other 4 left as plain text because the language cannot say what they mean.

0

invented patients: 100 generated and 10 hand-written edge cases. Every person in this project is synthetic.

1 + 1

a working screening report (who fails, on which rule, and which single rule change would admit the most people) and an interactive workbenchthe visual app with five screens, including the live funnel below

What a trial coordinator would see

DEMO-HF-001 10 synthetic patients
Funnel Thresholds Amendment Checks Review
Screening funnelwho gets removed, rule by rule
age 18 or older
"Age 18 years or older"
removes 1
kidney safety
"eGFR below 45 at screening"
removes 4
severity grade
kept as text · needs chart review
3 pending
7 screen fail 3 need a human 0 potentially eligible
A trimmed-down mockup of the real workbench, counting the ten hand-written synthetic patients. In the real thing, clicking a bar opens the reasoning for each patient, line by line.

The honest coverage number

0%

Of 12,060 entry criteria pulled from 996 real trials, 56.7% look like the rule language could express them as written, 12.2% partially, and 31.1% not at all. That is a heuristic estimate: pattern matching over the text, never checked against human judges. It reads two ways at once. The language handles more than half of what real trials ask, and a third of it is beyond what the language can say. Both numbers are the result.

05the build

How it was made, and where it wants to go

This is a prototype built in the open. The next part of it needs people who run trials.

Emmanuel Cuyugan built this against public registry text and invented patients. No coordinator, no screener and no data manager has yet held it up against a real screening day. That is the part he wants to do next, alongside the people who do that work. What follows is how the thing was made, so you can judge whether it was made with any care.

vitest 470 automated tests, written before the code they test YAML structured text people can read the rules themselves zod checks every file at the door TypeScript typed code, mistakes surface before running the engine and the command line React the workbench app command line the printed report HUMAN GATE Anthropic SDK reads notes, proposes facts always behind that gate promptfoo scores that step offline
What it is made of, plainly. The rules are text files, not code. One typed engine reads them. Two screens read the engine. The note-reading step sits below the line and can only send work upward through a person. The outer box is the test suite, and it was written first.

The rule format was written down before the engine existed, so the code had something fixed to be wrong against. Reviewers were then told to attack it, and a claimed flaw only counted if it came with code that proved it. Every proven flaw became a permanent regression testkeeps fixed bugs fixed before anyone was allowed to fix it. Three of the scars:

the over-eager checkerThe conflict checker once announced a clash that could not actually happen. A reviewer proved it, the checker learned to keep quiet in that case, and the false alarm is pinned down as a test in tests/adversarial/conflicts.test.ts.
the two screens that disagreedThe report and the visual app each did their own arithmetic, and they disagreed on every headline count: 0 potentially eligible on one screen, 2 on the other, over the same 100 patients. The arithmetic moved into one shared module, src/core/attrition.ts, and a test now forces the two to agree.
the sentence with its own bodyguardThe format's most important sentence, "an absent value is unknown, never false", has a test suite of its own (tests/adversarial/kleene.test.ts), so no future change can quietly weaken it.
main scaffold core engine trial packs data pipeline workbench facts compiler adversarial reviews fixes gated by tests docs
The whole history is in the repository, reviews and reversals included.

Where it wants to go next is more trial packs, written with the people who screen for those trials, and an honest written record of every criterion the language cannot hold. The third of criteria it cannot express is the interesting part, not the part to hide. So: if you run trials, or you sit close to the people who do, he would like to hear what this gets wrong.

one engine same input, same answer the rule file pass fail don't know three answers the protocol printed report 7 screen fail of 10 visual app 7 screen fail of 10

chapter 06 · close

pull back and the parts are small, and you have met every one of them: a compiled chip, a patient, the collision band, a stamp. a page, a file, one check, one answer, printed twice.

06close

The limits, up front

⚠ not medical software This is a demonstration of rule-governance tooling. It is not validated, not cleared by any regulator, and not for clinical, feasibility, or research screening use. Every patient, note, clinician and institution here is invented. The trial criteria are copied from real public registry text, but every number this tool produces is about people who do not exist.
The narrow claim: there is no open implementation of this whole shape in one place. AI suggestions that carry their quotes. Human approval as the only way in. A deterministicsame input, same answer, always engine as the only thing that decides. And the rule format written down separately, so somebody else can go build a second engine. from the project README, stated with its own caveats attached

Where to look next: README.md in the repository for the runnable version of all this, FORMAT.md for the rule language itself, and the technical thesis (also docs/thesis.html in the repository), which is this same story told longer, for engineers, with the engine's real output in it.

The repository itself is at github.com/emmcygn/rulekit. There will also be the engineering readlink to follow, a shorter account of the build decisions and the things that had to be reversed.

Open the live workbench

The real engine, running on ten synthetic patients in your browser. No sign-up.

pass fail don't know

Every verdict this page handed down is one of these three marks. There is no fourth.

agents propose·humans confirm·the engine decides

In that order, every time, with no way around the middle step.

medirulekit · the home of rulekit · Apache-2.0 · set in Public Sans, Spline Sans Mono & Martian Mono
R&D efficiency decline: Scannell et al., Nat. Rev. Drug Discovery 2012 · amendment costs: Tufts CSDD · criteria coverage: Chia corpus (CC-BY-4.0, Kury et al. 2020) · trial criteria quoted from ClinicalTrials.gov