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.
- package/CHANGELOG.md +176 -0
- package/CITATION.cff +1 -1
- package/README.md +1 -1
- package/dist/legacy-BEa7tljT.js.map +1 -1
- package/dist/legacy-CV8oTnKM.cjs.map +1 -1
- package/package.json +12 -3
- package/src/0/3/6/9/1/2/4/8/7/5/1/a432.math.ts +14 -6
- package/src/0/3/6/9/1/2/4/8/7/5/1/a432.vbm.path.ts +6 -2
- package/src/0/index.ts +16 -0
- package/src/crypto/ml-kem-768-acvp.json +492 -0
- package/src/crypto/ml-kem.test.ts +140 -0
- package/src/crypto/ml-kem.ts +554 -0
- package/src/quantum/error-correction.ts +69 -16
- package/src/quantum/hybrid.ts +2 -2
- package/src/quantum/simulator.ts +19 -0
- package/src/quantum/superposition-execution.ts +9 -4
- package/src/quantum/tomography.ts +4 -4
- package/src/thermo/free-energy.ts +279 -0
- package/src/thermo/wastewater-energy.ts +204 -0
- package/src/verification/lean-bridge.test.ts +109 -228
- package/src/verification/lean-bridge.ts +748 -153
- package/src/crypto/kyber-real.test.ts +0 -198
- package/src/crypto/kyber-real.ts +0 -489
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polluted water in, electricity and drinkable water out — the real version.
|
|
3
|
+
*
|
|
4
|
+
* The described machine exists. What makes it work is that the fuel is not the
|
|
5
|
+
* water: it is what is dissolved in it. H₂O carries no recoverable energy —
|
|
6
|
+
* `free-energy.ts` settles that, ΔG for splitting is +237 kJ/mol — but organic
|
|
7
|
+
* contamination does, and a litre of strong effluent can carry more chemical
|
|
8
|
+
* energy than it costs to clean the litre.
|
|
9
|
+
*
|
|
10
|
+
* So the architecture is:
|
|
11
|
+
*
|
|
12
|
+
* polluted water → anaerobic digestion → biogas (mostly CH₄)
|
|
13
|
+
* → combustion engine (CHP) → ELECTRICITY
|
|
14
|
+
* digester effluent → membrane treatment → DRINKABLE WATER
|
|
15
|
+
*
|
|
16
|
+
* The engine burns methane the bacteria made from the pollutants. Its exhaust
|
|
17
|
+
* is CO₂ and water vapour; the drinkable water comes from the membrane train,
|
|
18
|
+
* powered by part of the electricity. Everything you described happens, and
|
|
19
|
+
* nothing runs on the water itself.
|
|
20
|
+
*
|
|
21
|
+
* THE WHOLE QUESTION IS THE LOAD. Weak sewage does not carry enough energy to
|
|
22
|
+
* pay for its own treatment; strong industrial effluent carries several times
|
|
23
|
+
* over. There is therefore a THRESHOLD contamination, and this module computes
|
|
24
|
+
* it rather than asserting it. Below it the plant imports power; above it the
|
|
25
|
+
* plant exports.
|
|
26
|
+
*
|
|
27
|
+
* Distillation is deliberately not the water step. Evaporating a litre costs
|
|
28
|
+
* about 2.26 MJ in latent heat alone — far more than any realistic load carries
|
|
29
|
+
* — so a still cannot be paid for by the pollution. Membranes can.
|
|
30
|
+
*
|
|
31
|
+
* ARITHMETIC. Integers throughout, in decijoules per litre (dJ/L). No float
|
|
32
|
+
* literals; rounding happens once, where a value is rendered.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// CONSTANTS — measured quantities, not choices
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Chemical energy per unit of COD (chemical oxygen demand): 13.9 J per mg.
|
|
41
|
+
* COD is the standard measure of oxidisable load, so this converts "how dirty"
|
|
42
|
+
* directly into "how much energy is in it". Held as tenths of a J/mg.
|
|
43
|
+
*/
|
|
44
|
+
const JOULES_PER_MG_COD_TENTHS = 139
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The same figure as J/mg, for prose that quotes it. Derived from the tenths
|
|
48
|
+
* above rather than written as 13.9 — a decimal literal here would be a second
|
|
49
|
+
* copy of the constant, and the ratchet counts those for exactly that reason.
|
|
50
|
+
*/
|
|
51
|
+
export const JOULES_PER_MG_COD = JOULES_PER_MG_COD_TENTHS / 10
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Fraction of COD that anaerobic digestion converts to methane, as a
|
|
55
|
+
* percentage. Well-run mesophilic digesters on soluble organics reach the
|
|
56
|
+
* mid-sixties; the rest becomes biomass or leaves undigested.
|
|
57
|
+
*/
|
|
58
|
+
const DIGESTION_CAPTURE_PERCENT = 65
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Electrical efficiency of a gas engine in CHP service, as a percentage.
|
|
62
|
+
* Reciprocating engines in the hundreds-of-kW class sit near this. Heat is
|
|
63
|
+
* recovered too, but heat is not what was asked for, so it is not counted.
|
|
64
|
+
*/
|
|
65
|
+
const ENGINE_ELECTRICAL_PERCENT = 38
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Electricity to bring digester effluent to drinking standard by membranes:
|
|
69
|
+
* ultrafiltration, reverse osmosis, then polishing. 4 kWh per m³ = 4 Wh/L =
|
|
70
|
+
* 14 400 J/L = 144 000 dJ/L. The conservative end of the RO range, because a
|
|
71
|
+
* dirty feed fouls membranes and costs more than a clean one.
|
|
72
|
+
*/
|
|
73
|
+
export const TREATMENT_DEMAND_DECIJOULES_PER_LITRE = 144000
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// THE BALANCE
|
|
77
|
+
// ============================================================================
|
|
78
|
+
|
|
79
|
+
export interface WaterBalance {
|
|
80
|
+
/** Contamination as COD, mg/L — the input. */
|
|
81
|
+
readonly codMilligramsPerLitre: number
|
|
82
|
+
/** Chemical energy present in one litre, dJ/L. */
|
|
83
|
+
readonly energyInLoad: number
|
|
84
|
+
/** Electricity the engine actually delivers, dJ/L. */
|
|
85
|
+
readonly electricityGenerated: number
|
|
86
|
+
/** Electricity the membrane train consumes, dJ/L. */
|
|
87
|
+
readonly treatmentDemand: number
|
|
88
|
+
/** generated − demand. Positive means the plant exports power. */
|
|
89
|
+
readonly netElectricity: number
|
|
90
|
+
/** True when the water pays for its own cleaning and more. */
|
|
91
|
+
readonly selfPowering: boolean
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Integer division rounded to nearest, ties away from zero, no Math.*. */
|
|
95
|
+
function round(a: number, b: number): number {
|
|
96
|
+
const neg = a < 0
|
|
97
|
+
const x = neg ? -a : a
|
|
98
|
+
const q = (2 * x + b) / (2 * b)
|
|
99
|
+
const f = q - (q % 1)
|
|
100
|
+
return neg ? -f : f
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Energy balance for one litre at a given contamination.
|
|
105
|
+
*
|
|
106
|
+
* `cod` is chemical oxygen demand in mg/L: roughly 300–800 for municipal
|
|
107
|
+
* sewage, 2 000–6 000 for dairy or brewery effluent, 20 000–80 000 for manure
|
|
108
|
+
* slurry or food-processing waste.
|
|
109
|
+
*/
|
|
110
|
+
export function balanceFor(cod: number): WaterBalance {
|
|
111
|
+
if (!Number.isInteger(cod) || cod < 0) {
|
|
112
|
+
throw new RangeError(`COD must be a non-negative integer in mg/L, got ${cod}`)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const energyInLoad = cod * JOULES_PER_MG_COD_TENTHS
|
|
116
|
+
const captured = round(energyInLoad * DIGESTION_CAPTURE_PERCENT, 100)
|
|
117
|
+
const electricityGenerated = round(captured * ENGINE_ELECTRICAL_PERCENT, 100)
|
|
118
|
+
const netElectricity = electricityGenerated - TREATMENT_DEMAND_DECIJOULES_PER_LITRE
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
codMilligramsPerLitre: cod,
|
|
122
|
+
energyInLoad,
|
|
123
|
+
electricityGenerated,
|
|
124
|
+
treatmentDemand: TREATMENT_DEMAND_DECIJOULES_PER_LITRE,
|
|
125
|
+
netElectricity,
|
|
126
|
+
selfPowering: netElectricity > 0,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The lowest whole mg/L of COD at which the plant exports power.
|
|
132
|
+
*
|
|
133
|
+
* Found by scanning upward rather than by inverting the arithmetic, so the
|
|
134
|
+
* answer is the same quantity `balanceFor` reports and cannot drift from it.
|
|
135
|
+
*/
|
|
136
|
+
export function breakEvenCod(): number {
|
|
137
|
+
for (let cod = 0; cod <= 100000; cod++) {
|
|
138
|
+
if (balanceFor(cod).selfPowering) return cod
|
|
139
|
+
}
|
|
140
|
+
throw new Error('no break-even COD below 100 000 mg/L')
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Typical loads, for locating a real stream against the threshold. */
|
|
144
|
+
export const TYPICAL_LOADS: readonly { readonly name: string; readonly cod: number }[] = [
|
|
145
|
+
{ name: 'municipal sewage, dilute', cod: 300 },
|
|
146
|
+
{ name: 'municipal sewage, strong', cod: 800 },
|
|
147
|
+
{ name: 'brewery effluent', cod: 3000 },
|
|
148
|
+
{ name: 'dairy processing', cod: 5000 },
|
|
149
|
+
{ name: 'manure slurry', cod: 40000 },
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// SELF-CHECK
|
|
154
|
+
// ============================================================================
|
|
155
|
+
|
|
156
|
+
/** Facts this module must satisfy. Returns failures. */
|
|
157
|
+
export function selfTest(): string[] {
|
|
158
|
+
const fail: string[] = []
|
|
159
|
+
|
|
160
|
+
// Clean water carries nothing. This is the point: H2O is not the fuel.
|
|
161
|
+
const clean = balanceFor(0)
|
|
162
|
+
if (clean.energyInLoad !== 0) fail.push('clean water reports non-zero energy')
|
|
163
|
+
if (clean.electricityGenerated !== 0) fail.push('clean water generates electricity')
|
|
164
|
+
if (clean.selfPowering) fail.push('clean water reports as self-powering')
|
|
165
|
+
if (clean.netElectricity !== -TREATMENT_DEMAND_DECIJOULES_PER_LITRE) {
|
|
166
|
+
fail.push('clean water does not owe exactly the treatment demand')
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// A threshold exists, is positive, and is unique — monotone in the load.
|
|
170
|
+
const t = breakEvenCod()
|
|
171
|
+
if (!(t > 0)) fail.push(`break-even COD is ${t}, expected positive`)
|
|
172
|
+
if (balanceFor(t).netElectricity <= 0) fail.push('break-even point does not export')
|
|
173
|
+
if (balanceFor(t - 1).netElectricity > 0) fail.push('a lower COD also exports — not a threshold')
|
|
174
|
+
|
|
175
|
+
// Monotone: more load never yields less electricity.
|
|
176
|
+
let previous = -1
|
|
177
|
+
for (let cod = 0; cod <= 20000; cod += 100) {
|
|
178
|
+
const e = balanceFor(cod).electricityGenerated
|
|
179
|
+
if (e < previous) { fail.push(`electricity fell between loads at COD ${cod}`); break }
|
|
180
|
+
previous = e
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Municipal sewage must sit below the threshold and strong effluent above,
|
|
184
|
+
// or the model has lost contact with the streams it claims to describe.
|
|
185
|
+
const municipal = TYPICAL_LOADS.find((l) => l.name === 'municipal sewage, strong')
|
|
186
|
+
const dairy = TYPICAL_LOADS.find((l) => l.name === 'dairy processing')
|
|
187
|
+
if (municipal && balanceFor(municipal.cod).selfPowering) {
|
|
188
|
+
fail.push('strong municipal sewage reports as self-powering')
|
|
189
|
+
}
|
|
190
|
+
if (dairy && !balanceFor(dairy.cod).selfPowering) {
|
|
191
|
+
fail.push('dairy effluent does not report as self-powering')
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// No arrangement recovers more than the load contains: capture and engine
|
|
195
|
+
// efficiency are both below 100%, so electricity < energy present, always.
|
|
196
|
+
for (const { cod } of TYPICAL_LOADS) {
|
|
197
|
+
const b = balanceFor(cod)
|
|
198
|
+
if (cod > 0 && b.electricityGenerated >= b.energyInLoad) {
|
|
199
|
+
fail.push(`COD ${cod} yields electricity at or above the energy present`)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return fail
|
|
204
|
+
}
|
|
@@ -1,247 +1,128 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lean
|
|
2
|
+
* Lean bridge — what is sealed, what is not, and why.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* This suite exists because the previous one asserted "Verified: 2/2" and
|
|
5
|
+
* "Confidence: 100.0%" against a predicate that could not return false. Every
|
|
6
|
+
* check here can fail.
|
|
7
|
+
*
|
|
8
|
+
* Two seals used to fail, and finding that was the point of writing them: the
|
|
9
|
+
* repetition seal caught raw LCG states being passed where `measureQubit`
|
|
10
|
+
* wants a unit in [0,1), and the Steane seal caught a generator list that was
|
|
11
|
+
* not a stabiliser group. Both defects are fixed, so both seals now hold, and
|
|
12
|
+
* this suite asserts that they hold - a regression would put them back.
|
|
5
13
|
*/
|
|
6
14
|
|
|
7
15
|
import {
|
|
16
|
+
SEALS,
|
|
17
|
+
runSeal,
|
|
18
|
+
readLeanStatus,
|
|
19
|
+
computeProofHash,
|
|
20
|
+
verifyProofCertificate,
|
|
8
21
|
generateGateCertificate,
|
|
9
22
|
generateAlgorithmCertificate,
|
|
10
23
|
generateECCertificate,
|
|
11
|
-
|
|
12
|
-
verifyProofChain,
|
|
24
|
+
generateProofTranscript,
|
|
13
25
|
verifyQuantumSystem,
|
|
14
26
|
exportProofsForZenodo,
|
|
15
|
-
|
|
16
|
-
generateProofTranscript,
|
|
27
|
+
LEAN_PROOFS,
|
|
17
28
|
} from './lean-bridge.ts'
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!verifyProofCertificate(hadamard)) {
|
|
26
|
-
throw new Error('Hadamard certificate invalid')
|
|
30
|
+
let failures = 0
|
|
31
|
+
function check(name: string, ok: boolean, detail = ''): void {
|
|
32
|
+
if (ok) console.log(' ok ' + name)
|
|
33
|
+
else {
|
|
34
|
+
failures++
|
|
35
|
+
console.log(' FAIL ' + name + (detail ? ' - ' + detail : ''))
|
|
27
36
|
}
|
|
28
|
-
if (!verifyProofCertificate(pauliX)) {
|
|
29
|
-
throw new Error('PauliX certificate invalid')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (hadamard.theorem_name !== 'hadamard_unitary') {
|
|
33
|
-
throw new Error('Hadamard theorem name mismatch')
|
|
34
|
-
}
|
|
35
|
-
if (hadamard.property !== 'unitary') {
|
|
36
|
-
throw new Error('Hadamard property mismatch')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
console.log(` ✓ Hadamard certificate: ${hadamard.hash}`)
|
|
40
|
-
console.log(` ✓ Hadamard theorem: ${hadamard.theorem_name}`)
|
|
41
|
-
console.log(` ✓ PauliX certificate: ${pauliX.hash}`)
|
|
42
37
|
}
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
console.log('Test: Algorithm proof certificates...')
|
|
46
|
-
|
|
47
|
-
const grover = generateAlgorithmCertificate('Grover')
|
|
48
|
-
const shor = generateAlgorithmCertificate('Shor')
|
|
49
|
-
const qft = generateAlgorithmCertificate('QFT')
|
|
50
|
-
|
|
51
|
-
if (!verifyProofCertificate(grover)) {
|
|
52
|
-
throw new Error('Grover certificate invalid')
|
|
53
|
-
}
|
|
54
|
-
if (!verifyProofCertificate(shor)) {
|
|
55
|
-
throw new Error('Shor certificate invalid')
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (grover.speedup_factor < 2) {
|
|
59
|
-
throw new Error(`Grover speedup too low: ${grover.speedup_factor}`)
|
|
60
|
-
}
|
|
61
|
-
if (shor.speedup_factor < 1000) {
|
|
62
|
-
throw new Error(`Shor speedup too low: ${shor.speedup_factor}`)
|
|
63
|
-
}
|
|
39
|
+
console.log('Lean bridge: computational seals\n')
|
|
64
40
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
41
|
+
// ------------------------------------------------------------ seal outcomes
|
|
42
|
+
console.log('Seals (each decides a concrete instance)')
|
|
43
|
+
const held: string[] = []
|
|
44
|
+
const notHeld: string[] = []
|
|
45
|
+
for (const name of Object.keys(SEALS)) {
|
|
46
|
+
const r = runSeal(name)
|
|
47
|
+
;(r.seal === 'held' ? held : notHeld).push(name)
|
|
48
|
+
console.log(' ' + (r.seal === 'held' ? 'held ' : 'FAILED') + ' ' + name)
|
|
69
49
|
}
|
|
70
50
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
51
|
+
check('at least one seal holds', held.length > 0)
|
|
52
|
+
check(
|
|
53
|
+
'seals that hold are the expected set',
|
|
54
|
+
held.length === Object.keys(SEALS).length - notHeld.length
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
// --------------------------------------------- the two formerly-broken seals
|
|
58
|
+
console.log('\nSeals that used to fail, and what they caught')
|
|
59
|
+
check(
|
|
60
|
+
'repetition_detects_error holds - syndrome extraction distinguishes clean from flipped',
|
|
61
|
+
runSeal('repetition_detects_error').seal === 'held',
|
|
62
|
+
'regressed: measureQubit is being handed a raw LCG state again'
|
|
63
|
+
)
|
|
64
|
+
check(
|
|
65
|
+
'steane_corrects_error holds - STEANE_CODE is a genuine stabiliser group',
|
|
66
|
+
runSeal('steane_corrects_error').seal === 'held',
|
|
67
|
+
'regressed: generator count, commutation or independence broke'
|
|
68
|
+
)
|
|
69
|
+
check('every seal holds', notHeld.length === 0, notHeld.join(', ') + ' failed')
|
|
70
|
+
|
|
71
|
+
// ------------------------------------------------------------ falsifiability
|
|
72
|
+
console.log('\nThe verifier can say no')
|
|
73
|
+
const fake = { ...generateGateCertificate('Hadamard'), seal: 'failed' as const }
|
|
74
|
+
check('a failed seal is not verified', verifyProofCertificate(fake) === false)
|
|
75
|
+
check('a held seal is verified', verifyProofCertificate(generateGateCertificate('Hadamard')) === true)
|
|
76
|
+
|
|
77
|
+
// --------------------------------------------------------------- lean status
|
|
78
|
+
console.log('\nLean status is read from the script, not declared')
|
|
79
|
+
check("a script containing sorry reads as 'sorry'", readLeanStatus('theorem t : X := by\n sorry') === 'sorry')
|
|
80
|
+
check("an axiom reads as 'axiom'", readLeanStatus('axiom a : P') === 'axiom')
|
|
81
|
+
check("an empty script reads as 'absent'", readLeanStatus(' ') === 'absent')
|
|
82
|
+
check("a complete script reads as 'script'", readLeanStatus('theorem t : X := by decide') === 'script')
|
|
83
|
+
const sorryCount = Object.values(LEAN_PROOFS).filter((s) => readLeanStatus(s) === 'sorry').length
|
|
84
|
+
check('the sorry scripts are reported, not hidden', sorryCount > 0, sorryCount + ' found')
|
|
85
|
+
console.log(' ' + sorryCount + ' of ' + Object.keys(LEAN_PROOFS).length + ' Lean scripts end in sorry')
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------- hashing
|
|
88
|
+
console.log('\nHash covers content, not the name')
|
|
89
|
+
const h1 = computeProofHash('IsUnitary hadamard', 'theorem a := by decide')
|
|
90
|
+
const h2 = computeProofHash('IsUnitary hadamard', 'theorem a := by sorry')
|
|
91
|
+
const h3 = computeProofHash('IsUnitary pauliX', 'theorem a := by decide')
|
|
92
|
+
check('changing the proof script changes the hash', h1 !== h2)
|
|
93
|
+
check('changing the statement changes the hash', h1 !== h3)
|
|
94
|
+
check('the same content hashes the same', h1 === computeProofHash('IsUnitary hadamard', 'theorem a := by decide'))
|
|
95
|
+
|
|
96
|
+
// --------------------------------------------------------------- reporting
|
|
97
|
+
console.log('\nReporting does not overstate')
|
|
98
|
+
const report = verifyQuantumSystem()
|
|
99
|
+
check('lean_machine_checked is false', report.lean_machine_checked === false)
|
|
100
|
+
check('every theorem in the report is sealed', report.sealed_fraction === 1, String(report.sealed_fraction))
|
|
101
|
+
check('nothing is left unsealed', report.unsealed.length === 0, report.unsealed.join(', '))
|
|
102
|
+
console.log(' sealed ' + report.total_theorems + '/' + report.total_theorems)
|
|
103
|
+
|
|
104
|
+
const zenodo = exportProofsForZenodo() as { ready_for_publication: boolean; caveats: string[] }
|
|
105
|
+
// Still false, and correctly so: seals are computed instances, not Lean proofs.
|
|
106
|
+
check('not marked ready for publication (no Lean toolchain runs here)', zenodo.ready_for_publication === false)
|
|
107
|
+
check('caveats are attached', zenodo.caveats.length >= 3)
|
|
108
|
+
|
|
109
|
+
const transcript = generateProofTranscript([
|
|
110
|
+
generateGateCertificate('Hadamard'),
|
|
111
|
+
generateAlgorithmCertificate('Shor'),
|
|
112
|
+
generateECCertificate('Steane[7,1,3]'),
|
|
113
|
+
])
|
|
114
|
+
check('transcript confidence counts held seals', transcript.confidence === 1, String(transcript.confidence))
|
|
115
|
+
check('transcript lists no unsealed theorem', transcript.unsealed.length === 0)
|
|
116
|
+
// The confidence number must still be able to move, or it is decoration.
|
|
117
|
+
const withFailure = generateProofTranscript([
|
|
118
|
+
generateGateCertificate('Hadamard'),
|
|
119
|
+
{ ...generateGateCertificate('PauliX'), seal: 'failed' as const },
|
|
120
|
+
])
|
|
121
|
+
check('a failed seal drags confidence down', withFailure.confidence === 1 / 2, String(withFailure.confidence))
|
|
122
|
+
|
|
123
|
+
console.log('')
|
|
124
|
+
if (failures > 0) {
|
|
125
|
+
console.error('lean-bridge: ' + failures + ' check(s) failed')
|
|
126
|
+
process.exit(1)
|
|
112
127
|
}
|
|
113
|
-
|
|
114
|
-
function testProofHash(): void {
|
|
115
|
-
console.log('Test: Proof hash computation...')
|
|
116
|
-
|
|
117
|
-
const hash1 = computeProofHash('hadamard_unitary')
|
|
118
|
-
const hash2 = computeProofHash('hadamard_unitary')
|
|
119
|
-
const hash3 = computeProofHash('pauliX_unitary')
|
|
120
|
-
|
|
121
|
-
if (hash1 !== hash2) {
|
|
122
|
-
throw new Error('Hash not deterministic')
|
|
123
|
-
}
|
|
124
|
-
if (hash1 === hash3) {
|
|
125
|
-
throw new Error('Different theorems have same hash')
|
|
126
|
-
}
|
|
127
|
-
if (hash1.length !== 16) {
|
|
128
|
-
throw new Error(`Hash wrong length: ${hash1.length}`)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
console.log(` ✓ Hash deterministic: ${hash1}`)
|
|
132
|
-
console.log(` ✓ Hash collision-free`)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function testQuantumSystemVerification(): void {
|
|
136
|
-
console.log('Test: Complete quantum system verification...')
|
|
137
|
-
|
|
138
|
-
const report = verifyQuantumSystem()
|
|
139
|
-
|
|
140
|
-
if (report.total_theorems === 0) {
|
|
141
|
-
throw new Error('No theorems verified')
|
|
142
|
-
}
|
|
143
|
-
if (report.overall_confidence < 0.8) {
|
|
144
|
-
throw new Error(`Confidence too low: ${report.overall_confidence}`)
|
|
145
|
-
}
|
|
146
|
-
if (report.gates_verified.length === 0) {
|
|
147
|
-
throw new Error('No gates verified')
|
|
148
|
-
}
|
|
149
|
-
if (report.algorithms_verified.length === 0) {
|
|
150
|
-
throw new Error('No algorithms verified')
|
|
151
|
-
}
|
|
152
|
-
if (report.error_correction_verified.length === 0) {
|
|
153
|
-
throw new Error('No error correction verified')
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
console.log(` ✓ ${report.total_theorems} theorems formalized`)
|
|
157
|
-
console.log(` ✓ ${report.total_lines_of_proof} proof lines`)
|
|
158
|
-
console.log(` ✓ Gates: ${report.gates_verified.join(', ')}`)
|
|
159
|
-
console.log(` ✓ Algorithms: ${report.algorithms_verified.join(', ')}`)
|
|
160
|
-
console.log(` ✓ Error correction: ${report.error_correction_verified.join(', ')}`)
|
|
161
|
-
console.log(` ✓ Overall confidence: ${(report.overall_confidence * 100).toFixed(1)}%`)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function testProofTranscript(): void {
|
|
165
|
-
console.log('Test: Proof transcript generation...')
|
|
166
|
-
|
|
167
|
-
const certs = [
|
|
168
|
-
generateGateCertificate('Hadamard'),
|
|
169
|
-
generateAlgorithmCertificate('Grover'),
|
|
170
|
-
]
|
|
171
|
-
|
|
172
|
-
const transcript = generateProofTranscript(certs)
|
|
173
|
-
|
|
174
|
-
if (!transcript.title) {
|
|
175
|
-
throw new Error('Transcript missing title')
|
|
176
|
-
}
|
|
177
|
-
if (transcript.theorems.length === 0) {
|
|
178
|
-
throw new Error('Transcript missing theorems')
|
|
179
|
-
}
|
|
180
|
-
if (transcript.verified_count === 0) {
|
|
181
|
-
throw new Error('Transcript has no verified theorems')
|
|
182
|
-
}
|
|
183
|
-
if (transcript.confidence < 0.5) {
|
|
184
|
-
throw new Error(`Transcript confidence too low: ${transcript.confidence}`)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
console.log(` ✓ Title: ${transcript.title}`)
|
|
188
|
-
console.log(` ✓ Theorems: ${transcript.theorems.join(', ')}`)
|
|
189
|
-
console.log(` ✓ Total proof lines: ${transcript.total_lines}`)
|
|
190
|
-
console.log(` ✓ Verified: ${transcript.verified_count}/${certs.length}`)
|
|
191
|
-
console.log(` ✓ Confidence: ${(transcript.confidence * 100).toFixed(1)}%`)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function testZenodoExport(): void {
|
|
195
|
-
console.log('Test: Zenodo publication export...')
|
|
196
|
-
|
|
197
|
-
const export_data = exportProofsForZenodo()
|
|
198
|
-
|
|
199
|
-
if (!export_data.system) {
|
|
200
|
-
throw new Error('Export missing system name')
|
|
201
|
-
}
|
|
202
|
-
if (!export_data.verification_framework) {
|
|
203
|
-
throw new Error('Export missing verification framework')
|
|
204
|
-
}
|
|
205
|
-
if (!export_data.formal_verification_report) {
|
|
206
|
-
throw new Error('Export missing verification report')
|
|
207
|
-
}
|
|
208
|
-
if (!export_data.ready_for_publication) {
|
|
209
|
-
throw new Error('Export not marked ready for publication')
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const report = export_data.formal_verification_report as any
|
|
213
|
-
if (report.overall_confidence < 0.8) {
|
|
214
|
-
throw new Error('System confidence below publication threshold')
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
console.log(` ✓ System: ${export_data.system}`)
|
|
218
|
-
console.log(` ✓ Framework: ${export_data.verification_framework}`)
|
|
219
|
-
console.log(` ✓ Confidence: ${(report.overall_confidence * 100).toFixed(1)}%`)
|
|
220
|
-
console.log(` ✓ Ready for Zenodo: ${export_data.ready_for_publication}`)
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// ============================================================================
|
|
224
|
-
// TEST RUNNER
|
|
225
|
-
// ============================================================================
|
|
226
|
-
|
|
227
|
-
async function runTests(): Promise<void> {
|
|
228
|
-
console.log('🧪 Lean Bridge Verification Tests\n')
|
|
229
|
-
|
|
230
|
-
try {
|
|
231
|
-
testGateCertificates()
|
|
232
|
-
testAlgorithmCertificates()
|
|
233
|
-
testECCertificates()
|
|
234
|
-
testProofChain()
|
|
235
|
-
testProofHash()
|
|
236
|
-
testQuantumSystemVerification()
|
|
237
|
-
testProofTranscript()
|
|
238
|
-
testZenodoExport()
|
|
239
|
-
|
|
240
|
-
console.log('\n✅ All Lean bridge verification tests passed!')
|
|
241
|
-
} catch (error) {
|
|
242
|
-
console.error(`\n❌ Test failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
243
|
-
process.exit(1)
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
runTests()
|
|
128
|
+
console.log('lean-bridge ok - all seals hold, Lean scripts still not machine-checked')
|