Exact answers from your own data.
No model in the loop.
Ask a question about your data once. Get back a signed tool your AI assistant can call from then on. It runs offline and free, it's exact, and it refuses instead of guessing.
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
Verified install: nothing runs until the release signature checks out. There's no curl | bash.
Six questions. Four ways to break it.
These are the demo tools that ship in the download, over fictional invoices and vendors. Pick a question to see what the tool computes and the exact answer the runtime returned. Then try to break it.
Every output on this page was recorded on 2026-09-27 from the real v1.1.2 release, over MCP stdio. Nothing was typed by hand. Run python3 floor-serve.py --data demo/data --tools demo/tools --check to reproduce it.
A model proposes. The floor checks. A person approves. You run it.
A model writes a spec, never code
It composes a pipeline from a closed vocabulary, such as rows → filter → join → group_by → sum. There's no way out into Python.
Eight checks prove it
Columns exist, the data supports an exact answer, and the result is deterministic. The verifier rejects near-misses, the spec abstains without evidence, and the answer moves when the data moves.
A person approves it
The reviewer reads what the tool computes in plain words, next to its answer on the real data, plus any warnings. They sign the approval with their own key, and the runtime refuses any tool without a valid approval.
It runs on your machine
Ed25519-signed and served over MCP. Every answer carries its derivation and model_calls: 0.
status == 'open' passes every mechanical check. So nothing ships until someone reads what it computes, next to its answer, and says yes. Editing the spec afterwards voids that approval.It fails closed.
Guess
No evidence gives NO_EVIDENCE, and no matching rows gives NO_VALUE. It never fills the gap with a plausible number.
Skip what it can't read
N/A in a number column, 03/04/2026 in a date column, a corrupt JSON row, or a file still being written: each is refused by name, never silently dropped.
Undercount or double-count
A lookup key that appears twice would double-count, and a row with no match would vanish from a total. Both are refused unless the tool explicitly (and signed) says otherwise.
Run a tool nobody admitted
The runtime holds only public keys, so it can check signatures but can't create them. An edited tool is refused by name, and the rest keep working.
Round a total
Totals, minimums and maximums are exact decimals: 9007199254740992 + 1 = 9007199254740993. Only an average rounds, to 10 places, and the tool says so.
Phone home
There is no network code. Shareable logs record which tools ran and why a call was refused, with no values and no question text. Your questions stay in tools/private/.
Don't take our word for it.
Releases are signed with a Perslis release key. The same public key is pinned here, in the GitHub README and at perslis.com. Compare them: a key published in only one place proves nothing.
# the release key (identical on perslis.com and GitHub) echo 'releases@perslis.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJfmXcRm2o52skHrajOCntbGMwPIB13CWnzt/tRGxXxd' > perslis_signers # 1. the checksums really come from Perslis ssh-keygen -Y verify -f perslis_signers -I releases@perslis.com -n perslis-release -s SHA256SUMS.sig < SHA256SUMS # 2. the files you downloaded match the signed checksums; every file inside matches the manifest grep ' perslis-floor-1.1.2.zip$' SHA256SUMS | shasum -a 256 -c - grep ' install.sh$' SHA256SUMS | shasum -a 256 -c - unzip perslis-floor-1.1.2.zip && cd perslis-floor-1.1.2 && shasum -a 256 -c MANIFEST.sha256 # 3. there is no network code grep -rnE "socket|urllib|http|requests" floor_runtime/ # finds nothing
Builds are reproducible byte for byte: the same sources produce the same SHA-256.
Pilot, honestly.
PILOT · v1.1.2 It's tested end to end, including a real MCP client calling a built kit, on Python 3.9 (the macOS default) and 3.13.
| Measured | Value |
|---|---|
| Load 500k rows (18 MB CSV) | ≈ 1.3 s, ≈ 400 MB RAM (M-series laptop) |
| First query after the data changes | ≈ 2.3 s at 500k rows; repeat answers are cached until the file changes |
| Admitting one spec (authoring side) | ≈ 27 s at 500k rows |
| Not yet | Why it matters |
|---|---|
| Relative dates ("last 30 days") | They make the answer depend on the clock. Absolute date ranges work. |
| Parameterised tools | It's one tool per question for now; "total for vendor X" needs a tool per X. |
| More than 1M rows in memory | That's the default cap; --max-rows raises it. Export a narrower slice for bigger data. |
| Direct database connections | Deliberately left out (no network). Export to CSV or SQLite instead. |
Send an export and your questions. Get back a kit.
The admission gate and the signing keys stay at Perslis. A wrong spec that got signed would answer confidently, offline and forever, so the part that decides stays where it can be maintained. You send an export (CSV, JSON or SQLite) and your questions in your own words. We build each tool, review it and sign it. You get this 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.