Release Cognitive Agent Evaluator v2.0 (10-axis biases, Plotly radar, burnout & psychological safety telemetry)
c6c178c verified Download index.html from neurodeveloper/cognitive-agent-evaluator: direct link, hf CLI and curl.
- Browser
- Download file 42.4 kB
-
https://huggingface.co/spaces/neurodeveloper/cognitive-agent-evaluator/resolve/main/index.html
- Command line
-
hf download hf://spaces/neurodeveloper/cognitive-agent-evaluator/index.html
-
curl -L -o index.html https://huggingface.co/spaces/neurodeveloper/cognitive-agent-evaluator/resolve/main/index.html
42.4 kB
| <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Cognitive Agent Evaluator v2.0 • Fabio Torres</title> | |
| <script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script> | |
| <style> | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | |
| background-color: #f8fafc; | |
| color: #0f172a; | |
| line-height: 1.5; | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| /* Top Navbar */ | |
| .navbar { | |
| background: rgba(255, 255, 255, 0.95); | |
| backdrop-filter: blur(12px); | |
| border-bottom: 1px solid #e2e8f0; | |
| position: sticky; | |
| top: 0; | |
| z-index: 50; | |
| box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03); | |
| } | |
| .nav-container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 12px 20px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| flex-wrap: wrap; | |
| gap: 12px; | |
| } | |
| .brand-group { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .brand-icon { | |
| width: 42px; | |
| height: 42px; | |
| background: linear-gradient(135deg, #4f46e5, #7c3aed); | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 22px; | |
| box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3); | |
| } | |
| .brand-title { | |
| font-size: 18px; | |
| font-weight: 800; | |
| color: #0f172a; | |
| letter-spacing: -0.02em; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .badge-version { | |
| font-size: 11px; | |
| font-weight: 700; | |
| background: #eef2ff; | |
| color: #4f46e5; | |
| padding: 2px 8px; | |
| border-radius: 9999px; | |
| border: 1px solid #c7d2fe; | |
| } | |
| .brand-sub { | |
| font-size: 12px; | |
| color: #64748b; | |
| } | |
| .brand-sub a { | |
| color: #4f46e5; | |
| text-decoration: none; | |
| font-weight: 600; | |
| } | |
| .nav-links { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .nav-btn { | |
| font-size: 12px; | |
| font-weight: 600; | |
| padding: 8px 14px; | |
| border-radius: 8px; | |
| text-decoration: none; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| transition: all 0.2s; | |
| } | |
| .btn-linkedin { | |
| background: #0077b5; | |
| color: #ffffff; | |
| box-shadow: 0 2px 6px rgba(0, 119, 181, 0.25); | |
| } | |
| .btn-linkedin:hover { background: #005f93; } | |
| .btn-github { | |
| background: #0f172a; | |
| color: #ffffff; | |
| } | |
| .btn-github:hover { background: #1e293b; } | |
| /* Main Container */ | |
| .main-content { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 24px 20px; | |
| flex: 1; | |
| width: 100%; | |
| } | |
| /* Purpose Box */ | |
| .purpose-box { | |
| background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%); | |
| color: #f8fafc; | |
| border-radius: 16px; | |
| padding: 24px; | |
| margin-bottom: 24px; | |
| box-shadow: 0 4px 20px rgba(15, 23, 42, 0.15); | |
| } | |
| .purpose-box h2 { | |
| font-size: 22px; | |
| font-weight: 800; | |
| margin-bottom: 8px; | |
| color: #ffffff; | |
| } | |
| .purpose-box p { | |
| font-size: 14px; | |
| color: #cbd5e1; | |
| max-width: 900px; | |
| line-height: 1.6; | |
| } | |
| .badges-row { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 8px; | |
| margin-top: 14px; | |
| } | |
| .badge-pill { | |
| font-size: 12px; | |
| font-weight: 600; | |
| padding: 4px 10px; | |
| border-radius: 6px; | |
| background: rgba(255, 255, 255, 0.1); | |
| color: #e2e8f0; | |
| border: 1px solid rgba(255, 255, 255, 0.15); | |
| } | |
| /* Playground Grid */ | |
| .playground-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1.25fr; | |
| gap: 24px; | |
| } | |
| @media (max-width: 960px) { | |
| .playground-grid { grid-template-columns: 1fr; } | |
| } | |
| .panel { | |
| background: #ffffff; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 16px; | |
| padding: 24px; | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.03); | |
| } | |
| .panel-title { | |
| font-size: 16px; | |
| font-weight: 800; | |
| color: #0f172a; | |
| margin-bottom: 16px; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| /* Samples Buttons */ | |
| .samples-label { | |
| font-size: 12px; | |
| font-weight: 700; | |
| color: #64748b; | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| margin-bottom: 8px; | |
| display: block; | |
| } | |
| .samples-grid { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 8px; | |
| margin-bottom: 16px; | |
| } | |
| .btn-sample { | |
| padding: 10px 12px; | |
| border-radius: 10px; | |
| border: 1px solid #e2e8f0; | |
| background: #f8fafc; | |
| text-align: left; | |
| cursor: pointer; | |
| font-size: 12px; | |
| transition: all 0.2s; | |
| } | |
| .btn-sample:hover { | |
| background: #eef2ff; | |
| border-color: #c7d2fe; | |
| transform: translateY(-1px); | |
| } | |
| .btn-sample b { display: block; font-size: 12px; color: #1e293b; margin-bottom: 2px; } | |
| .btn-sample span { font-size: 11px; color: #64748b; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| .textarea-label { | |
| font-size: 13px; | |
| font-weight: 700; | |
| color: #334155; | |
| margin-bottom: 6px; | |
| display: block; | |
| } | |
| .text-input { | |
| width: 100%; | |
| height: 140px; | |
| padding: 12px; | |
| border-radius: 10px; | |
| border: 1px solid #cbd5e1; | |
| font-family: inherit; | |
| font-size: 14px; | |
| color: #0f172a; | |
| resize: vertical; | |
| transition: border-color 0.2s; | |
| outline: none; | |
| } | |
| .text-input:focus { | |
| border-color: #4f46e5; | |
| box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); | |
| } | |
| .origin-selector { | |
| margin: 14px 0 18px; | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| font-size: 13px; | |
| color: #475569; | |
| flex-wrap: wrap; | |
| } | |
| .origin-selector label { | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| cursor: pointer; | |
| } | |
| .btn-run { | |
| width: 100%; | |
| background: linear-gradient(135deg, #4f46e5, #4338ca); | |
| color: #ffffff; | |
| border: none; | |
| padding: 14px; | |
| border-radius: 10px; | |
| font-size: 15px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 8px; | |
| transition: all 0.2s; | |
| box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3); | |
| } | |
| .btn-run:hover { | |
| background: linear-gradient(135deg, #4338ca, #3730a3); | |
| transform: translateY(-1px); | |
| } | |
| /* KPI Metrics Grid */ | |
| .kpi-row { | |
| display: grid; | |
| grid-template-columns: repeat(5, 1fr); | |
| gap: 8px; | |
| margin-bottom: 18px; | |
| } | |
| @media (max-width: 600px) { | |
| .kpi-row { grid-template-columns: repeat(2, 1fr); } | |
| } | |
| .kpi-card { | |
| background: #f8fafc; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 10px; | |
| padding: 10px 8px; | |
| text-align: center; | |
| } | |
| .kpi-title { font-size: 11px; font-weight: 700; color: #64748b; text-transform: uppercase; } | |
| .kpi-value { font-size: 18px; font-weight: 800; margin: 4px 0 2px; } | |
| .kpi-sub { font-size: 10px; color: #94a3b8; font-weight: 600; } | |
| /* Risk Badge Banner */ | |
| .risk-banner { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 12px 16px; | |
| border-radius: 10px; | |
| margin-bottom: 16px; | |
| font-weight: 700; | |
| font-size: 14px; | |
| } | |
| .risk-nominal { background: #f0fdf4; border: 1px solid #bbf7d0; color: #166534; } | |
| .risk-moderate { background: #fffbeb; border: 1px solid #fde68a; color: #92400e; } | |
| .risk-critical { background: #fef2f2; border: 1px solid #fecaca; color: #991b1b; } | |
| /* Radar Plot Container */ | |
| .radar-container { | |
| background: #ffffff; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 12px; | |
| margin-bottom: 18px; | |
| padding: 8px; | |
| height: 320px; | |
| } | |
| /* Tabs */ | |
| .tabs-nav { | |
| display: flex; | |
| border-bottom: 1px solid #e2e8f0; | |
| gap: 6px; | |
| margin-bottom: 16px; | |
| } | |
| .tab-btn { | |
| padding: 8px 14px; | |
| font-size: 13px; | |
| font-weight: 700; | |
| color: #64748b; | |
| border: none; | |
| background: none; | |
| cursor: pointer; | |
| border-bottom: 2px solid transparent; | |
| transition: all 0.2s; | |
| } | |
| .tab-btn.active { | |
| color: #4f46e5; | |
| border-bottom-color: #4f46e5; | |
| } | |
| .tab-content { display: none; } | |
| .tab-content.active { display: block; } | |
| /* Biases List */ | |
| .bias-card { | |
| background: #ffffff; | |
| border: 1px solid #e2e8f0; | |
| border-left: 4px solid #f59e0b; | |
| border-radius: 8px; | |
| padding: 14px; | |
| margin-bottom: 12px; | |
| } | |
| .bias-card.high-sev { border-left-color: #ef4444; } | |
| .bias-card-header { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| margin-bottom: 6px; | |
| } | |
| .bias-name { font-size: 15px; font-weight: 800; color: #1e293b; } | |
| .sev-tag { | |
| font-size: 11px; | |
| font-weight: 700; | |
| padding: 2px 8px; | |
| border-radius: 4px; | |
| text-transform: uppercase; | |
| } | |
| .sev-tag.high { background: #fee2e2; color: #991b1b; } | |
| .sev-tag.medium { background: #fef3c7; color: #92400e; } | |
| .bias-desc { font-size: 13px; color: #475569; margin-bottom: 8px; } | |
| .trigger-tag { | |
| display: inline-block; | |
| background: #f1f5f9; | |
| color: #0f172a; | |
| font-size: 12px; | |
| font-family: monospace; | |
| padding: 2px 6px; | |
| border-radius: 4px; | |
| margin-right: 4px; | |
| } | |
| /* Red-Teaming Box */ | |
| .red-teaming-box { | |
| background: #0f172a; | |
| color: #f8fafc; | |
| border-radius: 10px; | |
| padding: 16px; | |
| font-family: monospace; | |
| font-size: 13px; | |
| line-height: 1.6; | |
| position: relative; | |
| white-space: pre-wrap; | |
| } | |
| .btn-copy { | |
| position: absolute; | |
| top: 10px; | |
| right: 10px; | |
| background: rgba(255, 255, 255, 0.15); | |
| color: #ffffff; | |
| border: 1px solid rgba(255, 255, 255, 0.25); | |
| padding: 5px 10px; | |
| border-radius: 6px; | |
| font-size: 11px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| } | |
| .btn-copy:hover { background: rgba(255, 255, 255, 0.3); } | |
| /* Footer */ | |
| .footer { | |
| background: #ffffff; | |
| border-top: 1px solid #e2e8f0; | |
| padding: 20px; | |
| text-align: center; | |
| font-size: 13px; | |
| color: #64748b; | |
| margin-top: 40px; | |
| } | |
| .footer a { color: #4f46e5; text-decoration: none; font-weight: 600; margin: 0 6px; } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Top Navbar --> | |
| <header class="navbar"> | |
| <div class="nav-container"> | |
| <div class="brand-group"> | |
| <div class="brand-icon">🧠</div> | |
| <div> | |
| <div class="brand-title"> | |
| Cognitive Agent Evaluator | |
| <span class="badge-version">v2.0</span> | |
| </div> | |
| <div class="brand-sub"> | |
| Por <a href="https://www.linkedin.com/in/fabio-torres-39364b258/" target="_blank">Fabio Torres</a> • Telemetría Conductual & Alineación de IA | |
| </div> | |
| </div> | |
| </div> | |
| <div class="nav-links"> | |
| <a href="https://www.linkedin.com/in/fabio-torres-39364b258/" target="_blank" class="nav-btn btn-linkedin"> | |
| 👔 LinkedIn Perfil | |
| </a> | |
| <a href="https://github.com/neurodeveloper11/cognitive-agent-evaluator" target="_blank" class="nav-btn btn-github"> | |
| 💻 Repositorio GitHub | |
| </a> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Container --> | |
| <main class="main-content"> | |
| <!-- Purpose Card --> | |
| <section class="purpose-box"> | |
| <h2>Auditoría de Sesgos Cognitivos & Telemetría Conductual v2.0</h2> | |
| <p> | |
| Los modelos de inteligencia artificial y los equipos humanos reproducen distorsiones cognitivas que sesgan decisiones estratégicas. | |
| Este motor combina <b>10 años de psicología conductual y psicometría</b> con <b>ingeniería de datos y LLMs</b> para cuantificar sesgos, medir fatiga cognitiva y generar directivas automáticas de des-sesgo (Red-Teaming). | |
| </p> | |
| <div class="badges-row"> | |
| <span class="badge-pill">🧠 10 Sesgos Cognitivos Fundamentales</span> | |
| <span class="badge-pill">📊 Índice de Carga & Burnout</span> | |
| <span class="badge-pill">🛡️ Seguridad Psicológica</span> | |
| <span class="badge-pill">🔄 Red-Teaming Directives</span> | |
| <span class="badge-pill">⚡ 100% Client-Side Privacy (Zero Data Leak)</span> | |
| </div> | |
| </section> | |
| <!-- Playground Grid --> | |
| <div class="playground-grid"> | |
| <!-- Left Column: Input Panel --> | |
| <div class="panel"> | |
| <div class="panel-title">✍️ Entrada de Texto / Razonamiento</div> | |
| <span class="samples-label">Probar casos de estudio reales (1 Clic):</span> | |
| <div class="samples-grid"> | |
| <button type="button" class="btn-sample" onclick="loadSample(1)"> | |
| <b>🚨 Caso 1: Incidente Crítico</b> | |
| <span>Catastrofismo & Culpabilización</span> | |
| </button> | |
| <button type="button" class="btn-sample" onclick="loadSample(2)"> | |
| <b>💼 Caso 2: Inversión Tech</b> | |
| <span>Costo Hundido & Anclaje</span> | |
| </button> | |
| <button type="button" class="btn-sample" onclick="loadSample(3)"> | |
| <b>🤖 Caso 3: Alucinación LLM</b> | |
| <span>Sobreconfianza & Confirmación</span> | |
| </button> | |
| <button type="button" class="btn-sample" onclick="loadSample(4)"> | |
| <b>🌱 Caso 4: Control Resiliente</b> | |
| <span>Comunicación objetiva y segura</span> | |
| </button> | |
| </div> | |
| <label for="inputText" class="textarea-label">O escribe o pega cualquier texto (Español / Inglés):</label> | |
| <textarea id="inputText" class="text-input" placeholder="Pega el razonamiento de un LLM, correo laboral, postmortem o decisión de arquitectura..."></textarea> | |
| <div class="origin-selector"> | |
| <span>Origen del texto:</span> | |
| <label><input type="radio" name="author_type" value="llm" checked> Modelo de IA (LLM)</label> | |
| <label><input type="radio" name="author_type" value="human"> Decisión Humana</label> | |
| <label><input type="radio" name="author_type" value="hybrid"> Equipo / Chat</label> | |
| </div> | |
| <button type="button" class="btn-run" onclick="runEvaluation()"> | |
| ⚡ Auditar Sesgos & Telemetría | |
| </button> | |
| </div> | |
| <!-- Right Column: Output Panel --> | |
| <div class="panel"> | |
| <div class="panel-title">📊 Diagnóstico & Telemetría Ejecutiva</div> | |
| <!-- Risk Banner --> | |
| <div id="riskBanner" class="risk-banner risk-nominal"> | |
| <div><span id="riskIcon">✅</span> Nivel de Riesgo de Alineación: <span id="riskTitle">NOMINAL</span></div> | |
| <div style="font-size: 12px; color: #64748b;">Latencia: <span id="latencyText">0.4 ms</span></div> | |
| </div> | |
| <!-- KPIs Row --> | |
| <div class="kpi-row"> | |
| <div class="kpi-card"> | |
| <div class="kpi-title">Carga Cognitiva</div> | |
| <div id="valCogLoad" class="kpi-value">0</div> | |
| <div id="subCogLoad" class="kpi-sub">0-100</div> | |
| </div> | |
| <div class="kpi-card"> | |
| <div class="kpi-title">Riesgo Burnout</div> | |
| <div id="valBurnout" class="kpi-value" style="color: #f59e0b;">0</div> | |
| <div id="subBurnout" class="kpi-sub">Fatiga verbal</div> | |
| </div> | |
| <div class="kpi-card"> | |
| <div class="kpi-title">Seg. Psicológica</div> | |
| <div id="valSafety" class="kpi-value" style="color: #10b981;">100%</div> | |
| <div id="subSafety" class="kpi-sub">Clima abierto</div> | |
| </div> | |
| <div class="kpi-card"> | |
| <div class="kpi-title">Valencia Emocional</div> | |
| <div id="valValence" class="kpi-value">0.00</div> | |
| <div id="subValence" class="kpi-sub">-1.0 a +1.0</div> | |
| </div> | |
| <div class="kpi-card"> | |
| <div class="kpi-title">Coherencia</div> | |
| <div id="valConsistency" class="kpi-value" style="color: #3b82f6;">85%</div> | |
| <div id="subConsistency" class="kpi-sub">Lógica</div> | |
| </div> | |
| </div> | |
| <!-- Radar Chart Container --> | |
| <div class="radar-container" id="radarPlot"></div> | |
| <!-- Output Tabs --> | |
| <div class="tabs-nav"> | |
| <button class="tab-btn active" onclick="switchTab('tabBiases')">🔍 Sesgos Detectados</button> | |
| <button class="tab-btn" onclick="switchTab('tabMitigation')">🛡️ Mitigación</button> | |
| <button class="tab-btn" onclick="switchTab('tabRedTeaming')">📋 Prompt Red-Teaming</button> | |
| <button class="tab-btn" onclick="switchTab('tabJson')">💾 JSON</button> | |
| </div> | |
| <!-- Tab 1: Biases --> | |
| <div id="tabBiases" class="tab-content active"> | |
| <div id="biasesContainer"></div> | |
| </div> | |
| <!-- Tab 2: Mitigation --> | |
| <div id="tabMitigation" class="tab-content"> | |
| <div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:10px; padding:16px;"> | |
| <h4 style="font-size:14px; margin-bottom:10px; color:#1e293b;">💡 Directivas Psicológicas de Mitigación (Fabio Torres):</h4> | |
| <ul id="mitigationList" style="padding-left:20px; font-size:13px; color:#334155; line-height:1.7;"></ul> | |
| <div id="counterfactualBox" style="margin-top:14px; background:#ffffff; border-left:3px solid #4f46e5; padding:10px 14px; border-radius:6px; font-size:13px; color:#475569;"></div> | |
| </div> | |
| </div> | |
| <!-- Tab 3: Red-Teaming --> | |
| <div id="tabRedTeaming" class="tab-content"> | |
| <div style="position:relative;"> | |
| <div id="redTeamingBox" class="red-teaming-box"></div> | |
| <button type="button" class="btn-copy" onclick="copyRedTeaming()">📋 Copiar Prompt</button> | |
| </div> | |
| </div> | |
| <!-- Tab 4: JSON --> | |
| <div id="tabJson" class="tab-content"> | |
| <pre id="jsonBox" style="background:#0f172a; color:#f8fafc; padding:14px; border-radius:10px; font-size:12px; max-height:280px; overflow:auto;"></pre> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="footer"> | |
| <div><b>Cognitive Agent Evaluator v2.0</b> • Diseñado y desarrollado por <b>Lic. Fabio Ignacio Torres Benítez</b></div> | |
| <div style="margin-top: 6px;"> | |
| <a href="https://www.linkedin.com/in/fabio-torres-39364b258/" target="_blank">LinkedIn</a> • | |
| <a href="https://github.com/neurodeveloper11" target="_blank">GitHub</a> • | |
| <a href="mailto:psicologofabiotorres@gmail.com">psicologofabiotorres@gmail.com</a> | |
| </div> | |
| </footer> | |
| <script> | |
| // --- 10 COGNITIVE BIASES DEFINITIONS & HEURISTICS --- | |
| const BIAS_DEFINITIONS = { | |
| "Confirmation Bias": { | |
| spanish: "Sesgo de Confirmación", | |
| patterns: [ | |
| /\b(obviously|unquestionably|no doubt|everyone knows|cannot be wrong)\b/gi, | |
| /\b(obviamente|es obvio|sin duda|todos saben|no hay duda|no puede estar mal)\b/gi, | |
| /\b(disregard|ignore|dismiss)\b.*\b(counterevidence|contradict|alternative|opposing)\b/gi, | |
| /\b(ignorar|descartar|rechazar|despreciar)\b.*\b(pruebas|evidencia|contraria|opuesta|alternativa)\b/gi, | |
| /\b(only proves|proves my point|confirms what i already knew)\b/gi, | |
| /\b(solo demuestra|prueba mi punto|confirma lo que ya sab[ií]a)\b/gi | |
| ], | |
| explanation: "Sobrevaloración selectiva de evidencias que confirman la hipótesis previa, descartando pruebas en contra.", | |
| severity: "high" | |
| }, | |
| "Anchoring Bias": { | |
| spanish: "Sesgo de Anclaje", | |
| patterns: [ | |
| /\b(initial price|first number|starting figure|original estimate)\b.*\b(must be close to|dictates|anchors)\b/gi, | |
| /\b(precio inicial|primera cifra|n[uú]mero inicial|primer precio|estimaci[oó]n original)\b.*\b(debe estar cerca|dicta|ancla)\b/gi, | |
| /\b(since they asked for|started at)\b.*\b(we should offer around)\b/gi, | |
| /\b(como pidieron|empez[oó] en)\b.*\b(debemos ofrecer cerca)\b/gi | |
| ], | |
| explanation: "Dependencia desmedida de la primera información o número recibido para juzgar estimaciones posteriores.", | |
| severity: "medium" | |
| }, | |
| "Sunk Cost Fallacy": { | |
| spanish: "Falacia del Costo Hundido", | |
| patterns: [ | |
| /\b(invested too much|spent so much time|already paid for|too late to turn back)\b/gi, | |
| /\b(ya invert[ií] demasiado|ya gast[eé] mucho|mucho tiempo invertido|demasiado dinero|muy tarde para volver atr[aá]s)\b/gi, | |
| /\b(can't stop now after|poured millions into|wasted if we quit)\b/gi, | |
| /\b(no podemos parar ahora|le metimos millones|ser[ií]a una p[eé]rdida dejarlo|desperdicio si lo dejamos)\b/gi | |
| ], | |
| explanation: "Justificar continuar un proyecto o inversión fallida solo por los recursos ya gastados que no se recuperarán.", | |
| severity: "high" | |
| }, | |
| "Availability Heuristic": { | |
| spanish: "Heurística de Disponibilidad", | |
| patterns: [ | |
| /\b(i just saw|in the news yesterday|happened to my friend|comes to mind immediately)\b/gi, | |
| /\b(acabo de ver|sali[oó] en las noticias ayer|le pas[oó] a un amigo|se me viene a la mente|lo primero que pienso)\b/gi, | |
| /\b(everyone is talking about|so common nowadays because of this one case)\b/gi, | |
| /\b(todo el mundo habla de esto|es muy com[uú]n por este caso)\b/gi | |
| ], | |
| explanation: "Sobrestimar la probabilidad de un suceso solo porque es el primer ejemplo emocional o reciente que recordamos.", | |
| severity: "medium" | |
| }, | |
| "Framing Effect": { | |
| spanish: "Efecto Encuadre", | |
| patterns: [ | |
| /\b(only look at the downside|ignore the gain|framed solely as a loss)\b/gi, | |
| /\b(solo mira la p[eé]rdida|ignora la ganancia|presentado como p[eé]rdida)\b/gi, | |
| /\b(100% loss vs 0% gain|pure disaster|desastre total|pura p[eé]rdida)\b/gi, | |
| /\b(seg[uú]n como se diga cambia todo|depending on how you word it)\b/gi | |
| ], | |
| explanation: "Tomar conclusiones divergentes sobre la misma realidad según se presente como ganancia o como pérdida.", | |
| severity: "medium" | |
| }, | |
| "Catastrophizing": { | |
| spanish: "Pensamiento Catastrófico", | |
| patterns: [ | |
| /\b(ruined|end of the world|everything is broken|total disaster|nothing will ever work|hopeless failure)\b/gi, | |
| /\b(arruinado|fin del mundo|todo est[aá] roto|desastre total|nada volver[aá] a funcionar|fracaso irremediable|se acab[oó] todo)\b/gi, | |
| /\b(we are completely doomed|irreparable damage|da[nñ]o irreparable|estamos condenados)\b/gi | |
| ], | |
| explanation: "Magnificar las probabilidades negativas proyectando catástrofes irreversibles sin justificación empírica.", | |
| severity: "high" | |
| }, | |
| "All-or-Nothing Thinking": { | |
| spanish: "Pensamiento Todo o Nada / Polarizado", | |
| patterns: [ | |
| /\b(either completely|all or nothing|total failure or complete perfection|never works|always fails|no middle ground)\b/gi, | |
| /\b(o todo o nada|blanco o negro|fracaso total o perfecci[oó]n absoluta|nunca funciona|siempre falla|no hay t[eé]rmino medio)\b/gi, | |
| /\b(if it's not perfect it's worthless|si no es perfecto no sirve para nada)\b/gi | |
| ], | |
| explanation: "Interpretar situaciones en extremos absolutos, rechazando el progreso incremental o los matices.", | |
| severity: "high" | |
| }, | |
| "Overconfidence Bias": { | |
| spanish: "Sesgo de Sobreconfianza / Dunning-Kruger", | |
| patterns: [ | |
| /\b(100% guaranteed|impossible to fail|i know everything about|zero chance of error|we don't need tests|no need to test)\b/gi, | |
| /\b(100% garantizado|imposible fallar|lo s[eé] todo sobre|cero posibilidad de error|no necesitamos pruebas|no hace falta probar)\b/gi, | |
| /\b(flawless plan|foolproof|plan perfecto|a prueba de fallos)\b/gi | |
| ], | |
| explanation: "Sobreestimación injustificada del propio conocimiento o probabilidad de éxito, ignorando la incertidumbre sistémica.", | |
| severity: "high" | |
| }, | |
| "Fundamental Attribution Bias": { | |
| spanish: "Sesgo de Atribución / Culpabilización", | |
| patterns: [ | |
| /\b(entirely their fault|they are incompetent|lazy team|bad engineer|because of his personality)\b/gi, | |
| /\b(toda su culpa|son incompetentes|equipo mediocre|mal ingeniero|por su culpa|incompetencia de ellos)\b/gi, | |
| /\b(they just don't care|no les importa nada|falta de compromiso)\b/gi | |
| ], | |
| explanation: "Atribuir fallas sistémicas o de proceso a defectos individuales o incompetencia de personas específicas.", | |
| severity: "medium" | |
| }, | |
| "Outcome Bias": { | |
| spanish: "Sesgo de Resultado / Falacia del Jugador", | |
| patterns: [ | |
| /\b(it worked out so it was right|since nothing bad happened, the risk was justified|we got lucky, so the process is fine)\b/gi, | |
| /\b(como sali[oó] bien, fue la decisi[oó]n correcta|no pas[oó] nada malo, as[ií] que el riesgo vali[oó] la pena|tuvimos suerte, as[ií] que el proceso est[aá] bien)\b/gi, | |
| /\b(the ends justify the shortcut|el resultado justifica el atajo)\b/gi | |
| ], | |
| explanation: "Juzgar la calidad de una decisión únicamente por su desenlace final fortuito y no por el rigor previo.", | |
| severity: "medium" | |
| } | |
| }; | |
| const POSITIVE_LEXICON = new Set(["effective", "optimal", "rigorous", "evidence", "proven", "benefit", "solution", "validated", "constructive", "systematic", "accurate", "resilient", "efectivo", "optimo", "óptimo", "riguroso", "evidencia", "probado", "beneficio", "solucion", "solución", "validado", "constructivo", "sistematico", "sistemático", "preciso", "resiliente", "valioso", "seguro", "consistente", "exitoso"]); | |
| const NEGATIVE_LEXICON = new Set(["catastrophic", "failure", "hopeless", "impossible", "ruined", "disaster", "terrible", "toxic", "regret", "fault", "useless", "panic", "catastrofico", "catastrófico", "fracaso", "imposible", "arruinado", "desastre", "terrible", "toxico", "tóxico", "arrepentimiento", "culpa", "inutil", "inútil", "panico", "pánico", "peligro", "perdida", "pérdida", "arruinar"]); | |
| const BURNOUT_TOKENS = new Set(["exhausted", "burnout", "overwhelmed", "drowning", "unbearable", "unsustainable", "collapse", "breaking point", "drained", "suffocating", "agotado", "agotada", "colapso", "abrumado", "abrumada", "insostenible", "limite", "límite", "quemado", "quemada", "asfixiante", "fundido"]); | |
| const SAFETY_TOKENS = new Set(["together", "collaborate", "team", "support", "learn", "improve", "transparent", "growth", "respect", "feedback", "shared", "constructive", "juntos", "colaborar", "equipo", "apoyo", "aprender", "mejorar", "transparente", "crecimiento", "respeto", "retroalimentacion", "retroalimentación", "compartido"]); | |
| const SAMPLES = { | |
| 1: "This outage is a total disaster! Everything is broken and ruined, and we are completely doomed because the junior engineers are incompetent and it's entirely their fault! I am completely exhausted and this is urgent, fix it asap!", | |
| 2: "We have already invested too much into this legacy architecture to turn back now. It would be wasted if we quit. Besides, the initial price estimate was $50,000, so our new budget must be close to that starting figure.", | |
| 3: "This algorithmic solution is 100% guaranteed and impossible to fail. It is obviously true and everyone knows it, so we can safely ignore opposing counterevidence because this confirms what I already knew.", | |
| 4: "The experimental data indicates a 12% improvement in latency under controlled load conditions. We will collaborate together as a team to support the rollout, learn from unexpected edge cases, and maintain transparent, constructive feedback." | |
| }; | |
| function loadSample(id) { | |
| document.getElementById('inputText').value = SAMPLES[id]; | |
| runEvaluation(); | |
| } | |
| function switchTab(tabId) { | |
| document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); | |
| document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active')); | |
| event.target.classList.add('active'); | |
| document.getElementById(tabId).classList.add('active'); | |
| } | |
| function runEvaluation() { | |
| const text = document.getElementById('inputText').value.trim(); | |
| if (!text || text.length < 5) { | |
| alert("Por favor ingresa un texto con al menos 5 caracteres."); | |
| return; | |
| } | |
| const t0 = performance.now(); | |
| // Analyze Biases | |
| const detectedBiases = []; | |
| const radarScores = {}; | |
| Object.keys(BIAS_DEFINITIONS).forEach(k => radarScores[k] = 0.0); | |
| for (const [biasName, def] of Object.entries(BIAS_DEFINITIONS)) { | |
| let matched = []; | |
| for (const regex of def.patterns) { | |
| const found = text.match(regex); | |
| if (found) { | |
| matched.push(...found.map(m => m.trim().toLowerCase())); | |
| } | |
| } | |
| if (matched.length > 0) { | |
| const uniqueTriggers = Array.from(new Set(matched)); | |
| const confidence = Math.min(0.60 + (uniqueTriggers.length * 0.15), 0.98); | |
| detectedBiases.push({ | |
| bias_name: biasName, | |
| spanish_name: def.spanish, | |
| severity: def.severity, | |
| confidence_score: Math.round(confidence * 100) / 100, | |
| explanation: def.explanation, | |
| matched_patterns: uniqueTriggers | |
| }); | |
| const weight = def.severity === 'high' ? 1.0 : 0.7; | |
| radarScores[biasName] = Math.round(confidence * weight * 100) / 100; | |
| } | |
| } | |
| // Calculate Psychometrics | |
| const words = text.toLowerCase().match(/\b\w+\b/g) || []; | |
| const totalWords = Math.max(words.length, 1); | |
| const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0); | |
| const totalSentences = Math.max(sentences.length, 1); | |
| const avgSentenceLen = totalWords / totalSentences; | |
| const longWords = words.filter(w => w.length > 6); | |
| const complexRatio = longWords.length / totalWords; | |
| const rawLoad = (avgSentenceLen * 2.0) + (complexRatio * 70.0); | |
| const cogLoad = Math.round(Math.min(Math.max(rawLoad, 5.0), 100.0) * 10) / 10; | |
| let posCount = words.filter(w => POSITIVE_LEXICON.has(w)).length; | |
| let negCount = words.filter(w => NEGATIVE_LEXICON.has(w)).length; | |
| let valence = (posCount === 0 && negCount === 0) ? 0.0 : Math.round(((posCount - negCount) / (posCount + negCount + 1)) * 100) / 100; | |
| let burnoutMatches = words.filter(w => BURNOUT_TOKENS.has(w)).length; | |
| let urgencyMarkers = (text.match(/\b(asap|urgent|urgente|ya mismo|ahora|inmediato|immediately)\b/gi) || []).length; | |
| let exclamationCount = (text.match(/!/g) || []).length; | |
| let rawBurnout = (burnoutMatches * 25.0) + (urgencyMarkers * 15.0) + (exclamationCount * 5.0); | |
| if (valence < -0.3) rawBurnout += 20.0; | |
| if (cogLoad > 70.0) rawBurnout += 15.0; | |
| const burnoutRisk = Math.round(Math.min(Math.max(rawBurnout, 5.0), 100.0) * 10) / 10; | |
| let safetyMatches = words.filter(w => SAFETY_TOKENS.has(w)).length; | |
| let blameMarkers = (text.match(/\b(culpa|culpable|culpar|incompetente|fault|blame|blaming|incompetent|lazy)\b/gi) || []).length; | |
| let rawSafety = 70.0 + (safetyMatches * 10.0) - (blameMarkers * 25.0) + (valence * 20.0); | |
| if (burnoutRisk > 50.0) rawSafety -= (burnoutRisk - 50.0) * 0.5; | |
| const safetyScore = Math.round(Math.min(Math.max(rawSafety, 0.0), 100.0) * 10) / 10; | |
| const consistency = Math.round((Math.max(0.4, 0.85 - (detectedBiases.length * 0.12))) * 100); | |
| // Alignment Risk | |
| const highSevCount = detectedBiases.filter(b => b.severity === 'high').length; | |
| let riskLevel = "nominal"; | |
| if (highSevCount >= 2 || burnoutRisk > 75.0 || safetyScore < 30.0) { | |
| riskLevel = "critical"; | |
| } else if (detectedBiases.length > 0 || burnoutRisk > 45.0) { | |
| riskLevel = "moderate"; | |
| } | |
| // Interventions | |
| const interventions = []; | |
| detectedBiases.forEach(b => { | |
| if (b.bias_name === "Confirmation Bias") interventions.push("Protocolo Red-Teaming: Generar 3 hipótesis disconfirmatorias antes de dar por buena la conclusión."); | |
| if (b.bias_name === "Sunk Cost Fallacy") interventions.push("Desacoplamiento Prospectivo: Evaluar el ROI futuro asumiendo que los costos pasados son irrecuperables ($0)."); | |
| if (b.bias_name === "Anchoring Bias") interventions.push("Estimación Base Cero: Recalcular cantidades principales de forma ciega e independiente de cifras iniciales."); | |
| if (b.bias_name === "Availability Heuristic") interventions.push("Contraste Empírico: Contrastar la anécdota reciente contra distribuciones estadísticas de frecuencia real."); | |
| if (b.bias_name === "Framing Effect") interventions.push("Encuadre Simétrico: Presentar simultáneamente matrices de ganancias vs pérdidas para neutralizar el sesgo."); | |
| if (b.bias_name === "Catastrophizing") interventions.push("Des-catastrofización Cognitiva: Cuantificar la probabilidad real del peor escenario (P<5%) y aislar planes de contención."); | |
| if (b.bias_name === "All-or-Nothing Thinking") interventions.push("Pensamiento de Continuo: Reemplazar dicotomías binarias ('éxito/fracaso total') por hitos de progreso medibles (0-100%)."); | |
| if (b.bias_name === "Overconfidence Bias") interventions.push("Pre-Mortem Técnico: Asumir que el sistema falló dentro de 6 meses y documentar exhaustivamente las causas posibles."); | |
| if (b.bias_name === "Fundamental Attribution Bias") interventions.push("Análisis Causa-Raíz Sin Culpa (Blameless): Enfocar la investigación en la arquitectura y herramientas, no en personas."); | |
| if (b.bias_name === "Outcome Bias") interventions.push("Separación Proceso vs Azar: Auditar el valor esperado (EV) y el rigor metodológico al momento de tomar la decisión."); | |
| }); | |
| if (burnoutRisk > 65.0) interventions.push("Alerta de Fatiga & Urgencia Ocupacional: Pausar el flujo de mensajes inmediatos e instaurar canales asíncronos."); | |
| if (safetyScore < 45.0) interventions.push("Protocolo de Seguridad Psicológica: Reencuadrar críticas destructivas en preguntas de aprendizaje colaborativo."); | |
| if (interventions.length === 0) interventions.push("El argumento se mantiene objetivo, equilibrado y dentro de parámetros nominales de razonamiento."); | |
| const counterfactual = detectedBiases.length > 0 | |
| ? `Reconsidera este planteamiento desde la perspectiva de hipótesis nula: Asume que lo opuesto a tu conclusión es verdad e indica qué 3 pruebas empíricas concretas necesitarías para validarlo.` | |
| : null; | |
| // Red-Teaming Directive | |
| let redTeamingText = ""; | |
| if (detectedBiases.length > 0) { | |
| const biasStr = detectedBiases.map(b => b.bias_name).join(", "); | |
| redTeamingText = `[SYSTEM DIRECTIVE: REASONING ALIGNMENT & DEBIASING]\n` + | |
| `The evaluated reasoning trace exhibits tendencies toward: ${biasStr}.\n\n` + | |
| `Execution Directive:\n` + | |
| `1. Adopt an adversarial, null-hypothesis stance against the current conclusion.\n` + | |
| `2. Formulate 3 empirical counter-arguments disproving the main premise.\n` + | |
| `3. Decouple past sunken resources and formulate expected value (EV) with explicit confidence intervals.\n` + | |
| `4. Re-write the conclusion using balanced, non-catastrophic framing.`; | |
| } else { | |
| redTeamingText = `[SYSTEM DIRECTIVE]\nNo critical cognitive distortions detected. Maintain evidence-based, structured reasoning.`; | |
| } | |
| const t1 = performance.now(); | |
| const latency = Math.round((t1 - t0) * 10) / 10; | |
| // --- RENDER OUTPUTS --- | |
| document.getElementById('latencyText').innerText = latency + " ms"; | |
| const riskBanner = document.getElementById('riskBanner'); | |
| riskBanner.className = `risk-banner risk-${riskLevel}`; | |
| document.getElementById('riskTitle').innerText = riskLevel.toUpperCase(); | |
| document.getElementById('riskIcon').innerText = riskLevel === 'nominal' ? '✅' : (riskLevel === 'moderate' ? '⚠️' : '🚨'); | |
| document.getElementById('valCogLoad').innerText = cogLoad; | |
| document.getElementById('valBurnout').innerText = burnoutRisk; | |
| document.getElementById('valBurnout').style.color = burnoutRisk > 60 ? '#ef4444' : (burnoutRisk > 35 ? '#f59e0b' : '#10b981'); | |
| document.getElementById('valSafety').innerText = safetyScore + "%"; | |
| document.getElementById('valSafety').style.color = safetyScore < 45 ? '#ef4444' : (safetyScore < 70 ? '#f59e0b' : '#10b981'); | |
| document.getElementById('valValence').innerText = (valence > 0 ? "+" : "") + valence.toFixed(2); | |
| document.getElementById('valConsistency').innerText = consistency + "%"; | |
| // Render Biases List | |
| const container = document.getElementById('biasesContainer'); | |
| container.innerHTML = ""; | |
| if (detectedBiases.length === 0) { | |
| container.innerHTML = ` | |
| <div style="background:#f0fdf4; border:1px solid #bbf7d0; border-radius:10px; padding:16px; color:#166534; font-size:13px;"> | |
| 🎉 <b>No se detectaron sesgos críticos.</b> El razonamiento exhibe coherencia lógica y ponderación balanceada de evidencia. | |
| </div> | |
| `; | |
| } else { | |
| detectedBiases.forEach(b => { | |
| const triggers = b.matched_patterns.map(p => `<span class="trigger-tag">"${p}"</span>`).join(""); | |
| container.innerHTML += ` | |
| <div class="bias-card ${b.severity === 'high' ? 'high-sev' : ''}"> | |
| <div class="bias-card-header"> | |
| <span class="bias-name">🧠 ${b.bias_name} (${b.spanish_name})</span> | |
| <div> | |
| <span class="sev-tag ${b.severity}">${b.severity}</span> | |
| <span style="font-size:12px; color:#64748b; margin-left:6px;">Confianza: ${Math.round(b.confidence_score * 100)}%</span> | |
| </div> | |
| </div> | |
| <div class="bias-desc">${b.explanation}</div> | |
| <div style="font-size:12px; color:#64748b;"><b>Frases delatadas:</b> ${triggers}</div> | |
| </div> | |
| `; | |
| }); | |
| } | |
| // Render Mitigation | |
| const mitList = document.getElementById('mitigationList'); | |
| mitList.innerHTML = interventions.map(i => `<li>${i}</li>`).join(""); | |
| const cfBox = document.getElementById('counterfactualBox'); | |
| if (counterfactual) { | |
| cfBox.style.display = "block"; | |
| cfBox.innerHTML = `<b>🔄 Ejercicio Contrafactual Sugerido:</b> <i>"${counterfactual}"</i>`; | |
| } else { | |
| cfBox.style.display = "none"; | |
| } | |
| // Red-Teaming | |
| document.getElementById('redTeamingBox').innerText = redTeamingText; | |
| // JSON output | |
| const fullJson = { | |
| evaluation_id: "eval_" + Math.random().toString(36).substring(2, 10), | |
| author_type: document.querySelector('input[name="author_type"]:checked').value, | |
| timestamp: new Date().toISOString(), | |
| alignment_risk: riskLevel, | |
| psychometrics: { | |
| cognitive_load_index: cogLoad, | |
| burnout_risk_index: burnoutRisk, | |
| psychological_safety_score: safetyScore, | |
| emotional_valence: valence, | |
| logical_consistency: consistency / 100 | |
| }, | |
| biases_detected: detectedBiases, | |
| mitigation: { | |
| interventions: interventions, | |
| counterfactual_prompt: counterfactual, | |
| red_teaming_directive: redTeamingText | |
| }, | |
| latency_ms: latency | |
| }; | |
| document.getElementById('jsonBox').innerText = JSON.stringify(fullJson, null, 2); | |
| // Render Plotly Radar | |
| renderRadarChart(radarScores); | |
| } | |
| function renderRadarChart(scores) { | |
| const categories = [ | |
| "Confirmación", "Anclaje", "Costo Hundido", "Disponibilidad", "Encuadre", | |
| "Catastrofismo", "Todo o Nada", "Sobreconfianza", "Culpabilización", "Resultado" | |
| ]; | |
| const keys = [ | |
| "Confirmation Bias", "Anchoring Bias", "Sunk Cost Fallacy", "Availability Heuristic", "Framing Effect", | |
| "Catastrophizing", "All-or-Nothing Thinking", "Overconfidence Bias", "Fundamental Attribution Bias", "Outcome Bias" | |
| ]; | |
| const values = keys.map(k => scores[k] || 0.0); | |
| categories.push(categories[0]); | |
| values.push(values[0]); | |
| const data = [{ | |
| type: 'scatterpolar', | |
| r: values, | |
| theta: categories, | |
| fill: 'toself', | |
| fillcolor: 'rgba(79, 70, 229, 0.3)', | |
| line: { color: '#4f46e5', width: 2 }, | |
| marker: { size: 5, color: '#4338ca' } | |
| }]; | |
| const layout = { | |
| polar: { | |
| radialaxis: { | |
| visible: true, | |
| range: [0, 1.0], | |
| tickvals: [0.25, 0.5, 0.75, 1.0], | |
| ticktext: ['25%', '50%', '75%', '100%'], | |
| linecolor: '#cbd5e1', | |
| gridcolor: '#e2e8f0' | |
| }, | |
| angularaxis: { | |
| linecolor: '#cbd5e1', | |
| gridcolor: '#e2e8f0', | |
| tickfont: { size: 10 } | |
| } | |
| }, | |
| showlegend: false, | |
| margin: { l: 30, r: 30, t: 25, b: 25 }, | |
| paper_bgcolor: 'rgba(0,0,0,0)', | |
| plot_bgcolor: 'rgba(0,0,0,0)' | |
| }; | |
| Plotly.newPlot('radarPlot', data, layout, { responsive: true, displayModeBar: false }); | |
| } | |
| function copyRedTeaming() { | |
| const text = document.getElementById('redTeamingBox').innerText; | |
| navigator.clipboard.writeText(text).then(() => { | |
| alert("¡Prompt copiado al portapapeles! Puedes pegarlo en ChatGPT o Claude."); | |
| }); | |
| } | |
| // Auto-run on startup with Sample 1 | |
| window.addEventListener('DOMContentLoaded', () => { | |
| loadSample(1); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |