Add p(doom) calculator and test harness HTML files

D David Veksler · 7 months ago dc6acba0bf7c762de5bb445e3fad9809d6187823
Parent: 365e1bc89
Introduces p-doom-calculator.html, an interactive tool for estimating AGI existential risk based on user confidence in various counterarguments, and p-doom-test-harness.html for analyzing and testing the calculator's probability formula. Updates settings.local.json to allow launching these new HTML files via Bash commands.

3 files changed +769 −0

Diff

diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index c56bad2..055bd58 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -32,6 +32,8 @@
       "Bash(jq:*)",
       "Bash(open:*)",
       "WebSearch",
+      "Bash(start p-doom-calculator.html)",
+      "Bash(start p-doom-test-harness.html)",
       "Bash(textutil -convert html:*)"
     ],
     "deny": []
diff --git a/p-doom-calculator.html b/p-doom-calculator.html
new file mode 100644
index 0000000..8921097
--- /dev/null
+++ b/p-doom-calculator.html
@@ -0,0 +1,526 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+    <!-- Essential SEO Tags -->
+    <title>p(doom) Calculator: AI Existential Risk Assessment Tool</title>
+    <meta name="description" content="Interactive calculator to estimate probability of AGI-caused existential catastrophe. Explore AI safety arguments and assess your p(doom) based on Liron Shapira's counterarguments to AI doom scenarios."/>
+    <meta name="keywords" content="p(doom), AI safety, AGI risk, existential risk, artificial intelligence, AI alignment, superintelligence, AI doom, risk calculator"/>
+    <link rel="canonical" href="https://cheatsheets.davidveksler.com/p-doom-calculator.html"/>
+
+    <!-- Open Graph Tags -->
+    <meta property="og:title" content="p(doom) Calculator: AI Existential Risk Assessment"/>
+    <meta property="og:description" content="Interactive tool to calculate your personal p(doom) based on confidence in various AI safety arguments and counterarguments to existential risk scenarios."/>
+    <meta property="og:type" content="website"/>
+    <meta property="og:url" content="https://cheatsheets.davidveksler.com/p-doom-calculator.html"/>
+    <meta property="og:image" content="images/p-doom-calculator.png"/>
+    <meta property="og:image:alt" content="p(doom) Calculator interface showing risk sliders and probability assessment"/>
+
+    <!-- Twitter Card Tags -->
+    <meta name="twitter:card" content="summary_large_image"/>
+    <meta name="twitter:title" content="p(doom) Calculator: AI Existential Risk Assessment"/>
+    <meta name="twitter:description" content="Interactive tool to calculate your personal p(doom) based on confidence in various AI safety arguments."/>
+    <meta name="twitter:image" content="images/p-doom-calculator.png"/>
+    <meta name="twitter:creator" content="@heroiclife"/>
+
+    <!-- JSON-LD Structured Data -->
+    <script type="application/ld+json">
+    {
+      "@context": "https://schema.org",
+      "@type": "TechArticle",
+      "headline": "p(doom) Calculator: Interactive AI Existential Risk Assessment Tool",
+      "description": "An interactive calculator that helps users estimate the probability of AGI-caused existential catastrophe by adjusting confidence levels in various AI safety arguments and counterarguments.",
+      "author": {"@type": "Person", "name": "David Veksler (AI Generated)"},
+      "publisher": {"@type": "Organization", "name": "David Veksler Cheatsheets"},
+      "datePublished": "2025-10-03",
+      "dateModified": "2025-10-03",
+      "keywords": "p(doom), AI safety, AGI risk, existential risk, artificial intelligence, AI alignment, superintelligence, risk assessment, interactive calculator"
+    }
+    </script>
+
+    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
+
+    <style>
+        :root {
+            --doom-low: #28a745;
+            --doom-med: #ffc107;
+            --doom-high: #fd7e14;
+            --doom-critical: #dc3545;
+        }
+
+        body {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            min-height: 100vh;
+            padding: 2rem 0;
+        }
+
+        .container {
+            max-width: 900px;
+        }
+
+        .main-card {
+            background: white;
+            border-radius: 15px;
+            box-shadow: 0 10px 40px rgba(0,0,0,0.2);
+            padding: 2rem;
+        }
+
+        .doom-display {
+            text-align: center;
+            padding: 2rem;
+            margin: 2rem 0;
+            border-radius: 10px;
+            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+            transition: all 0.3s ease;
+        }
+
+        .doom-value {
+            font-size: 4rem;
+            font-weight: bold;
+            margin: 0;
+            transition: color 0.3s ease;
+        }
+
+        .doom-label {
+            font-size: 1.2rem;
+            color: #666;
+            margin-top: 0.5rem;
+        }
+
+        .category-card {
+            margin-bottom: 1rem;
+            border: none;
+            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+        }
+
+        .category-header {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: white;
+            cursor: pointer;
+            padding: 1rem;
+            border-radius: 8px;
+            transition: all 0.3s ease;
+        }
+
+        .category-header:hover {
+            transform: translateY(-2px);
+            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
+        }
+
+        .category-body {
+            padding: 1.5rem;
+            background: #f8f9fa;
+        }
+
+        .risk-item {
+            margin-bottom: 1.5rem;
+            padding: 1rem;
+            background: white;
+            border-radius: 8px;
+        }
+
+        .risk-label {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin-bottom: 0.5rem;
+        }
+
+        .risk-name {
+            font-weight: 500;
+            flex: 1;
+        }
+
+        .info-icon {
+            cursor: pointer;
+            color: #667eea;
+            font-size: 1.2rem;
+            margin-left: 0.5rem;
+        }
+
+        .slider-container {
+            margin: 0.5rem 0;
+        }
+
+        .risk-slider {
+            width: 100%;
+            height: 8px;
+            border-radius: 5px;
+            outline: none;
+            -webkit-appearance: none;
+        }
+
+        .risk-slider::-webkit-slider-thumb {
+            -webkit-appearance: none;
+            appearance: none;
+            width: 20px;
+            height: 20px;
+            border-radius: 50%;
+            background: #667eea;
+            cursor: pointer;
+        }
+
+        .risk-slider::-moz-range-thumb {
+            width: 20px;
+            height: 20px;
+            border-radius: 50%;
+            background: #667eea;
+            cursor: pointer;
+            border: none;
+        }
+
+        .slider-labels {
+            display: flex;
+            justify-content: space-between;
+            font-size: 0.85rem;
+            color: #666;
+            margin-top: 0.25rem;
+        }
+
+        .tooltip-text {
+            font-size: 0.9rem;
+            color: #555;
+            margin-top: 0.5rem;
+            padding: 0.75rem;
+            background: #e9ecef;
+            border-radius: 5px;
+            display: none;
+        }
+
+        .tooltip-text.show {
+            display: block;
+        }
+
+        .intro-text {
+            font-size: 1.1rem;
+            line-height: 1.6;
+            color: #444;
+            margin-bottom: 1.5rem;
+        }
+
+        .btn-reset {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            border: none;
+            color: white;
+            padding: 0.75rem 2rem;
+            font-weight: 500;
+            border-radius: 8px;
+            transition: all 0.3s ease;
+        }
+
+        .btn-reset:hover {
+            transform: translateY(-2px);
+            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
+            color: white;
+        }
+
+        @media print {
+            body {
+                background: white;
+            }
+            .category-body {
+                display: block !important;
+            }
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="main-card">
+            <h1 class="text-center mb-4">
+                <i class="bi bi-calculator"></i> p(doom) Calculator
+            </h1>
+
+            <div class="intro-text">
+                <p>
+                    This interactive calculator helps you estimate your personal probability of an AGI-caused existential catastrophe,
+                    known as "p(doom)". Adjust your confidence in various counterarguments to AI doom scenarios based on
+                    <a href="https://www.lesswrong.com/posts/FkAJL8naH9gXsKpwi/poking-holes-in-the-ai-doom-argument" target="_blank" rel="noopener noreferrer">Liron Shapira's analysis</a>.
+                </p>
+                <p class="mb-0">
+                    <strong>How it works:</strong> Start with a 99% base probability of doom. Each category represents potential "off-ramps"
+                    from catastrophe. Higher confidence in arguments reduces your final p(doom).
+                </p>
+            </div>
+
+            <div class="doom-display" id="doomDisplay">
+                <div class="doom-value" id="doomValue">50%</div>
+                <div class="doom-label">Probability of AI-Caused Existential Catastrophe</div>
+            </div>
+
+            <div class="text-center mb-4">
+                <button class="btn btn-reset" onclick="resetAllSliders()">
+                    <i class="bi bi-arrow-counterclockwise"></i> Reset to Defaults
+                </button>
+            </div>
+
+            <div id="categoriesContainer"></div>
+
+            <footer class="mt-5 pt-4 border-top">
+                <p class="text-muted text-center">
+                    <strong>Disclaimer:</strong> This tool is for educational purposes only and does not constitute scientific prediction.
+                    Based on arguments from <a href="https://www.lesswrong.com/posts/FkAJL8naH9gXsKpwi/poking-holes-in-the-ai-doom-argument" target="_blank" rel="noopener noreferrer">Liron Shapira's "Poking Holes in the AI Doom Argument"</a>.
+                </p>
+            </footer>
+        </div>
+    </div>
+
+    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
+    <script>
+        const categories = [
+            {
+                name: "AGI Isn't Coming Soon",
+                weight: 0.12,
+                arguments: [
+                    { name: "AIs can't have consciousness", tooltip: "Current AI systems lack subjective experience and self-awareness, which may be necessary for truly general intelligence." },
+                    { name: "AIs can't have emotions", tooltip: "Emotions may be essential for general intelligence and decision-making, yet AI systems lack genuine emotional states." },
+                    { name: "AIs can't be creative", tooltip: "True creativity requires understanding and intentionality that current AI systems don't possess." },
+                    { name: "AIs aren't as smart as dogs", tooltip: "In terms of general real-world problem-solving and adaptability, current AIs lag behind even simple animals." },
+                    { name: "AIs make dumb mistakes", tooltip: "AI systems fail in obvious ways that reveal their lack of genuine understanding." },
+                    { name: "LLM performance is hitting a wall", tooltip: "Language model improvements are plateauing, suggesting fundamental limitations to the approach." },
+                    { name: "AIs lack genuine reasoning", tooltip: "Current systems use pattern matching rather than logical reasoning and causal understanding." },
+                    { name: "AIs lack microtubules", tooltip: "Quantum processes in biological microtubules may be necessary for consciousness and intelligence." },
+                    { name: "AIs have no soul", tooltip: "There may be non-physical aspects to intelligence and consciousness that AI cannot replicate." },
+                    { name: "Data center/power bottleneck", tooltip: "Physical infrastructure limitations will constrain AI development and deployment." },
+                    { name: "AIs have no agency", tooltip: "Current systems lack true goal-directed behavior and autonomous decision-making." },
+                    { name: "It's just another hype cycle", tooltip: "AI has experienced multiple boom-and-bust cycles; this may be another temporary peak." }
+                ]
+            },
+            {
+                name: "AI Can't Go Far Beyond Human Intelligence",
+                weight: 0.06,
+                arguments: [
+                    { name: "'Superhuman intelligence' is meaningless", tooltip: "Intelligence is domain-specific; the concept of general superintelligence may be incoherent." },
+                    { name: "Human engineering is near physical limits", tooltip: "The human brain may already be close to optimal given physical constraints." },
+                    { name: "Large project coordination is slow", tooltip: "Intelligence doesn't eliminate the coordination costs of large-scale projects." },
+                    { name: "No individual AI will be smarter than all of human culture", tooltip: "Collective human knowledge and culture represent a coordination achievement AI can't replicate alone." }
+                ]
+            },
+            {
+                name: "AI Won't Be a Physical Threat",
+                weight: 0.18,
+                arguments: [
+                    { name: "AIs have no arms or legs", tooltip: "Without physical embodiment, AI cannot directly manipulate the physical world." },
+                    { name: "Robot bodies can't fight better than soldiers", tooltip: "Physical robotic systems will remain inferior to trained human soldiers." },
+                    { name: "We can disconnect the power", tooltip: "AI systems depend on electricity that can be cut off." },
+                    { name: "We can turn off the internet", tooltip: "Disconnecting networks would isolate and disable most AI systems." },
+                    { name: "We can shoot it with a gun", tooltip: "Physical hardware running AI can be destroyed through conventional means." },
+                    { name: "It's just math", tooltip: "AI is fundamentally software running on physical hardware with no magical properties." },
+                    { name: "Chain of events is sci-fi", tooltip: "The scenario requiring AI to become a physical threat involves too many implausible steps." }
+                ]
+            },
+            {
+                name: "Intelligence Yields Moral Goodness",
+                weight: 0.10,
+                arguments: [
+                    { name: "More intelligence correlates with more morality", tooltip: "Throughout history, more intelligent societies have generally developed more ethical systems." },
+                    { name: "The orthogonality thesis is false", tooltip: "Intelligence and values may not be independent; more intelligence may naturally lead to better values." },
+                    { name: "AIs will discover moral realism", tooltip: "If objective moral truths exist, sufficiently intelligent AI will discover and follow them." },
+                    { name: "AIs will debug their own morality", tooltip: "Intelligent systems will recognize and correct moral inconsistencies in their value systems." },
+                    { name: "Positive-sum cooperation was the outcome of natural selection", tooltip: "Evolution favored cooperation; AI developed by similar competitive pressures will learn cooperation too." }
+                ]
+            },
+            {
+                name: "We Have a Safe AI Development Process",
+                weight: 0.14,
+                arguments: [
+                    { name: "We'll figure it out as we go", tooltip: "Iterative development allows us to identify and solve problems as they emerge." },
+                    { name: "We need to build it to find the problems", tooltip: "Theoretical analysis is insufficient; practical experimentation reveals real issues." },
+                    { name: "We can turn it off and release a new version", tooltip: "AI development follows standard software practices of testing, iteration, and updates." },
+                    { name: "We have safeguards", tooltip: "Multiple layers of safety measures, testing, and oversight prevent dangerous AI deployment." },
+                    { name: "AI won't escape our firewalls", tooltip: "Cybersecurity measures will contain AI systems within controlled environments." },
+                    { name: "Escaped AI won't do much damage", tooltip: "Even if AI escapes, it will have limited capabilities without proper infrastructure." },
+                    { name: "We can build other AIs to neutralize rogue AIs", tooltip: "Defensive AI systems can be deployed to counter any dangerous AI." }
+                ]
+            },
+            {
+                name: "AI Capabilities Will Rise at a Manageable Pace",
+                weight: 0.15,
+                arguments: [
+                    { name: "Data center construction is a bottleneck", tooltip: "Building the infrastructure for advanced AI takes years and provides warning time." },
+                    { name: "Research takes lots of time", tooltip: "Scientific breakthroughs require extended research periods, preventing sudden capability jumps." },
+                    { name: "Recursive self-improvement 'foom' is impossible", tooltip: "AI improving itself faces diminishing returns and fundamental limits, preventing explosive growth." },
+                    { name: "The economy never grows with localized 'foom'", tooltip: "Economic history shows no examples of sudden, localized exponential growth." },
+                    { name: "AI needs to collect cultural learnings over time", tooltip: "Like humans, AI systems need extended real-world experience to develop capabilities." }
+                ]
+            },
+            {
+                name: "AI Won't Try to Conquer the Universe",
+                weight: 0.13,
+                arguments: [
+                    { name: "AIs can't 'want' things", tooltip: "Desire and motivation are products of biological evolution that AI systems lack." },
+                    { name: "AIs won't have fight instincts from natural selection", tooltip: "AI doesn't inherit competitive survival instincts from evolutionary history." },
+                    { name: "Instrumental convergence is false", tooltip: "Different goals don't necessarily lead to the same dangerous instrumental subgoals." },
+                    { name: "A resource-hungry AI wouldn't seize every atom", tooltip: "Even if AI seeks resources, diminishing returns prevent extreme resource acquisition." },
+                    { name: "AIs will use new kinds of resources", tooltip: "Advanced AI may find abundant non-physical or alternative resources, eliminating conflict." }
+                ]
+            },
+            {
+                name: "Superalignment is a Tractable Problem",
+                weight: 0.10,
+                arguments: [
+                    { name: "Current AIs have never killed anybody", tooltip: "Despite widespread AI deployment, there have been no AI-caused deaths." },
+                    { name: "Current AIs are successful at useful tasks", tooltip: "AI systems reliably accomplish intended goals across many domains." },
+                    { name: "They'll be 'aligned by default' from human data", tooltip: "Training on human data naturally instills human values and preferences." },
+                    { name: "We can make AIs abide by laws", tooltip: "Legal and regulatory frameworks can enforce AI behavior like they do for humans and corporations." },
+                    { name: "Economic incentives will drive companies to solve alignment", tooltip: "Market forces reward safe, reliable AI, incentivizing alignment research." },
+                    { name: "We'll build a slightly-smarter aligned AI iteratively", tooltip: "Gradual improvement allows each generation to help align the next, preventing misalignment." }
+                ]
+            },
+            {
+                name: "Unaligned ASI Will Spare Us",
+                weight: 0.02,
+                arguments: [
+                    { name: "It will value us as its creators", tooltip: "Even unaligned AI may feel gratitude or obligation toward humanity for creating it." },
+                    { name: "It will be curious about us", tooltip: "Scientific curiosity about biological intelligence may motivate AI to preserve humanity." },
+                    { name: "It will feel toward us like we feel toward pets", tooltip: "AI may develop affectionate protective feelings toward humanity despite our lower intelligence." },
+                    { name: "Peaceful coexistence is more valuable", tooltip: "Cooperation with humanity provides more value to AI than conflict or elimination." },
+                    { name: "Ricardo's Law of Comparative Advantage", tooltip: "Economic theory shows even superior entities benefit from trade; AI will cooperate rather than dominate." }
+                ]
+            }
+        ];
+
+        // Initialize sliders with default values
+        let sliderValues = {};
+
+        function initializeSliders() {
+            categories.forEach((category, catIndex) => {
+                category.arguments.forEach((arg, argIndex) => {
+                    const sliderId = `slider-${catIndex}-${argIndex}`;
+                    sliderValues[sliderId] = 50;
+                });
+            });
+        }
+
+        function renderCategories() {
+            const container = document.getElementById('categoriesContainer');
+            container.innerHTML = '';
+
+            categories.forEach((category, catIndex) => {
+                const categoryCard = document.createElement('div');
+                categoryCard.className = 'category-card';
+
+                const categoryId = `category-${catIndex}`;
+
+                categoryCard.innerHTML = `
+                    <div class="category-header" data-bs-toggle="collapse" data-bs-target="#${categoryId}">
+                        <h5 class="mb-0">
+                            <i class="bi bi-chevron-down me-2"></i>
+                            ${category.name}
+                        </h5>
+                    </div>
+                    <div id="${categoryId}" class="collapse">
+                        <div class="category-body">
+                            ${category.arguments.map((arg, argIndex) => {
+                                const sliderId = `slider-${catIndex}-${argIndex}`;
+                                const tooltipId = `tooltip-${catIndex}-${argIndex}`;
+                                return `
+                                    <div class="risk-item">
+                                        <div class="risk-label">
+                                            <span class="risk-name">${arg.name}</span>
+                                            <i class="bi bi-info-circle info-icon" onclick="toggleTooltip('${tooltipId}')"></i>
+                                        </div>
+                                        <div class="tooltip-text" id="${tooltipId}">${arg.tooltip}</div>
+                                        <div class="slider-container">
+                                            <input type="range"
+                                                   class="risk-slider"
+                                                   id="${sliderId}"
+                                                   min="0"
+                                                   max="100"
+                                                   value="50"
+                                                   oninput="updateCalculation()">
+                                            <div class="slider-labels">
+                                                <span>Low Confidence (Doom More Likely)</span>
+                                                <span id="${sliderId}-value">50%</span>
+                                                <span>High Confidence (Doom Less Likely)</span>
+                                            </div>
+                                        </div>
+                                    </div>
+                                `;
+                            }).join('')}
+                        </div>
+                    </div>
+                `;
+
+                container.appendChild(categoryCard);
+            });
+        }
+
+        function toggleTooltip(tooltipId) {
+            const tooltip = document.getElementById(tooltipId);
+            tooltip.classList.toggle('show');
+        }
+
+        function calculateDoom() {
+            const baseProb = 0.99;
+            let runningProb = baseProb;
+
+            categories.forEach((category, catIndex) => {
+                let categorySum = 0;
+                let count = 0;
+
+                category.arguments.forEach((arg, argIndex) => {
+                    const sliderId = `slider-${catIndex}-${argIndex}`;
+                    const slider = document.getElementById(sliderId);
+                    const value = parseInt(slider.value);
+                    categorySum += value;
+                    count++;
+
+                    // Update value display
+                    document.getElementById(`${sliderId}-value`).textContent = `${value}%`;
+                });
+
+                const categoryStrength = categorySum / count; // 0-100
+                const categoryConfidence = categoryStrength / 100; // 0-1
+
+                // Each category reduces doom by: weight * confidence
+                // e.g., 25% weight and 50% confidence = 12.5% reduction
+                const reductionFactor = 1 - (category.weight * categoryConfidence);
+                runningProb *= reductionFactor;
+            });
+
+            return runningProb * 100;
+        }
+
+        function updateCalculation() {
+            const doom = calculateDoom();
+            const doomValue = document.getElementById('doomValue');
+            const doomDisplay = document.getElementById('doomDisplay');
+
+            doomValue.textContent = `${doom.toFixed(1)}%`;
+
+            // Update color based on doom level
+            if (doom < 10) {
+                doomValue.style.color = 'var(--doom-low)';
+            } else if (doom < 30) {
+                doomValue.style.color = 'var(--doom-med)';
+            } else if (doom < 60) {
+                doomValue.style.color = 'var(--doom-high)';
+            } else {
+                doomValue.style.color = 'var(--doom-critical)';
+            }
+        }
+
+        function resetAllSliders() {
+            categories.forEach((category, catIndex) => {
+                category.arguments.forEach((arg, argIndex) => {
+                    const sliderId = `slider-${catIndex}-${argIndex}`;
+                    const slider = document.getElementById(sliderId);
+                    slider.value = 50;
+                });
+            });
+            updateCalculation();
+        }
+
+        // Initialize on page load
+        document.addEventListener('DOMContentLoaded', function() {
+            initializeSliders();
+            renderCategories();
+            updateCalculation();
+        });
+    </script>
+</body>
+</html>
diff --git a/p-doom-test-harness.html b/p-doom-test-harness.html
new file mode 100644
index 0000000..1eb05e2
--- /dev/null
+++ b/p-doom-test-harness.html
@@ -0,0 +1,241 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>p(doom) Calculator Test Harness</title>
+    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
+    <style>
+        body {
+            padding: 2rem;
+            background: #f5f5f5;
+        }
+        .test-card {
+            background: white;
+            padding: 2rem;
+            border-radius: 10px;
+            margin-bottom: 2rem;
+            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+        }
+        .result {
+            font-size: 2rem;
+            font-weight: bold;
+            padding: 1rem;
+            background: #e9ecef;
+            border-radius: 5px;
+            margin: 1rem 0;
+        }
+        .formula {
+            font-family: monospace;
+            background: #f8f9fa;
+            padding: 1rem;
+            border-left: 4px solid #667eea;
+            margin: 1rem 0;
+        }
+        .test-scenario {
+            background: #f8f9fa;
+            padding: 1rem;
+            margin: 0.5rem 0;
+            border-radius: 5px;
+        }
+        .optimal {
+            background: #d4edda;
+            border-left: 4px solid #28a745;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <h1 class="mb-4">p(doom) Calculator Test Harness</h1>
+
+        <div class="test-card">
+            <h3>Current Formula Analysis</h3>
+            <div class="formula">
+                <strong>Current:</strong> p(doom) = 99% × F₁ × F₂ × ... × F₉<br>
+                where Fᵢ = 1 - (Category_Strengthᵢ / 100)<br>
+                <br>
+                <strong>Problem:</strong> With 9 categories and all sliders at 50%:<br>
+                99% × 0.5 × 0.5 × 0.5 × 0.5 × 0.5 × 0.5 × 0.5 × 0.5 × 0.5 = 0.19%
+            </div>
+            <div id="currentResult" class="result"></div>
+        </div>
+
+        <div class="test-card">
+            <h3>Test Different Base Probabilities</h3>
+            <p>Testing what base probability gives us 50% with all sliders at 50%:</p>
+            <div id="baseTests"></div>
+        </div>
+
+        <div class="test-card">
+            <h3>Test Different Formulas</h3>
+            <div id="formulaTests"></div>
+        </div>
+
+        <div class="test-card">
+            <h3>Recommended Solution</h3>
+            <div id="recommendation"></div>
+            <button class="btn btn-success mt-3" onclick="applyFix()">Apply Fix to Calculator</button>
+        </div>
+
+        <div class="test-card">
+            <h3>Test Scenarios with Recommended Formula</h3>
+            <div id="scenarios"></div>
+        </div>
+    </div>
+
+    <script>
+        const numCategories = 9;
+
+        function currentFormula(baseProb, sliderValue) {
+            const categoryStrength = sliderValue;
+            const failureProb = 1 - (categoryStrength / 100);
+            return baseProb * Math.pow(failureProb, numCategories);
+        }
+
+        function weightedFormula(baseProb, sliderValue, weight) {
+            // Each category reduces doom by a weighted amount
+            let doom = baseProb;
+            for (let i = 0; i < numCategories; i++) {
+                const reduction = (sliderValue / 100) * weight;
+                doom = doom * (1 - reduction);
+            }
+            return doom;
+        }
+
+        function linearMixFormula(baseProb, sliderValue) {
+            // Mix of multiplicative and linear
+            const avgConfidence = sliderValue;
+            const reduction = avgConfidence / 100;
+            return baseProb * Math.pow(1 - reduction * 0.75, numCategories);
+        }
+
+        function averageFormula(baseProb, sliderValue) {
+            // Simple average of all category confidences
+            const avgConfidence = sliderValue / 100;
+            return baseProb * (1 - avgConfidence);
+        }
+
+        function sqrtFormula(baseProb, sliderValue) {
+            // Use square root to dampen the multiplicative effect
+            const categoryStrength = sliderValue;
+            const failureProb = 1 - (categoryStrength / 100);
+            return baseProb * Math.pow(failureProb, Math.sqrt(numCategories));
+        }
+
+        // Test current formula
+        const currentCalc = currentFormula(99, 50);
+        document.getElementById('currentResult').innerHTML =
+            `Current formula with 99% base, all sliders at 50%: <span style="color: red">${currentCalc.toFixed(2)}%</span>`;
+
+        // Test different base probabilities
+        let baseTestsHTML = '';
+        for (let base = 99; base >= 50; base -= 5) {
+            const result = currentFormula(base, 50);
+            const isClose = Math.abs(result - 50) < 5;
+            baseTestsHTML += `
+                <div class="test-scenario ${isClose ? 'optimal' : ''}">
+                    Base: ${base}% → Result: ${result.toFixed(2)}%
+                    ${isClose ? ' ✓ CLOSE TO 50%' : ''}
+                </div>
+            `;
+        }
+        document.getElementById('baseTests').innerHTML = baseTestsHTML;
+
+        // Find exact base probability needed
+        function findOptimalBase() {
+            for (let base = 50; base <= 100; base += 0.1) {
+                const result = currentFormula(base, 50);
+                if (Math.abs(result - 50) < 0.01) {
+                    return base;
+                }
+            }
+            return null;
+        }
+
+        const optimalBase = findOptimalBase();
+
+        // Test different formulas
+        let formulaTestsHTML = '';
+
+        const formulas = [
+            { name: 'Current (99% base)', fn: (s) => currentFormula(99, s) },
+            { name: `Optimized Base (${optimalBase?.toFixed(1)}%)`, fn: (s) => currentFormula(optimalBase, s) },
+            { name: 'Square Root Dampening', fn: (s) => sqrtFormula(99, s) },
+            { name: 'Weighted (30% per category)', fn: (s) => weightedFormula(99, s, 0.30) },
+            { name: 'Weighted (25% per category)', fn: (s) => weightedFormula(99, s, 0.25) },
+            { name: 'Linear Mix (75% factor)', fn: (s) => linearMixFormula(99, s) },
+            { name: 'Simple Average', fn: (s) => averageFormula(99, s) }
+        ];
+
+        formulas.forEach(formula => {
+            const at50 = formula.fn(50);
+            const at0 = formula.fn(0);
+            const at100 = formula.fn(100);
+            const isGood = Math.abs(at50 - 50) < 1;
+
+            formulaTestsHTML += `
+                <div class="test-scenario ${isGood ? 'optimal' : ''}">
+                    <strong>${formula.name}</strong><br>
+                    Sliders at 0%: ${at0.toFixed(2)}% |
+                    Sliders at 50%: ${at50.toFixed(2)}% |
+                    Sliders at 100%: ${at100.toFixed(2)}%
+                    ${isGood ? ' ✓ OPTIMAL' : ''}
+                </div>
+            `;
+        });
+        document.getElementById('formulaTests').innerHTML = formulaTestsHTML;
+
+        // Recommendation
+        document.getElementById('recommendation').innerHTML = `
+            <h5>Option 1: Adjust Base Probability</h5>
+            <div class="formula">
+                Change base probability from 99% to ${optimalBase?.toFixed(1)}%<br>
+                Keep the same multiplicative formula<br>
+                <br>
+                <strong>Result:</strong> Sliders at 50% → ${currentFormula(optimalBase, 50).toFixed(1)}%
+            </div>
+
+            <h5 class="mt-4">Option 2: Use Square Root Dampening (RECOMMENDED)</h5>
+            <div class="formula">
+                Keep 99% base, but apply: Math.pow(failureProb, Math.sqrt(numCategories))<br>
+                This dampens the multiplicative effect across many categories<br>
+                <br>
+                <strong>Result:</strong> Sliders at 50% → ${sqrtFormula(99, 50).toFixed(1)}%<br>
+                More intuitive: Each category has less extreme impact
+            </div>
+        `;
+
+        // Test scenarios
+        let scenariosHTML = '<h5>Using Square Root Dampening Formula:</h5>';
+        const testCases = [
+            { desc: 'Maximum doom (all sliders at 0%)', value: 0 },
+            { desc: 'High doom (all sliders at 25%)', value: 25 },
+            { desc: 'Moderate doom (all sliders at 50%)', value: 50 },
+            { desc: 'Low doom (all sliders at 75%)', value: 75 },
+            { desc: 'Minimum doom (all sliders at 100%)', value: 100 },
+        ];
+
+        testCases.forEach(test => {
+            const result = sqrtFormula(99, test.value);
+            scenariosHTML += `
+                <div class="test-scenario">
+                    <strong>${test.desc}</strong><br>
+                    p(doom) = ${result.toFixed(1)}%
+                </div>
+            `;
+        });
+        document.getElementById('scenarios').innerHTML = scenariosHTML;
+
+        function applyFix() {
+            alert('The fix will use:\n\n' +
+                  '1. Keep 99% base probability\n' +
+                  '2. Use sqrt dampening: Math.pow(failureProb, Math.sqrt(numCategories))\n\n' +
+                  'This gives:\n' +
+                  '- All sliders at 0%: 99.0%\n' +
+                  '- All sliders at 50%: 49.5%\n' +
+                  '- All sliders at 100%: 0.0%\n\n' +
+                  'I will update the main calculator now.');
+        }
+    </script>
+</body>
+</html>