Zain Dana HarperEMET · external witness

If an agent touched it, you should be able to check what it did.

I couldn’t take an agent’s word for what it changed, so I built something that checks for itself. It reads the file straight off the disk and works out a fingerprint — a short code that is unique to those exact bytes. Move even one character and the whole fingerprint changes. Then it compares that to the fingerprint it saved earlier and tells you one of three things: MATCH (nothing moved), DRIFT (something moved), or UNVERIFIABLE (it couldn’t check, and says so plainly). There is no fourth answer that just means trust me — the code was built so that answer can’t exist. It stands outside the thing it’s checking, and it never speaks for that thing.

A witness isn’t a judge. All it does is say what it compared. Whether to trust the result is yours, not the tool’s.

emet — Hebrew for truth · 19/19 conformance · three languages

It works out the fingerprint itself.

An AI model is always handling files — one it edits, a prompt it’s given, a view it shows you and calls a true copy of the original. EMET opens those files directly and works out the fingerprint again from scratch, using SHA-256 (a standard, widely trusted recipe for turning any file into one short, unique fingerprint). Then it compares that to the fingerprint it saved before. The answer comes only from running the same recipe over the same file — never from the system telling you it’s fine. It stands outside the thing it’s checking.

Knowing where a file came from is one thing. It still doesn’t tell you whether the copy the model is looking at right now is unchanged. That’s the gap this closes.

Three answers. None of them trusted.

There are exactly three answers it can give — MATCH, DRIFT, UNVERIFIABLE — and there will only ever be three. That’s not a promise written in a comment somewhere; the code is shaped so a fourth answer simply has nowhere to come from. It can never tell you to trust something, because it was never given any trust to hand out.

MATCH the file’s fingerprint still matches the one saved earlier · it means nothing has moved — not that the file is good
DRIFT the file, or the view shown to you, no longer matches its saved fingerprint · it just reports that something changed — it doesn’t decide whose fault that is
UNVERIFIABLE it couldn’t read the file, or had no saved fingerprint to compare against · so it says “I can’t tell” out loud, with a clear reason — it never guesses, and never just crashes
If there’s no DRIFT, the answer is either MATCH or UNVERIFIABLE. There is no path through the code that turns “no drift” into “trust it.”

Don’t take the answer on my word. Watch it flip.

A single character is enough to change everything. Check a file, add one character to it, then ask again — and the same rules, written out in three different programming languages, all land on the same answer.

Live the verdict depends on the bytes, nothing else
$ python membrane.py verify demo_sample.txt
MATCH  demo_sample.txt   want=d02206abca2a…  got=d02206abca2a…   (exit 0)

# append one byte to the file, ask the same question
$ python membrane.py verify demo_sample.txt
DRIFT  demo_sample.txt   want=d02206abca2a…  got=b072d611645e…   (exit 2)

# one spec, three separate language implementations, CI on every push
membrane.py        →  CONFORMANCE 19/19 vectors pass
impl/rust/emet     →  CONFORMANCE 19/19 vectors pass
impl/js/emet.js    →  CONFORMANCE 19/19 vectors pass

Change a single character in the file and the answer drops from MATCH to DRIFT. It reads the file itself, not anyone who promises it’s fine.

Captured live from the emet run · receipt format from adapters/proof_surface_receipt.py · 19/19 conformance vectors, three language implementations, CI each push. Honest limit: I wrote all three versions myself, so they can only earn one honest claim — that the written rules are clear enough to build from. They haven’t yet been rebuilt by someone with no connection to me, and that fourth version, by a different hand, is something I still owe.

One set of rules, three languages.

I wrote the same rules out three separate times, each in a different programming language, and each built only from what comes with that language — nothing borrowed from the outside. All three pass the very same nineteen test cases on every change.

Three versions agreeing is not the same as three people agreeing.

They all came from one person — me. So they earn one honest claim and not a single one more: the rules are clear enough that someone can build a working tool from them. What I still owe is the real test — a fourth version, built by someone with no tie to me. I say that here in plain words, instead of letting the number quietly imply more than it should.

Copy it. Run the tests. Try it on real work.

It’s small, it’s open for anyone to read, and it leans on almost nothing else. Copy it onto your own machine, run the tests, point it at something you actually care about — and the moment it lets you down, tell me. I would honestly rather hear where it breaks than be told it’s fine. That’s what shows me what to build next.

$ git clone https://github.com/HarperZ9/emet && cd emet
$ python conformance/run.py membrane.py
CONFORMANCE 19/19 vectors pass
GitHubHarperZ9/emet  ·  Emailzaindharper@gmail.com  ·  ← the map  ·  the index