fix(dashboard): heatmap cell click + 5th tab + model sync fixes\n\n- restore hmModal with 4 legacy tabs + new Performance Graph tab\n- fix event.target in research-dashboard.template.html switchTab\n- fix showCellDetail event.stopPropagation for modal persistence\n- update agent models + sync KILO_SPEC.md and AGENTS.md
This commit is contained in:
@@ -983,6 +983,7 @@
|
||||
<button class="hm-tab-btn" onclick="switchHmTab('gitea')">Gitea History</button>
|
||||
<button class="hm-tab-btn" onclick="switchHmTab('skills')">Skills</button>
|
||||
<button class="hm-tab-btn" onclick="switchHmTab('models')">Model Timeline</button>
|
||||
<button class="hm-tab-btn" onclick="switchHmTab('graph')">Performance Graph</button>
|
||||
</div>
|
||||
<div class="modal-body" id="hmModalBody">
|
||||
<!-- Content injected by JS -->
|
||||
@@ -1016,7 +1017,7 @@ Chart.defaults.borderColor = '#1e2d45';
|
||||
Chart.defaults.font.family = "'Inter', sans-serif";
|
||||
|
||||
// Inline recommendation data fallback (from model-research-latest.json)
|
||||
const INLINE_RECOMMENDATIONS = []; // REMOVED — data now comes from agentData, not hardcoded
|
||||
const INLINE_RECOMMENDATIONS = []; // Deprecated — data now comes from agentData.agents[].current.recommendations
|
||||
|
||||
// Inline benchmark data (fallback when embedded data doesn't have model_benchmarks)
|
||||
// SOURCE: agent-evolution/data/model-benchmarks-verified.json v2.0.0
|
||||
@@ -5736,33 +5737,15 @@ function renderOverview() {
|
||||
`).join('')
|
||||
: '<p style="color: var(--text-muted);">No history yet</p>';
|
||||
|
||||
// Recommended agents (use inline recs if available)
|
||||
let recAgents = [];
|
||||
if (INLINE_RECOMMENDATIONS && INLINE_RECOMMENDATIONS.length > 0) {
|
||||
recAgents = INLINE_RECOMMENDATIONS.slice(0, 6).map(r => ({ agent: r.agent, current: { recommendations: [{ priority: r.impact, target: r.source_of_truth_model || r.recommended_model, reason: r.rationale, score_before: r.score_before, score_after: r.score_after, score_delta: r.score_delta }], model: r.current_model_in_agent_versions || r.current_model, category: 'Core Dev', description: '', benchmark: { fit_score: r.score_after || 0 } } }));
|
||||
} else {
|
||||
recAgents = Object.entries(agentData.agents)
|
||||
.filter(([_, a]) => a.current.recommendations && a.current.recommendations.length > 0)
|
||||
.slice(0, 6);
|
||||
}
|
||||
// Recommended agents from live data
|
||||
const recAgents = Object.entries(agentData.agents || {})
|
||||
.filter(([_, a]) => (a.current?.recommendations || []).length > 0)
|
||||
.slice(0, 6);
|
||||
|
||||
document.getElementById('recCount').textContent = recAgents.length;
|
||||
if (INLINE_RECOMMENDATIONS && INLINE_RECOMMENDATIONS.length > 0) {
|
||||
document.getElementById('recAgents').innerHTML = recAgents.map((r, idx) => renderRecCard({
|
||||
agent: r.agent,
|
||||
current_model: r.current?.model || '',
|
||||
recommended_model: r.current?.recommendations?.[0]?.target || '',
|
||||
impact: r.current?.recommendations?.[0]?.priority?.toLowerCase() || 'medium',
|
||||
score_before: r.current?.recommendations?.[0]?.score_before || 0,
|
||||
score_after: r.current?.recommendations?.[0]?.score_after || 0,
|
||||
score_delta: r.current?.recommendations?.[0]?.score_delta || 0,
|
||||
rationale: r.current?.recommendations?.[0]?.reason || ''
|
||||
}, idx)).join('');
|
||||
} else {
|
||||
document.getElementById('recAgents').innerHTML = recAgents.map(([name, agent]) =>
|
||||
renderAgentCard(name, agent, true)
|
||||
).join('');
|
||||
}
|
||||
document.getElementById('recAgents').innerHTML = recAgents.map(([name, agent]) =>
|
||||
renderAgentCard(name, agent, true)
|
||||
).join('');
|
||||
}
|
||||
|
||||
// Render All Agents
|
||||
@@ -6068,7 +6051,7 @@ function renderHeatmap() {
|
||||
h += `<td style="background:${hmColor(s)};color:${hmText(s)};cursor:pointer" class="${cur ? 'hm-cur' : ''}" title="${ag.n} × ${hmModels[j].n}: ${s}"
|
||||
onmouseover="showTT(event,'${ag.n}','${hmModels[j].n} (${hmModels[j].p})',${s},${best},${cur},${hmModels[j].if})"
|
||||
onmouseout="hideTT()"
|
||||
onclick="showCellDetail('${hmModels[j].full}', '${ag.n}')">${s}${marks}</td>`;
|
||||
onclick="openHmModal(event, '${ag.n}', '${hmModels[j].n}', ${s}, ${hmModels[j].if})">${s}${marks}</td>`;
|
||||
});
|
||||
h += '</tr>';
|
||||
});
|
||||
@@ -6131,7 +6114,8 @@ function closeHmModal() {
|
||||
}
|
||||
|
||||
// Show cell detail modal with Chart.js line chart and prompt history
|
||||
function showCellDetail(modelName, agentName) {
|
||||
function showCellDetail(event, modelName, agentName) {
|
||||
event.stopPropagation();
|
||||
const agent = agentData.agents[agentName];
|
||||
if (!agent) {
|
||||
console.error('Agent not found:', agentName);
|
||||
@@ -6345,9 +6329,13 @@ function renderHmModalContent(tabName) {
|
||||
case 'models':
|
||||
content = renderModelsTab(agent);
|
||||
break;
|
||||
case 'graph':
|
||||
content = renderGraphTab(agent);
|
||||
break;
|
||||
}
|
||||
|
||||
body.innerHTML = `<div class="hm-tab-content active" style="display:block">${content}</div>`;
|
||||
if (tabName === 'graph') setTimeout(() => renderCellChart(hmCurrentAgent, agent.current?.model || ''), 50);
|
||||
}
|
||||
|
||||
function renderPromptTab(agent) {
|
||||
@@ -6486,6 +6474,46 @@ function renderModelsTab(agent) {
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderGraphTab(agent) {
|
||||
return `
|
||||
<div style="margin-bottom:20px">
|
||||
<h3 style="margin-bottom:10px;color:var(--accent-cyan)">Performance Over Time</h3>
|
||||
<div style="position:relative;height:300px">
|
||||
<canvas id="cellChartCanvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="margin-bottom:10px;color:var(--accent-cyan)">Prompt Change History</h3>
|
||||
<div id="promptHistoryList" style="max-height:300px;overflow-y:auto">
|
||||
${renderPromptHistory(agent)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderPromptHistory(agent) {
|
||||
const promptChanges = (agent.history || []).filter(item => item.change_type === 'prompt_change');
|
||||
|
||||
if (promptChanges.length === 0) {
|
||||
return '<p style="color:var(--text-muted);text-align:center;padding:20px">No prompt change history found</p>';
|
||||
}
|
||||
|
||||
let html = '<ul style="list-style:none;padding:0">';
|
||||
promptChanges.forEach(change => {
|
||||
html += `
|
||||
<li style="padding:10px;border-bottom:1px solid var(--border);margin-bottom:10px">
|
||||
<div style="display:flex;justify-content:space-between;margin-bottom:5px">
|
||||
<span style="font-family:'JetBrains Mono',monospace;font-size:.8em;color:var(--text-muted)">${formatDate(change.date)}</span>
|
||||
<span style="font-family:'JetBrains Mono',monospace;font-size:.8em;color:var(--accent-cyan)">${change.commit ? change.commit.substring(0,7) : 'unknown'}</span>
|
||||
</div>
|
||||
<div style="font-size:.9em;color:var(--text-secondary)">${change.reason || 'No reason provided'}</div>
|
||||
</li>
|
||||
`;
|
||||
});
|
||||
html += '</ul>';
|
||||
return html;
|
||||
}
|
||||
|
||||
// Compute composite score for any model name
|
||||
// Formula (v2): IF_score * 0.85 + context_window_bonus (SWE-bench removed — all values unverifiable)
|
||||
function computeAgentScore(modelName) {
|
||||
@@ -6919,7 +6947,7 @@ function simulateApply() {
|
||||
progressStatus.textContent = 'Complete!';
|
||||
progressResult.classList.add('show');
|
||||
|
||||
const recs = INLINE_RECOMMENDATIONS && INLINE_RECOMMENDATIONS.length > 0 ? INLINE_RECOMMENDATIONS : [];
|
||||
const recs = Object.values(agentData.agents || {}).filter(a => (a.current?.recommendations || []).length > 0);
|
||||
progressResultText.textContent = `✅ ${recs.length} recommendations applied. Run 'bun run sync:evolution' to update dashboard.`;
|
||||
}
|
||||
}
|
||||
@@ -6970,11 +6998,11 @@ function showResearchModal() {
|
||||
step.classList.add('done');
|
||||
});
|
||||
|
||||
const recs = INLINE_RECOMMENDATIONS && INLINE_RECOMMENDATIONS.length > 0 ? INLINE_RECOMMENDATIONS : [];
|
||||
const modelsCount = new Set(recs.map(r => r.current_model).concat(recs.map(r => r.source_of_truth_model || r.recommended_model))).size;
|
||||
const recsCount = recs.filter(r => r.score_delta > 0).length;
|
||||
|
||||
document.getElementById('researchSummaryText').textContent =
|
||||
const recs = Object.values(agentData.agents || {}).filter(a => (a.current?.recommendations || []).length > 0);
|
||||
const modelsCount = new Set(recs.flatMap(a => [a.current?.model, a.current?.recommendations?.[0]?.target])).size;
|
||||
const recsCount = recs.filter(a => (a.current?.recommendations?.[0]?.score_delta || 0) > 0).length;
|
||||
|
||||
document.getElementById('researchSummaryText').textContent =
|
||||
`${modelsCount} models evaluated. ${recsCount} recommendations found. ${recs.length - recsCount} idle models detected.`;
|
||||
researchSummary.classList.add('show');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user