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>