Perslis projects · Perslis Floor
Pilot · 1.1.2Exact answers
from your own data.
Ask a question once. A model writes the procedure, the floor proves it, a person approves it, and you keep a signed tool that answers from your data — offline, exactly, with no model in the loop. When the data can't support an exact answer, it refuses.
you> How much have we paid, by vendor region? → tools/call derive_demo_paid_by_region ← DERIVED · model_calls: 0 Central 11215.45 East 21576.59 South 4800.25 West 32996.02 rows → filter(status = paid) → join(vendors) → group_by(vendors.region) → sum(amount)
Recorded from the 1.1.2 release over MCP stdio. The demo data is fictional and ships in the download.
Why we built it
Most questions about your data are arithmetic.
What did we pay each region? Who are our top three vendors? How many invoices have no PO number? These are not inference problems. They are counting, filtering and adding over data you already hold. Sending them to a model means paying per call for an answer that was checkable all along — and getting a number you cannot check.
Perslis Floor keeps the model where it is useful: reading the question once and composing a procedure from a closed vocabulary. It never writes code. From then on, a small runtime on your machine executes that procedure exactly, every time, and shows its working. It grew out of our symbolic floor research.
The loop, made visible
Ask. Compose. Prove. Approve. Run.
- Your questionIn your own words: “how much have we paid, by vendor region?”
- A spec, not codeA model composes a pipeline: filter → join → group → sum.
- The gateEight checks: real columns, trustworthy data, deterministic, grounded, and the verifier must reject wrong answers.
- A personReads what the tool computes, in plain words, next to its answer on the real data — and approves it or not.
- Your machineThe signed tool runs locally over MCP. No network, no key, no model.
status = open passes every mechanical check. So nothing ships until someone reads it and says yes, and the approval is signed into the tool. Editing the tool, its table or the review afterwards voids it.What we discovered building it
The failures that look like answers.
A gate proves the procedure, not the meaning.
An adversarial review showed a spec labelled “total of paid invoices” that actually summed open ones passing every automated check. That is why every tool now carries a person’s signed approval, and why a changed tool, table or data snapshot voids it.
Our first grounding test refused correct tools.
On 10,000 realistic rows it refused all four correct specs we tried: it only perturbed the first 25 rows, and the matching rows were further down. It now perturbs the rows that actually reach the answer, and it is tested at that scale for every kind of question.
Floats and silent drops look right and are wrong.
9,007,199,254,740,992 + 1 came back unchanged. A lookup silently dropped a $900 invoice and reported $100. Arithmetic is now exact decimal, and a row with no match is refused unless the tool explicitly says otherwise.
A checksum next to a download proves nothing.
Anyone who can replace the zip can replace its checksum. Releases are now signed with a Perslis release key that is published in two places, and the installer refuses anything that does not verify — we tested it against a tampered mirror.
Build status · 26 September 2026
What you can test today.
| Capability | Current evidence and limit |
|---|---|
| Runtime and MCP server | Standard-library Python 3.9+, no dependencies, no network code. Over 300 automated tests pass on Python 3.9 and 3.13; a real Claude Code session called a built kit, reported exact answers and recorded an unanswerable question as a gap. |
| Data | CSV, TSV, JSON, JSONL, SQLite, or a folder of them; re-read when it changes. Measured at 500,000 rows (18 MB CSV): about 1.3 s to load, about 400 MB, about 2.3 s for the first query; repeat answers are cached. Default cap 1 million rows. |
| Admission and review | Eight-check gate, then a human review signed with the reviewer’s own key; the runtime refuses any tool without a valid reviewer attestation. Four rounds of adversarial review on 26 September; 1.1.2 fixes every finding, each pinned by a regression test. |
| Signing and releases | Tools are Ed25519-signed and the runtime can only verify. Release checksums are signed and verifiable with ssh-keygen; builds are reproducible byte for byte. |
| Not yet | Relative dates (“last 30 days”), parameterised tools, direct database connections, and a self-serve gate. Tools for your data currently come through a pilot. |
Try it
Verify, then install. Start with the demo.
Nothing runs until the release signature checks out. Download the installer and the signed checksums, then verify them with the Perslis release key below. The same key is in the GitHub README, so compare the two. Only then run the installer. It fetches the zip, verifies it again, unpacks it to ~/perslis-floor and runs the demo: fictional invoices and vendors, with six reviewed and signed tools.
V=1.1.2; B=https://github.com/AgewellEPM/perslis-floor/releases/download/v$V
curl -fsSL -O "$B/install.sh" -O "$B/SHA256SUMS" -O "$B/SHA256SUMS.sig"
echo 'releases@perslis.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJfmXcRm2o52skHrajOCntbGMwPIB13CWnzt/tRGxXxd' > perslis_signers
ssh-keygen -Y verify -f perslis_signers -I releases@perslis.com -n perslis-release -s SHA256SUMS.sig < SHA256SUMS
grep ' install.sh$' SHA256SUMS | shasum -a 256 -c -
bash install.sh
We don’t publish a curl … | bash line: piping a script straight from a branch runs it before anything has been verified. Once it’s installed, connect it to Claude Code and ask a question in plain English:
claude mcp add perslis-floor-demo -- python3 ~/perslis-floor/floor-serve.py \
--data ~/perslis-floor/demo/data --tools ~/perslis-floor/demo/tools
Tools for your data
Send an export and your questions. Get back a kit.
The admission gate and the signing keys stay at Perslis, deliberately: a wrong tool that got signed would answer confidently, offline and forever, with nothing left to re-examine it. In the pilot you send an export (CSV, JSON or SQLite) and your questions; we build each tool, review it and sign it; you get the runtime, your tools and a five-minute guide. Questions that need judgment rather than arithmetic come back marked as needing a model — never as a guess.
Standards behind it
Protocol and cryptography references — not endorsements.
- Model Context Protocol specification (stdio transport)
- RFC 8032 — Ed25519 signatures (the runtime’s verifier is pinned by the RFC test vectors)
- ssh-keygen -Y sign / verify (release signatures)
More Perslis work: Jira Monkey · all tools.