eaglelandsonce's picture
Update index.html
68e5a86 verified
Raw
History Blame Contribute Delete
53.2 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AI Research Multi-Agent System</title>
<style>
:root {
--bg: #07090f;
--panel: #0d1119;
--panel-2: #111722;
--line: #263044;
--line-soft: #192130;
--ink: #eef4ff;
--muted: #8996aa;
--blue: #4f9cff;
--cyan: #2de2e6;
--green: #4ade80;
--amber: #fbbf24;
--violet: #a78bfa;
--rose: #fb7185;
--sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
}
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; background: var(--bg); color: var(--ink); font-family: var(--sans); }
body { min-height: 100vh; overflow: hidden; }
button, input, select { font: inherit; }
button { color: inherit; }
.app { height: 100vh; min-height: 680px; display: grid; grid-template-rows: 64px minmax(0, 1fr) 96px; }
.topbar {
display: grid; grid-template-columns: minmax(280px, 1fr) auto minmax(210px, 1fr);
align-items: center; gap: 24px; padding: 0 20px;
background: #0a0d14; border-bottom: 1px solid var(--line);
box-shadow: 0 8px 28px rgba(0,0,0,.25); z-index: 4;
}
.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.brand-mark { width: 36px; height: 36px; position: relative; display: grid; place-items: center; color: var(--cyan); }
.brand-mark::before, .brand-mark::after { content: ""; position: absolute; border: 1px solid currentColor; transform: rotate(45deg); }
.brand-mark::before { width: 27px; height: 27px; opacity: .65; }
.brand-mark::after { width: 16px; height: 16px; animation: markPulse 2.4s ease-in-out infinite; }
.brand-core { width: 5px; height: 5px; background: currentColor; box-shadow: 0 0 14px currentColor; }
@keyframes markPulse { 50% { transform: rotate(135deg) scale(.72); opacity: .35; } }
.brand-copy { min-width: 0; }
.eyebrow { color: var(--cyan); font: 700 9px/1 var(--mono); letter-spacing: 1.8px; text-transform: uppercase; }
h1 { font-size: 16px; line-height: 1.2; margin: 5px 0 0; letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.header-metrics { display: flex; align-items: stretch; height: 42px; }
.header-metric { min-width: 86px; padding: 3px 14px; text-align: center; border-left: 1px solid var(--line-soft); }
.header-metric:last-child { border-right: 1px solid var(--line-soft); }
.metric-value { color: var(--ink); font: 700 17px/1.2 var(--mono); }
.metric-value.cyan { color: var(--cyan); }
.metric-value.green { color: var(--green); }
.metric-value.amber { color: var(--amber); }
.metric-label { color: var(--muted); font: 600 8px/1.3 var(--mono); letter-spacing: 1px; text-transform: uppercase; }
.system-state { justify-self: end; text-align: right; }
.live-row { display: flex; justify-content: flex-end; align-items: center; gap: 7px; color: var(--green); font: 700 10px/1 var(--mono); letter-spacing: .8px; }
.live-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; box-shadow: 0 0 10px currentColor; animation: livePulse 1.5s ease-in-out infinite; }
@keyframes livePulse { 50% { opacity: .35; transform: scale(.75); } }
#clock { margin-top: 6px; color: var(--muted); font: 10px/1 var(--mono); }
.workspace { display: grid; grid-template-columns: minmax(500px, 1.4fr) minmax(280px, .78fr) minmax(300px, .9fr); min-height: 0; }
.panel { min-width: 0; min-height: 0; background: var(--panel); border-right: 1px solid var(--line); display: flex; flex-direction: column; }
.panel:last-child { border-right: 0; }
.panel-title { height: 39px; padding: 0 13px; border-bottom: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; flex: 0 0 auto; }
.panel-title h2 { margin: 0; color: #b9c5d7; font: 700 9px/1 var(--mono); letter-spacing: 1.45px; text-transform: uppercase; }
.panel-title h2::before { content: ""; display: inline-block; width: 5px; height: 5px; margin-right: 8px; border-radius: 1px; background: var(--cyan); box-shadow: 0 0 8px rgba(45,226,230,.7); vertical-align: 1px; }
.tiny-badge { border: 1px solid var(--line); border-radius: 12px; padding: 3px 7px; color: var(--muted); font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; }
.supervisor-strip { margin: 10px 11px 0; min-height: 73px; border: 1px solid rgba(251,191,36,.55); background: #12140f; border-radius: 7px; display: grid; grid-template-columns: 48px 1fr auto; gap: 10px; align-items: center; padding: 9px 11px; position: relative; overflow: hidden; }
.supervisor-strip::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--amber); transform: scaleX(var(--supervisor-progress, 0)); transform-origin: left; transition: transform .2s linear; }
.supervisor-anim { width: 42px; height: 42px; position: relative; display: grid; place-items: center; }
.supervisor-anim span { position: absolute; border-radius: 50%; border: 1px solid var(--amber); }
.supervisor-anim span:nth-child(1) { inset: 2px; border-style: dashed; animation: orbit 5s linear infinite; }
.supervisor-anim span:nth-child(2) { inset: 8px; border-color: var(--violet); animation: orbit 2.8s linear reverse infinite; }
.supervisor-anim span:nth-child(3) { width: 7px; height: 7px; background: var(--amber); border: 0; box-shadow: 0 0 13px var(--amber); animation: coreBeat 1.1s ease-in-out infinite; }
@keyframes orbit { to { transform: rotate(360deg); } }
@keyframes coreBeat { 50% { transform: scale(.62); opacity: .55; } }
.supervisor-copy { min-width: 0; }
.supervisor-name { color: var(--amber); font-size: 12px; font-weight: 750; }
.supervisor-role { margin-top: 2px; color: var(--muted); font: 8px/1.2 var(--mono); text-transform: uppercase; letter-spacing: .8px; }
#supervisorDecision { margin-top: 7px; color: #dbe4f1; font: 10px/1.2 var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#supervisorDecision::before { content: "> "; color: var(--amber); }
.phase-pill { color: var(--amber); border: 1px solid rgba(251,191,36,.55); background: rgba(251,191,36,.07); border-radius: 10px; padding: 4px 7px; font: 700 8px/1 var(--mono); letter-spacing: .8px; }
.topology { position: relative; flex: 1; min-height: 0; margin: 7px 8px 8px; border: 1px solid var(--line-soft); border-radius: 6px; overflow: hidden; background-color: #090d14; background-image: linear-gradient(rgba(79,156,255,.035) 1px, transparent 1px), linear-gradient(90deg, rgba(79,156,255,.035) 1px, transparent 1px); background-size: 28px 28px; }
.topology::after { content: "SIMULATION MODE / LOCAL STATE"; position: absolute; right: 10px; bottom: 8px; color: #39465a; font: 8px/1 var(--mono); letter-spacing: .7px; }
#workflowSvg { width: 100%; height: 100%; display: block; }
.route { fill: none; stroke: #2c3950; stroke-width: 1.5; stroke-dasharray: 5 7; }
.route.return { opacity: .55; }
.route-active { stroke: var(--cyan); animation: routeFlow 1s linear infinite; filter: url(#softGlow); }
@keyframes routeFlow { to { stroke-dashoffset: -24; } }
.node .node-shell { fill: #0e1520; stroke: #344158; stroke-width: 1.5; transition: stroke .25s, fill .25s; }
.node .node-ring { fill: none; stroke: #344158; stroke-width: 1; stroke-dasharray: 2 5; opacity: .45; }
.node text { font-family: var(--mono); text-anchor: middle; }
.node .node-name { fill: #eef4ff; font-size: 11px; font-weight: 700; }
.node .node-sub { fill: #748197; font-size: 8px; }
.node .node-glyph { fill: #b8c5d7; font-size: 17px; font-weight: 700; }
.node.active .node-shell { stroke: var(--node-color); fill: #101824; filter: url(#softGlow); }
.node.active .node-ring { stroke: var(--node-color); opacity: .9; animation: nodeOrbit 4s linear infinite; transform-box: fill-box; transform-origin: center; }
.node.done .node-shell { stroke: var(--green); }
.node.done .node-glyph { fill: var(--green); }
@keyframes nodeOrbit { to { transform: rotate(360deg); } }
.supervisor-node .node-shell { stroke: var(--amber); }
.supervisor-node .node-ring { stroke: var(--amber); animation: nodeOrbit 5s linear infinite; transform-box: fill-box; transform-origin: center; }
.supervisor-node.active .node-shell { fill: #18170e; filter: url(#amberGlow); }
.paper-packet { opacity: 0; pointer-events: none; }
.paper-packet rect { fill: #ecf8ff; stroke: var(--cyan); stroke-width: .8; }
.paper-packet line { stroke: #387283; stroke-width: .6; }
.topology[data-phase="discovery"] .search-packet { opacity: 1; }
.topology[data-phase="evaluation"] .eval-packet { opacity: 1; }
.topology[data-phase="reporting"] .report-packet { opacity: 1; }
.pulse-wave { fill: none; stroke: var(--amber); stroke-width: 1.2; opacity: 0; transform-origin: center; animation: wave 1.8s ease-out infinite; }
.pulse-wave.delay { animation-delay: .8s; }
@keyframes wave { 0% { opacity: .65; transform: scale(.55); } 100% { opacity: 0; transform: scale(1.35); } }
.source-chip { fill: #0e1520; stroke: #2f455b; }
.source-label { fill: var(--cyan); font: 700 9px var(--mono); text-anchor: middle; }
.source-sub { fill: #6f7d92; font: 7px var(--mono); text-anchor: middle; }
.agents-body { padding: 9px; overflow: auto; flex: 1; scrollbar-width: thin; scrollbar-color: #344158 transparent; }
.agent-card { border: 1px solid var(--line); border-radius: 6px; background: #0b1018; margin-bottom: 7px; padding: 10px; transition: border-color .25s, background .25s; }
.agent-card.active { border-color: var(--agent-color); background: #101722; box-shadow: inset 3px 0 0 var(--agent-color); }
.agent-card.done { border-color: rgba(74,222,128,.55); }
.agent-head { display: grid; grid-template-columns: 31px 1fr auto; align-items: center; gap: 8px; }
.agent-icon { width: 31px; height: 31px; display: grid; place-items: center; border-radius: 5px; border: 1px solid var(--agent-color); color: var(--agent-color); font: 800 10px var(--mono); background: color-mix(in srgb, var(--agent-color) 8%, transparent); }
.agent-name { font-size: 11px; font-weight: 750; }
.agent-spec { color: var(--muted); font: 8px/1.4 var(--mono); margin-top: 2px; }
.status-badge { color: var(--muted); border: 1px solid var(--line); border-radius: 10px; padding: 3px 6px; font: 700 7px/1 var(--mono); letter-spacing: .65px; text-transform: uppercase; }
.active .status-badge { color: var(--agent-color); border-color: var(--agent-color); animation: statusBlink 1.2s ease-in-out infinite; }
.done .status-badge { color: var(--green); border-color: rgba(74,222,128,.6); }
@keyframes statusBlink { 50% { opacity: .45; } }
.agent-task { min-height: 14px; margin: 9px 0 7px; color: #b7c2d2; font: 9px/1.5 var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.progress { height: 3px; overflow: hidden; border-radius: 2px; background: #171f2c; }
.progress-fill { height: 100%; width: 0; border-radius: inherit; background: var(--agent-color); transition: width .18s linear; box-shadow: 0 0 8px color-mix(in srgb, var(--agent-color) 70%, transparent); }
.framework-mini { margin: 2px 0 8px; padding: 10px; border: 1px solid var(--line-soft); border-radius: 6px; }
.framework-mini-title { display: flex; justify-content: space-between; color: #c5d0df; font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; }
.framework-mini-title span:last-child { color: var(--violet); }
.weight-strip { display: flex; gap: 2px; height: 5px; margin-top: 8px; }
.weight-strip span { background: var(--violet); opacity: calc(.35 + var(--o)); border-radius: 1px; }
.right-panel { overflow: hidden; }
.tabs { display: flex; border-bottom: 1px solid var(--line); flex: 0 0 auto; }
.tab { flex: 1; padding: 9px 7px; border: 0; border-right: 1px solid var(--line); border-bottom: 2px solid transparent; background: #0b1018; color: var(--muted); cursor: pointer; font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; }
.tab:last-child { border-right: 0; }
.tab.active { color: var(--cyan); border-bottom-color: var(--cyan); background: #0f151f; }
.tab-view { display: none; flex: 1; min-height: 0; overflow: auto; }
.tab-view.active { display: flex; flex-direction: column; }
.ranking { padding: 8px; flex: 1; min-height: 0; overflow: auto; }
.empty-state { height: 100%; min-height: 190px; display: grid; place-items: center; text-align: center; color: var(--muted); padding: 24px; }
.empty-radar { width: 60px; height: 60px; margin: 0 auto 13px; border: 1px solid #314057; border-radius: 50%; position: relative; }
.empty-radar::before, .empty-radar::after { content: ""; position: absolute; inset: 10px; border: 1px solid #263348; border-radius: 50%; }
.empty-radar::after { inset: 27px; border-color: var(--cyan); background: var(--cyan); box-shadow: 0 0 12px rgba(45,226,230,.6); }
.empty-title { color: #c8d2df; font-size: 12px; font-weight: 700; }
.empty-copy { max-width: 230px; margin-top: 5px; font: 9px/1.55 var(--mono); }
.paper-card { border: 1px solid var(--line-soft); background: #0a0f17; border-radius: 5px; padding: 9px 9px 8px; margin-bottom: 6px; animation: resultIn .35s ease both; }
@keyframes resultIn { from { opacity: 0; transform: translateY(7px); } }
.paper-row { display: grid; grid-template-columns: 22px minmax(0,1fr) 42px; gap: 7px; align-items: start; }
.paper-rank { color: var(--muted); font: 800 9px/1 var(--mono); padding-top: 2px; }
.paper-title { color: #dfe7f2; font-size: 10px; line-height: 1.25; font-weight: 650; }
.paper-meta { color: var(--muted); font: 8px/1.4 var(--mono); margin-top: 4px; }
.paper-score { text-align: right; color: var(--score-color); font: 800 15px/1 var(--mono); }
.paper-score span { display: block; margin-top: 3px; color: var(--muted); font-size: 7px; }
.score-track { margin-top: 8px; height: 3px; background: #171f2b; border-radius: 2px; overflow: hidden; }
.score-fill { height: 100%; width: var(--score); background: var(--score-color); border-radius: inherit; }
.framework-view { padding: 9px; }
.framework-note { padding: 9px; border: 1px solid var(--line-soft); background: #0a0f17; border-radius: 5px; color: var(--muted); font: 9px/1.5 var(--mono); }
.criterion { margin-top: 8px; }
.criterion-row { display: flex; justify-content: space-between; gap: 10px; color: #c9d4e2; font: 9px/1.3 var(--mono); }
.criterion-row strong { color: var(--violet); }
.criterion-track { height: 3px; margin-top: 5px; background: #171f2b; }
.criterion-track span { display: block; height: 100%; background: var(--violet); }
.log-section { height: 174px; min-height: 120px; border-top: 1px solid var(--line); display: flex; flex-direction: column; flex: 0 0 auto; }
.log-head { height: 31px; display: flex; align-items: center; justify-content: space-between; padding: 0 10px; color: var(--muted); font: 700 8px/1 var(--mono); letter-spacing: .7px; text-transform: uppercase; border-bottom: 1px solid var(--line-soft); }
.log-head span:last-child { color: var(--green); }
#eventLog { overflow: auto; flex: 1; padding: 6px 9px; font: 8px/1.6 var(--mono); scrollbar-width: thin; scrollbar-color: #344158 transparent; }
.log-line { display: grid; grid-template-columns: 54px 46px minmax(0,1fr); gap: 5px; border-bottom: 1px solid rgba(255,255,255,.025); padding: 1px 0; animation: logIn .25s ease; }
@keyframes logIn { from { opacity: 0; } }
.log-time { color: #59677c; }
.log-type { color: var(--log-color); font-weight: 700; }
.log-msg { color: #aebaca; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.control-dock { display: grid; grid-template-columns: minmax(280px, 1fr) 185px 230px 255px; gap: 12px; align-items: center; padding: 11px 16px; background: #0a0d14; border-top: 1px solid var(--line); box-shadow: 0 -10px 26px rgba(0,0,0,.28); z-index: 4; }
.field label { display: block; color: var(--muted); font: 700 8px/1 var(--mono); text-transform: uppercase; letter-spacing: .8px; margin-bottom: 6px; }
.query-input { width: 100%; height: 36px; padding: 0 11px; border: 1px solid #344158; border-radius: 5px; background: #0d131d; color: var(--ink); outline: none; font: 10px var(--mono); }
.query-input:focus { border-color: var(--cyan); box-shadow: 0 0 0 2px rgba(45,226,230,.09); }
.paper-control { display: grid; grid-template-columns: 1fr 33px; gap: 8px; align-items: center; }
input[type="range"] { width: 100%; accent-color: var(--cyan); }
#paperLimitValue { height: 27px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 4px; color: var(--cyan); font: 800 10px var(--mono); }
.speed-group { display: flex; height: 36px; }
.speed-button { flex: 1; border: 1px solid var(--line); border-right: 0; background: #0d131d; color: var(--muted); cursor: pointer; font: 700 9px var(--mono); }
.speed-button:first-child { border-radius: 5px 0 0 5px; }
.speed-button:last-child { border-right: 1px solid var(--line); border-radius: 0 5px 5px 0; }
.speed-button.active { background: rgba(167,139,250,.12); color: var(--violet); border-color: var(--violet); }
.actions { display: grid; grid-template-columns: 1fr 38px 38px; gap: 7px; align-items: end; }
.button { height: 36px; border: 1px solid var(--line); border-radius: 5px; background: #111824; cursor: pointer; font: 750 9px var(--mono); letter-spacing: .45px; transition: transform .15s, border-color .15s; }
.button:hover { transform: translateY(-1px); border-color: #53627a; }
.button.primary { background: var(--cyan); color: #041014; border-color: var(--cyan); }
.button.primary.running { background: var(--amber); border-color: var(--amber); }
.button:disabled { cursor: not-allowed; opacity: .35; transform: none; }
.icon-button { font-size: 15px; padding: 0; }
.download-button { position: absolute; right: 10px; top: 48px; z-index: 2; height: 28px; padding: 0 9px; border: 1px solid rgba(74,222,128,.55); border-radius: 4px; background: #0c1812; color: var(--green); cursor: pointer; font: 700 8px var(--mono); display: none; }
.download-button.visible { display: block; }
.screen-reader { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; }
@media (max-width: 1120px) {
body { overflow: auto; }
.app { height: auto; min-height: 100vh; grid-template-rows: auto auto auto; }
.topbar { min-height: 64px; grid-template-columns: 1fr auto; }
.header-metrics { display: none; }
.workspace { grid-template-columns: 1fr 340px; min-height: 760px; }
.right-panel { grid-column: 1 / -1; height: 480px; border-top: 1px solid var(--line); }
.control-dock { grid-template-columns: 1fr 160px 200px; }
.actions { grid-column: auto; }
.speed-field { display: none; }
}
@media (max-width: 760px) {
.topbar { grid-template-columns: 1fr; gap: 6px; padding: 12px 14px; }
.system-state { display: none; }
.workspace { display: block; }
.panel { border-right: 0; border-bottom: 1px solid var(--line); }
.workflow-panel { height: 680px; }
.agents-panel { height: 540px; }
.right-panel { height: 520px; }
.control-dock { grid-template-columns: 1fr 1fr; position: sticky; bottom: 0; }
.field:first-child { grid-column: 1 / -1; }
.actions { grid-column: 2; }
h1 { white-space: normal; }
}
</style>
</head>
<body>
<div class="app">
<header class="topbar">
<div class="brand">
<div class="brand-mark" aria-hidden="true"><div class="brand-core"></div></div>
<div class="brand-copy">
<div class="eyebrow">Research intelligence lab</div>
<h1>AI Research Multi-Agent System</h1>
</div>
</div>
<div class="header-metrics" aria-label="System metrics">
<div class="header-metric"><div class="metric-value cyan" id="papersFound">0</div><div class="metric-label">Discovered</div></div>
<div class="header-metric"><div class="metric-value" id="papersEvaluated">0</div><div class="metric-label">Evaluated</div></div>
<div class="header-metric"><div class="metric-value amber" id="avgScore">--</div><div class="metric-label">Avg AGI score</div></div>
<div class="header-metric"><div class="metric-value green" id="coverage">0%</div><div class="metric-label">Pipeline</div></div>
</div>
<div class="system-state">
<div class="live-row"><span class="live-dot"></span><span id="systemState">SYSTEM READY</span></div>
<div id="clock">--:--:-- ET</div>
</div>
</header>
<main class="workspace">
<section class="panel workflow-panel" aria-labelledby="workflowTitle">
<div class="panel-title"><h2 id="workflowTitle">LangGraph workflow topology</h2><span class="tiny-badge">StateGraph</span></div>
<div class="supervisor-strip" id="supervisorStrip">
<div class="supervisor-anim" aria-hidden="true"><span></span><span></span><span></span></div>
<div class="supervisor-copy">
<div class="supervisor-name">Supervisor Agent</div>
<div class="supervisor-role">Phase routing / state coordination / report control</div>
<div id="supervisorDecision">Awaiting research objective</div>
</div>
<div class="phase-pill" id="phasePill">IDLE</div>
</div>
<div class="topology" id="topology" data-phase="idle">
<svg id="workflowSvg" viewBox="0 0 720 500" role="img" aria-label="Animated multi-agent research workflow">
<defs>
<filter id="softGlow"><feGaussianBlur stdDeviation="2.2" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
<filter id="amberGlow"><feGaussianBlur stdDeviation="3.5" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
<path id="pathSupervisorPlanner" d="M360 190 C290 145 255 112 188 91"/>
<path id="pathPlannerSupervisor" d="M185 112 C250 147 290 172 333 194"/>
<path id="pathSupervisorDiscovery" d="M348 221 C331 274 330 313 345 350"/>
<path id="pathDiscoverySupervisor" d="M378 349 C394 295 394 260 375 222"/>
<path id="pathSupervisorEvaluation" d="M389 207 C450 238 508 283 551 347"/>
<path id="pathEvaluationSupervisor" d="M564 339 C516 278 468 234 390 197"/>
<path id="pathSupervisorReport" d="M392 181 C455 149 503 119 550 93"/>
<path id="pathArxivDiscovery" d="M130 382 C207 389 265 383 326 375"/>
</defs>
<path class="route" id="routeSupervisorPlanner" d="M360 190 C290 145 255 112 188 91"/>
<path class="route return" id="routePlannerSupervisor" d="M185 112 C250 147 290 172 333 194"/>
<path class="route" id="routeSupervisorDiscovery" d="M348 221 C331 274 330 313 345 350"/>
<path class="route return" id="routeDiscoverySupervisor" d="M378 349 C394 295 394 260 375 222"/>
<path class="route" id="routeSupervisorEvaluation" d="M389 207 C450 238 508 283 551 347"/>
<path class="route return" id="routeEvaluationSupervisor" d="M564 339 C516 278 468 234 390 197"/>
<path class="route" id="routeSupervisorReport" d="M392 181 C455 149 503 119 550 93"/>
<path class="route" id="routeArxivDiscovery" d="M130 382 C207 389 265 383 326 375"/>
<g transform="translate(130 382)">
<rect class="source-chip" x="-53" y="-23" width="106" height="46" rx="6"/>
<text class="source-label" y="-3">arXiv API</text>
<text class="source-sub" y="10">cs.AI / cs.LG / cs.CL</text>
</g>
<g class="node" id="node-planner" style="--node-color: var(--blue)" transform="translate(155 86)">
<circle class="node-ring" r="48"/><rect class="node-shell" x="-43" y="-34" width="86" height="68" rx="8"/>
<text class="node-glyph" y="-9">PL</text><text class="node-name" y="10">PLANNER</text><text class="node-sub" y="24">execution plan</text>
</g>
<g class="node supervisor-node active" id="node-supervisor" style="--node-color: var(--amber)" transform="translate(360 195)">
<circle class="pulse-wave" r="49"/><circle class="pulse-wave delay" r="49"/><circle class="node-ring" r="51"/>
<polygon class="node-shell" points="0,-43 37,-21 37,21 0,43 -37,21 -37,-21"/>
<text class="node-glyph" y="-9">SV</text><text class="node-name" y="10">SUPERVISOR</text><text class="node-sub" y="24">state router</text>
</g>
<g class="node" id="node-discovery" style="--node-color: var(--cyan)" transform="translate(360 378)">
<circle class="node-ring" r="48"/><rect class="node-shell" x="-45" y="-34" width="90" height="68" rx="8"/>
<text class="node-glyph" y="-9">DS</text><text class="node-name" y="10">DISCOVERY</text><text class="node-sub" y="24">paper search</text>
</g>
<g class="node" id="node-evaluation" style="--node-color: var(--violet)" transform="translate(585 378)">
<circle class="node-ring" r="48"/><rect class="node-shell" x="-46" y="-34" width="92" height="68" rx="8"/>
<text class="node-glyph" y="-9">EV</text><text class="node-name" y="10">EVALUATION</text><text class="node-sub" y="24">10 AGI criteria</text>
</g>
<g class="node" id="node-report" style="--node-color: var(--green)" transform="translate(585 86)">
<circle class="node-ring" r="48"/><rect class="node-shell" x="-45" y="-34" width="90" height="68" rx="8"/>
<text class="node-glyph" y="-9">RP</text><text class="node-name" y="10">REPORT</text><text class="node-sub" y="24">ranked findings</text>
</g>
<g class="paper-packet search-packet">
<rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/>
<animateMotion dur="2.7s" repeatCount="indefinite"><mpath href="#pathArxivDiscovery"/></animateMotion>
</g>
<g class="paper-packet search-packet">
<rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/>
<animateMotion dur="2.7s" begin=".9s" repeatCount="indefinite"><mpath href="#pathArxivDiscovery"/></animateMotion>
</g>
<g class="paper-packet eval-packet">
<rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/>
<animateMotion dur="2.4s" repeatCount="indefinite" path="M390 378 C455 378 505 378 538 378"/>
</g>
<g class="paper-packet eval-packet">
<rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/>
<animateMotion dur="2.4s" begin=".8s" repeatCount="indefinite" path="M390 378 C455 378 505 378 538 378"/>
</g>
<g class="paper-packet report-packet">
<rect x="-6" y="-8" width="12" height="16" rx="1"/><line x1="-3" y1="-3" x2="3" y2="-3"/><line x1="-3" y1="1" x2="3" y2="1"/>
<animateMotion dur="2s" repeatCount="indefinite"><mpath href="#pathSupervisorReport"/></animateMotion>
</g>
</svg>
</div>
</section>
<section class="panel agents-panel" aria-labelledby="agentsTitle">
<div class="panel-title"><h2 id="agentsTitle">Agent operations</h2><span class="tiny-badge" id="activeCount">0 active</span></div>
<div class="agents-body">
<div class="agent-card" id="card-planner" style="--agent-color: var(--blue)">
<div class="agent-head"><div class="agent-icon">PL</div><div><div class="agent-name">Planner Agent</div><div class="agent-spec">GPT-4o mini / structured JSON</div></div><span class="status-badge">Idle</span></div>
<div class="agent-task">Waiting for a research objective</div><div class="progress"><div class="progress-fill"></div></div>
</div>
<div class="agent-card" id="card-discovery" style="--agent-color: var(--cyan)">
<div class="agent-head"><div class="agent-icon">DS</div><div><div class="agent-name">Discovery Agent</div><div class="agent-spec">arXiv 2.3.1 / validation tools</div></div><span class="status-badge">Idle</span></div>
<div class="agent-task">Standing by for execution plan</div><div class="progress"><div class="progress-fill"></div></div>
</div>
<div class="agent-card" id="card-evaluation" style="--agent-color: var(--violet)">
<div class="agent-head"><div class="agent-icon">EV</div><div><div class="agent-name">Evaluation Agent</div><div class="agent-spec">Weighted AGI scoring / JSON repair</div></div><span class="status-badge">Idle</span></div>
<div class="agent-task">Waiting for validated papers</div><div class="progress"><div class="progress-fill"></div></div>
</div>
<div class="agent-card" id="card-report" style="--agent-color: var(--green)">
<div class="agent-head"><div class="agent-icon">RP</div><div><div class="agent-name">Report Generator</div><div class="agent-spec">Executive synthesis / recommendations</div></div><span class="status-badge">Idle</span></div>
<div class="agent-task">Waiting for evaluation results</div><div class="progress"><div class="progress-fill"></div></div>
</div>
<div class="framework-mini">
<div class="framework-mini-title"><span>AGI evaluation framework</span><span>10 dimensions</span></div>
<div class="weight-strip" title="Weights from the notebook">
<span style="width:15%;--o:.9"></span><span style="width:15%;--o:.8"></span><span style="width:15%;--o:.7"></span><span style="width:12%;--o:.6"></span><span style="width:10%;--o:.5"></span><span style="width:10%;--o:.45"></span><span style="width:8%;--o:.4"></span><span style="width:8%;--o:.35"></span><span style="width:4%;--o:.3"></span><span style="width:3%;--o:.25"></span>
</div>
</div>
</div>
</section>
<section class="panel right-panel" aria-labelledby="intelligenceTitle">
<div class="panel-title"><h2 id="intelligenceTitle">Research intelligence</h2><span class="tiny-badge" id="requestId">No request</span></div>
<button class="download-button" id="downloadReport" type="button">Download report</button>
<div class="tabs" role="tablist">
<button class="tab active" type="button" role="tab" aria-selected="true" data-tab="results">Ranked papers</button>
<button class="tab" type="button" role="tab" aria-selected="false" data-tab="framework">Scoring framework</button>
</div>
<div class="tab-view active" id="view-results" role="tabpanel">
<div class="ranking" id="ranking">
<div class="empty-state"><div><div class="empty-radar"></div><div class="empty-title">Research queue ready</div><div class="empty-copy">Run the workflow to discover, validate, score, and rank simulated AGI papers.</div></div></div>
</div>
</div>
<div class="tab-view framework-view" id="view-framework" role="tabpanel"></div>
<div class="log-section">
<div class="log-head"><span>Supervisor event stream</span><span id="logState">listening</span></div>
<div id="eventLog" aria-live="polite"></div>
</div>
</section>
</main>
<footer class="control-dock">
<div class="field">
<label for="queryInput">Research objective</label>
<input class="query-input" id="queryInput" value="Find AGI papers from Jan 1st 2026 to Jan 31st 2026" autocomplete="off">
</div>
<div class="field">
<label for="paperLimit">Maximum papers</label>
<div class="paper-control"><input id="paperLimit" type="range" min="5" max="15" value="10"><output id="paperLimitValue" for="paperLimit">10</output></div>
</div>
<div class="field speed-field">
<label>Simulation speed</label>
<div class="speed-group" aria-label="Simulation speed">
<button class="speed-button" type="button" data-speed="0.75">0.75x</button><button class="speed-button active" type="button" data-speed="1">1x</button><button class="speed-button" type="button" data-speed="2">2x</button>
</div>
</div>
<div class="field">
<label>Pipeline control</label>
<div class="actions">
<button class="button primary" id="runButton" type="button">Run research</button>
<button class="button icon-button" id="pauseButton" type="button" title="Pause simulation" aria-label="Pause simulation" disabled>II</button>
<button class="button icon-button" id="resetButton" type="button" title="Reset simulation" aria-label="Reset simulation">R</button>
</div>
</div>
</footer>
</div>
<script>
const CRITERIA = [
["Novel Problem Solving", 15], ["Few-Shot Learning", 15], ["Task Transfer", 15],
["Abstract Reasoning", 12], ["Contextual Adaptation", 10], ["Multi-Rule Integration", 10],
["Generalization Efficiency", 8], ["Meta-Learning", 8], ["World Modeling", 4],
["Autonomous Goal Setting", 3]
];
const PAPER_LIBRARY = [
["Adaptive World Models for Long-Horizon Generalization", "I. Chen, M. Alvarez", 82],
["Compositional Transfer Across Unseen Task Families", "S. Rao, J. Kim", 76],
["Learning Abstract Rules from Sparse Demonstrations", "L. Okafor, P. Singh", 72],
["Self-Refining Memory for Continual Agent Learning", "E. Brooks, N. Patel", 68],
["Multi-Modal Planning with Uncertain World States", "A. Laurent, R. Davis", 64],
["Efficient Meta-Learning Through Latent Skill Graphs", "T. Wang, C. Foster", 59],
["Context-Aware Tool Selection in Language Agents", "M. Hassan, Y. Ito", 55],
["Benchmarking Cross-Domain Reasoning Under Shift", "V. Novak, D. Green", 49],
["Few-Shot Policy Adaptation for Embodied Systems", "K. Mensah, F. Ruiz", 45],
["Structured Retrieval for Scientific Question Answering", "B. Carter, Z. Li", 39],
["Improving Long-Context Classification with Routing", "H. Park, S. Bell", 35],
["Domain-Specific Agents for Automated Data Labeling", "R. Evans, G. Moore", 31],
["Compact Representation Learning for Edge Inference", "N. Shah, D. Klein", 28],
["Synthetic Preference Optimization for Dialogue", "J. Wilson, A. Nair", 25],
["A Taxonomy of Modular AI Evaluation Protocols", "C. Young, P. Martin", 22]
];
const PHASES = {
idle: { label: "IDLE", progress: 0 }, initialization: { label: "INITIALIZE", progress: 6 },
planning: { label: "PLANNING", progress: 22 }, discovery: { label: "DISCOVERY", progress: 47 },
evaluation: { label: "EVALUATION", progress: 76 }, reporting: { label: "REPORTING", progress: 92 },
complete: { label: "COMPLETE", progress: 100 }
};
const state = {
phase: "idle", running: false, paused: false, speed: 1, phaseElapsed: 0,
lastTick: performance.now(), papersFound: 0, evaluated: 0, results: [],
limit: 10, requestId: "", report: "", phaseLogged: false
};
const el = id => document.getElementById(id);
const topology = el("topology");
const runButton = el("runButton");
const pauseButton = el("pauseButton");
const ranking = el("ranking");
function formatTime() {
return new Intl.DateTimeFormat("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false, timeZone: "America/New_York" }).format(new Date()) + " ET";
}
function addLog(type, message, color = "var(--cyan)") {
const row = document.createElement("div");
row.className = "log-line";
row.style.setProperty("--log-color", color);
row.innerHTML = `<span class="log-time">${formatTime().slice(0,8)}</span><span class="log-type">${type}</span><span class="log-msg"></span>`;
row.querySelector(".log-msg").textContent = message;
el("eventLog").prepend(row);
while (el("eventLog").children.length > 28) el("eventLog").lastChild.remove();
}
function setPhase(phase) {
state.phase = phase;
state.phaseElapsed = 0;
state.phaseLogged = false;
topology.dataset.phase = phase;
el("phasePill").textContent = PHASES[phase].label;
el("coverage").textContent = PHASES[phase].progress + "%";
el("supervisorStrip").style.setProperty("--supervisor-progress", PHASES[phase].progress / 100);
updateTopology();
updateCards();
}
function updateTopology() {
const activeMap = { planning: "planner", discovery: "discovery", evaluation: "evaluation", reporting: "report" };
const doneByPhase = {
idle: [], initialization: [], planning: [], discovery: ["planner"],
evaluation: ["planner", "discovery"], reporting: ["planner", "discovery", "evaluation"],
complete: ["planner", "discovery", "evaluation", "report"]
};
["planner", "discovery", "evaluation", "report"].forEach(name => {
const node = el("node-" + name);
node.classList.toggle("active", activeMap[state.phase] === name);
node.classList.toggle("done", doneByPhase[state.phase].includes(name));
});
el("node-supervisor").classList.toggle("active", state.phase !== "idle" && state.phase !== "complete");
document.querySelectorAll(".route").forEach(route => route.classList.remove("route-active"));
const routes = {
planning: ["routeSupervisorPlanner", "routePlannerSupervisor"],
discovery: ["routeSupervisorDiscovery", "routeArxivDiscovery", "routeDiscoverySupervisor"],
evaluation: ["routeSupervisorEvaluation", "routeEvaluationSupervisor"],
reporting: ["routeSupervisorReport"]
};
(routes[state.phase] || []).forEach(id => el(id).classList.add("route-active"));
}
function cardState(name, mode, task, progress) {
const card = el("card-" + name);
card.classList.remove("active", "done");
if (mode !== "idle") card.classList.add(mode);
card.querySelector(".status-badge").textContent = mode === "active" ? "Working" : mode === "done" ? "Done" : "Idle";
card.querySelector(".agent-task").textContent = task;
card.querySelector(".progress-fill").style.width = Math.max(0, Math.min(100, progress)) + "%";
}
function updateCards() {
const p = state.phaseElapsed;
const defaults = {
planner: ["idle", "Waiting for a research objective", 0],
discovery: ["idle", "Standing by for execution plan", 0],
evaluation: ["idle", "Waiting for validated papers", 0],
report: ["idle", "Waiting for evaluation results", 0]
};
const order = ["planner", "discovery", "evaluation", "report"];
const completed = {
discovery: ["planner"], evaluation: ["planner", "discovery"],
reporting: ["planner", "discovery", "evaluation"], complete: order
}[state.phase] || [];
completed.forEach(name => defaults[name] = ["done", name === "report" ? "Executive report generated" : "State returned to Supervisor", 100]);
if (state.phase === "planning") defaults.planner = ["active", p < 1300 ? "Parsing objective and temporal constraints" : "Building keywords, categories, and success criteria", p / 32];
if (state.phase === "discovery") defaults.discovery = ["active", state.papersFound < state.limit ? `Searching arXiv and validating metadata (${state.papersFound}/${state.limit})` : "Deduplicating and finalizing paper set", Math.min(100, p / 60)];
if (state.phase === "evaluation") defaults.evaluation = ["active", `Scoring paper ${Math.min(state.evaluated + 1, state.limit)} of ${state.limit} across 10 AGI dimensions`, state.limit ? state.evaluated / state.limit * 100 : 0];
if (state.phase === "reporting") defaults.report = ["active", p < 1500 ? "Ranking findings and computing distribution" : "Writing executive insights and recommendations", p / 28];
order.forEach(name => cardState(name, ...defaults[name]));
el("activeCount").textContent = ["planning", "discovery", "evaluation", "reporting"].includes(state.phase) ? "1 active" : "0 active";
}
function supervisorDecision(text) { el("supervisorDecision").textContent = text; }
function scoreColor(score) {
if (score >= 70) return "var(--green)";
if (score >= 40) return "var(--amber)";
return "var(--rose)";
}
function renderRanking() {
if (!state.results.length) return;
ranking.innerHTML = "";
[...state.results].sort((a,b) => b.score - a.score).forEach((paper, index) => {
const card = document.createElement("article");
card.className = "paper-card";
card.style.setProperty("--score", paper.score + "%");
card.style.setProperty("--score-color", scoreColor(paper.score));
card.innerHTML = `<div class="paper-row"><div class="paper-rank">#${String(index + 1).padStart(2, "0")}</div><div><div class="paper-title"></div><div class="paper-meta"></div></div><div class="paper-score">${paper.score}<span>/100</span></div></div><div class="score-track"><div class="score-fill"></div></div>`;
card.querySelector(".paper-title").textContent = paper.title;
card.querySelector(".paper-meta").textContent = paper.authors + " / arXiv / " + (paper.score >= 70 ? "High" : paper.score >= 40 ? "Medium" : "Low");
ranking.appendChild(card);
});
}
function renderFramework() {
const view = el("view-framework");
view.innerHTML = `<div class="framework-note">Each abstract is evaluated with a strict JSON-only prompt. Weighted scores are converted to a 0-100 AGI potential score. The data shown in this browser experience is simulated.</div>`;
CRITERIA.forEach(([name, weight]) => {
const item = document.createElement("div");
item.className = "criterion";
item.innerHTML = `<div class="criterion-row"><span></span><strong>${weight}%</strong></div><div class="criterion-track"><span style="width:${weight * 4}%"></span></div>`;
item.querySelector(".criterion-row span").textContent = name;
view.appendChild(item);
});
}
function advancePaperDiscovery() {
const target = Math.min(state.limit, Math.floor(state.phaseElapsed / 470));
if (target > state.papersFound) {
for (let i = state.papersFound; i < target; i++) addLog("DISC", `Paper ${i + 1} received from arXiv and passed metadata validation`, "var(--cyan)");
state.papersFound = target;
}
}
function advanceEvaluation() {
const target = Math.min(state.limit, Math.floor(state.phaseElapsed / 680));
if (target > state.evaluated) {
for (let i = state.evaluated; i < target; i++) {
const [title, authors, base] = PAPER_LIBRARY[i];
const score = Math.max(10, Math.min(94, base + ((state.requestId.charCodeAt(3) + i * 3) % 5 - 2)));
state.results.push({ title, authors, score });
addLog("EVAL", `${title.slice(0, 36)} scored ${score}/100`, scoreColor(score));
}
state.evaluated = target;
renderRanking();
}
}
function calculateAverage() {
return state.results.length ? Math.round(state.results.reduce((sum, p) => sum + p.score, 0) / state.results.length) : 0;
}
function generateReport() {
const sorted = [...state.results].sort((a,b) => b.score - a.score);
const high = sorted.filter(p => p.score >= 70).length;
const medium = sorted.filter(p => p.score >= 40 && p.score < 70).length;
const low = sorted.filter(p => p.score < 40).length;
const findings = sorted.slice(0,5).map((p,i) => `${i + 1}. ${p.title}\n Authors: ${p.authors}\n AGI Score: ${p.score}/100`).join("\n\n");
state.report = `# AGI Research Analysis Report\n\n## Executive Summary\n\nResearch Objective: ${el("queryInput").value}\n\nPapers discovered: ${state.papersFound}\nPapers evaluated: ${state.evaluated}\nAverage AGI score: ${calculateAverage()}/100\n\n## AGI Potential Distribution\n\n- High AGI Potential: ${high}\n- Medium AGI Potential: ${medium}\n- Low AGI Potential: ${low}\n\n## Top Papers\n\n${findings}\n\n## Recommended Actions\n\n1. Deepen analysis of the highest-potential papers.\n2. Track developments from the leading research groups.\n3. Expand discovery to full-text analysis and additional sources.\n\n---\nGenerated by the AI Research Multi-Agent System simulation.\n`;
el("downloadReport").classList.add("visible");
}
function updateMetrics() {
el("papersFound").textContent = state.papersFound;
el("papersEvaluated").textContent = state.evaluated;
el("avgScore").textContent = state.results.length ? calculateAverage() : "--";
el("systemState").textContent = state.paused ? "PIPELINE PAUSED" : state.running ? "PIPELINE ACTIVE" : state.phase === "complete" ? "RUN COMPLETE" : "SYSTEM READY";
el("logState").textContent = state.paused ? "paused" : state.running ? "streaming" : "listening";
}
function runPhaseLogic() {
const p = state.phaseElapsed;
if (state.phase === "initialization") {
supervisorDecision("Assigning request ID and loading clean research state");
if (!state.phaseLogged) { addLog("SUPV", "INITIALIZATION -> PLANNING", "var(--amber)"); state.phaseLogged = true; }
if (p >= 900) setPhase("planning");
} else if (state.phase === "planning") {
supervisorDecision(p < 1300 ? "Planner is extracting dates and focus areas" : "Validating structured execution plan");
if (!state.phaseLogged) { addLog("PLAN", "Parsing query into keywords, sources, dates, and success criteria", "var(--blue)"); state.phaseLogged = true; }
if (p >= 3200) { addLog("SUPV", "PLANNING -> DISCOVERY / execution plan accepted", "var(--amber)"); setPhase("discovery"); }
} else if (state.phase === "discovery") {
advancePaperDiscovery();
supervisorDecision(state.papersFound < state.limit ? `Monitoring arXiv paper search / ${state.papersFound} validated` : "Reviewing deduplication and source validation summary");
if (!state.phaseLogged) { addLog("TOOL", "arXiv search started across cs.AI, cs.LG, and cs.CL", "var(--cyan)"); state.phaseLogged = true; }
if (p >= Math.max(5400, state.limit * 470 + 800)) { addLog("SUPV", `DISCOVERY -> EVALUATION / ${state.papersFound} papers found`, "var(--amber)"); setPhase("evaluation"); }
} else if (state.phase === "evaluation") {
advanceEvaluation();
supervisorDecision(state.evaluated < state.limit ? `Evaluating abstract ${state.evaluated + 1} of ${state.limit} with weighted AGI rubric` : "Checking score distribution and evaluation completeness");
if (!state.phaseLogged) { addLog("MODEL", "JSON-only AGI evaluator initialized with 10 weighted parameters", "var(--violet)"); state.phaseLogged = true; }
if (p >= state.limit * 680 + 900) { addLog("SUPV", "EVALUATION -> COMPLETION / report requested", "var(--amber)"); setPhase("reporting"); }
} else if (state.phase === "reporting") {
supervisorDecision(p < 1500 ? "Sorting results and identifying high-potential papers" : "Generating executive summary and recommended actions");
if (!state.phaseLogged) { addLog("RPRT", "Synthesizing ranked findings and score distribution", "var(--green)"); state.phaseLogged = true; }
if (p >= 2800) {
generateReport();
setPhase("complete");
state.running = false;
supervisorDecision(`Research complete / ${state.evaluated} papers scored / report ready`);
addLog("DONE", `Pipeline completed with average AGI score ${calculateAverage()}/100`, "var(--green)");
runButton.textContent = "Run again";
runButton.classList.remove("running");
pauseButton.disabled = true;
}
}
updateCards();
updateMetrics();
}
function tick(now) {
const delta = now - state.lastTick;
state.lastTick = now;
if (state.running && !state.paused) {
state.phaseElapsed += delta * state.speed;
runPhaseLogic();
}
requestAnimationFrame(tick);
}
function startSimulation() {
if (state.paused) {
state.paused = false;
pauseButton.textContent = "II";
runButton.textContent = "Research running";
addLog("SUPV", "Pipeline resumed", "var(--amber)");
return;
}
if (state.running) return;
resetSimulation(false);
state.limit = Number(el("paperLimit").value);
state.requestId = "RQ-" + Math.random().toString(36).slice(2, 8).toUpperCase();
el("requestId").textContent = state.requestId;
state.running = true;
runButton.textContent = "Research running";
runButton.classList.add("running");
pauseButton.disabled = false;
setPhase("initialization");
addLog("START", `Research request ${state.requestId} accepted`, "var(--green)");
updateMetrics();
}
function pauseSimulation() {
if (!state.running) return;
state.paused = !state.paused;
pauseButton.textContent = state.paused ? ">" : "II";
runButton.textContent = state.paused ? "Resume research" : "Research running";
if (state.paused) addLog("SUPV", "Pipeline paused by operator", "var(--amber)");
updateMetrics();
}
function resetSimulation(log = true) {
state.running = false; state.paused = false; state.phaseElapsed = 0;
state.papersFound = 0; state.evaluated = 0; state.results = []; state.report = ""; state.requestId = "";
el("requestId").textContent = "No request";
el("downloadReport").classList.remove("visible");
ranking.innerHTML = `<div class="empty-state"><div><div class="empty-radar"></div><div class="empty-title">Research queue ready</div><div class="empty-copy">Run the workflow to discover, validate, score, and rank simulated AGI papers.</div></div></div>`;
runButton.textContent = "Run research";
runButton.classList.remove("running");
pauseButton.textContent = "II";
pauseButton.disabled = true;
setPhase("idle");
supervisorDecision("Awaiting research objective");
updateMetrics();
if (log) addLog("RESET", "Research state cleared", "var(--muted)");
}
function downloadReport() {
const blob = new Blob([state.report], { type: "text/markdown" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url; a.download = `agi-research-report-${state.requestId.toLowerCase()}.md`; a.click();
URL.revokeObjectURL(url);
}
el("paperLimit").addEventListener("input", event => el("paperLimitValue").textContent = event.target.value);
runButton.addEventListener("click", () => state.paused ? pauseSimulation() : startSimulation());
pauseButton.addEventListener("click", pauseSimulation);
el("resetButton").addEventListener("click", () => resetSimulation(true));
el("downloadReport").addEventListener("click", downloadReport);
document.querySelectorAll(".speed-button").forEach(button => button.addEventListener("click", () => {
document.querySelectorAll(".speed-button").forEach(b => b.classList.remove("active"));
button.classList.add("active"); state.speed = Number(button.dataset.speed);
addLog("SPEED", `Simulation speed set to ${button.textContent}`, "var(--violet)");
}));
document.querySelectorAll(".tab").forEach(button => button.addEventListener("click", () => {
document.querySelectorAll(".tab").forEach(b => { b.classList.toggle("active", b === button); b.setAttribute("aria-selected", b === button); });
document.querySelectorAll(".tab-view").forEach(view => view.classList.remove("active"));
el("view-" + button.dataset.tab).classList.add("active");
}));
renderFramework();
el("clock").textContent = formatTime();
setInterval(() => el("clock").textContent = formatTime(), 1000);
addLog("READY", "Supervisor online / all agents standing by", "var(--green)");
requestAnimationFrame(tick);
</script>
</body>
</html>