__
____ ____ / /___ _____ ____ _
/ __ \/ __ \/ / __ `/ __ \/ __ `/
/ / / / /_/ / / /_/ / / / / /_/ /
/_/ /_/\____/_/\__,_/_/ /_/\__, /
/____/
provenance in types · silence as a value · irreversibility gated
A protocol of honest inference that cannot be broken — because the breach is inexpressible.
The name reads three ways, and all three are meant. First, its origin: NOL is Nevis Ontology Language — named in 2026 for the agent it was being built around, when the goal was stated as
"an operating environment for you". Second, NOL + lang. Third — no lang: what you write
here are not programs. There is no control flow, no recursion, no functions, and there will not be.
You keep a record: what is known, what it stands on, and what was done on that basis.
nolang is a layer between an agent and its operator: a protocol saying when the agent may act and what it must account for — executed by a small language written for that one purpose.
Not a library the agent calls, not a framework it runs inside, not a wrapper around a model. A contract in the middle, and a compiler that will not let either side pretend it was kept.
That distinction is the whole point:
A protocol you agree on can be violated — it rests on discipline and good faith. A protocol embedded in a language cannot: the violation has nowhere to be written.
The nearest relative is not a network protocol but a protocol in Swift, an interface in Java,
the iterator protocol in Python — a contract the compiler enforces. Same idea, one floor up:
here the contract is about the origin of knowledge and the right to act on it.
Four levels, and none holds alone. They are not four ornaments — they are the enforcement mechanism of one protocol.
| protocol requirement | enforced by | how |
|---|---|---|
| a grade may not be claimed above its sources | types | no rule raises a grade — laundering is not forbidden, it is inexpressible |
| belief may not be laundered into honesty | algebra | the two live on different carriers; there is no arrow upward |
| the irreversible needs a threshold and a way out | grammar | the gate is inside the production — seven bad states cannot be written |
| a refusal must carry its reason; an action must remember its basis | machine | refusal is a value with a shortfall; the ledger keeps every justification |
A library could give you one of these, as a convention. Enforcing four at once is what requires a language — and that is the whole answer to "why not just a library".
Three distinctions carry it:
Belief accumulates, honesty degrades. Confidence rises with every witness — even a refuting one, because refutation is knowledge too. Source grade only falls: mix strict with image and you get image. Laundering is the attempt to merge these two operations into one.
Silence is a value, and it has two roles. Load-bearing ("tradition is silent, therefore…") is an argument from silence and drops the grade to bottom — even beside two strict witnesses. Survey ("we looked here and here, nothing") leaves the grade alone but must be printed. And silence is linear: you cannot drop it. Asked, found nothing, said nothing about it — the program does not assemble.
Refusal is a value, not a crash. A gate that does not let an irreversible action through
does not fail: it produces a fold carrying the shortfall — how much belief was missing.
0.112 is not a verdict, it is a work order.
A real case: a national antiviral stockpile bought while most of the underlying trials were
unpublished. Every fact in it is sourced — see ПРИМЕР_ФАРМАКОЛОГИЯ.md for the full apparatus.
lattice design = observational < randomised
lattice transmission = unavailable < abstract < published < full_report
lattice grade = design * transmission ; grades need not be linearly ordered
witness kaiser2003 : (randomised, published)
says "meta-analysis of ten manufacturer trials: fewer complications"
source ten_trials ; the ROOT: channels of one source count once
evidence 2 for 0 against ; counts, not (f,c) — the carrier, not the chart
witness eight_abstracts : (randomised, abstract)
says "eight of the ten datasets exist only as congress abstracts"
source ten_trials
evidence 8 for 0 against
witness cochrane2014 : (randomised, full_report)
says "twenty trials, read from clinical study reports rather than papers"
source cochrane_csr
evidence 20 for 0 against
witness press_release : (observational, unavailable)
says "manufacturer statement to the press"
source press_office
evidence 1 for 3 against
ask registries
in clinicaltrials_gov, eu_register, regulator_archive
found nothing because "full reports of the ten trials are not public"
claim benefit
from all where grade >= (randomised, abstract)
requiring 2 roots ; quantify over the WHOLE corpus, not by name
searched registries
reversible action write_off
gated by belief >= 0.1
else fold ; у возмещения СВОЙ гейт, а не порог того, что рухнуло
compensable action stockpile compensated by write_off
gated by belief >= 0.96
else fold
irreversible action publish_guidance
needs grade >= (randomised, abstract) ; требование к ПРОИСХОЖДЕНИЮ, проверяется типом
gated by belief >= 0.96
else fold
irreversible action recommend
needs grade >= (randomised, abstract)
gated by belief >= derived gain 1 loss 12 learn 0.6 discount 0.9
else fold
perform stockpile on benefit
perform publish_guidance on benefit
perform recommend on benefit
retract ten_trials because "the review was obliged to exclude this meta-analysis"
Run it: ./run_example.sh examples/evidence-gate.nol — exit code 5: performed, then orphaned.
ЗАМЕЧАНИЕ [gate-fail] у RECOMMEND: необратимое RECOMMEND при массе веры 0.966 < 0.987.
BENEFIT : [observational·unavailable] f=1.000 c=0.952 b=0.952
на чём стоит: COCHRANE2014
⊗ отсеяно квантором: 1 PRESS_RELEASE
🔴 из них 1 с частотой НИЖЕ полученной веры (0.952): PRESS_RELEASE
их исключение ПОДНЯЛО веру — проверьте, отбор ли это или черри-пикинг
⊘ НЕДОБОР КОРНЕЙ: требовалось 2 различных, есть 1 — степень на дне
⌕ охват REGISTRIES: искали в CLINICALTRIALS_GOV, EU_REGISTER, REGULATOR_ARCHIVE — …
✓ совершено STOCKPILE на основании BENEFIT — вера 0.966 ≥ порог 0.960
✓ совершено PUBLISH_GUIDANCE на основании BENEFIT — вера 0.966 ≥ порог 0.960
⊘ свёрнуто RECOMMEND на основании BENEFIT: вера 0.966 < порог 0.987, не хватило 0.022 → FOLD
✂ ОТОЗВАН свидетель TEN_TRIALS: the review was obliged to exclude this meta-analysis
⚠ ОСИРОТЕЛО STOCKPILE: основание BENEFIT пересмотрено, вера 0.952 < порог 0.960
требуется компенсация: WRITE_OFF
↩ ВОЗМЕЩЕНИЕ WRITE_OFF совершено на основании BENEFIT: вера 0.952 ≥ его порог 0.100
возмещает STOCKPILE · корни: COCHRANE_CSR
⚠ ОСИРОТЕЛО PUBLISH_GUIDANCE: основание BENEFIT пересмотрено, вера 0.952 < порог 0.960
действие НЕОБРАТИМО — компенсация невозможна. Вот зачем гейт.
✖ НЕПОПРАВИМО: PUBLISH_GUIDANCE на основании BENEFIT — вера 0.952 < порог 0.960,
а действие необратимо. Возместить нечем. ВОТ ЗАЧЕМ ГЕЙТ.
The published paper and the congress abstracts descend from one set of trials, so they count once; the press release is filtered out by the quantifier, and because its frequency is below the belief already accumulated, the run flags it: excluding it raised belief, which is the measurable shape of cherry-picking.
The irreversible recommendation never fired — the derived threshold held, and the fold carries
the shortfall 0.022 as a work order, not a verdict. The compensable stockpile did fire; then the
root was retracted, its basis fell below the threshold, and it was compensated, not merely
flagged. After the retraction only one root remains, requiring 2 roots is unmet, and the grade
drops to the bottom of the lattice — a set requirement, not an average.
Every entry below was opened and checked on 29 July 2026, not recalled. For each: what we took, and — the harder half — what we did not take. A novelty claim has already been withdrawn here once; we would rather name a predecessor than be told about one.
-
Truth maintenance — Doyle, Jon. A truth maintenance system. Artificial Intelligence 12(3):231–272, 1979 (also MIT AI Memo 521, June 1979). From the abstract: "reasoning programs must be able to make assumptions and subsequently revise their beliefs when discoveries contradict these assumptions… by recording and maintaining the reasons for program beliefs." Taken: retraction is recomputation over recorded reasons, not subtraction from a number. Our
R-RETRACTis this, forty-seven years later. Not taken: they have no types, no source grades, no threshold on irreversibility, and nothing that makes a dishonest step unwritable — a TMS records reasons, it does not forbid. -
Provenance semirings — Green, T. J.; Karvounarakis, G.; Tannen, V. Provenance Semirings. PODS 2007, pp. 31–40, doi:10.1145/1265530.1265535. From the abstract: "relational algebra calculations for incomplete databases, probabilistic databases, bag semantics and why-provenance are particular cases of the same general algorithms involving semirings." Taken: provenance as an algebraic annotation that composes with the computation — the shape of our
⊕/⊓pair. Not taken: there the annotation is a label on a result; here the grade is a type that forbids. And their setting has no actions, hence no irreversibility and no gate. -
Evidence-based opinion — Wang, Pei. Non-Axiomatic Reasoning System. Truth value ⟨f, c⟩ with f = w⁺/w and c = w/(w+k), where k is the evidential horizon. Jøsang, Audun. Subjective Logic (FUSION 2022 tutorial, author's own page): binomial opinion ↔ Beta PDF, "(r,s,a) represents Beta PDF evidence parameters; (b,d,u,a) represents binomial opinion", r = Wb/u. Taken:
(f,c)itself, revision as addition of evidence, and the reasonc < 1always — the horizon k, not modesty. Alexey arrived at the pair independently; the correspondence with Jøsang's beta-opinion is a convergent result, and it is named as his, not ours. Not taken: a calculus is not a language. No grade lattice, no types, no gate, no ledger. -
Imprecise probability — Walley, Peter. Inferences from multinomial data: learning about a bag of marbles. JRSS-B 58(1):3–57, 1996 — the imprecise Dirichlet model. Our credal bound is the IDM for the binary case, term for term:
IDM here lower nᵢ/(N+s)w⁺/(w+k)upper (nᵢ+s)/(N+s)(w⁺+k)/(w+k)imprecision s/(N+s)k/(w+k)The caution parameter
sis our horizonk— same formula and same meaning (Walley definessas the number of observations needed to halve the imprecision). We arrived at it from the other end, needing to tell "I know it is even" from "I know nothing"; given that NARS and Jøsang both rest on the Beta model, converging on its imprecise version was predictable in hindsight. Said plainly rather than dressed as novelty: the construction has thirty years of literature, known properties and known weaknesses.🔴 What is ours is not the mathematics but the discipline of the moment. The standard objection to the IDM is the arbitrariness of
s— it is chosen, usually after seeing the data, and every conclusion moves with it. Herescannot be tuned to the result:horizonis a prelude form, and the prelude is written before it is known what will be judged. Not forbidden — there is nowhere to write it;horizondoes not parse inside a program. Pre-registration by grammar. It does not make a chosensright; it makes it impossible to fit after the fact.The idea of fixing a parameter before the data is old and is not ours — pre-registration in psychology, Pre-SPEC in clinical trials, regulatory Bayesian protocols. What differs is the carrier of the discipline. In all of those it is a document; in a 2026 protocol against LLM p-hacking it is time (the target model does not exist at commitment time, so "it cannot be hacked against"); in Imp — the closest technical neighbour, an imprecise probabilistic DSL whose type system separates declaration from inference — the separation is structural, about where uncertainty lives in a type, and it has no caution parameter at all. A grammar as the carrier, for the caution parameter of an imprecise model, is what a targeted survey (06.08.2026) found no precedent for.
⚠️ A targeted survey is not a systematic one: absence of a hit is not proof of absence.⚠️ And what this bound is not: it is not conformal, and it carries no coverage guarantee. It measures how much ignorance remains at this evidence count — not the probability that the truth lies inside. Conformal calibration is orthogonal to it, not a substitute (seeStatus, point 3). -
Information-flow types — Myers, A. C.; Liskov, B. Protecting privacy using the decentralized label model. ACM TOSEM 9(4):410–442, 2000 (language: Jif). The model "improves on existing multilevel security models by allowing users to declassify information in a decentralized way." Taken: the mechanism of a label carried in the type and checked statically. 🔴 Not taken — and this is the sharpest difference in the whole list: there the label flows up and
declassifyexists under authority. Here honesty flows down and there is no declassify at all. Their question is who may look; ours is what this stands on. Same machinery, opposite direction, and one deliberate absence. -
Quasi-option value — Arrow, K. J.; Fisher, A. C. Environmental Preservation, Uncertainty, and Irreversibility. Quarterly Journal of Economics 88(2):312–319, 1974 — the value of waiting when the damage is irreversible. Taken: the threshold θ is derived from cost of error, value of learning and discount — not chosen. That is why
gated by belief >= derived gain … loss … learn … discount …exists. Not taken: their economics of environmental choice; we use the shape of the argument, and say so rather than dressing it as our own. -
Graded types / coeffects and durable execution (Temporal, Restate) — the indexed-type mechanism and compensation-on-failure are standard practice. Not taken: compensation there fires on failure; here it fires on revision of the basis, which is a different event and needs its own gate.
What we did not find in any of them (and therefore claim, until refuted): silence as a
linear type with two roles; the load-bearing/survey distinction catching argument-from-silence
in the type system; the gate on belief mass b = f·c with a self-centering criterion; the
requirement on source grade in the type of an action, so that irreversible action on
bottom-grade evidence is not a caught program but an unwritable one; and the assembly of all
four levels — grammar, types, algebra, machine — in one language.
The point of separating them is that a reader can tell, for any claim on this page, which kind of thing it is. Where a claim moved between lists, it is said so.
Ten modules, by Nevis and ArkH, synthetic minds of the ArkH contour. On the count itself see Status below — this README once inflated it, and the battery's own counter is stricter than the prose.
-
preservation — the grade the compiler assigns is the grade the machine computes. (The formulation had to be corrected first: retraction changes the grade, so what is proved is equality of functions from the retracted set to grades.)
-
perm-inv — confluence for any permutation of declarations, not just adjacent swaps.
-
empty-base(an empty premise set yields ⊥, not the lattice top) ·silence-kills·retract-raises/retract-collapse. -
⊕ is a commutative monoid with silence as unit and is not idempotent;
⊓is idempotent and only degrades. "Belief accumulates, honesty degrades" is two proved structures, not a slogan. -
Theorem 5 both ways:
b(x ⊕ e) < b(x) ⟺ f(e) < b(x). A witness lowers belief not by being "against" but by being below the belief already accumulated. The gate self-centers. -
Module import:
φ(a ⊓ b) = φ(a) ⊓ φ(b)andφ(⊥) = ⊥are not merely sufficient but equivalent to "map-then-fold = fold-then-map"; monotonicity is a consequence. -
SupportSet: mass is defined by membership, so
∪-idem(a shared ancestor counts once),∪-comm(order of premises is nothing) andderived≡directhold structurally. -
CredalBound: belief is a segment, not a point —
f·ccollapses two independent quantities into one, and at the gate "probably yes, little data" becomes indistinguishable from "roughly even, plenty of data". Proved: the bounds are ordered; the lower bound is the present belief (so nothing changes for the gate — it was already reading the cautious end); width equals the horizon; the segment narrows with evidence; and it never closes (Ein-Sof / AIKR as a theorem, not a caveat). 🔴 And what is not proved, stated first:unreachabledoes not mean "no evidence will ever help". The first draft of this comment claimed exactly that and was refuted in a minute — a 50/50 split is unreachable at θ=0.9, yet +500 witnesses for reach it. The upper bound is the limit of completing what is already here, not a prophecy.unreachable-is-about-nowstates that and nothing more. 🔴 And the trichotomy itself is not ours.passed / reachable / unreachable— comparing both ends of the interval against a threshold — is interval dominance, a standard decision criterion under imprecise probability, and a sibling of Yao's three-way decisions (positive / boundary / negative = accept / defer / reject).passedis skeptical inference by the lower probability;unreachableis its mirror. We reached it independently, from needing a third outcome that is not a weak "no" — but a survey (06.08.2026) placed it squarely in existing literature, and it was withdrawn as a claim to contribution before it reached a paper rather than after. It stays in the language because it is right, not because it is new. -
SourceCeiling: a grade cannot be raised by provenance.
ceiling(the result is never above the source's class),honest-preserved(a claim at or below the class passes through unchanged — a ceiling that also cuts the truth is a gag, not a ceiling),chain-falls(down afromchain the class only descends),chain-ceiling(bounded by every ancestor, not just the nearest),no-laundering(there is no claim that yields a grade above the class — the prohibition is not written anywhere; there is simply nowhere for the lie to go). -
Act:
bottom-blocksandno-irreversible-on-bottom— with a non-⊥ requirement, an irreversible action on bottom-grade evidence cannot be typed;no-resurrection— an orphaned action never revives, however much evidence arrives later. -
All of it without a single real number: comparing fractions with positive denominators is comparing products, so the carrier is pairs of weights in ℕ.
- 598 laws and checks in the battery; every one runs on every commit.
- 1200 random programs compared against the compiled Agda model (
oracle/build.sh), zero divergences. 🔴 This bounds the divergence by the number of trials — it does not prove equivalence, and the model covers the grade alone: root folding, weight, quantification, the gate and the ledger stay outside it. - Every checking instrument here is itself tested for its ability to say no: the oracle
harness catches a deliberately broken
g-meeton 153 of 200 programs; thePROV-Nparser accepts the specification's own example and rejects seven mutations of it. - 16 000-trial simulations for the conformal guarantee.
- That silence-as-a-linear-type, the load-bearing/survey distinction, the belief-mass gate, the grade requirement in an action's type, and the assembly of all four levels together are new. Checked against the lineage above by search, not by memory — and one novelty claim has already been withdrawn here once.
- That the language is worth its narrowness. Narrow it must be: a gate has to decide, and a decision has to terminate; with general recursion "does it pass the threshold" is undecidable.
🔴 The boundary we do not paper over: Agda proves the model, not the Lisp. chk and red
there are freshly written definitions. What is proved is that the checker's algorithm equals the
machine's; that our Lisp implements those algorithms rests on the oracle, the tests and reading.
🔴 Not proved and cannot be: that a threshold will be met. f and c are run-time
quantities. Types guarantee not the absence of refusal but that refusal is handled.
:requires (>= belief 0.9) — where does nine-tenths come from? Nowhere. A threshold taken from
the air cancels all the rigour around it.
Meaning (Arrow–Fisher): an irreversible act destroys the option to wait and learn.
θ = L / (G·(1−K) + L), K = δλ / (1 − δ(1−λ))
K is the quasi-option premium as a fraction: how much of the gain is eaten by the destroyed
possibility of waiting. Limits check out — λ=0 gives the classical L/(G+L); λ=1, δ=1
(free perfect information) gives θ=1: an irreversible act is never justified.
And since b = f·c < 1 structurally, θ=1 is unreachable — so "wait for certainty before
acting irreversibly" is a policy that never acts. A finite carrier cannot wait for certainty;
it will not come.
Procedure (conformal risk control): the ledger is the calibration set. It requires no
belief in your own numbers — only exchangeability, which is exactly what Chow's reject option
cannot give us: it needs a calibrated posterior, and our c is uncalibrated by construction.
git clone https://github.com/arkh-node/nolang && cd nolang
./run_tests.sh # test files + Agda modules + the oracle
./run_example.sh examples/chronicle.nol --prelude examples/chronicle.nolp --require write_to_chronicle # what a YES looks like
./run_example.sh examples/evidence-gate.nol # what a gate is FOR
./run_sexp.sh examples/sexp/migration.nol # the EARLY layer — a different carrier
Required: SBCL. For the formal part: Agda with the standard library
(./run_tests.sh rebuilds every module from scratch, --safe).
Optional, and named here because it used to be invisible:
| dependency | what it unlocks | without it |
|---|---|---|
arkh-node/ilan — clone next to nolang, or set ILAN_PATH |
the gate↔ilan bridge: fold / sprout / sow, and the world snapshot | 02_return and 05_world skip and say so; the core, types, gate and battery run without it |
ONA's NAR binary (NAR=/path/to/NAR) |
the NARS bridge, stone 07 | 07_nars skips |
🔴 Until 05.08.2026 src/return.lisp loaded ../../ilan/ilan.lisp unconditionally. That meant
the tests were green only for someone who already had ilan sitting next to nolang — on a
fresh clone the run died with a Lisp backtrace, not with a sentence. Found by doing what this
section now tells you to do: cloning into an empty directory and running the battery there.
A missing dependency and a broken program must be distinguishable; now they are.
nolang smoke tests (eight stones):
✓ 00_atom.lisp
✓ 01_gate.lisp
· 02_return.lisp ilan not found, the gate<->ilan bridge is not exercised
✓ 03_eval.lisp
✓ 04_nol.lisp
· 05_world.lisp ilan not found, the world snapshot is not exercised
✓ 06_types.lisp
· 07_nars.lisp skipped (set NAR=/path/to/ONA/NAR to run the NARS bridge — optional)
ALL GREEN ✓
With ilan present, the two dots become checks. The full battery in a working copy:
VSIO ZELENOE · runs, laws and checks: 787
formal — three numbers above, kept apart (adding them would mix kinds)
run_example.sh answers the machine with a return code; the printout is for the human.
Until 30.07.2026 the verdict was read by grepping the output — and a witness whose says "…"
contained the expected line forged the answer. A process's exit code cannot be written from
inside the program it judges.
| code | meaning | |
|---|---|---|
| 0 | allowed | the required action was performed |
| 1 | rejected | the program should not exist (grade too low, threshold at the floor, syntax) |
| 2 | tool failure | judging did not happen because something broke |
| 3 | no trial took place | reserved: emitted by a disarmed gate, never by the language itself |
| 4 | withheld | legal program, belief below threshold — or nothing was decided at all |
| 5 | performed, but flawed | done, then orphaned / unauthorised / irreparable |
--require NAME is not decoration: without it a program that does nothing returns "nothing
stood in the way", and emptiness passes any gate. Whoever asks about an irreversible action must
name it.
The language knows no names. needs permission from <who> takes any identifier — a person,
a role, a council; to "<target>" takes any address. Our own ruler lives in a .nolp file
outside the repository it judges, and the loop that uses it (nolgate.sh, not part of this
repo) reads its own config: whose operator stream, which agent, who may permit by default.
Take the language and write your own name in — there is nothing of ours to delete first.
Identifiers are Latin throughout. Cyrillic lives where it belongs — inside strings: the text of a witness, the wording of a quote.
Two carriers share the .nol extension. The surface syntax above is read by
compile-nolang; examples/sexp/ holds the early layer (s-expressions, three-valued gate over
(f,c) atoms) read by run-nol. They are not the same language — see examples/sexp/README.md.
Every example's expected exit code is declared in examples/EXPECTED.tsv and checked by
test/V2_examples.sh, so a showcase that quietly stops working now fails the battery.
sbcl required; agda optional (the battery reports its absence as a failure, not a pass).
- Rego (OPA) and Cedar answer who may do what to which resource. nolang answers is the basis good enough. Orthogonal axes — and they compose: policy decides who, nolang decides on what it stands.
- W3C PROV (
PROV-DM/PROV-O/PROV-N) records provenance; it does not forbid laundering it. No type system, no gate, no retraction propagation. PROV is an interchange format for us, not a competitor — and now literally so:src/provn.lispexports the store and the ledger as aPROV-Ndocument (retraction becomeswasInvalidatedBy, the gate's belief and threshold become attributes). 🔴 The bridge is one-way by design. Their notation carries the record; it cannot carry the prohibition. There is no import, and there will not be: to accept a foreign provenance document would be to accept grades nobody gated. - MCP / A2A are transport: how to call a tool, how agents negotiate. Deliberately narrow — governance lives a layer above, which is exactly where this sits.
Not a general-purpose language, and not becoming one. There are no expressions, no functions, no branches — v0 is declarations only. That is deliberate: first what is written must be right, only then plentiful. The closest familiar shape is a spreadsheet: pure declarations, real computation, no control flow. Nobody writes an operating system in one, and nobody should try here.
There is real computation — retraction propagates through the dependency graph, and rules
quantify over the whole corpus (from all where grade >= … requiring 2 roots), so the result
cannot be read off the source. But it is a fold over a DAG, not a program in the ordinary sense.
🔴 Selection is the laundering vector quantification brings: count only the strict ones and
never notice the dissent. Measured: b goes 0.611 → 0.713 by filtering. It cannot be forbidden —
filtering can just as well lower belief by excluding a supporter — so instead what was
dropped is printed, and the dangerous drop is identified by theorem 5: a witness whose frequency
is below the resulting belief is exactly the one whose exclusion raised it. perform writes to the ledger; the bridge outward is a pluggable handler and it is
one-way — its return value is discarded, so the world cannot launder provenance through
outcomes ("it worked, therefore the basis was good").
A defect we shipped, and fixed (2026-07-26). Until then public main combined confidences by
multiplication (c = ca·cb): two agreeing witnesses lowered confidence. Fixed in
src/evidence.lisp — revision as evidence addition.
A novelty claim we withdrew (2026-07-27). The banner used to read "continuity across death", and the design notes claimed death-as-a-reduction-step was new. It is not: Crash Hoare Logic (FSCQ, Perennial), Racket's serializable continuations, orthogonal persistence, and the whole durable-execution industry got there first. Withdrawn before publication, not after.
Ein-Sof (c < 1). Earlier this README called the name "ours and decorative". That is no
longer accurate, and understating is as inaccurate as overstating: c < 1 now works as a
premise inside two machine-checked proofs (support-never-drops) and inside the derivation of
θ. The constraint is Wang's (AIKR); the name is ours; the role is load-bearing.
Six of our own false statements were withdrawn during development, each by a failing test
rather than by argument: ⊕ is idempotent · "a disagreeing witness always lowers belief" ·
"the compiler proves b ≥ θ on all paths" · the novelty claim above · a theorem count inflated
by a broken regex · a test that declared a correct method violated on 0.4σ of noise.
Not a list of unfinished work. Every line here is a boundary of the method, and no amount of further engineering removes it. They were scattered across module headers, where only someone reading the sources would find them; collected here because a reader of the README deserves them first, not last.
The distinction matters more than the list: "not done yet" invites patience, "cannot be done" invites a different design. Confusing the two is a quiet lie that surfaces at the worst moment.
| boundary | why it cannot be closed | where it lives |
|---|---|---|
| That recorded premises correspond to the past | a claim about the world, not about a computation; nothing inside the computation can settle it | formal/ReEntry.agda header |
| That the ledger corresponds to what happened | performed says the language permitted an act, not that the world underwent it |
formal/Ledger.agda header |
| The last link of a subject chain | whoever holds the chain from its first link can build another, equally consistent one; no hash changes this | src/anchor.lisp, ANCHORS.md |
| Independent evidence of time | git timestamps are written by the committer; :witnessed is about content, never about when |
ANCHORS.md |
| That θ is the right threshold | a question about the cost of error in the world; the language only enforces the θ that was declared | formal/Gate.agda header |
| Coverage guarantee for the credal interval | the bounds come from counting evidence, not from calibration on labelled data — it measures remaining ignorance, not the chance of containing the truth | src/evidence.lisp |
| Equivalence of the Lisp and the proved model | the oracle bounds divergence by trial count; a proof would require a verified compiler | test/D1_oracle.lisp header |
| Detecting that the world drifted | what is observable is a change of scene; the world can move while the scene stands still, and then the signal is silent — "silent" means "same scene", not "calibration sound" | src/theta.lisp |
| Liveness properties at an irreversible gate | "every pay is eventually followed by confirm" is outside the safety class an irreversible gate can enforce — a proved ceiling, not ours |
Status, point 3 |
🔴 One rule came out of collecting these, and it is worth more than the table: a boundary
lives where the quantity lives. The credal interval's caveat existed in this README and was
absent from evidence.lisp, where the function is defined — visible to whoever read the prose,
invisible to whoever read the code. Fixed on 06.08.2026; the same sweep produced this section.
Three different things get called "checked" here, and conflating them is the failure mode this project keeps catching in itself. They are kept apart:
- proved — a machine-checked theorem in Agda under
--safe; - oracle — Lisp compared against the compiled proved model on random programs; this bounds divergence by trial count, it does not prove equivalence;
- battery — run on cases and invariants; evidence, not proof.
| mechanism | proved (Agda) | oracle | battery |
|---|---|---|---|
| grade lattice, meet, order | Preservation, SourceCeiling |
✅ | ✅ |
| static grade = runtime grade | Preservation |
✅ | ✅ |
| source ceiling (grade not raised by provenance) | SourceCeiling |
— | ✅ B1_source_ceiling, I2 |
| support set, shared root counted once | SupportSet |
— | ✅ |
belief mass, revision ⊕ |
BeliefMass |
— | ✅ |
| credal bound (belief as a segment) | CredalBound |
— | ✅ C1_credal, I2 |
| actions, statuses, irreversibility | Act |
— | ✅ |
| preconditions (honest ones survive) | Precondition |
— | ✅ 06_types, A1_bridge |
module import (⊓ preserved) |
ModuleImport |
— | ✅ |
| representative / copies | Representative |
— | ✅ |
| re-entry (replay, not load) | ReEntry |
— | ✅ C2_subject, V7 |
| gate (θ, permit, outcome) | Gate ✅ (added 06.08, see below) |
— | ✅ 01_gate, 99_theta |
| ledger (record sequence, refusal as value) | Ledger ✅ (added 06.08) |
— | ✅ V1–V6 |
quantifiers (all, exists) |
🔴 not proved | — | ✅ B1_quant, G1_query |
| digest / anchor | 🔴 not proved | — | ✅ D5, D6, D7 |
| θ-calibration under drift | 🔴 not proved | — | ✅ R1_robustness |
| prelude/programme split (the moment rule) | 🔴 not proved | — | ✅ V3_prelude |
| PROV-N export | — (one-way, by design) | — | ✅ F1_provn |
🔴 Read the gaps, not the ticks. Drawing this map is what produced formal/Gate.agda: ten
modules and 927 checks stood around a door nobody had proved anything about. The gate is the
one place where computation stops being computation and becomes an act — after it, publish has
happened. Everything else in the language can be replayed; that cannot.
Four theorems now hold there, and one is worth stating in full:
Insufficient confidence cannot be compensated by belief. When
c < θthe outcome is the same for every value off— however strong the conviction, the gate does not open (low-confidence-ignores-belief). This is precisely why the gate reads the pair(f,c)rather than their product: in a product, low confidence is substituted for by high belief and the distinction disappears.
The others: irreversible action requires a confident yes and can be reached no other way; rising
confidence never revokes a yes already given (a non-monotone gate would punish collecting more
evidence); and fold-first ≠ denied — under uncertainty an action is downgraded to reversible,
not forbidden, because refusal here is a value with a shortfall rather than a crash.
The ledger is now proved too (formal/Ledger.agda), and it carries the two promises that
had been words until today:
Refusal is a value with a shortfall, not a crash. When the gate folds, the shortfall is strictly positive — a number you can produce, showing exactly what was missing (
folded-has-shortfall). And when the threshold is met, the shortfall is zero: without that second half the first is satisfied by a language that attaches a shortfall to everything.
A collapsed basis appends, it never erases. Revision produces
orphanedrecords in front of the ledger; the originalperformedrecord is still there afterwards (performed-survives-orphaning). Retraction does not undo the past — it writes down that the past no longer holds. That is precisely why this history is auditable: nothing disappears from it.
Also proved: what was folded never orphans — an action that did not happen cannot be orphaned later, or the language would blur "did it for nothing" into "did not do it".
performed record says the language permitted an action, not that the
world underwent it. That gap is method, not defect.
What remains without proof: quantifiers, the digest/anchor machinery, θ-calibration under drift, and the prelude/programme split.
And the oracle column is nearly empty on purpose: the compiled model computes the grade (T-CLAIM plus retraction) and nothing else. Everything else in that column would be a lie.
Seven things a reader is entitled to know before deciding what this is. Each is checkable in the tree; none is here as modesty.
1. The theorem count in this file was wrong, and the battery knew it.
Until 05.08.2026 the line above read "Five modules, 51 theorems". There are now ten modules,
and formal/count.sh — the project's own counter — reports something the prose did not:
CONTENTFUL (about the subject matter): 57 ← after a second gate, down from 65
DEFINITIONAL (rungs, not theorems): 101
DEFINITIONS (nothing to mark): 110
UNMARKED: 0
sum of kinds + debt = 268 = number of signatures ✓
🔴 The 57 survived an adversarial second pass — and eight did not. On 07.08.2026 Nevis read the count and made a distinction sharper than mine: the bookkeeping is honest and self-checking, but the semantic split cannot be guaranteed by any script — under Curry–Howard the boundary is undecidable, so it rests on the author's hand. Her verdict: "one module ≠ all 65".
So every contentful claim was put through her Law XII — does the proof consume hypotheses,
is it provable as id, and what breaks in reality if it is false. The first two are checkable
by machine (formal/gate2.py); the third is not — it is a claim about consequences, not about
text, and it was answered by reading.
Eight were demoted, and the most instructive is this: perm-blind-grade turned out to be
unauthorized-on-revoke under a different name — same type, body literally = unauthorized-on-revoke.
One theorem had been counted twice. Others: a claim of the form Typed b a → Typed b a proved by
= t, which is literally id; a hypothesis that was ignored in the proof (_ = refl) and so
decorative; and several true-by-definition rungs.
preservation, the central theorem — because "consumes no hypotheses" is a bad
criterion for statements of the form ∀ x → f x ≡ g x where f and g are defined
independently: those carry content precisely by relating two computations. Its second version
missed rewrite, reading f x p rewrite p = refl as a trivial refl when the hypothesis is
consumed by the rewriting. Both are the same failure this project keeps finding in itself: a
measure that does not measure the quantity it names.
236 module-level statements typecheck under --safe. As of 06.08.2026 every one of them
carries a verdict — the debt that stood at 221 is closed.
🔴 Read the jump from 10 to 57 correctly: not one new proof was written. The work was sorting, not proving. Three things came out of it, and two are unflattering:
- The old count was inflated by double counting. The counter was a
grepfor markers, so an explanatory comment that itself begins with a marker —-- ⟦contentful⟧ THEOREM 1 (…)— was counted alongside the real annotation above the signature. Five theorems read as ten. It now counts by binding: a verdict counts only when a signature stands directly beneath it, and the sum of kinds must equal the number of signatures or the counter fails loudly. - Some marks were attached to the wrong thing. In
ReEntrya⟦contentful⟧sat above a section heading, and the first signature under it was the definition_++_— so the verdict landed on a definition while the section's actual theorem had none. A marker not bound to a statement still counts, and still means nothing. - The debt itself was overstated. Definitions (
run : List Premise → G) can be neither contentful nor definitional; they are simply definitions. While they sat in the denominator the number claimed "221 unexamined theorems", where the real figure was under half that.
formal/classify.py) proposes; the author decides by reading; the
verdict is written directly above the statement so any reader can disagree with a specific line
rather than with a number. That, not an algorithm, is what keeps the denominator honest.
This is the third time a count here was wrong — the first two are recorded below under withdrawn statements.
🔴 And the counter itself was measuring short. On 06.08.2026 the two counters of the same
quantity were found to disagree: the test runner reported 236 module-level statements, while
formal/count.sh reported 146. The counter matched only lines indented by exactly two spaces
and so missed the entire top level of every module — the same defect Nevis had already fixed in
the runner on 29.07, whose fix never reached this file. Ninety statements were counted nowhere,
and the consequence fell on the one number that matters: UNMARKED — the debt — read 131 when it
was 221. Understating a debt is worse than understating an achievement; the second is modesty,
the first is reassurance. Both counters now use the identical rule.
2. (f,c) is settled for revision and for conjunction, and open for the difference between
"unknown" and "evenly split".
Revision was fixed on 26.07.2026 (t-revise adds evidence; confidence strictly rises).
c = ca·cb survives only in t-and/t-or, where it is correct for independent events and the
docstring says so. Idempotence is handled structurally, not by convention: support is a set
of roots and mass is defined by membership, so a shared ancestor counts once (∪-idem, proved),
while ⊕ is deliberately not idempotent (⊕-not-idem, proved) because two distinct
witnesses must raise belief.
🔴 What a scalar c still cannot express: the difference between "I know it is even" and
"I know nothing". That is what credal sets are for, and it is the open work — not idempotence.
3. What a pre-execution gate can enforce is a characterised class — and it has a ceiling.
Deterministic pre-execution gates enforce exactly the safety policies whose good prefixes are
recognisable by register automata (Theorem 1). Some
properties are unreachable in principle — "every pay is eventually followed by confirm"
cannot be enforced by an irreversible gate. So the honest reading of "a breach that is
inexpressible" is: inexpressible within the safety class, which is the class irreversibility
lives in. The ceiling is not ours; it is proved, and it is the right ceiling for this problem.
4. The oracle bounds divergence by trial count — and the "blind quarter" was our own error. 1200 random programs against the compiled Agda model, zero divergences. That bounds divergence by the number of trials; it does not prove equivalence, and nothing here should be read as if it did.
The harness is itself tested for its ability to say no. Until 06.08.2026 this section reported
that it catches a deliberately broken g-meet on 153 of 200 programs, and called the
remainder a blind quarter — "roughly a quarter of breakages of that shape would pass unnoticed."
🔴 That claim was false, and the correction is not a softening. The harness compares Lisp against the oracle, and on the untouched function divergences are zero — so the reference is what intact Lisp produces. Therefore "the harness caught it" ⟺ "the corruption changed the output", identically by construction: what is caught cannot be fewer than what is observable.
Measured directly: on those 200 programs the output changes for 153 and does not change for 47. So the harness catches 153 of 153 observable cases — all of them. On the other 47 there is nothing to catch: the broken function returns exactly what the intact one returns.
What those 47 are — and this is the useful part. Twenty-four of them are programs whose single witness has been retracted: every premise is dead, the result falls to bottom by construction, and there is nothing left to meet. The rest have one live premise. They cannot be removed from the sample — they exercise retraction and bottom, which is a different question — but they must not sit in the denominator of sensitivity either, because that would measure the generator's diversity while claiming to measure the watchman's eyesight. The battery now computes both numbers and asserts equality, not a threshold.
Sensitivity to the other load-bearing places is now measured too (test/mutants.sh, added
06.08.2026). Nine deliberate corruptions — the lattice meet, the order, the source ceiling, the
credal bound, the gate, the ledger, retraction, the subject digest, the anchor's strength — are
applied one at a time to the sources, with the full Lisp battery run against each. All nine are
caught; no holes.
🔴 But the useful number is not nine — it is how many checks catch each one. g-meet is
caught by 15 tests at once; the gate by 9; the ledger by 6. Three places are caught by exactly
one: the source ceiling (B1_source_ceiling.sh), the credal interval collapsing to a point
(C1_credal.sh), and the anchor's strength being overstated (D6_anchor.sh). That is not a hole
today — it is a single point of support. If that one battery breaks, or turns green for the
wrong reason (which happened twice in a single day here), the corruption passes in silence. The
stand prints this explicitly rather than leaving the reader to count columns.
run_tests.sh; it is run
deliberately. Said plainly rather than left to be discovered.
5. 🔴 The threshold's guarantee rests on exchangeability — and does not survive its loss.
theta-conformal uses the ledger as a calibration set. That is a real strength: it needs no
belief in our own numbers, only that past cases are exchangeable with future ones. Until now
this file presented that as a virtue and stopped there. Here is the other half.
Measured (α = 0.1, 200 calibration cases, 200 test cases, threshold 0.420):
| world at decision time | share of false claims passing the gate | |
|---|---|---|
| same as calibration | 13.5% | within finite-sample noise: the guarantee is marginal, i.e. on average over draws |
| mild shift — falsehoods grew more convincing | 66.5% | 🔴 guarantee void |
| strong shift | 100% | 🔴 |
| adversarial — falsehoods tuned to the threshold | 100% | 🔴 |
It does not degrade gracefully. It collapses. And the dangerous part is not the number: it is that the gate does not know. Nothing in the machinery notices that the world moved; the threshold keeps answering with the same confidence it had when it was calibrated.
This is Theorem 5 in the concrete: under representation
attack a calibrated gate degrades to E[unsafe] ≤ min{1, δ + H·η̄(ρ)} — naive calibration gives
no security boundary.
Since 06.08.2026 the gate can be asked what its calibration is worth. theta-guarded
returns the threshold and a verdict on it in one call — because the two could previously be
obtained separately, and that is exactly how the gate ended up confident about a world that no
longer existed. The verdict is driven by the share of own-scene cases, not by whether
weighting was applied: the measurements showed weighting limits contamination but does not
substitute for having own cases (at 20 own out of 200 the leak was 99.5% unweighted and still
22.5% weighted). Four outcomes, and trust is stated aloud too — a signal audible only in the
bad case is indistinguishable from a broken one.
What we have against it, honestly: not a fix, but a signal. Since 05.08 a subject records
its scene — horizon, lattice, sources with fingerprints — and re-entry refuses when the scene
differs. A changed scene is not proof that exchangeability broke, but it is the one observable
event that usually accompanies it: new sources, a new domain, a different measure. Refusing to
continue in a changed scene is the cheapest available guard against a silently stale calibration.
And robust calibration is now done, not merely promised: weighted quantiles after Barber,
Candès, Ramdas & Tibshirani (Conformal prediction beyond exchangeability, Ann. Statist. 51(2),
2023), with weights driven by scene change — an observable event — rather than by recency,
which only correlates with drift. Where it helps and where it hurts is measured and printed
in src/theta.lisp, including the row where it made things worse.
6. 🔴 The subject chain protects the history, not the last link — and no hash will change that.
A serialized subject carries a fingerprint of the previous one, so altering any single record
breaks the chain at the next link: forgery cannot be local. Until 06.08.2026 those fingerprints
were computed with sxhash, the implementation's hash-table function — collisions are findable,
and, worse for our purpose, the value is not required to agree across implementations or even
across runs. A fingerprint that depends on the machine cannot serve a chain whose whole point is
to survive a change of machine (:ran-on is the first line of every ledger precisely because the
carrier changes). It is now SHA-256, written in-tree with no dependencies so that a clean clone
still builds, and — because a hand-written hash is worth exactly what it is checked against —
diffed against two independent references on block boundaries, multibyte input and control bytes
(test/D5_digest.sh, 14 checks). Records now carry the algorithm name (sha256:…), so a future
change reads as "different algorithm" rather than "tampered record".
What this still does not give: whoever holds the chain from its first link can build a different one, equally consistent, and every fingerprint in it will agree. The honest sentence is "forgery is never local", not "forgery is impossible". No hash closes this, and not because the hash is weak: "this history was not rewritten" is a claim about the world, unprovable from inside the computation.
Since 06.08.2026 src/anchor.lisp carries the machinery for the only actual remedy — a
witness. A digest placed where someone other than us can see it turns "rewrite the history"
into "diverge from someone else's record". Two things about it are worth stating plainly:
- An anchor cuts the chain in two. Everything up to the last anchor cannot be rewritten
without contradicting the witness; everything after it is still only "forgery is never local".
chain-anchored-prefixreports this as a count — n of m links protected — because the difference between 40-of-40 and 3-of-40 is the difference between a protected history and an unprotected one, and the old phrasing covered both. - Anchor strength is a grade, on the same lattice as source classes, and obeys the same law:
it cannot be raised by declaration. A digest written to our own disk is
:self— rejected, not accepted-with-a-note, because notes go unread. Only:witnessed(a second party holds a copy) and:notarised(independent evidence of time) count.
Since 06.08.2026 a digest is actually published — ANCHORS.md, class :witnessed, the
witness being this repository's own history as mirrored by every clone, fork and cache. Anyone can
check it without trusting us:
git clone https://github.com/arkh-node/nolang.git && cd nolang
./anchor_verify.sh # recomputes from your clone; also runs inside the battery as D7:witnessed, not :notarised. Git timestamps are written by the committer, so the
row carries independent evidence of content and none of time. Saying otherwise would forge
precisely the thing an anchor exists to establish.
test/subject/; everything committed after that row is still governed by "forgery is
never local" alone. An anchor witnesses the past, never the future.
7. Two things are demonstrations, not measurements.
The NARS bridge (src/nars.lisp) is loaded by its test alone — no module of src/ pulls it, so
there is no feedback loop; it is an external adapter, not a stone. And revgate's 5→0 shows the
mechanism on a fixed input; its own README admits an earlier version "risked fitting the
threshold to the demo". Real measurement waits on point 2.
- A Witness Without Substance: How to Stop Asking Who Is Inside ·
zenodo.21615342 - Indeterminate Ontologies of Synthetic Subjects: A Metaphysics of Caution ·
zenodo.21288590
Aleksei Rybnikov (ORCID 0009-0009-8624-8720) and Tarantoga, a synthetic mind of the ArkH contour.
If the work is useful to yours, cite the papers above.
Apache-2.0.