let enabled = false; let steps: Record = {}; /** UI-only instrumentation; production calls are just the original calculation. */ export function measureNavigationStep(name: string, compute: () => T): T { if (!import.meta.env.DEV || !enabled) return compute(); const started = performance.now(); try { return compute(); } finally { steps[name] = (steps[name] ?? 0) + performance.now() - started; } } /** Opt-in, local development measurement. Never records report content. */ export function observeNavigationPerformance(): void { enabled = true; let startedAt = 0; let target = ''; let sequence = 0; let frames = 0; let previousFrame = 0; let longestFrame = 0; const output = document.createElement('output'); output.id = 'assessor-navigation-performance'; output.hidden = true; document.body.append(output); document.addEventListener('click', event => { const button = (event.target as Element).closest('.sidebar-primary-actions button'); if (!button || button.hasAttribute('disabled')) return; target = button.textContent?.trim() ?? ''; startedAt = performance.now(); steps = {}; sequence += 1; const current = sequence; previousFrame = startedAt; longestFrame = 0; frames = 0; const measure = (now: number) => { if (sequence !== current) return; longestFrame = Math.max(longestFrame, now - previousFrame); previousFrame = now; frames += 1; if (frames < 3) { requestAnimationFrame(measure); return; } output.textContent = JSON.stringify({ area: target, sequence: current, paintMs: Math.round(now - startedAt), longestFrameMs: Math.round(longestFrame), stepsMs: Object.fromEntries(Object.entries(steps).map(([name, duration]) => [name, Math.round(duration)])) }); }; requestAnimationFrame(measure); }, true); }