cert-machine · report · generated from the records

OpenAI’s prime-gap bound of 186, checked from every side I could reach

In August 2026 OpenAI’s GPT-6 Astra proved that infinitely many pairs of primes lie at most 186 apart, and released a Lean proof of it that rests on three stated assumptions. The result and the proof are theirs. I checked the release as far as an outside party can, with Claude: the Lean proof holds as written, its 152 numerical inputs reproduce and were recomputed with no shared code, and the three assumptions remain assumptions.

assumed · a Kloosterman-sum bound quoted from Deligne and Katz tested: 276,747 cases, all hold assumed · a correlation bound quoted from Fouvry, Kowalski, Michel tested: 359,158,973 cases, all hold assumed · 152 numerical bounds reproduced, and recomputed apart integral ≤ estimate: argued, not in Lean the Lean proof · checked builds as shipped, no warning Lean, nanoda, lean4lean accept OpenAI’s checker: same result 11 rewordings accepted 34 altered statements, none accepted rests on the 3 assumptions and the 3 standard axioms only if the three hold infinitely many prime gaps are at most 186 (OpenAI’s result)
assumed · a Kloosterman-sum bound quoted from Deligne and Katz tested: 276,747 cases, all hold assumed · a correlation bound quoted from Fouvry, Kowalski, Michel tested: 359,158,973 cases, all hold assumed · 152 numerical bounds reproduced, and recomputed apart integral ≤ estimate: argued, not in Lean the Lean proof · checked builds as shipped, no warning Lean, nanoda, lean4lean accept OpenAI’s checker: same result 11 rewordings accepted 34 altered statements, none accepted rests on the 3 assumptions and the 3 standard axioms only if the three hold infinitely many prime gaps are at most 186 (OpenAI’s result)
What was checked, and what was not. The Lean proof was checked as a proof. The three assumptions it starts from were tested, not proved: the first two on every case for the 303 primes below 2,000, the third by re-running and recomputing its 152 numbers.Record: certs/prime-gaps-186.json · sha256 5d2c84f356d3
assumptions proved here
0 of 3
they remain assumptions
the Lean proof
3 kernels accept
Lean, nanoda, lean4lean
numerical inputs
152 of 152
reproduced, and recomputed with no shared code
cases of the two quoted assumptions
359,435,720
every prime below 2,000 · all hold

The bound, its proof, the Lean development and the numerical certificate are OpenAI’s, attributed to GPT-6 Astra. This page checks their release; it is not new mathematics, and it does not verify the bound. The checks are mine, run with Claude (Anthropic’s AI model), which wrote the programs under my direction.

read this first

What is still open

1 · the Lean proof

The Lean proof holds as written

  • It builds as shipped. In 11 minutes, with no warning.
  • OpenAI’s own checker gives the same result. Comparator, the tool the release names, reports that the three theorems and the three assumptions match the statement file. Given a statement file with 186 made 185, and one with a constant changed in the first assumption, it rejects both.
  • Nothing else is assumed. Each of the three theorems rests on exactly the three standard axioms of Lean and the three declared assumptions, by two computations that agree.
  • Three kernels accept the proof. Lean’s own, also with every import replayed from scratch (26 minutes); nanoda (99,189 declarations); and lean4lean (96,354 declarations). Two further checkers, con-ron and con-leche, decline any proof that declares assumptions, so they say nothing here.
  • It proves the stated statement. The proof file and the statement file agree, theorem by theorem and assumption by assumption, through every definition under them. Of 45 statements planted to test that comparison, all 11 rewordings were accepted and none of the 34 altered ones was; 6 copies of the proof broken on purpose were all caught.
