Implements: ADR-049 · Status: Accepted (Phase 0 delivered) · Updated: 2026-06-15
This spec defines the contract for the recommended decentralised CI runner architecture: a tiered split where the untrusted contributor performs the expensive elaboration and a mandatory cheap central re-check is the sole load-bearing soundness gate. Phase 0 is delivered (the §5 conformance suite, see §6); the Phase-1+ control-flow change remains a design target. Today’s Gate A (ADR-006/SPEC-006-B) is the conformance reference because the central re-check already exists — this spec scopes which work it repeats and codifies what it must never trust. It is intentionally implementation-light: the full options analysis is in docs/proposals/decentralised-ci-runner-architecture.md, and the decision is ADR-049.
swarm/agent.sh::prove_local_verify() — full lake build UnsorryLibrary --wfail elaboration + axiom_audit + check_library_options as advisory preflight. It produces the proof and an advisory manifest. It is never trusted; its output gates nothing.UnsorryLibrary.The central PR-time re-check is the ADR-048 verify-on-ingest event for proof PRs. It MUST NOT consume any contributor-supplied compiled artifact (.olean, exported term, attestation, hash, or manifest field) as a trusted input. For each PR it MUST, on the trusted surface:
goals/<id>.lean + record, ADR-018 create-only; ADR-011 binding) — never from a contributor-supplied statement.library/Unsorry/*.lean modules plus their reverse-import closure and the generated ADR-011 *Binding modules — against dependency oleans that are either rebuilt on trusted CI or restored from a commit-exact trusted-CI cache (ADR-045). Restored dependency oleans are allowed only when their provenance binds them to the exact base commit, Lean toolchain, Lake manifest, and prior trusted Gate A run that produced them. It MUST NOT leanchecker a contributor-supplied olean.leanchecker replay (ADR-033), serialised axiom_audit against the whitelist {propext, Classical.choice, Quot.sound}, and ADR-011 defeq statement-binding of the proved term to the re-derived statement.lean-toolchain, lakefile*, lake-manifest.json, or tools/gate_a/**.A contributor-supplied .olean reaching leanchecker as a trusted input is a soundness defect, not an optimisation. Rationale (ADR-049 soundness argument): leanchecker trusts olean structure and replays the statement it is given, so trusting client oleans is unsound on (i) crafted-invalid oleans and (ii) real proofs of weakened/renamed statements (the ADR-011 / PR-#64 vacuity class).
The contributor MAY attach a manifest to the PR/claim record carrying: toolchain hash, mathlib release tag, the set of changed_modules, and the goal_sha. It is hygiene only — used for fast-fail pre-filters, diagnostics, and griefing metrics. The soundness gate does not depend on it; v1 soundness holds even if the manifest is absent, forged, or wrong, because §2 re-derives everything from canonical source. Any manifest parser is TCB-adjacent and lands under CODEOWNERS (ADR-019).
After the central re-check passes, downstream archive or leaderboard flows may trust the proof only as an already-ingested artifact under ADR-048: the artifact identity, statement binding, toolchain/mathlib context, and provenance must be preserved, and any byte or trusted-context change requires re-verification. Contributor-local logs or manifests are never evidence that the artifact was ingested.
.olean, and (b) a real, type-correct proof of a weaker or renamed statement than the goal demands. No code path lets a contributor-supplied .olean reach leanchecker as a trusted input.*Binding modules); a global-impact change forces the full re-check.tools/gate_a/tests/test_decentralised_runner_conformance.py), which locks in the §2 soundness invariant (no contributor-supplied artifact is a trusted input; scoping never under-scopes incl *Binding; global-impact forces a full re-check; the workflow feeds no downloaded artifact into the central build/replay). The Phase-1-dependent items (§5.4 cache provenance, §5.5 determinism) are recorded as skipped placeholders. No gate-a.yml control-flow change.--wfail build is ~41 s of a ~8 runner-min/PR gate dominated by fixed mathlib-environment loading (audit ~165 s, replay ~60 s, three cache restores), so target-narrowing buys only low-single-digit % per PR, not worth a TCB control-flow change. The §5 conformance suite (#926) remains the standing guard.lean4export + independent-checker re-check as a second, kernel-diverse anchor — adopted only if a determinism + wall-clock pilot shows it bounded (guard the “>100× slower” pathology). Authoritative gate stays leanchecker-on-locally-rebuilt-environment until then.lean4export cross-machine determinism and independent-checker wall-clock — open questions gating Phase 3 (see proposal Open Questions).