In this section

Every output lungo writes — the Rust module, each language’s package, each plugin’s output — carries the program’s assurance document as assurance.json: what its Lean code claims and proves of each export, the assumptions those claims rest on, the facilities each export needs, and what each export trusts. The document is built once per program and written byte for byte the same into every output; each language reads the same text (see in each language). Formal assurance explains the concepts.

The document is pretty-printed JSON (two-space indentation) ending with a newline. A field whose value is absent is null, never omitted. Every lungo reader — Rust, Go, Python, Swift and TypeScript — refuses a document of another schema_version, one with a field it does not know, and one missing a field (a nullable one included: it must be present as null), at any depth.

Top level

Field Type Meaning
schema_version number 1.
program string The program’s name (the Lake package’s, unless configured).
provenance object What produced the document (below).
library object or null lungo’s Lean library, when the program imports it: package (its Lake package, lungo) and schema_version (its record format, Lungo.Registry.schemaVersion).
specifications array Specifications.
facilities array Facilities.
assumptions array Assumptions.
claims array Claims.
roles array Roles.
exports array One summary per exported declaration.

A program that uses none of the library has library: null and empty record arrays; its exports are still listed, with their trust.

Provenance

Field Type Meaning
lean_version string The Lean version that elaborated and compiled the project, such as 4.34.1.
lean_githash string Its commit.
lungo_version string The lungo that generated the output.
bir_version number The Bridge IR version of the worker.
runtime_abi number The C ABI version of the runtime (LUNGO_ABI_VERSION).

Records

Every record of the four kinds below carries:

Field Type Meaning
name string The Lean declaration.
package string or null The Lake package declaring it.
fingerprint string The fingerprint of its meaning: 64 lowercase hexadecimal digits.
source object or null Where it is declared: package, file (/-separated, relative to that package’s directory), start and end (each {line, column}, or null).

Specifications

@[lungo_spec] declarations: name, kind (such as lungo.contract or acme.cost-model), statement (the declaration’s type, as Lean prints it), definition (its body, as Lean prints it, when the declaration is a definition; otherwise null), and the common fields.

Facilities

@[lungo_facility] declarations.

Field Type Meaning
id string The namespaced identifier, such as timing.clock.
form string extern: @[extern] operations the host implements, called synchronously; async: the constructors of an operation type, performed by a handler each async export is given.
op_type string or null The operation type of an async facility.
operations array {name, symbol, fingerprint}: for an extern facility, each operation the program compiles, with its extern symbol and its own fingerprint; for an async facility, each constructor of the operation type, with symbol and fingerprint null (the facility’s fingerprint covers them).
assumptions array of strings The assumptions registered for the facility.

Assumptions

@[lungo_assumption] declarations: name, facility (the facility’s Lean name), statement (the declaration’s type, as Lean prints it), definition (its body when it is a definition, otherwise null), and the common fields. An assumption defined as a proposition has the type Prop, so its definition is what it says: lungo assurance and lungo inspect print the definition when there is one, the type otherwise.

Claims

@[lungo_claim] theorems. A claim’s name is its evidence theorem’s.

Field Type Meaning
relation string Such as lungo.satisfies or acme.cost-bound.
subjects array of strings The declarations the claim is about, in the order the attribute names them.
specifications array of strings The specifications it cites, in the order the attribute names them.
statement string The theorem’s statement, as Lean prints it.
status string proved: the evidence is a theorem the kernel checked that depends on no sorry. incomplete: it depends on sorry; present only when the trust policy allows sorry.
evidence_trust object axioms: the axioms the evidence depends on, without sorryAx; depends_on_sorry.
assumptions array of strings The registered assumptions among the types of the statement’s leading ∀ binders: what the claim is conditional on.

Roles

@[lungo_role] declarations: name, role (such as lungo.oracle), and exported (whether the program exports the declaration). Roles carry no fingerprint or source.

Exports

One per exported declaration.

Field Type Meaning
name string The Lean declaration.
module string The Lean module declaring it.
async boolean Whether it returns an async program (Lungo.Async.Program).
trust object What its executable closure depends on: axioms, depends_on_sorry, unsafe_dependencies, partial_dependencies, extern_dependencies (extern symbols).
claims array of strings The claims whose subjects include it.
assumptions array of strings The assumptions those claims are conditional on.
facilities array of strings The facilities it needs: those of the operations its closure calls, and the async facility of the program it returns.
roles array of strings Its roles.
source object or null As for records.

