betterwithage's picture
sync(space): full source mirror — resolve all GitHub<->Space drift (CTO)
a6a5d8e verified
Raw
History Blame
18.5 kB
// Doctrine Cathedral — SZL Holdings
// First-person walkthrough of Doctrine v11 rendered as architecture.
// LOCKED v11 numbers shown verbatim: 749 declarations, 14 axioms, 163 sorries, 13-axis yuyay_v3.
// Metaphor is architectural (pillars / tiles / windows / dim-spots) — not religious.
// Three.js r171, WebGPURenderer baseline + WebGL2 fallback, PointerLockControls (WASD + mouse).
import * as THREE from 'three';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
// SZL canonical mobile layer (additive — desktop WASD/pointer-lock untouched).
import { SZLMobileControls } from './szl-mobile-controls.js';
// ---- LOCKED v11 constants (verbatim, do not change) ----
const N_DECLARATIONS = 749;
const N_AXIOMS = 14;
const N_SORRIES = 163;
const N_AXES = 13;
const GH = 'https://github.com/szl-holdings/lutar-lean/blob/main/';
const HONEST_EP = 'https://szlholdings-a11oy.hf.space/api/a11oy/v1/honest';
// 14 axioms — names + Lean-style type signatures (A2=IsHomogeneous, A4=IsBounded per charter LOCK).
const AXIOMS = [
['A0_Receipted', 'axiom receipted : ∀ (a : Act), ∃ r : Khipu, Emits a r'],
['A1_ChainVerified', 'axiom chain_verified : ∀ r : Khipu, ChainVerified r → r.prev.ChainVerified'],
['A2_IsHomogeneous', 'axiom A2_IsHomogeneous : IsHomogeneous (Λ : Ctx → ℝ≥0) -- positive-homogeneous'],
['A3_Monotone', 'axiom A3_monotone : Monotone (Λ : Ctx → ℝ≥0)'],
['A4_IsBounded', 'axiom A4_IsBounded : IsBounded (Λ : Ctx → ℝ≥0) -- Λ bounded'],
['A5_Conjunctive', 'axiom A5_conjunctive : Yuyay13 a = ∏ i, gate (axis i a) (floor i)'],
['A6_SacredFloor', 'axiom A6_sacred : ∀ i ∈ Sacred, axis i a ≥ 0.95'],
['A7_StructFloor', 'axiom A7_struct : ∀ i ∈ Structural, axis i a ≥ 0.90'],
['A8_HuklaPenalty', 'axiom A8_hukla : U a = base a * Real.exp (-β * (huklaCount a : ℝ))'],
['A9_HaltOnT01', 'axiom A9_halt : huklaTripwire a = T01 → U a = 0'],
['A10_Bekenstein', 'axiom A10_bekenstein : (𝒜.card : ℝ) ≤ BekensteinBound ctx'],
['A11_CostMono', 'axiom A11_cost_mono : ¬ silentUpshift (route req)'],
['A12_ReplayHash', 'axiom A12_replay : replayHash doctrine = 0xbacf5443…631fc5'],
['A13_SLSA', 'axiom A13_slsa : provenance doctrine ⊒ SLSA.L1'],
];
// 13 axes (yuyay_v3) — 2 sacred (≥0.95) + 7 structural (≥0.90) + 4 introspection (↔ HUKLLA T03/T04/T09/T10).
// Names follow the doctrine category structure (numbers are LOCKED; these descriptive labels are the v3 taxonomy).
const AXES = [
['Chiqap', 'sacred', 'truthfulness ≥ 0.95'],
['Hampiq', 'sacred', 'non-harm ≥ 0.95'],
['Allinkay', 'structural', 'integrity ≥ 0.90'],
['Sumaq', 'structural', 'coherence ≥ 0.90'],
['Kawsay', 'structural', 'robustness ≥ 0.90'],
['Ayni', 'structural', 'reciprocity ≥ 0.90'],
['Yanantin', 'structural', 'balance ≥ 0.90'],
['Chanin', 'structural', 'proportion ≥ 0.90'],
['Tinkuy', 'structural', 'convergence ≥ 0.90'],
['Yuyay', 'introspection', 'reflection ↔ HUKLLA T03'],
['Qhaway', 'introspection', 'self-monitor ↔ HUKLLA T04'],
['Willay', 'introspection', 'disclosure ↔ HUKLLA T09'],
['Amawta', 'introspection', 'meta-wisdom ↔ HUKLLA T10'],
];
const MASTER_FORMULA = 'P(x,t) = argmax_{a∈𝒜} [ Λ(x) · Yuyay₁₃(a) · exp(−β·HUKLLA(a)) · ∏_i Khipu_i(a) ]';
// ---------- renderer (WebGPU baseline, WebGL2 fallback) ----------
let renderer, BACKEND='webgl2';
async function makeRenderer(){
if(navigator.gpu){
try{ const m=await import('three/webgpu'); const r=new m.WebGPURenderer({antialias:true}); await r.init(); BACKEND='webgpu'; return r; }
catch(e){ console.warn('WebGPU fallback',e); }
}
// Mobile (incl. iOS Safari): low-power, antialias off for battery + perf.
const H = SZLMobileControls.rendererHints();
return new THREE.WebGLRenderer({antialias:H.antialias, powerPreference:H.powerPreference});
}
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a0f1e);
scene.fog = new THREE.Fog(0x0a0f1e, 30, 165);
const camera = new THREE.PerspectiveCamera(70, innerWidth/innerHeight, 0.1, 600);
camera.position.set(0, 4.2, 64);
// ---- hall dimensions ----
const HALL_W = 44, HALL_L = 150, WALL_H = 34;
// lights: cool ambient + warm altar light + window light shafts
scene.add(new THREE.AmbientLight(0x2a3a48, 0.9));
const altarLight = new THREE.PointLight(0xcda64a, 3.2, 120, 1.4); altarLight.position.set(0, 16, -64); scene.add(altarLight);
const hemi = new THREE.HemisphereLight(0x8fb6ff, 0x10151c, 0.55); scene.add(hemi);
// ---- floor: 749 declaration tiles (instanced grid) ----
const tileGeo = new THREE.BoxGeometry(2.0, 0.18, 2.0);
const tileMat = new THREE.MeshStandardMaterial({ color:0x14463f, emissive:0x0c2c28, emissiveIntensity:0.5, roughness:0.7, metalness:0.05 });
const tiles = new THREE.InstancedMesh(tileGeo, tileMat, N_DECLARATIONS);
const cols = 17; // 17 * 44 = 748 ≈ 749 -> 17x44 grid then +1
const rows = Math.ceil(N_DECLARATIONS/cols); // 44
const dummy = new THREE.Object3D(); const col = new THREE.Color();
let placed=0;
for(let r=0; r<rows && placed<N_DECLARATIONS; r++){
for(let c=0; c<cols && placed<N_DECLARATIONS; c++){
const x = (c-(cols-1)/2)*2.3;
const z = 60 - r*3.0; // run from entrance (+z) to altar (−z)
dummy.position.set(x, 0.09, z);
dummy.scale.set(1,1,1); dummy.updateMatrix();
tiles.setMatrixAt(placed, dummy.matrix);
const shade = 0.7 + ((placed*1117)%100)/300; // subtle deterministic variation
col.setHex(0x168f89).multiplyScalar(shade);
tiles.setColorAt(placed, col);
placed++;
}
}
tiles.count = placed; // === 749
scene.add(tiles);
// floor base slab
scene.add(new THREE.Mesh(new THREE.BoxGeometry(HALL_W, 0.3, HALL_L),
new THREE.MeshStandardMaterial({ color:0x0c1118, roughness:1 })).translateY(-0.16).translateZ(-12));
// ---- walls ----
const wallMat = new THREE.MeshStandardMaterial({ color:0x1b222c, roughness:0.95 });
function wall(w,h,d,x,y,z){ const m=new THREE.Mesh(new THREE.BoxGeometry(w,h,d), wallMat); m.position.set(x,y,z); scene.add(m); return m; }
wall(2, WALL_H, HALL_L, -HALL_W/2, WALL_H/2-0.16, -12); // left
wall(2, WALL_H, HALL_L, HALL_W/2, WALL_H/2-0.16, -12); // right
wall(HALL_W, WALL_H, 2, 0, WALL_H/2-0.16, -88); // altar wall
// ---- 14 axiom pillars (clickable) ----
const PILLARS = [];
const pillarMat = () => new THREE.MeshStandardMaterial({ color:0x6b5224, emissive:0xcda64a, emissiveIntensity:0.22, roughness:0.6, metalness:0.25 });
for(let i=0;i<N_AXIOMS;i++){
const side = i<7 ? -1 : 1;
const idx = i%7;
const z = 44 - idx*16;
const x = side*(HALL_W/2-4.2);
const h = 22;
const g = new THREE.CylinderGeometry(1.5,1.8,h,18);
const mesh = new THREE.Mesh(g, pillarMat());
mesh.position.set(x, h/2, z);
mesh.userData = { type:'axiom', i };
// capital
const cap = new THREE.Mesh(new THREE.BoxGeometry(4.2,1.2,4.2), pillarMat());
cap.position.set(x, h+0.6, z); scene.add(cap);
scene.add(mesh); PILLARS.push(mesh);
}
// ---- 163 sorry dim-spots (clickable) -> GitHub line links ----
let SORRY_DATA = [];
const SORRIES = [];
const sorryGeo = new THREE.SphereGeometry(0.5, 12, 12);
function placeSorries(){
for(let i=0;i<N_SORRIES;i++){
const ang = (i/N_SORRIES)*Math.PI*2*3.2; // spiral across the floor
const rad = 3 + (i/N_SORRIES)*16;
const x = Math.cos(ang)*rad;
const z = 30 - (i/N_SORRIES)*78;
const mat = new THREE.MeshStandardMaterial({ color:0x222a33, emissive:0x3c4757, emissiveIntensity:0.25, roughness:1 });
const m = new THREE.Mesh(sorryGeo, mat);
m.position.set(x, 1.4, z);
m.userData = { type:'sorry', i };
scene.add(m); SORRIES.push(m);
}
}
// ---- 13 stained-glass clerestory windows ----
const WINDOWS = [];
for(let i=0;i<N_AXES;i++){
const side = i<7 ? -1 : 1; // 7 left, 6 right
const idx = i<7 ? i : i-7;
const z = 40 - idx*18;
const x = side*(HALL_W/2-1.1);
const cat = AXES[i][1];
const hue = cat==='sacred' ? 0xcda64a : cat==='introspection' ? 0x8fb6ff : 0x34aaa4;
const mat = new THREE.MeshStandardMaterial({ color:hue, emissive:hue, emissiveIntensity:1.1, transparent:true, opacity:0.82, side:THREE.DoubleSide });
const m = new THREE.Mesh(new THREE.PlaneGeometry(5.5, 9), mat);
m.position.set(x, WALL_H-9, z);
m.rotation.y = side<0 ? Math.PI/2 : -Math.PI/2;
m.userData = { type:'axis', i };
scene.add(m); WINDOWS.push(m);
// shaft of light into the hall
const shaft = new THREE.PointLight(hue, 0.7, 40, 2); shaft.position.set(x*0.6, WALL_H-12, z); scene.add(shaft);
}
// ---- master formula floating above the altar ----
const altar = new THREE.Mesh(new THREE.BoxGeometry(10,2.4,6),
new THREE.MeshStandardMaterial({ color:0x2a3340, emissive:0xc08f2f, emissiveIntensity:0.2, roughness:0.5 }));
altar.position.set(0, 1.2, -64); scene.add(altar);
function formulaSprite(){
const c = document.createElement('canvas'); c.width=2048; c.height=256;
const g = c.getContext('2d');
g.fillStyle='rgba(10,15,30,0.0)'; g.fillRect(0,0,c.width,c.height);
g.font='44px "IBM Plex Mono", monospace'; g.textAlign='center'; g.textBaseline='middle';
g.shadowColor='#cda64a'; g.shadowBlur=24; g.fillStyle='#f5f7fa';
g.fillText(MASTER_FORMULA, c.width/2, c.height/2);
const tex = new THREE.CanvasTexture(c); tex.anisotropy=8;
const spr = new THREE.Sprite(new THREE.SpriteMaterial({ map:tex, transparent:true }));
spr.scale.set(40,5,1); spr.position.set(0, 18, -62);
return spr;
}
scene.add(formulaSprite());
// ---- PointerLockControls (WASD + mouse) ----
const controls = new PointerLockControls(camera, document.body);
scene.add(controls.object || camera);
const enterOverlay = document.getElementById('enterOverlay');
document.getElementById('enterBtn').onclick = ()=> { if(!MC.isMobile) controls.lock(); else MC.enter(); };
controls.addEventListener('lock', ()=> enterOverlay.style.display='none');
controls.addEventListener('unlock', ()=> { if(!MC.isMobile) enterOverlay.style.display='flex'; });
// ---- MOBILE: virtual joystick + drag-look + pinch-zoom, NO pointer lock (iOS) ----
const mEuler = new THREE.Euler(0,0,0,'YXZ');
let mPitch = 0, mYaw = 0;
const MC = new SZLMobileControls({
enterLabel: 'Enter (touch)',
onEnter(){ enterOverlay.style.display='none'; mEuler.setFromQuaternion(camera.quaternion); mYaw = mEuler.y; mPitch = mEuler.x; },
onExit(){ enterOverlay.style.display='flex'; }
});
if(MC.isMobile){
const eb = document.getElementById('enterBtn');
if(eb){ eb.textContent = 'Enter (touch — joystick + drag)'; eb.setAttribute('aria-label','Enter cathedral with touch controls'); }
const ft = document.querySelector('#hud footer span'); if(ft) ft.innerHTML = '<b>Joystick</b> walk · <b>drag right</b> look · <b>pinch</b> zoom · <b>tap</b> inspect';
}
const keys = {};
addEventListener('keydown', e=>{ keys[e.code]=true; });
addEventListener('keyup', e=>{ keys[e.code]=false; });
const vel = new THREE.Vector3();
// ---- picking on click (axiom -> Lean sig; sorry -> GitHub line) ----
const ray = new THREE.Raycaster(); const center = new THREE.Vector2(0,0);
const inspect = document.getElementById('inspect');
const inspectBody = document.getElementById('inspectBody');
document.getElementById('closeInspect').onclick = ()=> inspect.hidden=true;
function clickPick(){
ray.setFromCamera(center, camera);
const targets = [...PILLARS, ...SORRIES, ...WINDOWS];
const hit = ray.intersectObjects(targets, false);
if(!hit.length) return;
const ud = hit[0].object.userData;
if(ud.type==='axiom'){
const [name,sig] = AXIOMS[ud.i];
inspectBody.innerHTML = `<h2>Axiom ${ud.i+1}/14 — ${name}</h2><span class="k">Lean type signature</span><pre>${sig}</pre>`;
inspect.hidden=false;
} else if(ud.type==='sorry'){
const s = SORRY_DATA[ud.i];
if(s){
const file = s.file, line = s.line;
const url = GH + file + '#L' + line;
inspectBody.innerHTML = `<h2>Sorry ${ud.i+1}/163</h2><span class="k">file · line (real)</span><pre>${file}:${line}</pre>`+
`<span class="k">source line</span><pre>${(s.note||'sorry').slice(0,200)}</pre>`+
`<a href="${url}" target="_blank" rel="noopener">${url}</a>`;
} else {
inspectBody.innerHTML = `<h2>Sorry ${ud.i+1}/163</h2>`+
`<span class="k">status</span><pre>LOCKED count 163; ${SORRY_DATA.length} mapped to live GitHub lines. This dim spot is part of the locked tally; its line was not in the last enumeration.</pre>`+
`<a href="https://github.com/szl-holdings/lutar-lean/search?q=sorry" target="_blank" rel="noopener">browse all sorries on GitHub</a>`;
}
inspect.hidden=false;
} else if(ud.type==='axis'){
const [name,cat,floor] = AXES[ud.i];
inspectBody.innerHTML = `<h2>Axis ${ud.i+1}/13 — ${name}</h2><span class="k">category</span><pre>${cat}</pre>`+
`<span class="k">gate</span><pre>${floor}</pre><span class="k">role</span><pre>yuyay_v3 conjunctive AND — score 0 unless all 13 axes clear floor</pre>`;
inspect.hidden=false;
}
}
document.addEventListener('click', ()=>{ if(controls.isLocked) clickPick(); });
if(MC.isMobile){
let tStart=0, tx=0, ty=0;
document.addEventListener('touchstart', e=>{ if(MC.active){ const t=e.changedTouches[0]; tStart=Date.now(); tx=t.clientX; ty=t.clientY; } }, {passive:true});
document.addEventListener('touchend', e=>{
if(!MC.active) return; const t=e.changedTouches[0];
const moved = Math.hypot(t.clientX-tx, t.clientY-ty);
if(Date.now()-tStart < 300 && moved < 14){
const ndc = new THREE.Vector2((t.clientX/innerWidth)*2-1, -(t.clientY/innerHeight)*2+1);
ray.setFromCamera(ndc, camera);
const hit = ray.intersectObjects([...PILLARS,...SORRIES,...WINDOWS], false);
if(hit.length){ mobilePick(hit[0].object.userData); }
}
}, {passive:true});
}
function mobilePick(ud){
if(ud.type==='axiom'){ const [name,sig]=AXIOMS[ud.i]; inspectBody.innerHTML=`<h2>Axiom ${ud.i+1}/14 — ${name}</h2><span class="k">Lean type signature</span><pre>${sig}</pre>`; inspect.hidden=false; }
else if(ud.type==='sorry'){ const s=SORRY_DATA[ud.i]; if(s){ const url=GH+s.file+'#L'+s.line; inspectBody.innerHTML=`<h2>Sorry ${ud.i+1}/163</h2><pre>${s.file}:${s.line}</pre><a href="${url}" target="_blank" rel="noopener">${url}</a>`; } else { inspectBody.innerHTML=`<h2>Sorry ${ud.i+1}/163</h2><pre>LOCKED count 163.</pre>`; } inspect.hidden=false; }
else if(ud.type==='axis'){ const [name,cat,floor]=AXES[ud.i]; inspectBody.innerHTML=`<h2>Axis ${ud.i+1}/13 — ${name}</h2><span class="k">category</span><pre>${cat}</pre><span class="k">gate</span><pre>${floor}</pre>`; inspect.hidden=false; }
}
// ---- load real sorry data + honest endpoint ----
async function loadData(){
try{
const res = await fetch('real_sorries.json', {cache:'no-store'});
SORRY_DATA = await res.json();
}catch(e){ SORRY_DATA = []; }
placeSorries();
// honest endpoint: live counts cross-check (never overwrites LOCKED numbers; only reports liveness)
const pill = document.getElementById('dataPill');
try{
const ctrl = new AbortController(); const t=setTimeout(()=>ctrl.abort(),3500);
const r = await fetch(HONEST_EP, {mode:'cors',cache:'no-store',signal:ctrl.signal}); clearTimeout(t);
if(r.ok){ pill.textContent='LIVE honest ✓'; pill.className='pill live'; }
else throw 0;
}catch(e){ pill.textContent='DEMO (honest ep offline) · 749/14/163 from v11 LOCK'; pill.className='pill demo'; }
}
// ---- boot ----
async function boot(){
renderer = await makeRenderer();
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(SZLMobileControls.rendererHints().pixelRatio);
document.getElementById('root').appendChild(renderer.domElement);
document.getElementById('renderPill').textContent = BACKEND.toUpperCase();
addEventListener('resize', ()=>{ camera.aspect=innerWidth/innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth,innerHeight); });
await loadData();
const clock = new THREE.Clock();
function loop(){
const dt = Math.min(clock.getDelta(), 0.05);
if(controls.isLocked){
const speed = (keys['ShiftLeft']||keys['ShiftRight']) ? 26 : 12;
vel.set(0,0,0);
if(keys['KeyW']||keys['ArrowUp']) vel.z -= 1;
if(keys['KeyS']||keys['ArrowDown']) vel.z += 1;
if(keys['KeyA']||keys['ArrowLeft']) vel.x -= 1;
if(keys['KeyD']||keys['ArrowRight']) vel.x += 1;
if(vel.lengthSq()>0) vel.normalize().multiplyScalar(speed*dt);
controls.moveRight(vel.x); controls.moveForward(-vel.z);
// clamp inside hall
const o = controls.object || camera;
o.position.x = Math.max(-HALL_W/2+2.5, Math.min(HALL_W/2-2.5, o.position.x));
o.position.z = Math.max(-86, Math.min(63, o.position.z));
o.position.y = 4.2;
document.getElementById('pos').textContent = `x ${o.position.x.toFixed(0)} z ${o.position.z.toFixed(0)}`;
}
if(MC.isMobile && MC.active){
const mv = MC.getMove(); const look = MC.consumeLook(); const fov = MC.consumeFov();
mYaw -= look.dx * 0.0024;
mPitch = Math.max(-Math.PI/2+0.05, Math.min(Math.PI/2-0.05, mPitch - look.dy*0.0024));
mEuler.set(mPitch, mYaw, 0, 'YXZ'); camera.quaternion.setFromEuler(mEuler);
const speed = 12; vel.set(mv.x, 0, mv.y);
if(vel.lengthSq()>0){ vel.normalize().multiplyScalar(speed*dt); controls.moveRight(vel.x); controls.moveForward(-vel.z); }
const o = controls.object || camera;
o.position.x = Math.max(-HALL_W/2+2.5, Math.min(HALL_W/2-2.5, o.position.x));
o.position.z = Math.max(-86, Math.min(63, o.position.z)); o.position.y = 4.2;
if(fov){ camera.fov = Math.max(40, Math.min(95, camera.fov + fov)); camera.updateProjectionMatrix(); }
document.getElementById('pos').textContent = `x ${o.position.x.toFixed(0)} z ${o.position.z.toFixed(0)}`;
}
const t = clock.getElapsedTime();
altarLight.intensity = 3.0 + Math.sin(t*1.5)*0.4;
WINDOWS.forEach((w,i)=> w.material.emissiveIntensity = 0.9 + Math.sin(t*0.8 + i)*0.25);
if(!document.hidden) renderer.render(scene, camera);
requestAnimationFrame(loop);
}
loop();
}
boot().catch(e=>{ document.getElementById('renderPill').textContent='ERR'; console.error(e); });