zeropoint-node 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,27 +1,102 @@
1
1
  /**
2
- * Lean Bridge: Formal Verification API
2
+ * Lean bridge what is actually checked, and what is only written down.
3
3
  *
4
- * Connects Lean 4 proof system to quantum system:
5
- * - Compile Lean theorems to proof certificates
6
- * - Embed proofs in quantum operations
7
- * - Verify system claims against Lean proofs
8
- * - Generate proof transcripts for publication
4
+ * This module used to report "Verified: 2/2", "Confidence: 100.0%" and
5
+ * "Production Grade (Formally Verified)". None of it was measured. The hash
6
+ * covered the theorem's NAME rather than its proof; `verifyProofCertificate`
7
+ * tested that some strings were non-empty and that a hash was 16 characters,
8
+ * which is true of every certificate this file can construct; `lean_version`
9
+ * was asserted although no Lean has ever run here; and seven of the thirteen
10
+ * Lean scripts below end in `sorry`, which is Lean for "not proved".
9
11
  *
10
- * All quantum properties are formally verified, not assumed.
12
+ * The scripts are kept verbatim they were never the problem. What changed is
13
+ * that a certificate now carries two independent, separately reported facts:
14
+ *
15
+ * lean_status what the Lean source actually is: a script, a `sorry`
16
+ * placeholder, an axiom, or absent. Derived by reading the
17
+ * script, not declared.
18
+ * seal whether a RECOMPUTABLE predicate for that theorem ran and
19
+ * held, against the simulator in `src/quantum/`. Not a proof of
20
+ * the general theorem — a decision on a concrete instance.
21
+ *
22
+ * A theorem counts as verified here only when its seal holds. `sorry` scripts
23
+ * with a passing seal are reported as sealed-but-not-proved, because a checked
24
+ * instance is not a proof, and an unchecked proof script is not evidence.
25
+ * Nothing in this file claims Lean was invoked, because it was not.
26
+ *
27
+ * To make this honest at the Lean level someone must build the Lean
28
+ * development these scripts gesture at and run `lake build` in CI. Until then
29
+ * the seals are the real content and the scripts are documentation.
11
30
  */
12
31
 
13
32
  import { createHash } from 'node:crypto'
33
+ import { digitalRoot, throughVoid, bearingForDigit, VORTEX_SEQUENCE, VORTEX_ORBIT, VORTEX_AXIS } from '../0/index.ts'
34
+ import { angleForDigit } from '../0/3/6/9/1/2/4/8/7/5/1/a432.math.ts'
35
+ import {
36
+ GIBBS_FORMATION,
37
+ GIBBS_SPLITTING,
38
+ ENTHALPY_FORMATION,
39
+ ENTHALPY_SPLITTING,
40
+ reversiblePotentialMicrovolts,
41
+ thermoneutralPotentialMicrovolts,
42
+ roundTrip,
43
+ selfTest as thermoSelfTest,
44
+ SCALE,
45
+ ELECTRONS,
46
+ FARADAY,
47
+ reversiblePotentialExact,
48
+ thermoneutralPotentialExact,
49
+ energyFromPotential,
50
+ } from '../thermo/free-energy.ts'
51
+ import {
52
+ balanceFor,
53
+ breakEvenCod,
54
+ TYPICAL_LOADS,
55
+ TREATMENT_DEMAND_DECIJOULES_PER_LITRE,
56
+ selfTest as wastewaterSelfTest,
57
+ } from '../thermo/wastewater-energy.ts'
58
+ import {
59
+ zeroState,
60
+ applyGate1,
61
+ isNormalized,
62
+ qft,
63
+ iqft,
64
+ grover,
65
+ groverIterations,
66
+ shor,
67
+ measureSyndromeRepetition,
68
+ STEANE_CODE,
69
+ symplecticProduct,
70
+ estimateSurfaceCodeThreshold,
71
+ executeInSuperposition,
72
+ computeInterferencePattern,
73
+ describeQuantumExecution,
74
+ } from '../quantum/index.ts'
75
+ import { ML_KEM_768 } from '../crypto/ml-kem.ts'
76
+ import { sqrt } from '../0/algebra.ts'
14
77
 
15
78
  // ============================================================================
16
79
  // PROOF CERTIFICATE TYPES
17
80
  // ============================================================================
18
81
 
82
+ /** What the Lean source for a theorem actually is. Read, never declared. */
83
+ export type LeanStatus = 'script' | 'sorry' | 'axiom' | 'absent'
84
+
85
+ /** Whether a recomputable predicate ran and held for this theorem. */
86
+ export type SealStatus = 'held' | 'failed' | 'none'
87
+
19
88
  export interface ProofCertificate {
20
89
  readonly theorem_name: string
21
90
  readonly statement: string
22
91
  readonly proof_script: string
23
92
  readonly verified_at: string
24
- readonly lean_version: string
93
+ /** Derived from proof_script — 'sorry' means Lean would reject it. */
94
+ readonly lean_status: LeanStatus
95
+ /** 'none' when no executable predicate exists for this theorem. */
96
+ readonly seal: SealStatus
97
+ /** What the seal actually computes, so a reader can judge its weight. */
98
+ readonly seal_basis: string
99
+ /** Content address of statement + script. Changing either changes this. */
25
100
  readonly hash: string
26
101
  }
27
102
 
@@ -137,225 +212,745 @@ export const LEAN_PROOFS = {
137
212
  axiom lwe_hardness : ¬ (polynomial_time_solves_lwe 768 3329)
138
213
  `,
139
214
  } as const
140
-
141
215
  // ============================================================================
142
- // PROOF GENERATION & VERIFICATION
216
+ // SEALS - recomputable predicates, the only thing here that counts as checked
143
217
  // ============================================================================
144
218
 
145
- export function generateGateCertificate(gate: 'Hadamard' | 'PauliX'): GateCertificate {
146
- const gate_proofs = {
147
- Hadamard: {
148
- theorem_name: 'hadamard_unitary',
149
- statement: 'IsUnitary hadamard',
150
- property: 'unitary' as const,
151
- },
152
- PauliX: {
153
- theorem_name: 'pauliX_unitary',
154
- statement: 'IsUnitary pauliX',
155
- property: 'unitary' as const,
156
- },
157
- }
219
+ // 1/sqrt(2) via the repo's algebra, not ambient Math.
220
+ const SQRT1_2 = 1 / sqrt(2)
221
+ type C = { re: number; im: number }
222
+ const c = (re: number, im = 0): C => ({ re, im })
158
223
 
159
- const info = gate_proofs[gate]
224
+ const H: [C, C, C, C] = [c(SQRT1_2), c(SQRT1_2), c(SQRT1_2), c(-SQRT1_2)]
225
+ const X: [C, C, C, C] = [c(0), c(1), c(1), c(0)]
226
+ const Y: [C, C, C, C] = [c(0), c(0, -1), c(0, 1), c(0)]
160
227
 
161
- return {
162
- gate_name: gate,
163
- theorem_name: info.theorem_name,
164
- statement: info.statement,
165
- property: info.property,
166
- proof_script: LEAN_PROOFS[info.theorem_name as keyof typeof LEAN_PROOFS] || '',
167
- verified_at: new Date().toISOString(),
168
- lean_version: 'v4.8.0',
169
- hash: computeProofHash(info.theorem_name),
170
- }
228
+ const CLOSE = 1e-9
229
+ const near = (a: number, b: number): boolean => a - b < CLOSE && b - a < CLOSE
230
+
231
+ interface Seal {
232
+ /** One line a reader can check the predicate against. */
233
+ readonly basis: string
234
+ /** Decides a concrete instance. Must be able to return false. */
235
+ readonly decide: () => boolean
171
236
  }
172
237
 
173
- export function generateAlgorithmCertificate(algo: 'Grover' | 'Shor' | 'QFT'): AlgorithmCertificate {
174
- const algo_props = {
175
- Grover: {
176
- theorem_name: 'grover_speedup',
177
- statement: 'Grover search runs in O(√N) time',
178
- complexity_bound: 'O(√N)',
179
- speedup_factor: 3.16, // sqrt(N) / log(N) ≈ sqrt(10) speedup over classical
238
+ /**
239
+ * Every seal decides an INSTANCE, never the universally quantified theorem.
240
+ * hadamard_squared checks H^2 = I on both computational basis states of one
241
+ * qubit, which for a linear map is the whole story; grover_speedup checks a
242
+ * success probability at one problem size, which is NOT the asymptotic claim.
243
+ * The basis string says which is which so the distinction cannot be lost.
244
+ */
245
+ export const SEALS: Record<string, Seal> = {
246
+ hadamard_squared: {
247
+ basis: 'H applied twice to each basis state of one qubit returns the input amplitudes (linearity makes 2 states exhaustive)',
248
+ decide: () => {
249
+ for (const start of [0, 1]) {
250
+ let reg = zeroState(1)
251
+ if (start === 1) reg = applyGate1(reg, 0, X)
252
+ const twice = applyGate1(applyGate1(reg, 0, H), 0, H)
253
+ for (let i = 0; i < 2; i++) {
254
+ if (!near(twice.amps[i]!.re, reg.amps[i]!.re)) return false
255
+ if (!near(twice.amps[i]!.im, reg.amps[i]!.im)) return false
256
+ }
257
+ }
258
+ return true
180
259
  },
181
- Shor: {
182
- theorem_name: 'shor_period_finding',
183
- statement: 'Shor finds period r in O(log³N) gates',
184
- complexity_bound: 'O(log³N)',
185
- speedup_factor: 1e6, // Exponential speedup over classical GNFS
260
+ },
261
+
262
+ hadamard_unitary: {
263
+ basis: 'H preserves the norm of a 3-qubit register (unitary maps are exactly the norm-preserving ones)',
264
+ decide: () => {
265
+ let reg = zeroState(3)
266
+ for (const q of [0, 1, 2]) reg = applyGate1(reg, q, H)
267
+ return isNormalized(reg)
186
268
  },
187
- QFT: {
188
- theorem_name: 'qft_unitary',
189
- statement: 'QFT is unitary and computable in O(n²) gates',
190
- complexity_bound: 'O(n²)',
191
- speedup_factor: 1, // No direct speedup; enables other algorithms
269
+ },
270
+
271
+ pauliX_unitary: {
272
+ basis: 'X applied twice is the identity, and X preserves the norm',
273
+ decide: () => {
274
+ const reg = zeroState(2)
275
+ const twice = applyGate1(applyGate1(reg, 0, X), 0, X)
276
+ return isNormalized(twice) && near(twice.amps[0]!.re, 1)
192
277
  },
193
- }
278
+ },
279
+
280
+ pauli_anticomm: {
281
+ basis: 'XY and YX differ by an overall sign on both basis states of one qubit',
282
+ decide: () => {
283
+ for (const start of [0, 1]) {
284
+ let reg = zeroState(1)
285
+ if (start === 1) reg = applyGate1(reg, 0, X)
286
+ const xy = applyGate1(applyGate1(reg, 0, Y), 0, X)
287
+ const yx = applyGate1(applyGate1(reg, 0, X), 0, Y)
288
+ for (let i = 0; i < 2; i++) {
289
+ if (!near(xy.amps[i]!.re, -yx.amps[i]!.re)) return false
290
+ if (!near(xy.amps[i]!.im, -yx.amps[i]!.im)) return false
291
+ }
292
+ }
293
+ return true
294
+ },
295
+ },
296
+
297
+ born_rule_sum: {
298
+ basis: 'squared amplitudes sum to 1 after a Hadamard layer on 4 qubits',
299
+ decide: () => {
300
+ let reg = zeroState(4)
301
+ for (const q of [0, 1, 2, 3]) reg = applyGate1(reg, q, H)
302
+ const total = reg.amps.reduce((s, a) => s + a.re * a.re + a.im * a.im, 0)
303
+ return near(total, 1)
304
+ },
305
+ },
306
+
307
+ qft_unitary: {
308
+ basis: 'inverse QFT undoes QFT on a 3-qubit register, amplitude by amplitude',
309
+ decide: () => {
310
+ let reg = zeroState(3)
311
+ reg = applyGate1(reg, 0, H)
312
+ reg = applyGate1(reg, 2, X)
313
+ const back = iqft(qft(reg))
314
+ for (let i = 0; i < back.amps.length; i++) {
315
+ if (!near(back.amps[i]!.re, reg.amps[i]!.re)) return false
316
+ if (!near(back.amps[i]!.im, reg.amps[i]!.im)) return false
317
+ }
318
+ return true
319
+ },
320
+ },
321
+
322
+ grover_amplification: {
323
+ basis: 'Grover leaves the marked state with probability above the 1/N a random guess gets (n=4, N=16)',
324
+ decide: () => {
325
+ const n = 4
326
+ const target = 11
327
+ const out = grover(n, target, groverIterations(1 << n))
328
+ const p = out.amps[target]!.re ** 2 + out.amps[target]!.im ** 2
329
+ return p > 1 / (1 << n)
330
+ },
331
+ },
332
+
333
+ grover_speedup: {
334
+ basis: 'INSTANCE ONLY, not the asymptotic bound: round((pi/4)*sqrt(N)) iterations reach probability above 0.9 at N=16',
335
+ decide: () => {
336
+ const n = 4
337
+ const target = 6
338
+ const out = grover(n, target, groverIterations(1 << n))
339
+ const p = out.amps[target]!.re ** 2 + out.amps[target]!.im ** 2
340
+ return p > 9 / 10
341
+ },
342
+ },
343
+
344
+ shor_period_finding: {
345
+ basis: 'INSTANCE ONLY: shor(15, 7) returns non-trivial factors whose product is 15',
346
+ decide: () => {
347
+ const factors = shor(15, 7)
348
+ if (!Array.isArray(factors) || factors.length !== 2) return false
349
+ const [p, q] = factors as [number, number]
350
+ if (p <= 1 || q <= 1 || p >= 15 || q >= 15) return false
351
+ return p * q === 15
352
+ },
353
+ },
354
+
355
+ repetition_detects_error: {
356
+ basis: 'a clean 3-qubit codeword gives the zero syndrome and a single X error gives a non-zero one, so the syndrome distinguishes them',
357
+ decide: () => {
358
+ // |000> is the logical zero of the repetition code: no error, so the
359
+ // syndrome must be all zero. One X on qubit 0 must show up.
360
+ const clean = measureSyndromeRepetition(zeroState(3))
361
+ if (clean.detected || clean.syndrome.some((b) => b !== 0)) return false
362
+ const flipped = measureSyndromeRepetition(applyGate1(zeroState(3), 0, X))
363
+ return flipped.detected && flipped.syndrome.some((b) => b !== 0)
364
+ },
365
+ },
366
+
367
+ steane_corrects_error: {
368
+ basis: 'Steane [[7,1,3]] is a stabiliser group: exactly n-k = 6 generators, symplectically independent (rank 6), pairwise commuting, and distance 3 corrects floor((d-1)/2) = 1 arbitrary error',
369
+ decide: () => {
370
+ const code = STEANE_CODE
371
+ const n = code.physicalQubits
372
+ const k = code.logicalQubits
373
+ if (n !== 7 || k !== 1 || code.distance !== 3) return false
374
+ if ((code.distance - 1) / 2 < 1) return false
375
+
376
+ const g = code.generators
377
+ // A stabiliser group for [[n,k,d]] needs exactly n - k generators.
378
+ if (g.length !== n - k) return false
379
+ // Every pair must commute, i.e. have symplectic product zero.
380
+ for (let i = 0; i < g.length; i++) {
381
+ for (let j = i + 1; j < g.length; j++) {
382
+ if (symplecticProduct(g[i]!, g[j]!) !== 0) return false
383
+ }
384
+ }
385
+ // And they must be independent over GF(2), or they fix fewer qubits than
386
+ // claimed. Gaussian elimination on the 2n-bit rows.
387
+ const M = g.map((r) => [...r])
388
+ let rank = 0
389
+ for (let col = 0; col < 2 * n && rank < M.length; col++) {
390
+ let pivot = -1
391
+ for (let r = rank; r < M.length; r++) if (M[r]![col] === 1) { pivot = r; break }
392
+ if (pivot < 0) continue
393
+ const tmp = M[rank]!; M[rank] = M[pivot]!; M[pivot] = tmp
394
+ for (let r = 0; r < M.length; r++) {
395
+ if (r !== rank && M[r]![col] === 1) {
396
+ for (let b = 0; b < 2 * n; b++) M[r]![b] = M[r]![b]! ^ M[rank]![b]!
397
+ }
398
+ }
399
+ rank++
400
+ }
401
+ return rank === n - k
402
+ },
403
+ },
404
+
405
+ surface_code_threshold: {
406
+ basis: 'estimateSurfaceCodeThreshold separates the two sides of the 1% threshold: below it reports below, above it does not',
407
+ decide: () => {
408
+ const below = estimateSurfaceCodeThreshold(3, 1 / 1000)
409
+ const above = estimateSurfaceCodeThreshold(3, 1 / 10)
410
+ return below.isBelowThreshold === true && above.isBelowThreshold === false
411
+ },
412
+ },
413
+
414
+ kyber_security: {
415
+ basis: 'the shipped ML-KEM parameters are ML-KEM-768 (ek 1184, dk 2400, ct 1088). NIST puts that at category 3, NOT the 128 the Lean script states.',
416
+ decide: () =>
417
+ ML_KEM_768.encapsulationKeyBytes === 1184 &&
418
+ ML_KEM_768.decapsulationKeyBytes === 2400 &&
419
+ ML_KEM_768.ciphertextBytes === 1088,
420
+ },
421
+ doubling_avoids_the_triad: {
422
+ basis: 'VORTEX_ORBIT and VORTEX_AXIS are pinned to computation, not trusted. gcd(2,9) = 1, so every power of 2 is a unit mod 9 and can never be a multiple of 3; 2 is a primitive root, so its orbit is all six units {1,2,4,5,7,8}; 2^6 = 64 = 1 mod 9 gives period 6, which makes six cases exhaustive rather than sampled. Reflection through the void carries {1,4,7} onto {9,6,3}, so the triad is reachable only by reflecting.',
423
+ decide: () => {
424
+ // Bound to the kernel's own constants, not retyped here. VORTEX_AXIS had
425
+ // no reader anywhere in the repository before this seal, so nothing
426
+ // checked it was the triad at all.
427
+ const TRIAD: readonly number[] = VORTEX_AXIS
428
+
429
+ // Period 6, from 2^6 = 64 = 1 (mod 9). Without this the six cases below
430
+ // would be a sample; with it they are the whole sequence.
431
+ if (digitalRoot(64) !== digitalRoot(1)) return false
432
+
433
+ // The orbit of 2, generated by doubling and folded each step.
434
+ const orbit: number[] = []
435
+ let d = 1
436
+ for (let i = 0; i < 6; i++) {
437
+ orbit.push(d)
438
+ if (TRIAD.includes(d)) return false // a power of two landed on 3, 6 or 9
439
+ d = digitalRoot(d * 2)
440
+ }
441
+ // Six distinct values, and doubling returns to the start: a full cycle.
442
+ if (new Set(orbit).size !== 6 || d !== 1) return false
443
+
444
+ // Those six are exactly the units mod 9 — the residues coprime to 9.
445
+ // Everything else mod 9 is a multiple of 3, which is the triad.
446
+ const units = [1, 2, 4, 5, 7, 8]
447
+ if (orbit.slice().sort((a, b) => a - b).join() !== units.join()) return false
448
+
449
+ // VORTEX_ORBIT must BE the computed orbit, in doubling order — the
450
+ // constant is pinned to the computation rather than trusted.
451
+ if (VORTEX_ORBIT.join() !== orbit.join()) return false
452
+
453
+ // And VORTEX_AXIS must be exactly what the orbit cannot reach: the
454
+ // complement of the orbit in 1..9, in ascending order.
455
+ const complement = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter((n) => !orbit.includes(n))
456
+ if (TRIAD.join() !== complement.join()) return false
457
+
458
+ // VORTEX_SEQUENCE reads orbit then axis, so it is not an arbitrary order.
459
+ if (VORTEX_SEQUENCE.slice(0, orbit.length).join() !== orbit.join()) return false
460
+ if (VORTEX_SEQUENCE.slice(orbit.length).join() !== TRIAD.join()) return false
461
+
462
+ // Reflection is where the triad enters: 1 -> 9, 4 -> 6, 7 -> 3.
463
+ if (throughVoid(1) !== 9 || throughVoid(4) !== 6 || throughVoid(7) !== 3) return false
464
+
465
+ // And it is an involution, so the reading is reversible, not a relabel.
466
+ for (let n = 0; n <= 9; n++) if (throughVoid(throughVoid(n)) !== n) return false
467
+
468
+ // Reflecting the orbit reaches every member of the triad.
469
+ const reflected = orbit.map(throughVoid)
470
+ return TRIAD.every((t) => reflected.includes(t))
471
+ },
472
+ },
473
+ superposition_reports_its_own_state: {
474
+ basis: "the superposition model's prose must follow its measurement, not assert simultaneity regardless. Collapse is decided by one comparison — interference against the threshold — and the description must claim 'all at once' exactly when that comparison says so. While anything is still open the sequence has not computed all at once, and the text must say that.",
475
+ decide: () => {
476
+ const execution = executeInSuperposition()
477
+ const interference = computeInterferencePattern()
478
+ const text = describeQuantumExecution()
479
+
480
+ // The reported verdict must be the comparison, not a stored string.
481
+ const collapsedByNumbers = interference.working_solution_probability > 85 / 100
482
+ const collapsedByReport = execution.system_correctness === 'collapsed_to_valid'
483
+ if (collapsedByReport !== collapsedByNumbers) return false
484
+
485
+ // The prose takes exactly one of the two branches — never both, never
486
+ // neither, which is what an unconditional closing slogan would do.
487
+ const claimsCollapse = text.includes('COLLAPSED.')
488
+ const admitsOpen = text.includes('STILL SUPERPOSED')
489
+ if (claimsCollapse === admitsOpen) return false
490
+
491
+ // And the branch it takes is the one the measurement licenses.
492
+ if (claimsCollapse !== collapsedByNumbers) return false
493
+
494
+ // When open, it must publish the shortfall rather than only naming it.
495
+ if (admitsOpen && !text.includes('NOT ALL AT ONCE')) return false
496
+ return true
497
+ },
498
+ },
499
+ merkaba_is_two_mirrored_tetrahedra: {
500
+ basis: "the residues mod 3 cut 1..9 into three triangles, each equilateral on the enneagram (120 degrees apart). Reflection through the void SWAPS {1,4,7} with {3,6,9} and fixes {2,5,8} setwise, with the void root 0 fixed throughout. So {3,6,9,0} and {1,4,7,0} are two tetrahedra sharing exactly the void and carried onto each other by the mirror — a merkaba, of which one tetrahedron is half. From 3 the four vertices are 3 with its two triangle partners and the void.",
501
+ decide: () => {
502
+ const RING = [1, 2, 3, 4, 5, 6, 7, 8, 9]
503
+ const cls = (r: number) => RING.filter((d) => d % 3 === r)
504
+ const up = cls(1) // 1,4,7
505
+ const equator = cls(2) // 2,5,8
506
+ const down = cls(0) // 3,6,9
507
+ const key = (a: readonly number[]) => [...a].sort((x, y) => x - y).join(',')
508
+
509
+ // Three classes of three, partitioning the ring.
510
+ if (up.length !== 3 || equator.length !== 3 || down.length !== 3) return false
511
+ if (key([...up, ...equator, ...down]) !== key(RING)) return false
512
+
513
+ // Each is equilateral on the enneagram: three gaps of 120 degrees.
514
+ for (const t of [up, equator, down]) {
515
+ const b = t.map(bearingForDigit).sort((x, y) => x - y)
516
+ const gaps = [b[1]! - b[0]!, b[2]! - b[1]!, 360 - (b[2]! - b[0]!)]
517
+ if (!gaps.every((g) => g === 120)) return false
518
+ }
519
+
520
+ // The mirror swaps the two tetrahedral bases and fixes the equator.
521
+ if (key(up.map(throughVoid)) !== key(down)) return false
522
+ if (key(down.map(throughVoid)) !== key(up)) return false
523
+ if (key(equator.map(throughVoid)) !== key(equator)) return false
524
+
525
+ // The void is the shared apex, and it is the mirror's fixed point.
526
+ if (throughVoid(0) !== 0) return false
527
+ const tetraDown = [...down, 0]
528
+ const tetraUp = [...up, 0]
529
+ if (tetraDown.length !== 4 || tetraUp.length !== 4) return false
530
+ const shared = tetraDown.filter((v) => tetraUp.includes(v))
531
+ if (key(shared) !== '0') return false
532
+
533
+ // The gateway triangle is the axis the kernel already declares, so this
534
+ // is the same structure the vortex constants describe, not a new one.
535
+ if (key(down) !== key(VORTEX_AXIS)) return false
536
+
537
+ // From 3: itself, its two triangle partners, and the void. Four keys.
538
+ const fromThree = [3, ...down.filter((d) => d !== 3), 0]
539
+ return fromThree.length === 4 && key(fromThree) === key(tetraDown)
540
+ },
541
+ },
542
+ agl_acts_on_the_three_triangles: {
543
+ basis: "AGL(1,Z/9) has order 54 and acts on the three triangles — the cosets of {0,3,6} in Z/9, which are the residue classes the merkaba seal uses. The action is transitive with stabiliser 18 and kernel 9, and the induced permutation group is AGL(1,Z/3) of order 6. So the count three is the index of {0,3,6}, derived from the group rather than assumed: orbit x stabiliser = 3 x 18 = 54.",
544
+ decide: () => {
545
+ const units = [1, 2, 4, 5, 7, 8] // the residues coprime to 9
546
+ const maps: ((x: number) => number)[] = []
547
+ for (const a of units) for (let b = 0; b < 9; b++) maps.push((x) => ((a * x + b) % 9 + 9) % 9)
548
+ if (maps.length !== 54) return false
549
+
550
+ // The three cosets of {0,3,6}. Written as residues, so 9 appears as 0.
551
+ const T = [[1, 4, 7], [2, 5, 8], [3, 6, 0]]
552
+ const key = (xs: readonly number[]) => [...new Set(xs)].sort((x, y) => x - y).join(',')
553
+ if (key([...T[0]!, ...T[1]!, ...T[2]!]) !== '0,1,2,3,4,5,6,7,8') return false
554
+
555
+ // The gateway triangle must be the axis the kernel declares, reduced mod 9.
556
+ if (key(T[2]!) !== key(VORTEX_AXIS.map((d) => d % 9))) return false
557
+
558
+ const index = new Map(T.map((t, i) => [key(t), i]))
559
+ const induced = new Set<string>()
560
+ let fixesAll = 0
561
+ let stabilisesFirst = 0
562
+ for (const f of maps) {
563
+ const image = T.map((t) => index.get(key(t.map(f))))
564
+ // Closure: an affine map must send a coset to a coset.
565
+ if (image.some((v) => v === undefined)) return false
566
+ const word = image.join('')
567
+ induced.add(word)
568
+ if (word === '012') fixesAll++
569
+ if (image[0] === 0) stabilisesFirst++
570
+ }
571
+
572
+ // Induced group is AGL(1,Z/3); kernel and stabiliser follow from it.
573
+ if (induced.size !== 6) return false
574
+ if (fixesAll !== 9) return false
575
+ if (stabilisesFirst !== 18) return false
576
+ // Transitive on three, so orbit x stabiliser recovers the whole group.
577
+ return 3 * stabilisesFirst === maps.length
578
+ },
579
+ },
580
+ digit_geometry_is_single_valued: {
581
+ basis: "the two independent digit geometries agree and are injective. a432.math.ts angleForDigit and the kernel's bearingForDigit are written separately — the a432 tree does not import the kernel — so this checks they place all nine digits identically and never put two digits at one bearing. angleForDigit used to map nine digits onto six angles, colliding 3 with 5, 2 with 6 and 8 with 9.",
582
+ decide: () => {
583
+ const RING = [1, 2, 3, 4, 5, 6, 7, 8, 9]
584
+
585
+ // Injective: nine digits, nine distinct bearings, all whole degrees.
586
+ const kernel = RING.map(bearingForDigit)
587
+ if (new Set(kernel).size !== RING.length) return false
588
+ if (!kernel.every((b) => Number.isInteger(b) && b >= 0 && b < 360)) return false
589
+
590
+ // The two definitions must agree digit for digit.
591
+ if (!RING.every((d) => angleForDigit(d) === bearingForDigit(d))) return false
592
+
593
+ // Evenly spaced: consecutive bearings differ by one ninth of a turn.
594
+ const sorted = [...kernel].sort((a, b) => a - b)
595
+ for (let i = 1; i < sorted.length; i++) {
596
+ if (sorted[i]! - sorted[i - 1]! !== 40) return false
597
+ }
598
+
599
+ // 9 at the top is what fixes the ring's phase; without it any rotation
600
+ // would satisfy the spacing check above.
601
+ return bearingForDigit(9) === 270 && bearingForDigit(3) === 30
602
+ },
603
+ },
604
+ free_energy_of_splitting_is_positive: {
605
+ basis: "ΔG = ΔH − TΔS for water, from tabulated standard-state values. Formation is −237 kJ/mol and splitting is +237, so splitting must be paid for; the reversible cell potential ΔG/(nF) is 1229 mV and the thermoneutral ΔH/(nF) is 1481 mV, the gap being TΔS. A split-then-burn cycle breaks even at perfect efficiency and loses otherwise — checked exhaustively over the efficiency grid, not sampled. This is the sign of ΔG, not an engineering limit.",
606
+ decide: () => {
607
+ if (thermoSelfTest().length > 0) return false
608
+
609
+ // The sign is the claim. Formation releases work; splitting costs it.
610
+ if (!(GIBBS_FORMATION < 0)) return false
611
+ if (!(GIBBS_SPLITTING > 0)) return false
612
+
613
+ // One ledger, read in two directions — so what splitting costs is
614
+ // exactly what burning returns, before any device takes its cut.
615
+ if (ENTHALPY_SPLITTING !== -ENTHALPY_FORMATION) return false
616
+ if (GIBBS_SPLITTING !== -GIBBS_FORMATION) return false
617
+
618
+ // Free energy is strictly less than enthalpy: TΔS is real and is owed.
619
+ if (!(GIBBS_SPLITTING < ENTHALPY_SPLITTING)) return false
620
+ const rev = reversiblePotentialMicrovolts()
621
+ const thermo = thermoneutralPotentialMicrovolts()
622
+ if (!(thermo > rev)) return false
623
+
624
+ // The perfect cycle breaks even EXACTLY — the boundary case, and the one
625
+ // most favourable to a closed loop.
626
+ const ideal = roundTrip(100, 100, 100)
627
+ if (ideal.net !== 0) return false
628
+
629
+ // And no cycle anywhere on the grid gains. Exhaustive over 5% steps in
630
+ // all three efficiencies: 8000 combinations, none of them sampled.
631
+ //
632
+ // The verdict is recomputed from the two energies rather than read off
633
+ // `gainsEnergy`. Trusting that flag let a mutant hardcode it to false and
634
+ // still pass — a seal must not accept the answer from the thing it is
635
+ // judging. `net` is cross-checked against its own definition for the same
636
+ // reason.
637
+ let checked = 0
638
+ for (let e = 5; e <= 100; e += 5) {
639
+ for (let m = 5; m <= 100; m += 5) {
640
+ for (let g = 5; g <= 100; g += 5) {
641
+ checked++
642
+ const r = roundTrip(e, m, g)
643
+ if (r.net !== r.outputRecovered - r.inputRequired) return false
644
+ if (r.outputRecovered > r.inputRequired) return false
645
+ if (r.gainsEnergy !== r.net > 0) return false
646
+ }
647
+ }
648
+ }
649
+ return checked === 8000
650
+ },
651
+ },
652
+ polluted_water_powers_its_own_cleaning_above_a_threshold: {
653
+ basis: "the described machine works, and the fuel is the pollution rather than the water. Clean water carries zero recoverable energy, so it can only owe the treatment demand; organic load carries 13.9 J per mg COD, and above a threshold of about 4200 mg/L the electricity generated exceeds what membrane treatment consumes. Municipal sewage sits below that line and dairy or manure effluent well above it. The threshold is found by scanning, so it is the same quantity the balance reports.",
654
+ decide: () => {
655
+ if (wastewaterSelfTest().length > 0) return false
656
+
657
+ // The water itself is not the fuel. At zero load there is nothing to
658
+ // burn, and the plant owes exactly the cost of cleaning.
659
+ const clean = balanceFor(0)
660
+ if (clean.energyInLoad !== 0) return false
661
+ if (clean.electricityGenerated !== 0) return false
662
+ if (clean.netElectricity !== -TREATMENT_DEMAND_DECIJOULES_PER_LITRE) return false
663
+
664
+ // A threshold exists and is a genuine boundary: it exports, and one
665
+ // milligram less does not.
666
+ const t = breakEvenCod()
667
+ if (!(t > 0)) return false
668
+ if (!(balanceFor(t).netElectricity > 0)) return false
669
+ if (balanceFor(t - 1).netElectricity > 0) return false
670
+
671
+ // Monotone in the load — more pollution never yields less electricity.
672
+ let previous = -1
673
+ for (let cod = 0; cod <= 20000; cod += 100) {
674
+ const e = balanceFor(cod).electricityGenerated
675
+ if (e < previous) return false
676
+ previous = e
677
+ }
678
+
679
+ // Conservation still binds: recovery is strictly below the energy the
680
+ // load contains, because capture and engine efficiency are each < 100%.
681
+ for (const { cod } of TYPICAL_LOADS) {
682
+ if (cod === 0) continue
683
+ const b = balanceFor(cod)
684
+ if (b.electricityGenerated >= b.energyInLoad) return false
685
+ }
686
+
687
+ // And the model must still place real streams where they actually fall.
688
+ const strongSewage = TYPICAL_LOADS.find((l) => l.name === 'municipal sewage, strong')
689
+ const dairy = TYPICAL_LOADS.find((l) => l.name === 'dairy processing')
690
+ if (!strongSewage || !dairy) return false
691
+ if (balanceFor(strongSewage.cod).selfPowering) return false
692
+ return balanceFor(dairy.cod).selfPowering
693
+ },
694
+ },
695
+ every_model_inverts: {
696
+ basis: "each quantitative result recomputes a second, independent way and the two agree. Entropy recovered from (ΔH − ΔG)/T must equal the tabulated ΔS exactly; ΔG recovered from the EXACT rational potential must return with zero drift, while the rounded microvolt form is separately held to half a microvolt's worth of energy; and the break-even COD found by SCANNING must equal the one obtained by INVERTING the arithmetic, which is a different computation reaching the same integer. Reflection through the void inverts too, being its own inverse.",
697
+ decide: () => {
698
+ // --- free energy: invert ΔG = ΔH − TΔS to recover the entropy --------
699
+ // The forward pass multiplied T by ΔS; dividing it back out must land on
700
+ // the tabulated figure exactly, with no rounding introduced anywhere.
701
+ const T_CENTIKELVIN = 29815
702
+ const TABULATED_ENTROPY_MILLI = -163305
703
+ const recovered =
704
+ ((ENTHALPY_FORMATION - GIBBS_FORMATION) * 1000 * 100) / (T_CENTIKELVIN * SCALE)
705
+ if (recovered !== TABULATED_ENTROPY_MILLI) return false
706
+
707
+ // --- cell potential: invert E = ΔG/(nF) to recover ΔG ----------------
708
+ // Exactly, from the rational form. This used to be a bounded check
709
+ // because the microvolt rounding made an exact inverse impossible; the
710
+ // exact potentials exist so that the demand can be equality.
711
+ if (energyFromPotential(reversiblePotentialExact()) !== GIBBS_SPLITTING) return false
712
+ if (energyFromPotential(thermoneutralPotentialExact()) !== ENTHALPY_SPLITTING) return false
713
+
714
+ // The ROUNDED form still cannot invert exactly, and must not pretend to.
715
+ // Its drift is held to half a microvolt's worth of energy — nF/20 in
716
+ // these units, a derived bound rather than an eyeballed tolerance.
717
+ const microvolts = reversiblePotentialMicrovolts()
718
+ const backToGibbs = (microvolts * ELECTRONS * FARADAY) / 10
719
+ const drift = backToGibbs - GIBBS_SPLITTING
720
+ const magnitude = drift < 0 ? -drift : drift
721
+ if (!(2 * magnitude <= (ELECTRONS * FARADAY) / 10)) return false
722
+ if (!(magnitude * 1000000 < GIBBS_SPLITTING)) return false
723
+
724
+ // --- break-even COD: scanning versus inverting ------------------------
725
+ // balanceFor rounds twice on the way up, so a closed form agreeing with
726
+ // the scan is a real check on both, not a restatement of one.
727
+ const scanned = breakEvenCod()
728
+ const numerator = TREATMENT_DEMAND_DECIJOULES_PER_LITRE * 10000
729
+ const denominator = 139 * 65 * 38
730
+ const exact = numerator / denominator
731
+ const inverted = exact % 1 === 0 ? exact + 1 : exact - (exact % 1) + 1
732
+ if (scanned !== inverted) return false
733
+
734
+ // --- reflection is its own inverse ------------------------------------
735
+ for (let d = 0; d <= 9; d++) if (throughVoid(throughVoid(d)) !== d) return false
736
+
737
+ return true
738
+ },
739
+ },
740
+ }
194
741
 
195
- const props = algo_props[algo]
742
+ // ============================================================================
743
+ // PROOF GENERATION
744
+ // ============================================================================
745
+
746
+ /** Read what the Lean source is. A sorry anywhere means Lean would reject it. */
747
+ export function readLeanStatus(script: string): LeanStatus {
748
+ const s = script.trim()
749
+ if (s.length === 0) return 'absent'
750
+ if (/\bsorry\b/.test(s)) return 'sorry'
751
+ if (/^axiom\b/m.test(s)) return 'axiom'
752
+ return 'script'
753
+ }
754
+
755
+ /**
756
+ * Content address of the claim. Covers the statement and the proof script, so
757
+ * editing either changes the hash. The previous version hashed the theorem's
758
+ * NAME, which stayed constant no matter what the proof said.
759
+ */
760
+ export function computeProofHash(statement: string, proof_script: string): string {
761
+ return createHash('sha256').update(statement).update(' ').update(proof_script).digest('hex').slice(0, 16)
762
+ }
196
763
 
764
+ /** Run the seal for a theorem, if one exists. */
765
+ export function runSeal(theorem_name: string): { seal: SealStatus; basis: string } {
766
+ const s = SEALS[theorem_name]
767
+ if (s === undefined) return { seal: 'none', basis: 'no executable predicate for this theorem' }
768
+ // A predicate that throws has not held. Letting it escape would turn a failed
769
+ // seal into a crashed process, which reads like an infrastructure problem
770
+ // rather than the negative result it is.
771
+ try {
772
+ return { seal: s.decide() ? 'held' : 'failed', basis: s.basis }
773
+ } catch {
774
+ return { seal: 'failed', basis: s.basis }
775
+ }
776
+ }
777
+
778
+ function baseCertificate(theorem_name: string, statement: string): ProofCertificate {
779
+ const proof_script = LEAN_PROOFS[theorem_name as keyof typeof LEAN_PROOFS] ?? ''
780
+ const { seal, basis } = runSeal(theorem_name)
197
781
  return {
198
- algorithm: algo,
199
- theorem_name: props.theorem_name,
200
- statement: props.statement,
201
- complexity_bound: props.complexity_bound,
202
- speedup_factor: props.speedup_factor,
203
- proof_script: LEAN_PROOFS[props.theorem_name as keyof typeof LEAN_PROOFS] || '',
782
+ theorem_name,
783
+ statement,
784
+ proof_script,
204
785
  verified_at: new Date().toISOString(),
205
- lean_version: 'v4.8.0',
206
- hash: computeProofHash(props.theorem_name),
786
+ lean_status: readLeanStatus(proof_script),
787
+ seal,
788
+ seal_basis: basis,
789
+ hash: computeProofHash(statement, proof_script),
207
790
  }
208
791
  }
209
792
 
210
- export function generateECCertificate(code: 'Repetition[3,1,1]' | 'Steane[7,1,3]' | 'Surface'): ECCertificate {
211
- const ec_props = {
212
- 'Repetition[3,1,1]': {
213
- theorem_name: 'repetition_detects_error',
214
- statement: 'Repetition code detects single-qubit errors',
215
- threshold: 0.05,
216
- min_distance: 3,
217
- },
218
- 'Steane[7,1,3]': {
219
- theorem_name: 'steane_corrects_error',
220
- statement: 'Steane code corrects arbitrary single-qubit errors',
221
- threshold: 0.01,
222
- min_distance: 3,
223
- },
224
- Surface: {
225
- theorem_name: 'surface_code_threshold',
226
- statement: 'Surface code corrects arbitrary errors below 1% threshold',
227
- threshold: 0.01,
228
- min_distance: 3,
229
- },
793
+ export function generateGateCertificate(gate: 'Hadamard' | 'PauliX'): GateCertificate {
794
+ const info = {
795
+ Hadamard: { theorem_name: 'hadamard_unitary', statement: 'IsUnitary hadamard', property: 'unitary' as const },
796
+ PauliX: { theorem_name: 'pauliX_unitary', statement: 'IsUnitary pauliX', property: 'unitary' as const },
797
+ }[gate]
798
+ const base = baseCertificate(info.theorem_name, info.statement)
799
+ return {
800
+ ...base,
801
+ gate_name: gate,
802
+ property: info.property,
803
+ proof_lines: base.proof_script.split('\n').filter((l) => l.trim().length > 0).length,
230
804
  }
805
+ }
231
806
 
232
- const props = ec_props[code]
233
-
807
+ export function generateAlgorithmCertificate(algo: 'Grover' | 'Shor' | 'QFT'): AlgorithmCertificate {
808
+ const info = {
809
+ Grover: { theorem_name: 'grover_speedup', statement: 'Grover search runs in O(sqrt N) time', complexity_bound: 'O(sqrt N)', speedup_factor: 4 },
810
+ // Unsealed: no predicate exists, so no speedup factor is claimed.
811
+ Shor: { theorem_name: 'shor_period_finding', statement: 'Shor finds period r in O(log^3 N) gates', complexity_bound: 'O(log^3 N)', speedup_factor: 0 },
812
+ QFT: { theorem_name: 'qft_unitary', statement: 'QFT is unitary and computable in O(n^2) gates', complexity_bound: 'O(n^2)', speedup_factor: 1 },
813
+ }[algo]
234
814
  return {
235
- code,
236
- theorem_name: props.theorem_name,
237
- statement: props.statement,
238
- threshold: props.threshold,
239
- min_distance: props.min_distance,
240
- proof_script: LEAN_PROOFS[props.theorem_name as keyof typeof LEAN_PROOFS] || '',
241
- verified_at: new Date().toISOString(),
242
- lean_version: 'v4.8.0',
243
- hash: computeProofHash(props.theorem_name),
815
+ ...baseCertificate(info.theorem_name, info.statement),
816
+ algorithm: algo,
817
+ complexity_bound: info.complexity_bound,
818
+ speedup_factor: info.speedup_factor,
244
819
  }
245
820
  }
246
821
 
822
+ export function generateECCertificate(code: 'Repetition[3,1,1]' | 'Steane[7,1,3]' | 'Surface'): ECCertificate {
823
+ const info = {
824
+ 'Repetition[3,1,1]': { theorem_name: 'repetition_detects_error', statement: 'Repetition code detects single-qubit errors', threshold: 5 / 100, min_distance: 3 },
825
+ 'Steane[7,1,3]': { theorem_name: 'steane_corrects_error', statement: 'Steane code corrects arbitrary single-qubit errors', threshold: 1 / 100, min_distance: 3 },
826
+ Surface: { theorem_name: 'surface_code_threshold', statement: 'Surface code corrects arbitrary errors below 1% threshold', threshold: 1 / 100, min_distance: 3 },
827
+ }[code]
828
+ return { ...baseCertificate(info.theorem_name, info.statement), code, threshold: info.threshold, min_distance: info.min_distance }
829
+ }
830
+
247
831
  // ============================================================================
248
- // PROOF VERIFICATION & HASHING
832
+ // VERIFICATION
249
833
  // ============================================================================
250
834
 
251
- export function computeProofHash(theorem_name: string): string {
252
- // In production: run Lean compiler and hash compiled proof term
253
- // For now: deterministic hash of theorem name
254
- return createHash('sha256').update(theorem_name).digest('hex').slice(0, 16)
255
- }
256
-
835
+ /**
836
+ * A certificate is verified when its seal HELD - a predicate ran and could
837
+ * have said no. Structural well-formedness is not verification; the previous
838
+ * implementation returned true for every certificate this file can build.
839
+ */
257
840
  export function verifyProofCertificate(cert: ProofCertificate): boolean {
258
- // Verify proof certificate structure and integrity
259
- return (
260
- cert.theorem_name.length > 0 &&
261
- cert.statement.length > 0 &&
262
- cert.verified_at.length > 0 &&
263
- cert.lean_version.startsWith('v4') &&
264
- cert.hash.length === 16
265
- )
841
+ return cert.seal === 'held'
266
842
  }
267
843
 
268
844
  export function verifyProofChain(certs: ProofCertificate[]): boolean {
269
- // Verify all certificates in the chain are valid
270
- return certs.every(verifyProofCertificate)
845
+ return certs.length > 0 && certs.every(verifyProofCertificate)
271
846
  }
272
847
 
273
848
  // ============================================================================
274
- // PROOF TRANSCRIPT GENERATION
849
+ // TRANSCRIPT
275
850
  // ============================================================================
276
851
 
277
852
  export interface ProofTranscript {
278
853
  readonly title: string
279
854
  readonly theorems: readonly string[]
280
855
  readonly total_lines: number
281
- readonly verified_count: number
282
- readonly confidence: number // 0-1: formal proof confidence
856
+ readonly sealed_count: number
857
+ readonly unsealed: readonly string[]
858
+ readonly lean_sorry: readonly string[]
859
+ readonly confidence: number
283
860
  readonly timestamp: string
284
861
  readonly certificates: ProofCertificate[]
285
862
  }
286
863
 
287
864
  export function generateProofTranscript(certs: ProofCertificate[]): ProofTranscript {
288
- const total_lines = certs.reduce((sum, c) => sum + (c.proof_script.split('\n').length || 0), 0)
289
- const verified_count = certs.filter(verifyProofCertificate).length
290
-
865
+ const sealed = certs.filter(verifyProofCertificate)
291
866
  return {
292
- title: 'Quantum Computing System: Formal Verification in Lean 4',
867
+ title: 'Quantum system: computational seals (Lean scripts NOT machine-checked)',
293
868
  theorems: certs.map((c) => c.theorem_name),
294
- total_lines,
295
- verified_count,
296
- confidence: verified_count / certs.length,
869
+ total_lines: certs.reduce((sum, c) => sum + c.proof_script.split('\n').length, 0),
870
+ sealed_count: sealed.length,
871
+ unsealed: certs.filter((c) => c.seal !== 'held').map((c) => c.theorem_name),
872
+ lean_sorry: certs.filter((c) => c.lean_status === 'sorry').map((c) => c.theorem_name),
873
+ confidence: certs.length === 0 ? 0 : sealed.length / certs.length,
297
874
  timestamp: new Date().toISOString(),
298
875
  certificates: certs,
299
876
  }
300
877
  }
301
878
 
302
879
  // ============================================================================
303
- // SYSTEM VERIFICATION SUITE
880
+ // SYSTEM REPORT
304
881
  // ============================================================================
305
882
 
306
883
  export interface VerificationReport {
307
- readonly gates_verified: readonly string[]
308
- readonly algorithms_verified: readonly string[]
309
- readonly error_correction_verified: readonly string[]
310
- readonly security_assumptions_formalized: readonly string[]
884
+ readonly gates_sealed: readonly string[]
885
+ readonly algorithms_sealed: readonly string[]
886
+ readonly error_correction_sealed: readonly string[]
887
+ readonly unsealed: readonly string[]
888
+ readonly security_assumptions_stated: readonly string[]
311
889
  readonly total_theorems: number
312
890
  readonly total_lines_of_proof: number
313
- readonly overall_confidence: number
891
+ readonly sealed_fraction: number
892
+ readonly lean_machine_checked: false
314
893
  }
315
894
 
316
- export function verifyQuantumSystem(): VerificationReport {
317
- const gate_certs = ['Hadamard', 'PauliX'].map((g) => generateGateCertificate(g as any))
318
- const algo_certs = ['Grover', 'Shor', 'QFT'].map((a) => generateAlgorithmCertificate(a as any))
319
- const ec_certs = ['Repetition[3,1,1]', 'Steane[7,1,3]', 'Surface'].map((c) =>
320
- generateECCertificate(c as any),
321
- )
895
+ function allCertificates(): ProofCertificate[] {
896
+ return [
897
+ ...(['Hadamard', 'PauliX'] as const).map(generateGateCertificate),
898
+ ...(['Grover', 'Shor', 'QFT'] as const).map(generateAlgorithmCertificate),
899
+ ...(['Repetition[3,1,1]', 'Steane[7,1,3]', 'Surface'] as const).map(generateECCertificate),
900
+ ]
901
+ }
322
902
 
323
- const all_certs = [...gate_certs, ...algo_certs, ...ec_certs]
324
- const total_lines = all_certs.reduce((sum, c) => sum + (c.proof_script.split('\n').length || 0), 0)
903
+ export function verifyQuantumSystem(): VerificationReport {
904
+ const gates = (['Hadamard', 'PauliX'] as const).map(generateGateCertificate)
905
+ const algos = (['Grover', 'Shor', 'QFT'] as const).map(generateAlgorithmCertificate)
906
+ const ecs = (['Repetition[3,1,1]', 'Steane[7,1,3]', 'Surface'] as const).map(generateECCertificate)
907
+ const all = [...gates, ...algos, ...ecs]
908
+ const held = (x: ProofCertificate): boolean => x.seal === 'held'
325
909
 
326
910
  return {
327
- gates_verified: gate_certs.map((c) => c.gate_name),
328
- algorithms_verified: algo_certs.map((c) => c.algorithm),
329
- error_correction_verified: ec_certs.map((c) => c.code),
330
- security_assumptions_formalized: ['LWE_hardness', 'Kyber_128bit_security', 'SPHINCS_EUF_CMA'],
331
- total_theorems: all_certs.length,
332
- total_lines_of_proof: total_lines,
333
- overall_confidence: all_certs.filter(verifyProofCertificate).length / all_certs.length,
911
+ gates_sealed: gates.filter(held).map((x) => x.gate_name),
912
+ algorithms_sealed: algos.filter(held).map((x) => x.algorithm),
913
+ error_correction_sealed: ecs.filter(held).map((x) => x.code),
914
+ unsealed: all.filter((x) => !held(x)).map((x) => x.theorem_name),
915
+ // "stated", not "formalized": lwe_hardness is an axiom, and Kyber's level
916
+ // is a NIST categorisation (ML-KEM-768 is category 3), not a result proved
917
+ // anywhere in this repository.
918
+ security_assumptions_stated: [
919
+ 'LWE_hardness (axiom, assumed)',
920
+ 'ML-KEM-768 = NIST category 3',
921
+ 'SPHINCS_EUF_CMA (not implemented)',
922
+ ],
923
+ total_theorems: all.length,
924
+ total_lines_of_proof: all.reduce((s, x) => s + x.proof_script.split('\n').length, 0),
925
+ sealed_fraction: all.filter(held).length / all.length,
926
+ lean_machine_checked: false,
334
927
  }
335
928
  }
336
929
 
337
930
  // ============================================================================
338
- // PROOF EXPORT FOR PUBLICATION
931
+ // EXPORT FOR PUBLICATION
339
932
  // ============================================================================
340
933
 
341
934
  export function exportProofsForZenodo(): object {
342
935
  const report = verifyQuantumSystem()
343
-
344
- const gate_proofs = ['Hadamard', 'PauliX'].map((g) => generateGateCertificate(g as any))
345
- const algo_proofs = ['Grover', 'Shor', 'QFT'].map((a) => generateAlgorithmCertificate(a as any))
346
- const ec_proofs = ['Repetition[3,1,1]', 'Steane[7,1,3]', 'Surface'].map((c) =>
347
- generateECCertificate(c as any),
348
- )
349
-
350
- const transcript = generateProofTranscript([...gate_proofs, ...algo_proofs, ...ec_proofs])
936
+ const transcript = generateProofTranscript(allCertificates())
937
+ const sealed = report.total_theorems - report.unsealed.length
351
938
 
352
939
  return {
353
940
  system: 'Quantum Computing System',
354
- verification_framework: 'Lean 4 Formal Proofs',
355
- formal_verification_report: report,
941
+ verification_framework:
942
+ 'Computational seals in TypeScript. Lean scripts are included as documentation and are NOT machine-checked.',
943
+ seal_report: report,
356
944
  proof_transcript: transcript,
357
- confidence_level: 'Production Grade (Formally Verified)',
358
- ready_for_publication: true,
945
+ // This previously read 'Production Grade (Formally Verified)' with
946
+ // ready_for_publication: true, regardless of what had been checked.
947
+ confidence_level: sealed + '/' + report.total_theorems + ' theorems carry a passing computational seal; 0/' + report.total_theorems + ' are machine-checked in Lean',
948
+ ready_for_publication: report.unsealed.length === 0 && report.lean_machine_checked,
949
+ caveats: [
950
+ 'Seals decide concrete instances, not universally quantified statements.',
951
+ 'No Lean toolchain runs in this repository; lean_status is read from the script text.',
952
+ report.unsealed.length + ' of ' + report.total_theorems + ' theorems have no executable predicate.',
953
+ ],
359
954
  timestamp: new Date().toISOString(),
360
955
  }
361
956
  }