Order and determinism

The document is a function of the compiled project and the toolchain: generating it twice, or from another directory, gives the same bytes, and it holds no path of the machine.

  • specifications, facilities, assumptions, claims, roles and exports are sorted by name, comparing the names’ bytes (so Polyglot.Scaler comes before Polyglot.fetchInterface).
  • The operations of an extern facility are sorted by name; those of an async facility are in the operation type’s constructor order.
  • A claim’s assumptions, its evidence’s axioms, a facility’s assumptions, and an export’s assumptions and facilities are sorted. A claim’s subjects and specifications keep the attribute’s order; an export’s claims follow the order of claims.

Fingerprints

A fingerprint identifies what a record means, so two documents can be checked to agree on a name they share (lungo assurance --compose, LNG0708). It covers the record’s own Lean expressions and, transitively, the definitions of every constant they use that a package of the Lake workspace declares; the toolchain’s constants (Lean’s Init, Std, Lean) are covered by the Lean version, which every fingerprint names.

The worker writes a canonical text of each expression: its distinct subterms once each, in post order, without binder names or metadata, with universe parameters numbered by position, constants by name, after a header naming the record kind. A record’s canonical text covers:

Record Expressions
specification its type, and its value when it is a definition; the header names its kind
claim its statement, and its subjects and specifications (as constants); the header names its relation
facility its type, and for an async facility the type of each constructor of its operation type; the header names its identifier
operation its type; the header names its extern symbol
assumption its type, and its value when it is a definition

The worker also describes, once each, every workspace constant the records use, directly or through another such constant: a definition by its type and value; a theorem, an opaque constant or an axiom by its type (a proof’s or an opaque implementation’s content does not change what it states); an inductive type by its type and its constructors’; each with the workspace constants it uses in turn. lungo digests these definitions over that graph, so a definition’s digest changes when anything it uses changes. Definitions that use each other (a strongly connected component of the graph, such as mutually recursive functions) are digested together:

component = SHA-256( "lungo-assurance-1 definitions\nlean <lean_version>\n"
                     + for each member, by name: "member <name>\n<canonical text>\n"
                       + for each constant it uses outside the component, by name:
                         "uses <name> <digest>\n" )
digest(member) = SHA-256( component + "\n" + <name> )

A record’s fingerprint is then:

SHA-256( "lungo-assurance-1\nlean <lean_version>\n" + <canonical text>
         + for each workspace constant the record uses directly, by name:
           "\nuses <name> <digest>" )

Each is written as 64 lowercase hexadecimal digits. Renaming a binder or reformatting does not change a fingerprint, nor does the record’s own name or source position. Changing the statement, the definition, any definition of the workspace it reaches — such as a helper a specification unfolds to — or the Lean version does. A claim names its subjects as constants, so its fingerprint also changes when a subject’s definition does.

In each language

Language The document
Rust <module>::__meta::ASSURANCE_JSON is the text. __meta::assurance() returns a &'static lungo::Assurance with the records (claim, claims_about, facility, assumption, specification look them up), and __meta::declaration(name) gives an export’s assurance: its claims, assumptions, facilities, roles and asynchronous.
C const char *<id>_assurance_json(void) returns the text, NUL-terminated.
Go Assurance() *lungo.Assurance, parsed once from the package’s assurance.json (embedded with //go:embed) by lungo.ParseAssurance; Claim(name) and Export(name) look records up.
Python ASSURANCE, a lungo_py.Assurance (frozen dataclasses; an export’s async field is async_); claim(name) and export(name).
Swift assuranceJSON is the text; assurance is a LungoAssurance (Codable, camel-case fields, an export’s async as isAsync), with claim(_:) and export(_:).
TypeScript ASSURANCE, the document checked and frozen by parseAssurance of lungo-ts, with the JSON’s field names.

A plugin receives the document in its request (assurance) and must not write assurance.json itself: lungo writes it into every output (plugins).

lungo assurance reports the document of a project, filtered and checked against the policy, and lungo assurance --compose composes documents (the lungo command).