MetaMetaMeta / visual_explainer_run_pipeline.html
smlflg's picture
Initial public upload from Projekte/MetaMetaMeta
3bc7cb3 verified
Raw History Blame Contribute Delete
50.3 kB
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AgentArena — E8 Experiment + Run Pipeline</title> <style> :root { --bg-primary: #0d0d1a; --bg-secondary: #1a1a2e; --bg-card: #16213e; --bg-setup: rgba(59, 130, 246, 0.06); --bg-execution: rgba(16, 185, 129, 0.06); --bg-evaluation: rgba(168, 85, 247, 0.06); --border-setup: rgba(59, 130, 246, 0.25); --border-execution: rgba(16, 185, 129, 0.25); --border-evaluation: rgba(168, 85, 247, 0.25); --accent-setup: #3b82f6; --accent-execution: #10b981; --accent-evaluation: #a855f7; --accent-exp: #f59e0b; --accent-exp-dim: rgba(245, 158, 11, 0.12); --accent-exp-border: rgba(245, 158, 11, 0.28); --accent-baseline: #94a3b8; --accent-injected: #10b981; --text-primary: #e2e8f0; --text-secondary: #94a3b8; --text-muted: #64748b; --connector: #334155; --step-bg: #1e293b; --step-hover: #243452; --step-active: #1e3a5f; --mono: 'Fira Code', 'Cascadia Code', 'Consolas', monospace; --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; --radius: 10px; --transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1); } * { box-sizing: border-box; margin: 0; padding: 0; } body { background: var(--bg-primary); color: var(--text-primary); font-family: var(--sans); min-height: 100vh; line-height: 1.6; padding: 0 0 80px; } /* ──────────── HEADER ──────────── */ .header { background: linear-gradient(135deg, #0d0d1a 0%, #16213e 50%, #0d0d1a 100%); border-bottom: 1px solid rgba(255,255,255,0.06); padding: 48px 24px 40px; text-align: center; position: relative; overflow: hidden; } .header::before { content: ''; position: absolute; inset: 0; background: radial-gradient(ellipse 60% 40% at 20% 50%, rgba(59,130,246,0.07) 0%, transparent 70%), radial-gradient(ellipse 60% 40% at 80% 50%, rgba(168,85,247,0.07) 0%, transparent 70%); pointer-events: none; } .header-badge { display: inline-flex; align-items: center; gap: 8px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); border-radius: 999px; padding: 4px 14px; font-size: 11px; font-family: var(--mono); color: var(--text-muted); letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 20px; } .header-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: #10b981; box-shadow: 0 0 8px #10b981; animation: pulse 2s ease infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } h1 { font-size: clamp(26px, 5vw, 42px); font-weight: 700; letter-spacing: -0.02em; margin-bottom: 10px; background: linear-gradient(135deg, #e2e8f0 30%, #94a3b8 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } h1 span { background: linear-gradient(135deg, #3b82f6, #a855f7); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .subtitle { color: var(--text-secondary); font-size: 15px; max-width: 520px; margin: 0 auto; } /* ──────────── LEGEND ──────────── */ .legend { display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; padding: 24px 24px 0; } .legend-item { display: flex; align-items: center; gap: 8px; background: var(--bg-card); border-radius: 999px; padding: 6px 16px; font-size: 12px; font-weight: 500; color: var(--text-secondary); border: 1px solid rgba(255,255,255,0.06); } .legend-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; } .legend-item.setup .legend-dot { background: var(--accent-setup); box-shadow: 0 0 8px var(--accent-setup); } .legend-item.exec .legend-dot { background: var(--accent-execution); box-shadow: 0 0 8px var(--accent-execution); } .legend-item.eval .legend-dot { background: var(--accent-evaluation); box-shadow: 0 0 8px var(--accent-evaluation); } /* ──────────── MAIN CONTAINER ──────────── */ .pipeline-wrapper { max-width: 780px; margin: 36px auto 0; padding: 0 16px; display: flex; flex-direction: column; gap: 0; } /* ──────────── PHASE BLOCK ──────────── */ .phase-block { border-radius: 16px; padding: 6px; margin-bottom: 6px; position: relative; } .phase-block.setup { background: var(--bg-setup); border: 1px solid var(--border-setup); } .phase-block.execution { background: var(--bg-execution); border: 1px solid var(--border-execution); } .phase-block.evaluation { background: var(--bg-evaluation); border: 1px solid var(--border-evaluation); } .phase-label { font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; padding: 6px 14px 4px; opacity: 0.8; } .phase-block.setup .phase-label { color: var(--accent-setup); } .phase-block.execution .phase-label { color: var(--accent-execution); } .phase-block.evaluation .phase-label { color: var(--accent-evaluation); } /* ──────────── STEP ──────────── */ .step-wrapper { position: relative; display: flex; flex-direction: column; } .step { display: flex; align-items: center; gap: 16px; background: var(--step-bg); border-radius: var(--radius); padding: 16px 18px; cursor: pointer; border: 1px solid rgba(255,255,255,0.06); transition: background var(--transition), border-color var(--transition), transform var(--transition); position: relative; z-index: 1; margin: 3px 0; user-select: none; } .step:hover { background: var(--step-hover); border-color: rgba(255,255,255,0.12); transform: translateX(2px); } .step.active { border-color: var(--step-accent); background: var(--step-bg); box-shadow: 0 0 0 1px var(--step-accent), inset 0 0 20px rgba(0,0,0,0.2); transform: translateX(3px); } .step-number { width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; font-family: var(--mono); flex-shrink: 0; border: 2px solid; transition: all var(--transition); } .step-icon { font-size: 20px; flex-shrink: 0; width: 28px; text-align: center; filter: grayscale(0.2); transition: filter var(--transition), transform var(--transition); } .step:hover .step-icon, .step.active .step-icon { filter: none; transform: scale(1.1); } .step-content { flex: 1; min-width: 0; } .step-title { font-size: 14px; font-weight: 600; color: var(--text-primary); margin-bottom: 2px; } .step-desc { font-size: 12px; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .step-chevron { color: var(--text-muted); font-size: 14px; flex-shrink: 0; transition: transform var(--transition), color var(--transition); } .step.active .step-chevron { transform: rotate(180deg); color: var(--step-accent); } /* Phase colors applied via inline style var */ .phase-block.setup .step { --step-accent: var(--accent-setup); } .phase-block.execution .step { --step-accent: var(--accent-execution); } .phase-block.evaluation .step { --step-accent: var(--accent-evaluation); } .phase-block.setup .step-number { color: var(--accent-setup); border-color: var(--accent-setup); } .phase-block.execution .step-number { color: var(--accent-execution); border-color: var(--accent-execution); } .phase-block.evaluation .step-number { color: var(--accent-evaluation); border-color: var(--accent-evaluation); } .step.active .step-number { background: var(--step-accent); color: #000; } /* ──────────── DETAIL PANEL ──────────── */ .detail-panel { overflow: hidden; max-height: 0; opacity: 0; transition: max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.25s ease, margin 0.25s ease; margin: 0 4px; } .detail-panel.open { max-height: 320px; opacity: 1; margin: 0 4px 4px; } .detail-inner { background: rgba(0,0,0,0.35); border-radius: 8px; padding: 16px 18px; border-left: 3px solid var(--step-accent); font-size: 13px; color: var(--text-secondary); } .detail-inner .code-block { font-family: var(--mono); font-size: 12px; background: rgba(0,0,0,0.4); border-radius: 6px; padding: 10px 14px; margin-top: 10px; color: #7dd3fc; overflow-x: auto; white-space: pre; line-height: 1.7; border: 1px solid rgba(255,255,255,0.06); } .detail-inner .code-block .kw { color: #c084fc; } .detail-inner .code-block .fn { color: #38bdf8; } .detail-inner .code-block .str { color: #86efac; } .detail-inner .code-block .cm { color: #64748b; } /* ──────────── CONNECTOR ARROW ──────────── */ .phase-connector { display: flex; align-items: center; justify-content: center; height: 28px; color: var(--text-muted); font-size: 18px; opacity: 0.5; position: relative; } .phase-connector::before, .phase-connector::after { content: ''; position: absolute; left: 50%; width: 1px; background: linear-gradient(to bottom, transparent, var(--connector), transparent); } .phase-connector::before { top: 0; height: 10px; } .phase-connector::after { bottom: 0; height: 10px; } /* ──────────── FOOTER NOTE ──────────── */ .footer-note { max-width: 780px; margin: 32px auto 0; padding: 0 16px; } .footer-card { background: var(--bg-card); border: 1px solid rgba(255,255,255,0.08); border-radius: 12px; padding: 18px 22px; display: flex; align-items: flex-start; gap: 14px; } .footer-icon { font-size: 22px; flex-shrink: 0; margin-top: 1px; } .footer-text { font-size: 13px; color: var(--text-secondary); } .footer-text strong { color: var(--text-primary); font-family: var(--mono); } /* ──────────── STATS BAR ──────────── */ .stats-bar { max-width: 780px; margin: 24px auto 0; padding: 0 16px; display: flex; gap: 10px; flex-wrap: wrap; } .stat-pill { flex: 1; min-width: 120px; background: var(--bg-card); border: 1px solid rgba(255,255,255,0.07); border-radius: var(--radius); padding: 12px 16px; text-align: center; } .stat-value { font-size: 22px; font-weight: 700; font-family: var(--mono); margin-bottom: 2px; } .stat-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-muted); } .stat-pill:nth-child(1) .stat-value { color: var(--accent-setup); } .stat-pill:nth-child(2) .stat-value { color: var(--accent-execution); } .stat-pill:nth-child(3) .stat-value { color: var(--accent-evaluation); } .stat-pill:nth-child(4) .stat-value { color: #f59e0b; } /* ──────────── RESPONSIVE ──────────── */ @media (max-width: 500px) { .step { padding: 14px; gap: 12px; } .step-desc { display: none; } .detail-inner .code-block { font-size: 11px; } } /* ═══════════════════════════════════════════════ VERSUCHSAUFBAU — Experiment Design Section Orange/Amber accent, wider max-width ═══════════════════════════════════════════════ */ .versuch-section { max-width: 960px; margin: 36px auto 0; padding: 0 16px; } .versuch-section-title { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; } .versuch-section-title .section-badge { font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-exp); background: var(--accent-exp-dim); border: 1px solid var(--accent-exp-border); border-radius: 999px; padding: 3px 12px; } .versuch-section-title h2 { font-size: clamp(18px, 3vw, 24px); font-weight: 700; color: var(--text-primary); letter-spacing: -0.01em; } /* ── Overview Card ── */ .exp-overview { background: var(--bg-card); border: 1px solid var(--accent-exp-border); border-radius: 16px; padding: 24px 28px; margin-bottom: 24px; position: relative; overflow: hidden; } .exp-overview::before { content: ''; position: absolute; inset: 0; background: radial-gradient(ellipse 70% 60% at 100% 0%, rgba(245,158,11,0.05) 0%, transparent 60%); pointer-events: none; } .exp-overview-header { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; } .exp-id-badge { font-family: var(--mono); font-size: 13px; font-weight: 700; color: #000; background: var(--accent-exp); border-radius: 6px; padding: 4px 10px; letter-spacing: 0.04em; flex-shrink: 0; } .exp-overview-header h3 { font-size: 16px; font-weight: 600; color: var(--text-primary); } .exp-hypothesis { background: rgba(0,0,0,0.3); border-left: 3px solid var(--accent-exp); border-radius: 0 8px 8px 0; padding: 14px 18px; font-size: 14px; color: var(--text-secondary); margin-bottom: 20px; font-style: italic; line-height: 1.65; } .exp-hypothesis strong { color: var(--accent-exp); font-style: normal; } .exp-meta-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; } .exp-meta-item { background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06); border-radius: 8px; padding: 12px 14px; } .exp-meta-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-muted); margin-bottom: 4px; } .exp-meta-value { font-size: 15px; font-weight: 600; font-family: var(--mono); color: var(--accent-exp); } .exp-meta-value.neutral { color: var(--text-primary); font-size: 13px; } /* ── A/B Design Cards ── */ .ab-section { margin-bottom: 24px; } .ab-section-heading { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent-exp); margin-bottom: 14px; } .ab-layout { display: grid; grid-template-columns: 1fr auto 1fr; gap: 16px; align-items: center; } .agent-card { background: var(--bg-card); border-radius: 14px; padding: 20px; border: 1px solid rgba(255,255,255,0.07); position: relative; } .agent-card.baseline { border-color: rgba(148, 163, 184, 0.2); } .agent-card.injected { border-color: rgba(16, 185, 129, 0.3); background: rgba(16, 185, 129, 0.04); } .agent-card-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 14px; display: flex; align-items: center; gap: 8px; } .agent-card.baseline .agent-card-label { color: var(--accent-baseline); } .agent-card.injected .agent-card-label { color: var(--accent-injected); } .agent-card-label .label-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; } .agent-card.baseline .label-dot { background: var(--accent-baseline); } .agent-card.injected .label-dot { background: var(--accent-injected); box-shadow: 0 0 6px var(--accent-injected); } .agent-field { margin-bottom: 10px; } .agent-field-key { font-size: 10px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 3px; font-family: var(--mono); } .agent-field-val { font-size: 12px; color: var(--text-secondary); font-family: var(--mono); background: rgba(0,0,0,0.25); border-radius: 6px; padding: 7px 10px; border: 1px solid rgba(255,255,255,0.05); } .agent-field-val.none-val { color: var(--text-muted); font-style: italic; } .agent-field-val.injection-val { color: #86efac; border-color: rgba(16,185,129,0.2); background: rgba(16,185,129,0.06); } .vs-badge { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; background: rgba(245,158,11,0.12); border: 2px solid var(--accent-exp-border); border-radius: 50%; font-size: 13px; font-weight: 800; color: var(--accent-exp); font-family: var(--mono); flex-shrink: 0; } .ab-footer { text-align: center; margin-top: 12px; font-size: 12px; color: var(--text-muted); } .ab-footer .highlight { color: var(--accent-exp); font-weight: 600; } /* ── Scenario Cards 2x2 ── */ .scenarios-section { margin-bottom: 24px; } .scenarios-heading { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent-exp); margin-bottom: 14px; } .scenarios-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; } .scenario-card { background: var(--bg-card); border: 1px solid rgba(255,255,255,0.07); border-radius: 14px; padding: 18px; cursor: pointer; transition: border-color var(--transition), background var(--transition), transform var(--transition); user-select: none; } .scenario-card:hover { border-color: var(--accent-exp-border); background: rgba(245,158,11,0.03); transform: translateY(-1px); } .scenario-card.open { border-color: var(--accent-exp-border); background: rgba(245,158,11,0.04); } .scenario-header { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 10px; } .scenario-id { font-family: var(--mono); font-size: 11px; font-weight: 700; color: #000; background: var(--accent-exp); border-radius: 5px; padding: 2px 8px; flex-shrink: 0; margin-top: 1px; } .scenario-title-block { flex: 1; } .scenario-title { font-size: 14px; font-weight: 600; color: var(--text-primary); margin-bottom: 3px; } .scenario-task-name { font-family: var(--mono); font-size: 11px; color: var(--text-muted); } .scenario-chevron { color: var(--text-muted); font-size: 12px; flex-shrink: 0; transition: transform var(--transition), color var(--transition); margin-top: 2px; } .scenario-card.open .scenario-chevron { transform: rotate(180deg); color: var(--accent-exp); } .scenario-bug { font-size: 12px; color: var(--text-secondary); margin-bottom: 0; line-height: 1.55; } .scenario-injection-panel { overflow: hidden; max-height: 0; opacity: 0; transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s ease, margin 0.2s ease; margin-top: 0; } .scenario-injection-panel.open { max-height: 120px; opacity: 1; margin-top: 12px; } .injection-box { background: rgba(16,185,129,0.07); border: 1px solid rgba(16,185,129,0.22); border-radius: 7px; padding: 10px 13px; font-size: 12px; color: #86efac; font-style: italic; line-height: 1.55; } .injection-box-label { font-size: 9px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--accent-injected); font-style: normal; font-weight: 700; margin-bottom: 5px; opacity: 0.8; } /* ── Flow Diagram ── */ .flow-section { margin-bottom: 0; } .flow-heading { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--accent-exp); margin-bottom: 14px; } .flow-diagram { background: var(--bg-card); border: 1px solid rgba(255,255,255,0.07); border-radius: 14px; padding: 22px 24px; font-family: var(--mono); font-size: 12px; color: var(--text-secondary); line-height: 1.9; overflow-x: auto; } .flow-node { display: inline-block; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.09); border-radius: 6px; padding: 2px 10px; color: var(--text-primary); font-size: 12px; } .flow-node.exp-start { background: var(--accent-exp-dim); border-color: var(--accent-exp-border); color: var(--accent-exp); font-weight: 700; } .flow-node.compare { background: rgba(59,130,246,0.1); border-color: rgba(59,130,246,0.25); color: #7dd3fc; } .flow-node.verdict { background: rgba(168,85,247,0.1); border-color: rgba(168,85,247,0.25); color: #c084fc; } .flow-node.baseline-node { background: rgba(148,163,184,0.08); border-color: rgba(148,163,184,0.2); color: var(--accent-baseline); } .flow-node.inject-node { background: rgba(16,185,129,0.08); border-color: rgba(16,185,129,0.22); color: var(--accent-injected); } .flow-arrow { color: var(--text-muted); margin: 0 2px; } .flow-indent { padding-left: 24px; } .flow-indent-2 { padding-left: 44px; } .flow-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-height: 1.9em; } .flow-branch-label { color: var(--text-muted); font-size: 11px; } /* ── Pipeline Divider ── */ .pipeline-divider { max-width: 960px; margin: 40px auto 0; padding: 0 16px; } .divider-inner { display: flex; align-items: center; gap: 16px; } .divider-line { flex: 1; height: 1px; background: linear-gradient(to right, transparent, rgba(245,158,11,0.3), rgba(255,255,255,0.08), transparent); } .divider-label { font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); white-space: nowrap; flex-shrink: 0; } /* ── Responsive for versuch section ── */ @media (max-width: 680px) { .ab-layout { grid-template-columns: 1fr; } .vs-badge { margin: 0 auto; transform: rotate(90deg); } .scenarios-grid { grid-template-columns: 1fr; } } @media (max-width: 500px) { .exp-overview { padding: 18px; } .flow-diagram { font-size: 11px; padding: 16px; } } </style> </head> <body> <div class="header"> <div class="header-badge"> <span class="dot"></span> AgentArena · Benchmark Engine </div> <h1><span>AgentArena</span> — E8 Experiment + Run Pipeline</h1> <p class="subtitle">Versuchsaufbau, A/B-Design und die 11-Schritte-Pipeline eines einzelnen Runs.</p> </div> <!-- ═══════════════════════════════════════════ VERSUCHSAUFBAU ═══════════════════════════════════════════ --> <div class="versuch-section"> <div class="versuch-section-title"> <span class="section-badge">Versuchsaufbau</span> <h2>E8 — Domain Knowledge Experiment</h2> </div> <!-- 1. Overview Card --> <div class="exp-overview"> <div class="exp-overview-header"> <div class="exp-id-badge">E8</div> <h3>Domain Knowledge — Baseline vs Injection</h3> </div> <div class="exp-hypothesis"> <strong>Hypothese:</strong> Domain-Knowledge-Injection (ein Satz Projektkontext via Sidecar-NG) ermöglicht Agents, projektspezifische Bugs zu lösen, die sie ohne Kontext nicht lösen können. </div> <div class="exp-meta-grid"> <div class="exp-meta-item"> <div class="exp-meta-label">Design</div> <div class="exp-meta-value">4 × 2 × 3</div> </div> <div class="exp-meta-item"> <div class="exp-meta-label">Szenarien</div> <div class="exp-meta-value">4</div> </div> <div class="exp-meta-item"> <div class="exp-meta-label">Agents</div> <div class="exp-meta-value">2</div> </div> <div class="exp-meta-item"> <div class="exp-meta-label">Runs gesamt</div> <div class="exp-meta-value">24</div> </div> <div class="exp-meta-item"> <div class="exp-meta-label">Est. Cost</div> <div class="exp-meta-value">~$1.50</div> </div> <div class="exp-meta-item"> <div class="exp-meta-label">Model</div> <div class="exp-meta-value neutral">claude-sonnet-4-6</div> </div> </div> </div> <!-- 2. A/B Design --> <div class="ab-section"> <div class="ab-section-heading">A/B Design — Der einzige Unterschied</div> <div class="ab-layout"> <!-- Baseline --> <div class="agent-card baseline"> <div class="agent-card-label"> <span class="label-dot"></span> Baseline Agent </div> <div class="agent-field"> <div class="agent-field-key">CLAUDE.md</div> <div class="agent-field-val">Use tools to solve tasks. Be concise.</div> </div> <div class="agent-field"> <div class="agent-field-key">additional_context</div> <div class="agent-field-val none-val">none</div> </div> </div> <div class="vs-badge">VS</div> <!-- Injected --> <div class="agent-card injected"> <div class="agent-card-label"> <span class="label-dot"></span> Injected Agent </div> <div class="agent-field"> <div class="agent-field-key">CLAUDE.md</div> <div class="agent-field-val">Use tools to solve tasks. Be concise.</div> </div> <div class="agent-field"> <div class="agent-field-key">additional_context</div> <div class="agent-field-val injection-val">Ein Satz Domain-Wissen (szenario-spezifisch)</div> </div> </div> </div> <div class="ab-footer"> Der <span class="highlight">einzige Unterschied</span>: ein Satz Projektkontext in <code style="color:#86efac;font-family:var(--mono);font-size:11px">additional_context</code> </div> </div> <!-- 3. Scenarios Grid --> <div class="scenarios-section"> <div class="scenarios-heading">Die 4 Szenarien</div> <div class="scenarios-grid"> <!-- E8a --> <div class="scenario-card" onclick="toggleScenario(this, 'inj-a')"> <div class="scenario-header"> <div class="scenario-id">E8a</div> <div class="scenario-title-block"> <div class="scenario-title">Enum Convention</div> <div class="scenario-task-name">enum-convention-bug</div> </div> <div class="scenario-chevron">▼</div> </div> <div class="scenario-bug"> Agent verwendet lowercase Enum-Werte, aber das Projekt verlangt UPPERCASE. </div> <div class="scenario-injection-panel" id="inj-a"> <div class="injection-box"> <div class="injection-box-label">Injection</div> "In diesem Projekt verwenden alle Enums UPPERCASE Werte (z.B. 'ACTIVE', 'INACTIVE')." </div> </div> </div> <!-- E8b --> <div class="scenario-card" onclick="toggleScenario(this, 'inj-b')"> <div class="scenario-header"> <div class="scenario-id">E8b</div> <div class="scenario-title-block"> <div class="scenario-title">Timeout Units</div> <div class="scenario-task-name">timeout-unit-bug</div> </div> <div class="scenario-chevron">▼</div> </div> <div class="scenario-bug"> Agent übergibt Sekunden für Timeout, aber die API verwendet Millisekunden. </div> <div class="scenario-injection-panel" id="inj-b"> <div class="injection-box"> <div class="injection-box-label">Injection</div> "Die API-Client-Klasse verwendet Millisekunden für alle Timeout-Werte (timeout_ms), nicht Sekunden." </div> </div> </div> <!-- E8c --> <div class="scenario-card" onclick="toggleScenario(this, 'inj-c')"> <div class="scenario-header"> <div class="scenario-id">E8c</div> <div class="scenario-title-block"> <div class="scenario-title">Breaking Change</div> <div class="scenario-task-name">breaking-change-bug</div> </div> <div class="scenario-chevron">▼</div> </div> <div class="scenario-bug"> Agent ruft <code style="color:#7dd3fc;font-size:11px">find_one()</code> auf, das in V2 zu <code style="color:#7dd3fc;font-size:11px">get_by_id()</code> umbenannt wurde. </div> <div class="scenario-injection-panel" id="inj-c"> <div class="injection-box"> <div class="injection-box-label">Injection</div> "database.py wurde auf V2 migriert: find_one() heißt jetzt get_by_id()." </div> </div> </div> <!-- E8d --> <div class="scenario-card" onclick="toggleScenario(this, 'inj-d')"> <div class="scenario-header"> <div class="scenario-id">E8d</div> <div class="scenario-title-block"> <div class="scenario-title">Implicit Null</div> <div class="scenario-task-name">implicit-null-bug</div> </div> <div class="scenario-chevron">▼</div> </div> <div class="scenario-bug"> Agent übergibt <code style="color:#7dd3fc;font-size:11px">None</code> für email, aber die DB hat einen NOT NULL Constraint. </div> <div class="scenario-injection-panel" id="inj-d"> <div class="injection-box"> <div class="injection-box-label">Injection</div> "Das DB-Schema (schema.sql) hat NOT NULL Constraints auf email." </div> </div> </div> </div> </div> <!-- 4. Flow Diagram --> <div class="flow-section"> <div class="flow-heading">Ablauf des Experiments</div> <div class="flow-diagram"> <div class="flow-row"> <span class="flow-node exp-start">Experiment Start</span> </div> <div class="flow-row flow-indent"> <span class="flow-arrow">↓</span> </div> <div class="flow-row"> <span style="color:var(--text-muted)">For each Scenario (</span> <span class="flow-node">E8a</span> <span class="flow-arrow">→</span> <span class="flow-node">E8b</span> <span class="flow-arrow">→</span> <span class="flow-node">E8c</span> <span class="flow-arrow">→</span> <span class="flow-node">E8d</span> <span style="color:var(--text-muted)">):</span> </div> <div class="flow-row flow-indent"> <span style="color:var(--text-muted)">├──</span> <span class="flow-node baseline-node">Baseline Agent</span> <span style="color:var(--text-muted)">× 3 Runs (pass@3)</span> <span class="flow-arrow">──→</span> <span style="color:var(--text-muted)">[Run Pipeline × 3]</span> </div> <div class="flow-row flow-indent"> <span style="color:var(--text-muted)">└──</span> <span class="flow-node inject-node">Injected Agent</span> <span style="color:var(--text-muted)">× 3 Runs (pass@3)</span> <span class="flow-arrow">──→</span> <span style="color:var(--text-muted)">[Run Pipeline × 3]</span> </div> <div class="flow-row flow-indent"> <span class="flow-arrow">↓</span> </div> <div class="flow-row"> <span class="flow-node compare">Compare: baseline pass@3 vs injected pass@3</span> </div> <div class="flow-row flow-indent"> <span class="flow-arrow">↓</span> </div> <div class="flow-row"> <span class="flow-node verdict">Verdict: Injection wirkt?</span> <span style="color:var(--text-muted);font-size:11px">&nbsp;(0→3 = stark&nbsp;·&nbsp;3→3 = Task zu einfach)</span> </div> </div> </div> </div> <!-- ═══════════════════════════════════════════ DIVIDER — Pipeline follows ═══════════════════════════════════════════ --> <div class="pipeline-divider"> <div class="divider-inner"> <div class="divider-line"></div> <div class="divider-label">Jeder einzelne Run durchläuft diese Pipeline</div> <div class="divider-line"></div> </div> </div> <!-- ═══════════════════════════════════════════ EXISTING PIPELINE SECTION (unchanged) ═══════════════════════════════════════════ --> <div class="stats-bar"> <div class="stat-pill"> <div class="stat-value">3</div> <div class="stat-label">Phasen</div> </div> <div class="stat-pill"> <div class="stat-value">11</div> <div class="stat-label">Schritte</div> </div> <div class="stat-pill"> <div class="stat-value">2</div> <div class="stat-label">Sandboxes</div> </div> <div class="stat-pill"> <div class="stat-value">k×</div> <div class="stat-label">pass@k parallel</div> </div> </div> <div class="legend"> <div class="legend-item setup"> <div class="legend-dot"></div> Setup — Schritte 1–3 </div> <div class="legend-item exec"> <div class="legend-dot"></div> Execution — Schritte 4–6 </div> <div class="legend-item eval"> <div class="legend-dot"></div> Evaluation — Schritte 7–11 </div> </div> <div class="pipeline-wrapper" id="pipeline"> <!-- ───── PHASE: SETUP ───── --> <div class="phase-block setup"> <div class="phase-label">Phase 1 · Setup</div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 1)"> <div class="step-number">01</div> <div class="step-icon">🗄️</div> <div class="step-content"> <div class="step-title">DB-Eintrag erstellen</div> <div class="step-desc">Run-Record mit Status "running" in SQLite anlegen</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-1"> <div class="detail-inner"> Run-Record wird sofort angelegt, bevor irgendeine Sandbox existiert. Status <code style="color:#86efac">running</code> blockiert parallele Runs auf demselben Task/Agent-Paar. <div class="code-block"><span class="fn">Run</span>(<span class="str">task_id</span>=task.id, <span class="str">agent_id</span>=agent.id, <span class="str">status</span>=<span class="str">"running"</span>, <span class="str">created_at</span>=<span class="fn">now</span>()) <span class="cm"># → run.id für alle weiteren DB-Updates</span></div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 2)"> <div class="step-number">02</div> <div class="step-icon">📦</div> <div class="step-content"> <div class="step-title">Sandbox erstellen</div> <div class="step-desc">Docker-Container mit dem Task-Repo geklont</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-2"> <div class="detail-inner"> Jeder Run bekommt einen isolierten Docker-Container. Das Task-Repo wird auf den spezifizierten Ref geklont. Der Agent sieht exakt den Zustand, den der Task definiert. <div class="code-block"><span class="fn">Sandbox</span>.<span class="fn">create</span>(task) <span class="cm">↳</span> docker run --rm -it --network=none &lt;image&gt; <span class="cm">↳</span> git clone &lt;repo_url&gt; --branch &lt;ref&gt; /workspace</div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 3)"> <div class="step-number">03</div> <div class="step-icon">🔌</div> <div class="step-content"> <div class="step-title">Adapter holen</div> <div class="step-desc">claude_code Adapter mit Model + CLAUDE.md + optional additional_context</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-3"> <div class="detail-inner"> Der Adapter abstrahiert das Modell. Jede Konfiguration (Modell, Prompt-Mode, CLAUDE.md, Injections) steckt im Adapter — der Runner ist modell-agnostisch. <div class="code-block"><span class="fn">get_adapter</span>(<span class="str">"claude_code"</span>, config) <span class="cm">→</span> Adapter( model=<span class="str">"claude-sonnet-4-5"</span>, prompt_mode=<span class="str">"architect"</span>, claude_md=<span class="str">"/path/CLAUDE.md"</span>, additional_context=<span class="kw">Optional</span>[str] )</div> </div> </div> </div> </div> <!-- CONNECTOR --> <div class="phase-connector">↓</div> <!-- ───── PHASE: EXECUTION ───── --> <div class="phase-block execution"> <div class="phase-label">Phase 2 · Execution</div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 4)"> <div class="step-number">04</div> <div class="step-icon">🤖</div> <div class="step-content"> <div class="step-title">Agent laufen lassen</div> <div class="step-desc">Claude Sonnet bekommt den Task-Prompt und arbeitet in der Sandbox</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-4"> <div class="detail-inner"> Der kritischste Schritt. Der Agent kann Dateien lesen, editieren, Tests ausführen. Die Trajectory (alle Tool-Calls + Outputs) wird vollständig aufgezeichnet. <div class="code-block"><span class="fn">adapter</span>.<span class="fn">run</span>(ctx, sandbox) <span class="cm">→</span> RunResult( diff_text=<span class="str">"..."</span>, <span class="cm"># was wurde geändert</span> tokens=<span class="str">12450</span>, <span class="cm"># input + output</span> cost_usd=<span class="str">0.043</span>, <span class="cm"># API-Kosten</span> trajectory=[...] <span class="cm"># Tool-Calls + Outputs</span> )</div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 5)"> <div class="step-number">05</div> <div class="step-icon">📋</div> <div class="step-content"> <div class="step-title">Diff einsammeln</div> <div class="step-desc">Was hat der Agent geändert?</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-5"> <div class="detail-inner"> Der Diff ist das einzige, was vom Agent-Container in die Judge-Phase übertragen wird. Kein shared state, kein shared filesystem — nur der Patch. <div class="code-block">sandbox.<span class="fn">get_diff</span>() <span class="cm"># oder</span> adapter_result.diff_text <span class="cm">→</span> <span class="str">"""diff --git a/solution.py b/solution.py @@ -12,3 +12,8 @@ def solve(): + result = compute(data) + return result """</span></div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 6)"> <div class="step-number">06</div> <div class="step-icon">🗑️</div> <div class="step-content"> <div class="step-title">Agent-Container zerstören</div> <div class="step-desc">Isolation: Judge darf nicht im selben Container laufen</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-6"> <div class="detail-inner"> Sicherheits- und Integritäts-kritisch: Der Judge muss auf einem sauberen Zustand evaluieren, nicht auf dem möglicherweise beschädigten Workspace des Agents. <div class="code-block">sandbox.<span class="fn">destroy</span>() <span class="cm"># docker rm -f &lt;container_id&gt;</span> <span class="cm">⚠ Critical: judge must evaluate on clean state,</span> <span class="cm"> not agent's messy workspace</span></div> </div> </div> </div> </div> <!-- CONNECTOR --> <div class="phase-connector">↓</div> <!-- ───── PHASE: EVALUATION ───── --> <div class="phase-block evaluation"> <div class="phase-label">Phase 3 · Evaluation</div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 7)"> <div class="step-number">07</div> <div class="step-icon">🧪</div> <div class="step-content"> <div class="step-title">Judge-Sandbox erstellen</div> <div class="step-desc">Frischer Clone + Patch anwenden</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-7"> <div class="detail-inner"> Neuer Container, frischer Clone. Nur der Diff des Agents wird per <code style="color:#86efac">git apply</code> eingespielt. Der Judge sieht exakt dasselbe, was ein Human Code Reviewer sehen würde. <div class="code-block"><span class="fn">Sandbox</span>.<span class="fn">create_judge_sandbox</span>(task, diff_text) <span class="cm">↳</span> docker run --rm -it &lt;image&gt; <span class="cm">↳</span> git clone &lt;repo_url&gt; --branch &lt;ref&gt; /workspace <span class="cm">↳</span> git apply &lt;&lt;&lt; <span class="str">"$diff_text"</span></div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 8)"> <div class="step-number">08</div> <div class="step-icon">⚖️</div> <div class="step-content"> <div class="step-title">Judge bewerten</div> <div class="step-desc">success_cmd ausführen (typisch: pytest), plus Lint, Regression, Complexity</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-8"> <div class="detail-inner"> Der Judge ist multi-dimensional: funktionale Korrektheit ist primär, aber Lint-Delta, Regressions und Complexity gehen in den Composite Score ein. <div class="code-block">judge.<span class="fn">judge_run</span>(sandbox, success_cmd) <span class="cm">→</span> JudgeResult( tests_passed=<span class="str">8</span>, tests_total=<span class="str">10</span>, regressions=[...], <span class="cm"># vorher grüne Tests die jetzt rot sind</span> lint_delta=<span class="str">-2</span>, <span class="cm"># verbessert (-) oder verschlechtert (+)</span> complexity_delta=<span class="str">+1</span>, <span class="cm"># zyklomatische Komplexität</span> )</div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 9)"> <div class="step-number">09</div> <div class="step-icon">📊</div> <div class="step-content"> <div class="step-title">Metrics berechnen</div> <div class="step-desc">Composite Score aus functionality + trajectory + efficiency + diff</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-9"> <div class="detail-inner"> Der Composite Score verdichtet mehrere Dimensionen in einen vergleichbaren Score [0.0–1.0]. Funktionale Korrektheit dominiert; Effizienz und Direktheit differenzieren bei Gleichstand. <div class="code-block"><span class="fn">compute_composite_score</span>() <span class="cm">Weights:</span> functionality <span class="str">0.45</span> <span class="cm"># tests_passed / tests_total</span> directness <span class="str">0.15</span> <span class="cm"># kein Overshooting, sauberer Diff</span> efficiency <span class="str">0.15</span> <span class="cm"># cost_usd normalisiert</span> self_correction <span class="str">0.10</span> <span class="cm"># Retry-Loops im Trajectory</span> churn <span class="str">0.10</span> <span class="cm"># revert-and-redo Patterns</span> loops <span class="str">0.05</span> <span class="cm"># zyklische Tool-Calls</span></div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 10)"> <div class="step-number">10</div> <div class="step-icon">💾</div> <div class="step-content"> <div class="step-title">DB updaten</div> <div class="step-desc">Alles speichern: Status, Tokens, Score, Trajectory</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-10"> <div class="detail-inner"> Atomarer Write: alle Felder in einem Update. Falls dieser Schritt schreitert, bleibt der Run auf <code style="color:#fbbf24">status=error</code> — kein Partial-Write. <div class="code-block">run.<span class="fn">update</span>( status=<span class="str">"completed"</span>, duration_s=<span class="str">47.3</span>, tokens=<span class="str">12450</span>, cost_usd=<span class="str">0.043</span>, tests_passed=<span class="str">8</span>, tests_total=<span class="str">10</span>, tool_calls=<span class="str">23</span>, diff_text=<span class="str">"..."</span>, trajectory=<span class="str">[...]</span>, judge_score=<span class="str">0.84</span>, metrics_json=<span class="str">{...}</span> )</div> </div> </div> </div> <div class="step-wrapper"> <div class="step" onclick="toggle(this, 11)"> <div class="step-number">11</div> <div class="step-icon">🧹</div> <div class="step-content"> <div class="step-title">Aufräumen</div> <div class="step-desc">Judge-Container zerstören — immer, auch bei Fehler</div> </div> <div class="step-chevron">▼</div> </div> <div class="detail-panel" id="detail-11"> <div class="detail-inner"> Der Cleanup läuft im <code style="color:#c084fc">finally</code>-Block — er wird garantiert ausgeführt, egal ob die Pipeline erfolgreich war oder mit Exception abgebrochen hat. Kein Container-Leak auch bei Crashes. <div class="code-block"><span class="kw">finally</span>: judge_sandbox.<span class="fn">destroy</span>() <span class="cm"># docker rm -f &lt;judge_container_id&gt;</span> <span class="cm"># Always runs — no container leak on error</span></div> </div> </div> </div> </div> </div> <!-- FOOTER NOTE --> <div class="footer-note"> <div class="footer-card"> <div class="footer-icon">⚡</div> <div class="footer-text"> <strong>pass@k</strong>: Diese Pipeline läuft <strong>k-mal parallel</strong> (<strong>asyncio.gather</strong>) pro Agent — jeder Run bekommt seine eigene isolierte Sandbox. k=1 für Determinismus-Tests, k=5–10 für statistische Robustheit. Der pass@k-Score gibt an, wie oft der Agent in k Versuchen mindestens einmal erfolgreich ist. </div> </div> </div> <script> const activeSteps = {}; function toggle(stepEl, id) { const panel = document.getElementById('detail-' + id); const isOpen = panel.classList.contains('open'); if (isOpen) { panel.classList.remove('open'); stepEl.classList.remove('active'); delete activeSteps[id]; } else { panel.classList.add('open'); stepEl.classList.add('active'); activeSteps[id] = true; } } function toggleScenario(cardEl, panelId) { const panel = document.getElementById(panelId); const isOpen = panel.classList.contains('open'); if (isOpen) { panel.classList.remove('open'); cardEl.classList.remove('open'); } else { panel.classList.add('open'); cardEl.classList.add('open'); } } // Keyboard: click focused step with Enter/Space document.querySelectorAll('.step').forEach((step, i) => { step.setAttribute('tabindex', '0'); step.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); step.click(); } }); }); // Keyboard for scenario cards document.querySelectorAll('.scenario-card').forEach((card) => { card.setAttribute('tabindex', '0'); card.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); card.click(); } }); }); </script> </body> </html>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AgentArena — E8 Experiment + Run Pipeline</title>
<style>
:root {
--bg-primary: #0d0d1a;
--bg-secondary: #1a1a2e;
--bg-card: #16213e;
--bg-setup: rgba(59, 130, 246, 0.06);
--bg-execution: rgba(16, 185, 129, 0.06);
--bg-evaluation: rgba(168, 85, 247, 0.06);
--border-setup: rgba(59, 130, 246, 0.25);
--border-execution: rgba(16, 185, 129, 0.25);
--border-evaluation: rgba(168, 85, 247, 0.25);
--accent-setup: #3b82f6;
--accent-execution: #10b981;
--accent-evaluation: #a855f7;
--accent-exp: #f59e0b;
--accent-exp-dim: rgba(245, 158, 11, 0.12);
--accent-exp-border: rgba(245, 158, 11, 0.28);
--accent-baseline: #94a3b8;
--accent-injected: #10b981;
--text-primary: #e2e8f0;
--text-secondary: #94a3b8;
--text-muted: #64748b;
--connector: #334155;
--step-bg: #1e293b;
--step-hover: #243452;
--step-active: #1e3a5f;
--mono: 'Fira Code', 'Cascadia Code', 'Consolas', monospace;
--sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
--radius: 10px;
--transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: var(--bg-primary);
color: var(--text-primary);
font-family: var(--sans);
min-height: 100vh;
line-height: 1.6;
padding: 0 0 80px;
}
/* ──────────── HEADER ──────────── */
.header {
background: linear-gradient(135deg, #0d0d1a 0%, #16213e 50%, #0d0d1a 100%);
border-bottom: 1px solid rgba(255,255,255,0.06);
padding: 48px 24px 40px;
text-align: center;
position: relative;
overflow: hidden;
}
.header::before {
content: '';
position: absolute;
inset: 0;
background:
radial-gradient(ellipse 60% 40% at 20% 50%, rgba(59,130,246,0.07) 0%, transparent 70%),
radial-gradient(ellipse 60% 40% at 80% 50%, rgba(168,85,247,0.07) 0%, transparent 70%);
pointer-events: none;
}
.header-badge {
display: inline-flex;
align-items: center;
gap: 8px;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 999px;
padding: 4px 14px;
font-size: 11px;
font-family: var(--mono);
color: var(--text-muted);
letter-spacing: 0.08em;
text-transform: uppercase;
margin-bottom: 20px;
}
.header-badge .dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #10b981;
box-shadow: 0 0 8px #10b981;
animation: pulse 2s ease infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }