// Codex panel — click any chakra -> its codex (recipes/theses/formulas) opens in // the side panel. Click a kernel dot -> that kernel's docs + recent live activity. // Top-right "All Codices" -> unified search across all 5 chakras' codices. // Doctrine v11 LOCKED. ZERO BANDAID — links are real; live activity shows honest state. import { CHAKRAS, UNIVERSAL_KERNELS } from './config.js'; import { kernelEntry, lastHeartbeats } from './heartbeats.js'; let panel, body, closeBtn; export function initCodex(){ panel = document.getElementById('panel'); body = document.getElementById('panelBody'); closeBtn = document.getElementById('panelClose'); closeBtn.onclick = closePanel; document.getElementById('allCodices').onclick = openAllCodices; addEventListener('keydown', e => { if (e.key==='Escape') closePanel(); }); } function openPanel(){ panel.classList.add('open'); } function closePanel(){ panel.classList.remove('open'); } function chakraById(id){ return CHAKRAS.find(c => c.id===id); } // ---------- chakra codex ---------- export function openChakraCodex(id){ const c = chakraById(id); if (!c) return; const col = '#'+c.color.toString(16).padStart(6,'0'); const kernels = UNIVERSAL_KERNELS.map(k => `${k.name}`).join('') + c.vertical.map(k => `${k.name}`).join(''); body.innerHTML = `

${c.label}

${c.glyph} · 9 kernels (7 universal + 2 vertical)

Codex

${c.codex.map(x => `${x.label}`).join('')}

Kernels (wheel)

${kernels}

Live

polling ${c.label}…
`; openPanel(); pollChakraLive(c); } async function pollChakraLive(c){ const boxEl = document.getElementById('liveBox'); try { const r = await fetch(c.health.url, { cache:'no-store' }); if (!r.ok){ boxEl.textContent = `health → HTTP ${r.status}`; return; } let j; try { j = await r.json(); } catch(e){ boxEl.textContent='health → 200 (non-JSON)'; return; } const bits = []; if (j.status) bits.push(`status: ${j.status}`); if (j.version) bits.push(`version: ${j.version}`); if (j.doctrine) bits.push(`doctrine: ${j.doctrine}`); if (j.numbers) bits.push(`numbers: ${j.numbers.declarations}/${j.numbers.axioms}/${j.numbers.sorries}`); else if (j.declarations!==undefined) bits.push(`decl: ${j.declarations} · sorries: ${j.sorries}`); if (j.gates) bits.push(`gates: ${j.gates}`); if (j.traceparent_propagating) bits.push('traceparent: LIVE'); boxEl.innerHTML = bits.length ? bits.join('
') : '200 OK (no detail fields)'; } catch(e){ boxEl.textContent = 'flagship unreachable (honest offline state)'; } } // ---------- kernel panel ---------- const STATUS_LABEL = { green:'● live', amber:'● degraded', red:'● offline' }; const STATUS_HEX = { green:'#34d399', amber:'#fbbf24', red:'#f87171' }; export function openKernelPanel(c, kernel, vertical){ const col = '#'+c.color.toString(16).padStart(6,'0'); const sub = vertical ? 'vertical kernel' : `universal kernel · substrate: ${kernel.substrate}`; const e = kernelEntry(c.id, kernel.name); const st = e ? e.status : 'red'; const stHex = STATUS_HEX[st] || '#6b7280'; const ago = (e && e.agoSec != null) ? `${e.agoSec}s ago` : '—'; const ticks = (e && e.ticks != null) ? e.ticks.toLocaleString() : '—'; const endpoint = `${c.base}/api/${c.id}/v3/kernels/${kernel.name.toLowerCase()}`; body.innerHTML = `

${kernel.name}

${c.label} · ${sub}
${STATUS_LABEL[st]||'●'} last beat: ${ago} signed receipts: ${ticks}

What it does

${kernel.does}
${kernel.substrate ? `

Substrate

package: ${kernel.substrate}
` : ''}

Last 5 heartbeats

polling ${kernel.name}…

Kernel endpoint

GET /api/${c.id}/v3/kernels/${kernel.name.toLowerCase()}

Chakra codex

${c.codex.map(x => `${x.label}`).join('')}

Flagship health

polling ${c.label}…

Each kernel is a perpetual OODA loop (observe→decide→act→sign) rooted in a hash-linked, DSSE-signed codex. The Ouroboros loop threads SIGN→GATE→CHAIN→MEMORY→REPLAY through every chakra. Doctrine v11 LOCKED (749/14/163).

`; openPanel(); pollKernelHeartbeats(c, kernel); pollChakraLive(c); } async function pollKernelHeartbeats(c, kernel){ const box = document.getElementById('hbBox'); if (!box) return; const beats = await lastHeartbeats(c.id, kernel.name, 5); if (!document.getElementById('hbBox')) return; // panel changed while awaiting if (!beats.length){ box.textContent = 'no heartbeats yet (or flagship unreachable — honest offline state)'; return; } box.innerHTML = beats.map(b => { // codex entries may wrap the receipt under .payload / .data / be the receipt itself const rcpt = b.payload || b.data || b.receipt || b; const tick = rcpt.tick != null ? `#${rcpt.tick}` : ''; const ts = rcpt.ts || b.ts || b.created_at || ''; const sum = rcpt.summary || rcpt.did_work === false ? (rcpt.summary || 'no-op') : (rcpt.summary || 'tick'); const signed = (rcpt.signed_payload || rcpt.signatures || (rcpt.signed_payload && rcpt.signed_payload.signatures)) ? '🔏' : ''; return `
${tick} ${String(ts).replace('T',' ').replace('Z','')} ${signed}
${sum}
`; }).join(''); } // ---------- unified "All Codices" search ---------- function openAllCodices(){ const all = CHAKRAS.flatMap(c => c.codex.map(x => ({...x, chakra:c.label, color:c.color, id:c.id}))); body.innerHTML = `

All Codices

Unified search across all 5 chakras (${all.length} codex links · 45 kernels)
`; openPanel(); const input = document.getElementById('codexSearch'); const out = document.getElementById('codexResults'); const render = (q='') => { const ql = q.toLowerCase(); const rows = all.filter(x => (x.label+x.chakra).toLowerCase().includes(ql)); out.innerHTML = rows.map(x => { const col = '#'+x.color.toString(16).padStart(6,'0'); return ` ${x.chakra} · ${x.label}`; }).join('') || '
no match
'; }; render(); input.oninput = () => render(input.value); input.focus(); }