Lispex Vouch

Attach receipts to small decision rules. Keep a record you can check offline, and compare corpora when a rule changes.

Lispex Vouch is not a framework for building apps. It is a way to attach receipts to the small decision rules inside one. No screens, no servers, no databases live here. You pull out one judgement that may need explaining later, write it as a small Lispex rule, and each recorded answer gets a file you can check later. The reference interpreter is still what runs Lispex programs.

The questions it answers

Some of the judgements your code makes come back as questions later.

  • Support asks why an order was refused an automatic refund. You need a concrete record of what was written down for that rule and input three months ago.
  • You want to change the discount rule. Before merging, you want a list of last quarter's orders whose discount would come out differently under the new rule.
  • You maintain rules like approval limits or access decisions, the kind where an audit or a review asks you to show your grounds.

Rules like these are usually a tiny slice of the codebase. Lispex Vouch takes on only that slice.

One rule, end to end

The word rule stays abstract until you see one, so here is the whole thing. Say a refund is approved automatically when the order is within fourteen days of delivery and unopened.

LISPEX
(define (refund-auto-approved? days-since-delivery opened?)
  (and (<= days-since-delivery 14)
       (not opened?)))

(refund-auto-approved? 9 #f)  ; ⇒ #t

The host application passes the inputs in as arguments, and they are pinned exactly as given. Pin nine days since delivery and unopened, evaluate, and the answer is #t. In the Lispex Vouch workflow, that evaluation leaves a receipt file, csk.differential-receipt/v0, which records the rule, the pinned input, and the answer together with hashes. Commit the receipt next to the rule, and three months later the question "why did we answer that then" starts from a concrete file instead of memory. A receipt is a record, not a proof. It shows what was written down at evaluation time, and it is only as trustworthy as the process that produced it. Starting with v1.3.4, the native standalone binary is the public receipt generator.

You can paste this rule into the Playground right now. How to choose what belongs in a rule, and more realistic examples, are covered in the Writing Decision Rules guide.

What the Vouch commands answer

lispex diff-receipt --input <datum-file> <rule.lspx> generates a receipt with the native standalone binary. It evaluates a rule against a pinned datum and writes csk.differential-receipt/v0 JSON to stdout.

BASH
lispex diff-receipt --input inputs/refund-2026-03-0412.datum rules/refund.lspx > receipts/refund-2026-03-0412.json

lispex verify <receipt> checks that a receipt file holds together. It validates the schema, recomputes the hashes the receipt carries, and with --source confirms that a local rule file matches the recorded source hash. Run it when an old receipt resurfaces in a support case, an audit, or a handover and you want to know the file has not drifted. It works offline, with no network and no service. It does not re-run the evaluation, and it cannot tell you whether the receipt was generated honestly, who applied the decision, or when. A passing check means the file is consistent with itself and with the rule text you point it at, nothing more.

BASH
lispex verify receipts/refund-2026-03-0412.json

lispex replay <corpus> --against <version-or-receipts-dir> answers "if I change the rule, which past answers move". Run it before merging a rule change. It compares the committed decision corpus against a version pin or a directory of receipts and reports exactly which answers differ.

BASH
lispex replay decisions/refund --against receipts/2026-Q1

What a receipt says, and what it doesn't

A receipt records a specific rule, a pinned input, and an answer, then binds that record to hashes. It shows whether the recorded artifacts agree with each other. It does not prove that the receipt was generated honestly, that a real system treated a customer according to that answer, when, or by whom, and it is not a substitute for review. Those belong to separate signing, timestamping, deployment, and review layers.

The npm distribution of verify and replay is a checker for public-spec artifacts. It inspects bytes and hashes. It does not execute Lispex source and does not replace the reference interpreter.

The conditions of the checked subset

None of this works unless the same rule over the same input always gives the same answer. So Lispex Vouch operates only on a slice of Lispex closed off for exactly that.

  • a fixed set of forms in the R7RS tradition, with no macros and no ambient state
  • pinned builtins, with inputs bound explicitly by the host rather than fetched by the rule
  • receipts and the other outputs follow byte-exact JSON contracts

Lispex code outside these conditions still runs fine. The receipt promise simply holds only inside the subset.

What you can do today, and what is coming

  • Rules themselves evaluate right now in the Playground.
  • The native standalone binary generates receipts with lispex diff-receipt.
  • The CLI installed with npm install -g lispex runs files with lispex run and checks existing receipts and corpora with lispex verify and lispex replay. It does not generate receipts. Command examples are in Getting Started.
  • The browser Playground runs snippets only. It does not generate receipts.
  • The public mirror and release bundle include examples/vouch-loop, a one-rule corpus that runs generation, verification, and replay with no private repository state.