-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootDeterminismProbe.html
More file actions
72 lines (70 loc) · 3.89 KB
/
Copy pathbootDeterminismProbe.html
File metadata and controls
72 lines (70 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!DOCTYPE html>
<html lang="ko">
<head><meta charset="utf-8"><title>probe: bootDeterminism</title>
<style>body{font:14px/1.5 system-ui;margin:2rem;max-width:52rem} pre{background:#f4f4f5;padding:1rem;border-radius:6px;white-space:pre-wrap}</style></head>
<body>
<h1>probe: 부팅 결정성 측정기 (리플레이+델타 경로의 관문)</h1>
<p>같은 조건으로 두 번 부팅한 커널의 전체 페이지 해시를 비교한다. 상이 페이지 0이면
"결정적 리플레이 + 사용자 델타"로 warm-fork·불멸 커널이 열린다(전문 리서치 결론).</p>
<pre id="out">실행 중...</pre>
<script type="module">
import { boot } from "../../../index.js";
const out = document.getElementById("out");
const checks = []; const timings = {};
const check = (name, pass, info = "") => { checks.push({ name, pass: !!pass, info: String(info) }); out.textContent += `\n${pass ? "PASS" : "FAIL"} ${name}${info ? " (" + info + ")" : ""}`; };
const report = async () => {
const ok = checks.length > 0 && checks.every((c) => c.pass);
try { await fetch("/gateReport", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ok, checks, timings }) }); } catch (e) {}
};
const diffPages = (h1, h2) => {
const n = Math.min(h1.length, h2.length) / 2;
let d = 0; const idx = [];
for (let p = 0; p < n; p++) if (h1[2 * p] !== h2[2 * p] || h1[2 * p + 1] !== h2[2 * p + 1]) { d++; if (idx.length < 10) idx.push(p); }
return { d, idx, lenEq: h1.length === h2.length };
};
// 부팅 구간의 엔트로피/시간을 고정 스텁으로 스왑(리서치: 비결정의 주범 = getentropy/시간)
const stubEntropy = () => {
const o = { grv: crypto.getRandomValues.bind(crypto), dn: Date.now, pn: performance.now.bind(performance) };
crypto.getRandomValues = (a) => { new Uint8Array(a.buffer, a.byteOffset, a.byteLength).fill(0x42); return a; };
Date.now = () => 1750000000000;
performance.now = () => 12345;
return () => { crypto.getRandomValues = o.grv; Date.now = o.dn; performance.now = o.pn; };
};
try {
// 조건 i: 무조치
let a = await boot(), b = await boot();
let r = diffPages(a.memory.pageHashes(), b.memory.pageHashes());
timings.plain = `${r.d}p (len ${r.lenEq ? "동일" : "다름"})`;
check("조건 i(무조치): 상이 페이지 보고", true, timings.plain);
// 조건 iii: PYTHONHASHSEED=0 + 엔트로피/시간 스텁
const un = stubEntropy();
let a3, b3;
try {
a3 = await boot({ env: { PYTHONHASHSEED: "0" } });
b3 = await boot({ env: { PYTHONHASHSEED: "0" } });
} finally { un(); }
r = diffPages(a3.memory.pageHashes(), b3.memory.pageHashes());
timings.fixed = `${r.d}p, idx ${JSON.stringify(r.idx)}`;
check("조건 iii(시드+엔트로피 고정): 상이 페이지", true, timings.fixed);
const bareDeterministic = r.d === 0 && r.lenEq;
check("판정: bare 부팅 결정성", true, bareDeterministic ? "성립" : "불성립(위 분포 참조)");
// 조건 iv: (iii) + numpy 로드/임포트까지 동일 리플레이
const un2 = stubEntropy();
let a4, b4;
try {
a4 = await boot({ env: { PYTHONHASHSEED: "0" } });
await a4.loadPackages(["numpy"]); a4.run("import numpy");
b4 = await boot({ env: { PYTHONHASHSEED: "0" } });
await b4.loadPackages(["numpy"]); b4.run("import numpy");
} finally { un2(); }
r = diffPages(a4.memory.pageHashes(), b4.memory.pageHashes());
timings.numpy = `${r.d}p, idx ${JSON.stringify(r.idx)}, len ${r.lenEq ? "동일" : "다름"}`;
check("조건 iv(+numpy 리플레이): 상이 페이지", true, timings.numpy);
check("판정: 리플레이+델타 경로", true, (r.d === 0 && r.lenEq) ? "성립 - warm-fork/불멸 커널 개방" : "불성립 - 상이 분포로 원인 좁히기");
} catch (e) {
check("예외 없음", false, String(e).slice(-300));
}
await report();
</script>
</body>
</html>