# Perslis Symbolic Floor — Runtime

**Ask a model a question about your data once. Get a tool that answers it
forever, offline, for free.**

Most "AI decisions" inside software are not inference problems. *How many rows
match? What's the total of that column? How many are missing a value?* are
arithmetic over data you already have. Sending them to a model means paying per
token, every time, for something checkable — and getting an answer you cannot
verify.

This runs those questions locally. No network. No API key. No model. No
telemetry. Python 3.9+ and the standard library.

---

## Install

```bash
curl -LO https://github.com/perslis/symbolic-floor-runtime/releases/latest/download/perslis-symbolic-floor-runtime-1.0.0.zip
unzip perslis-symbolic-floor-runtime-1.0.0.zip && cd perslis-symbolic-floor-runtime-1.0.0
```

Verify it first:

```bash
shasum -a 256 -c SHA256SUMS
```

## Run

```bash
export PERSLIS_FLOOR_VERIFY_KEY=<your key>

python3 -m floor_runtime.serve --data invoices.json --tools ./floor --list
```

```
derive_numeric_property_approved_invoice_total
    class      : numeric_property:approved_invoice_total
    derivation : rows -> filter(approved) -> sum(amount)
```

Drop it into any MCP client:

```json
{"mcpServers": {"symbolic-floor": {
  "command": "python3",
  "args": ["-m", "floor_runtime.serve",
           "--data", "/abs/path/invoices.json", "--tools", "/abs/path/floor"]}}}
```

A `tools/call` returns the answer **and how it got there**:

```json
{"status": "DERIVED", "value": 1290.49, "model_calls": 0,
 "derivation": "rows -> filter(approved) -> sum(amount)"}
```

## What it will not do

- **It will not guess.** No evidence for your question returns `NO_EVIDENCE`,
  not a plausible number.
- **It will not run an unadmitted tool.** Specs carry a signature from the floor
  that admitted them. Edit one and the runtime refuses it and does not offer
  the tool — it tells you which, and serves the rest.
- **It will not phone home.** There is no network code in this package. Read
  it; it is 303 lines.

## Getting tools

Tools are produced by the **Perslis admission gate**, which is not in this
package. You describe a question in English, a model composes a specification,
and the gate decides whether that specification is admissible — checking that
it is deterministic, that it names columns that exist, that its verifier
actually rejects wrong answers, that it abstains when evidence is absent, and
that it is grounded in your data rather than a constant the model memorised.

Only specifications that survive all of that get signed. This runtime executes
those. It cannot admit one itself, by design — the part that decides what is
admissible is the part worth being careful with.

→ **[perslis.com/research/floor](https://www.perslis.com/research/floor)**

## Why the split

If the gate shipped here, a wrong specification could be hand-written, loaded,
and would then answer confidently, offline, forever, with no model left in the
loop to catch it. That is a worse failure than a model simply being wrong on
each call, because nothing ever re-examines it.

So the gate stays where it can be maintained, and what runs on your machine is
an executor — complete for execution, and honest about being only that.

## Status

**PROTOTYPE.** The runtime, the signature check and the MCP server are real and
tested. The primitive vocabulary is small — `rows`, `filter`, and seven
reducers — and a question outside it is correctly reported unmappable rather
than guessed at.

Licence: see `LICENSE.txt`. Free to use, including commercially.
