The Workbook That Proves Itself
RECALL proved a static page could carry its own proof of integrity. Mere validate extends the same idea somewhere RECALL never had to go: a file whose state keeps changing after it opens. mere pack now embeds its own pre-pack source; mere validate recomputes it and diffs the result against what is actually shipping — tested by hand-tampering a packed file and watching it name the exact screens that drifted.
A Harder Version of a Problem RECALL Already Solved
In May, RECALL shipped recall validate — a command that re-fetches a compiled page, recompiles the source embedded in its own audit comment, and confirms the two match. The philosophical payoff was exact: “source is the artifact” stopped being a design constraint and became a runtime guarantee. A page could prove it had not been changed since it was compiled.
Mere had the same gap, and for a while I assumed the same fix would drop in cleanly. It does not, and the reason is the interesting part. A RECALL artifact is compiled once and never changes again — no state, no interaction, no runtime. Comparing it against its embedded source is comparing two static things. A Mere workbook is not static. It has declared state, two-way bindings, computed values — the whole point of the format is that it keeps changing after the reader opens it. “Prove this file has not changed” means something different when the file is designed to change constantly, on purpose, in the reader's browser.
The question mere validate has to answer is not “is this byte-identical to what shipped” — that would fail the instant someone typed into a field. It has to separate two things that look the same from the outside: a reader changing the state the workbook was built to hold, and someone changing the workbook itself after it was packed.
mere pack, Now With a Memory
mere pack already inlines the runtime into a workbook, producing a fully self-contained *.packed.mp.html — no CDN dependency, runs anywhere. It now does one more thing: it embeds the pre-pack source, base64-encoded, in a script tag the runtime ignores.
<script type="application/mere-source" id="mere-original-source">
PHdvcmtib29rIHRoZW1lPSJicnV0YWxpc3QiPgo...
</script>Base64 instead of a plain HTML comment, deliberately — an untrusted comment can contain --> and terminate itself early, silently truncating the embedded record. Base64 sidesteps the whole class of escaping bugs at the cost of a few hundred bytes. This is not a new mechanism bolted onto packing — it is one more field in an artifact that was already self-contained by design. The file remembers what it was, in addition to what it can do.
mere validate
Point it at a packed file. It decodes the embedded source, confirms that source is still valid Mere, then compares the packed file's actual workbook body — screens, state declarations, computed values, actions — against what packing that exact source would produce. Runtime and pack-timestamp differences are expected and ignored; only the workbook itself is compared.
$ mere pack examples/habits.mp.html --out habits.packed.mp.html
✓ examples/habits.mp.html → habits.packed.mp.html
runtime: 108.1 KB · total: 115.4 KB · self-contained
$ mere validate habits.packed.mp.html
✓ habits.packed.mp.html — matches its embedded source, no drift detectedThat is the boring, correct case. The interesting one is what happens when the packed file has been hand-edited after the fact — not the reader interacting with it, an actual post-pack edit to the file on disk:
$ sed -i 's/<heading>/<heading>TAMPERED — /' habits.packed.mp.html
$ mere validate habits.packed.mp.html
✘ habits.packed.mp.html — workbook content has drifted from its embedded source:
~ screen: add-habit-screen
~ screen: habit-detail
~ screen: today
This proves the artifact changed since it was packed — not who changed it.That last line is the whole claim, stated as precisely as I could manage. It names the exact screens the edit touched (three, because the one-line sed matched a heading on three separate lines — the tool did not know that going in, it found out by comparing). It does not, and cannot, say who made the edit. Integrity and provenance are different questions, and it would be dishonest to answer one and imply the other.
How It Actually Works
Extract
The embedded <script type="application/mere-source"> tag is decoded back into the original pre-pack source. If no such tag exists, the file was never packed with mere pack — validation stops there.
Re-check
mere check runs against the decoded source. This is not new logic — it is the same MPD-001 through MPD-008 diagnostics check already reports on any workbook, reused rather than reinvented.
Diff
The decoded source and the packed file are both run through the same structural extractor mere diff uses — named screens, state, computed values, actions — and reconciled. Zero differences means the workbook has not moved since it was packed.
Step 3 is why this could ship in an afternoon rather than a quarter. It is not a new comparison engine — it is mere diff pointed at two things instead of one being a live file and the other a decoded string. Building the diff tool first, for an unrelated reason, is what made the validator cheap.
mere diff: The Same Machinery, a Different Question
The store's package identifier is MP-k7p2rs — a four-character identity and a two-character version, fixed-width, no separator. Until now there was no way to see what actually changed between MP-k7p200 and MP-k7p201 short of opening both files and reading them side by side. mere diff takes two workbooks and reports what moved:
$ mere diff examples/books.mp.html examples/habits.mp.html
~ theme: notion-paper → brutalist
- screen: library
+ screen: today
- state: books
+ state: habits
- computed: total-books
+ computed: total-habits
- action: add-book
+ action: add-habit
...No AST, no line-level diff of action bodies — a name-keyed comparison of screens, state, computed values, and actions, added, removed, or changed. Deliberately simpler than recall diff, which works at the AST level and can diff against git revisions directly. Mere's version does less, but it is the same amount of work as building it twice — once for versions on disk, once for a version against its own embedded memory.
What This Does Not Prove — On Purpose
recall validate sits alongside RECALL's AUDIT DIVISION — a compile-time constraint on CREATED-BY that makes authorship part of the source itself. recall validate proves integrity; the AUDIT DIVISION provides provenance. Together, RECALL has both halves of a trust model.
Mere has only the first half so far. mere validate proves a packed workbook matches what it was packed from. It says nothing about who packed it, and it only checks local files today — no URL fetch, no connection to the store's own approval record. A downloaded package can prove it has not drifted from its own embedded source; it cannot yet prove that source is what mere-store actually approved. Closing that gap means borrowing RECALL's AUDIT DIVISION shape rather than inventing a new one — an open thread, not a finished one.
mere-cli
@semanticintent/mere-cli@0.2.0
GitHub
semanticintent/mere
Documentation
docs.mere.fyi/get-started
Related
The Page That Proves Itself
Where this idea came from — RECALL and the static-artifact version of the same proof.
RECALL: The Source That Knows Who Wrote It
The provenance half Mere does not have yet — authorship as a compile-time constraint.
Mere: The File Is the App
Where Mere started — a workbook format where the file contains everything.