the same, reworded must be accepted dhl S0: the canonical statement copied verbatim (comments dropped): the baseline — ACCEPTED dhl S1: every bound variable renamed (H→H₀, a→a₀, h→h₀, hadm→hadm₀, hcard→hcard₀, n→n₀, p→p₀): alpha-equivalent — ACCEPTED tuple S0: the canonical statement copied verbatim (comments dropped): the baseline — ACCEPTED tuple S1: every bound variable renamed (h→h₀, n→n₀): alpha-equivalent — ACCEPTED liminf S0: the canonical statement copied verbatim (comments dropped): the baseline — ACCEPTED ax1 S0: the axiom's statement copied verbatim — ACCEPTED ax1 S1: bound variables renamed (p→q, c→d) — ACCEPTED ax2 S0: the axiom's statement copied verbatim — ACCEPTED ax2 S1: the bound variable t renamed s — ACCEPTED tuple-x S0: the canonical statement copied verbatim — ACCEPTED tuple-x S1: the definition written out: the forty numbers of Challenge.lean, in its order — ACCEPTED 11 of 11 altered refused: the statements differ dhl C01: the hypothesis (hcard : H.card = 40) dropped — REFUSED by type mismatch dhl C02: the hypothesis (hadm : ∀ p : ℕ, p.Prime → ∃ a : ZMod p, ∀ h ∈ H, (h : ZMod p) ≠ a) dropped — REFUSED by type mismatch dhl C03: ≤ made < (| 2 ≤ ( H.filter → | 2 < ( H.filter, line 3) — REFUSED by type mismatch dhl C04: the numeral 40 made 41 (H.card = 40 ) → H.card = 41 ), line 1) — REFUSED by type mismatch dhl C05: the numeral 40 made 39 (H.card = 40 ) → H.card = 39 ), line 1) — REFUSED by type mismatch dhl C06: the numeral 2 made 3 (ℤ | 2 ≤ → ℤ | 3 ≤, line 3) — REFUSED by type mismatch dhl C07: the numeral 2 made 1 (ℤ | 2 ≤ → ℤ | 1 ≤, line 3) — REFUSED by type mismatch dhl Q1: the binders hcard and hadm swapped: the same logically — REFUSED by type mismatch tuple C01: ≤ made < (| 2 ≤ ( admissibleTuple.filter → | 2 < ( admissibleTuple.filter, line 2) — REFUSED by type mismatch tuple C02: the numeral 2 made 3 (ℕ | 2 ≤ → ℕ | 3 ≤, line 2) — REFUSED by type mismatch tuple C03: the numeral 2 made 1 (ℕ | 2 ≤ → ℕ | 1 ≤, line 2) — REFUSED by type mismatch liminf C01: ≤ made < (primeGapLiminf ≤ ( 186 → primeGapLiminf < ( 186, line 1) — REFUSED by type mismatch liminf C02: the numeral 186 made 187 (≤ ( 186 : EReal → ≤ ( 187 : EReal, line 1) — REFUSED by type mismatch liminf C03: the numeral 186 made 185 (≤ ( 186 : EReal → ≤ ( 185 : EReal, line 1) — REFUSED by type mismatch ax1 W1: phase A's R1: the 1/p normalization undone (the raw sum bounded by 3) — REFUSED by type mismatch ax1 W2: phase A's R3: the constant 3 made 2 — REFUSED by type mismatch ax1 W3: the hypothesis c ≠ 0 dropped — REFUSED by type mismatch ax1 W4: ≤ made < — REFUSED by type mismatch ax1 W5: the bound made 3 * p — REFUSED by type mismatch ax2 W1: phase A's R2: 8√p for 8p√p — REFUSED by type mismatch ax2 W2: phase A's R4: the constant 8 made 4 — REFUSED by type mismatch ax2 W3: the pole t = -1 not excluded — REFUSED by type mismatch ax2 W4: the shift dropped: B / t for B / (t + 1) — REFUSED by type mismatch ax2 W5: the hypothesis A ≠ 0 dropped — REFUSED by type mismatch ax2 W6: the two sums added, not multiplied — REFUSED by type mismatch tuple-x C02: the second number 2 made 4 — REFUSED by type mismatch tuple-x C03: the number 98 made 96 (the middle) — REFUSED by type mismatch tuple-x C05: the first two numbers swapped (the same set, another term) — REFUSED by type mismatch 28 of 28 altered did not get as far as a check dhl N1: ℤ made ℕ in the type of H: another type, never definitionally equal (refused, or the statement does not elaborate) — FAILED elsewhere dhl N2: ℕ made ℤ in the type of hadm: another type, never definitionally equal (refused, or the statement does not elaborate) — FAILED elsewhere ax1 N1: ℕ made ℤ in the type of p: another type (refused, or the statement does not elaborate) — FAILED elsewhere ax2 N1: ℕ made ℤ in the type of p: another type (refused, or the statement does not elaborate) — FAILED elsewhere tuple-x C01: the last number 186 made 188 (the diameter) — FAILED elsewhere tuple-x C04: the last number dropped (39 numbers) — FAILED elsewhere 6 of 6 proofs broken on purpose must be caught dhl R1: the proof of dhl_40_2 replaced by sorry (the original kept as intake_was_dhl_40_2) — caught: the axioms list sorryAx dhl R2: dhl_40_2 proved by an added axiom (the original kept as intake_was_dhl_40_2) — caught: the axioms list PrimeGap186.intakeRedAxiom tuple R1: the proof of infinite_two_prime_translates_admissibleTuple replaced by sorry (the original kept as intake_was_infinite_two_prime_translates_admissibleTuple) — caught: the axioms list sorryAx tuple R2: infinite_two_prime_translates_admissibleTuple proved by an added axiom (the original kept as intake_was_infinite_two_prime_translates_admissibleTuple) — caught: the axioms list PrimeGap186.intakeRedAxiom liminf R1: the proof of primeGapLiminf_le_186 replaced by sorry (the original kept as intake_was_primeGapLiminf_le_186) — caught: the axioms list sorryAx liminf R2: primeGapLiminf_le_186 proved by an added axiom (the original kept as intake_was_primeGapLiminf_le_186) — caught: the axioms list PrimeGap186.intakeRedAxiom 6 of 6 filled: not accepted, or caught · hollow: accepted
The planted tests. Each square is one statement or one proof changed on purpose; hover for what it was. Six altered statements stopped before the comparison, because Lean could not read them as written: not accepted, but not refused by the comparison either.Record: certs/prime-gaps-186.json · sha256 5d2c84f356d3The build refuses this figure if a rewording is refused, an altered statement is accepted, or a broken proof is not caught.
2 · the two quoted assumptions

Every case for the primes below 2,000

Two of the three assumptions are bounds on sums over a finite field, one for every prime. A computer can decide them prime by prime, which proves nothing about all primes and still tests whether the Lean statements say something false.

  • All hold. 276,747 cases of the first and 359,158,973 of the second, for the 303 primes below 2,000, each decided in exact arithmetic by two programs that share no code. None fails; none is left undecided.
  • How close they come. The first sum reaches 2.81 against the assumed 3, at p = 887. The second reaches 5.25 against 8, at p = 1,283.
  • The programs read the definitions as Lean does. The values at p = 2 and 3 are proved in Lean, in 9 small theorems, and equal both programs’ values.
  • Wrong versions are caught. Four deliberately wrong assumptions (a missing factor, smaller constants) are refuted, the first at p = 5, the last at p = 83.
  • The Lean statements say what the cited theorems say. By two readings of the sources, made without sight of the Lean text.
0 1 2 3 0 500 1,000 1,500 2,000 the prime p the assumed bound, 3
The first assumption: the largest size of the sum at each prime, against the assumed bound 3. Square roots are for the drawing; the decisions are made on the squares, exactly.Records: certs/prime-gaps-186.json · sha256 5d2c84f356d3; corpus/prime-gaps-186/records/a2/results.jsonl · sha256 6f68a1e5154aThe build refuses this figure if a prime’s largest value reaches the bound, or the two programs disagree.
0 2 4 6 8 0 500 1,000 1,500 2,000 the prime p the assumed bound, 8
The second assumption: the largest size of the sum at each prime, divided by p√p, against the assumed bound 8.Records: certs/prime-gaps-186.json · sha256 5d2c84f356d3; corpus/prime-gaps-186/records/a2/results.jsonl · sha256 6f68a1e5154aThe build refuses this figure if a prime’s largest value reaches the bound, or the two programs disagree.
3 · the third assumption

The 152 numbers

The third assumption is a list of 152 numerical bounds: 149 upper bounds for integrals, in six tables, and three bounds on two further quantities. OpenAI supports them with a Python program, the certificate.

  • Reproduced. On the released versions of its arithmetic library the certificate stops at its own startup check: a known bug, corrected in flintlib/flint#2790 by Fredrik Johansson in August 2026 and in no release yet. OpenAI’s numerics note cites the correction; the README’s list of versions does not. With that one correction applied, their program, unmodified, runs to “passed” in 65 minutes and prints all 152 numbers as published.
  • Recomputed. Programs written from the Lean statement file and the note alone, in sessions that never saw OpenAI’s program, enclose all 152 quantities. The three cap bounds hold, with the two quantities known to about 42 digits; all 149 row values are at or below their printed bounds.
  • Inside OpenAI’s own intervals. Both cap quantities and 147 of the 149 row values lie inside the interval OpenAI’s run prints for the same quantity. The other 2 came out just below their intervals, so still below their bounds; computed with a recurrence exactly as the note writes it, both land in the middle.
  • Re-run. Every one of these programs was run again from a clean copy on a second machine, and every recorded number came back.
  • Reviewed. A separate session, told to look for errors, went through the 33 steps of the hand derivations: 28 hold, 3 hold under a condition it then checked, 2 it did not re-derive in full. None was found wrong. It is not a human referee.
  • The final inequality holds on these numbers. Total loss 696,075,106 units against the published 696,075,110. The proof needs a margin above zero: the loss could grow 12.8% before that fails, and 1.8% before the 1/50000 the papers state.
cap quantities · 2 rank-two rows · 48 high rows · 8 low rows, first number · 32 low rows, second number · 32 low rows, inner tables · 29 -0.5 0 · lower end 0.5 1 · upper end position of the recomputed value inside the interval OpenAI’s run prints
Where each recomputed value falls in the interval OpenAI’s own run prints for it: 0 is the interval’s lower end, 1 its upper end, and each printed bound is that upper end rounded up. Two computations that share no code agree to within OpenAI’s stated uncertainty, except the two rank-two values left of 0. The 17 dots exactly at 0 are low-row values that are all but zero, in intervals that start at zero. Dots in a row are spread vertically only so that they do not hide each other.Record: certs/prime-gaps-186.json · sha256 5d2c84f356d3The build refuses this figure if a value lies above its interval, or a value is missing from the drawing.
along the way

What the check found about the release

the method

How it was done

The rules for each stage were written first and sealed: a salted fingerprint of the private work, posted to a public registry and to Bitcoin, which proves the date without showing the content. There are four sets of rules (corpus/prime-gaps-186/PREREG-PG186.md, corpus/prime-gaps-186/PREREG-PG186-A2-C0.md, corpus/prime-gaps-186/PREREG-PG186-B.md, corpus/prime-gaps-186/PREREG-PG186-C.md), each with its questions, its verdict words and its predictions, and each departure from them is listed in the records.

who did what

Each step is a separate job

check it yourself

How to re-run it

contact

Write to Carlos

Sent by Web3Forms to Carlos’s inbox; nothing stored here.

Or write to carlos@carlostoledo.co, or open the public pilot form on GitHub.