=== ACTIVE INDEX ASSET REFERENCES === 9: 242: === ACTIVE panel.js TREE LOGIC === 24: phases: [], 30: openPhases: new Set(), 33: phaseId: null, 35: bucket: null, 39: subcategory: null 48: fetch('data/panel_canonical_tree.json').then(r => r.json()), 55: G.phases = hub.phases || []; 65: document.getElementById('dp-tree').innerHTML = 66: '
Load error: ' + e.message + '
'; 70:function phaseOfCat(cat) { 72: if (!m) return 'phase-01'; 73: return 'phase-' + String(parseInt(m[0])).padStart(2, '0'); 76:function catsForPhase(phaseId) { 77: return G.cats.filter(c => phaseOfCat(c) === phaseId); 97: String(r.component || r.subcategory || r.label || '').toLowerCase().includes(String(cardId || '').toLowerCase()) 104:function countsForStage(phaseId) { 105: const rows = (G.data.runtime?.runtime_snapshot || []).filter(r => String(r.deployment_stage || '').toLowerCase() === String(phaseId || '').toLowerCase()); 120: html += '
Deployment Stages
'; 121: for (const ph of G.phases) { 122: const isOpen = G.openPhases.has(ph.id); 123: const phActive = G.sel.phaseId === ph.id ? ' ph-active' : ''; 143: const bkActive = G.sel.catId === cat.id && G.sel.bucket === bk ? ' bk-active' : ''; 154: html += '
Content Index
'; 164: document.getElementById('dp-tree').innerHTML = html; 172: const wasOpen = G.openPhases.has(id); 173: G.openPhases = wasOpen ? new Set() : new Set([id]); 177: G.sel.bucket = null; 179: G.sel.phaseId = id; 188: G.sel.phaseId = el.dataset.ph; 190: G.sel.bucket = null; 191: G.openPhases = new Set([el.dataset.ph]); 200: G.sel.phaseId = el.dataset.ph; 202: G.sel.bucket = el.dataset.bk; 203: G.openPhases = new Set([el.dataset.ph]); 215: G.sel.subcategory = null; 230: el.innerHTML = renderSectionWorkspace(nav, sec); 235: if (!G.sel.phaseId) { el.innerHTML = renderSummary(); return; } 236: const ph = G.phases.find(p => p.id === G.sel.phaseId); 239: if (!G.sel.bucket) { el.innerHTML = renderCatOverview(ph, cat); return; } 240: el.innerHTML = renderBucketDetail(ph, cat, G.sel.bucket); 252:
Select a phase in the tree to navigate. Canon leads. Runtime validates. UI renders.
298:function renderSectionWorkspace(nav, sec) { 305: ${st} 318:
Workspace section driven by panel_content_index + panel_canonical_tree.
330:
${cards || '
No cards registered for this section.
'}
334:function renderBucketDetail(ph, cat, bucket) { 335: const phIdx = G.phases.findIndex(p => p.id === ph.id); 336: const bkIdx = BUCKETS.indexOf(bucket); 338: const items = docs.map(doc => { 340: const cls = st === 'PASS' ? 'item-ok' : st === 'FAIL' ? 'item-fail' : ''; 342: return `
343: ${ico} 344:
345:
${doc.title}
346:
${doc.role || ''}
347:
${doc.path || ''}
349: ${st} 353: const phPct = Math.round((phIdx / G.phases.length) * 100); 357: ${ph.step} / ${cat.title} / ${bucket} 358:
${ph.step}${bucket}
361:
${ph.step}/${cat.title}
363:
${BUCKET_DESC[bucket]}
367:
Phase ${phIdx + 1} of ${G.phases.length}
374:
${bucket}
377:
378:
Authority Documents — ${cat.title}
379: ${items || '
No documents registered for this category.
'} 388: (r.label || r.subcategory || r.component || '').toLowerCase().includes(name) 415: const ph10 = G.phases.find(p => p.id === 'phase-10'); 417: G.openPhases.add('phase-10'); 418: G.sel.phaseId = 'phase-10'; 419: G.sel.catId = null; G.sel.bucket = null; 442:/* ── CAT CARD CLICK (phase overview) ─────────────── */ 447: G.sel.phaseId = cc.dataset.ph; 449: G.sel.bucket = null; 450: G.openPhases.add(cc.dataset.ph); 456: G.sel.phaseId = bc.dataset.ph; 458: G.sel.bucket = bc.dataset.bk; 459: G.openPhases.add(bc.dataset.ph); === ACTIVE panel.runtime.fix TREE LOGIC === 67: state.openPhases = new Set(); 72: function phaseOfCategory(cat) { 75: if (!m) return normStageKey("phase-01"); 76: return normStageKey("phase-" + String(parseInt(m[0], 10)).padStart(2, "0")); 79: function categoriesForPhase(phaseId) { 81: const key = normStageKey(phaseId); 87: return normStageKey(doc && doc.phase) === key; 90: const badgeHit = phaseOfCategory(cat) === key; 102: function phaseStatusClass(phaseId) { 103: const roll = stageRollup(phaseId); 110: const phases = (state.hubIndex && Array.isArray(state.hubIndex.phases)) ? state.hubIndex.phases : []; 111: if (!phases.length) { 112: els.stageNav.innerHTML = '
MISSING hub phases / hubIndex binding
'; 120: function renderBuckets(phaseId, catId) { 122: '
', 123: BUCKETS.map(function (bucket) { 125: '
', 126: '