ZFL — Zero-trust Formal Language, the language of the studio (ZTL is the logic; ZFL is how you write for it)

Why a table and not a syntax

Everything you write here is one document: a list of NAMES, each saying where it stands with you, plus what you CLAIM about them. There is no genre to declare and no mode to pick. Which instruments answer — the numeric floor, the passport office, the ledger, the judge — follows from which cells you filled.

The one rule underneath

Truth is not granted on credit. A name is verified when a verification was produced, and the ground column is where you say what produced it. A name with nothing backing it is not false — it is unverified, which is an honest third answer and the reason this logic exists.

Asking for a number

Put `?` in a value and the row stops being an answer and becomes a question. `x = ?` with a claim of `x - 10 = 20` is answered: x is 30, and earned. This is the one cell that changes what the machine DOES — everywhere else you are telling it what you know, and here you are asking.

Where formulas survive, and the one cell that reads two ways

In two cells only. In GROUND, when a name is DEFINED by a formula over other names — that is how self-reference is written, and it is why the liar needs no special mode. And in CLAIM, which is what you are actually asserting. Note what the ground cell is doing: for a verified name it holds `inv-17`, an opaque name the machine never looks inside and which means nothing but its own identity; for a defined name it holds `~Tr(L)`, a formula the machine reads and evaluates. The status decides which, and the form asks again whenever you change it.

the columns of a row

columnwhat it isrequiredoptions / examples
namewhat we call it; formulas use thisalwaysline · budget · L
meanswhat it MEANS for this to be truenothe invoice line · this sentence is false
statuswhere it stands with usalwaysverified · refuted · not verified · defined
groundwhat backs it, or the formula defining itin contextinv-17 · ~Tr(L)
dimensiondoes this SUPPORT the claim or PERMIT itnoevidence (supports) · authority (permits)
kind of grounda document unless you say otherwisenodocument · act (nothing to withdraw) · certificate (expires) · another row
expires atthe name of the event after which this ground no longer holds — another rownocourt_judgment · registry_recheck
valuea number, an interval [0,10], or ? for the quantity the question asks for (it is solved for, not measured); an unknown input is an interval, e.g. [0,inf]no1500 · [0,10] · ?
unitonly with a value; metres never meet roublesnoRUB · m · m2
scalewhat it rounds tonoexact · whole · hundredths · thirds
separate measurementseach occurrence is its own act of measuringno

the document itself

columnwhat it isrequiredoptions / examples
admissible groundsthe grounds this document accepts, comma-separated. A row earning on a ground outside the list falls to unverified rather than to false. A tier may be given — 'master:story, perebor:act': story means 'so it was said', and what earns on it is marked. Empty: the gate says nothingnoregistry_extract:place, testimony:story · перебор:act, промер:act, мастер:story
claimwhat you are actually assertingnoline <= budget · rain -> umbrella
askreserved: the full report is always shown (this field narrows nothing yet)noverdict · warranty · passport · stipulations · blast · brackets

operators

&and
->if … then
=biconditional between rows: the same TRUTH value as
^exactly one of
|or
~not
Tr(x)the value of the row x — this is how self-reference is written
<=at most
>=at least
==numeric equality — for quantities only, not for rows
<less than
>greater than

Binding, strongest first: ~, then & > | > ^ > -> > = (also <->). Every connective is left-associative: a & b | c is (a & b) | c, and a -> b -> c is (a -> b) -> c, NOT a -> (b -> c). Write the brackets when you mean the other reading.

arithmetic

*times
+plus
-minus
/divided by
sum(a,b,…)the sum of several — the same as a + b + …
sqrt(x)the square root — a proved enclosure, exact where the root is rational; a negative quantity has no reading; the solver does not solve for a quantity under a root
( )brackets, to say what goes first
-xa leading minus: the sign of a term, not the operation between two — `-x + 100 = 70` is a fair question and was not accepted until 2026-08-13

what can go in a value

1500a number you have measured or read off a document
[0,10]a box: somewhere in this range, and the machine keeps the range rather than picking a point. Both ends are INCLUDED; for a strict bound put it in the claim — `x > 0`. Write it backwards, [10,0], and you get E: the row names nothing, which is a verdict rather than a typo
?A QUESTION. You do not know it and you are asking. If the rest of the table determines it, the solver answers with the value AND the provenance it inherited — `x = 30, earned`. If it does not, you get told what would settle it.

a worked example

columnmeansstatusgroundvalue
linethe invoice lineverifiedinv-171500
budgetthe ceilingverifiedorder-45000
rainit is rainingunverified——
Lthis sentence is falsedefined~Tr(L)—

admissible grounds: line <= budget

error codes

E_BADNAMEa name a formula could not use
E_CLAIMthe claim does not parse
E_DIMa dimension outside the list — a ground either supports a claim or permits it
E_DIM_CLASHa ground carries one mark, not two: 'authority' cannot be combined with an act, a certificate or another row
E_DUPNAMEthe same name twice
E_EMPTYthe table has no rows
E_EXPIRY_NO_GROUNDa clock on a row that has no earned ground to lose
E_FORMULAthe defining formula does not parse
E_GROUND_SPACESa ground with a space in it — a ground is one word, because it names a document
E_KINDa kind of ground outside the list
E_NOGROUNDverified, refuted or defined, with nothing backing it
E_NONAMEa row without a name
E_NO_VALUEa name the claim reads as a number has no value — give it a number, an interval, or ? if it is what the question asks for
E_NUMBER_AS_STATEMENTa name with a value is a number, and it stands where a statement goes — compare it (x > 0); a square is x*x, since ^ is XOR
E_OPEN_INTERVALan open bound like (0,10) — put the strictness in the claim instead
E_RESERVEDa constant of the language used as a row name — it silently changes the reading
E_SCALEa scale that is not empty/int/decimalK/fracM, or out of bounds
E_STATUSa status outside the four
E_TOOBIGmore than 10 atoms NAMED MORE THAN ONCE in the formulas, or more than 64 atoms in all. The exact guarantee branches only on atoms that repeat; an atom named once costs almost nothing (40 read-once atoms: under 0.01 s; 30 repeated atoms in a pigeonhole witness: 0.66 s — measured 2026-09-29). Rows are not capped. Split the question, not the table
E_TOOLONGa formula longer than 2000 characters — the readers cost the square of the length (4.6 s at 39 KB, 0.21 s at 4 KB, measured 2026-09-24); split the question
E_TOOMANYEVENTSmore than 6 expiry events in one document — the epoch floor reads the claim on both sides of each (800 events cost 76.7 s, measured 2026-09-27); split the question
E_UNITa unit that cannot be read — a word, optionally with a power (m2), joined by · or /
E_UNKNOWN_NAMEa formula names a row that does not exist
E_UNREADABLEthe instruments could not read the claim — the message says what they choked on
E_VALUE_FORMa value that is neither a number, an interval nor ?
E_VALUE_SETa choice between values, {0,10} — that is two rows, not one quantity
W_NO_GLOSSno gloss, so nobody can check the name means what it seems to
W_SOLVEDa `?` value was read as the question and solved: EARNED is the established answer to 'which values satisfy the claim', not a statement about the actual value — to ask whether the claim holds for a real input you do not know yet, give its range, e.g. [0,inf]
W_UNIT_NO_VALUEa unit with no value