Files
APAW/agent-evolution/scripts/patch-heatmap.js
Deploy Bot b95fd41587 feat(evolution): add real-fit dashboard, API, report builder, and docker compose
- real-fit.html: API-driven research dashboard with agent/model heatmap, detail modal with score breakdown and evaluator commentary
- api.py: FastAPI backend serving /api/real-fit-report (dynamic from SQLite), /api/research, /api/evolve-agent/start
- rebuild-report.py: generates real-fit-report.json from SQLite DB for static fallback
- docker-compose.yml: add evolution-api service (Python 3.12, uvicorn) for research endpoints
- index.standalone.html: sync with dashboard data updates
- archive/index.html: standalone dashboard snapshot (263KB)
- .gitignore: exclude *.db, research-jobs.json from tracking
2026-05-28 11:55:49 +01:00

99 lines
4.5 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const INDEX = path.join(__dirname, '../index.standalone.html');
// 1. New renderHeatmap that reads real-fit data
const newRenderHeatmap = `function renderHeatmap() {
const esc = str => (str || '').replace(/[&<>"']/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));
const dd = window.dashboardData;
// Merge real-fit if loaded
const rf = window.realFitData || {};
const realAgents = rf.agents || {};
if (!dd || !dd.agents) {
document.getElementById('hmTable').innerHTML = '<tr><td style="color:var(--text-secondary);padding:20px;text-align:center;">⚠️ No data. Run analysis.</td></tr>';
return;
}
// Build model list from real-fit (cross-model) + current dashboard data
const modelsSeen = new Set();
dd.agents.forEach(a => { modelsSeen.add(a.model_short); });
Object.values(realAgents).forEach(a => { Object.keys(a.evaluations || {}).forEach(m => modelsSeen.add(m)); });
const modelList = Array.from(modelsSeen).filter(m => m && m !== 'code-skeptic');
const t = document.getElementById('hmTable');
let h = '<thead><tr><th class="hm-role">Agent</th>';
modelList.forEach(m => {
h += '<th style="writing-mode:vertical-lr;transform:rotate(180deg);max-width:32px;font-size:.56em;padding:3px 1px;">' + esc(m) + '</th>';
});
h += '<th>Best</th><th>Score</th></tr></thead><tbody>';
dd.agents.forEach(a => {
const realAgent = realAgents[a.name];
h += '<tr><td class="hm-r">' + esc(a.name) + '</td>';
modelList.forEach(m => {
let score = 0;
if (realAgent && realAgent.evaluations && realAgent.evaluations[m] > 0) {
score = Math.round(realAgent.evaluations[m]);
}
const isCurrent = a.model_short === m;
let cls = 'na';
if (score >= 90) cls = 'high';
else if (score >= 75) cls = 'good';
else if (score >= 50) cls = 'med';
else if (score > 0) cls = 'low';
const display = score > 0 ? score : (isCurrent ? Math.round(a.fit_score || 0) : '·');
const curStyle = isCurrent ? 'box-shadow:inset 0 0 0 2px var(--accent-cyan)' : '';
h += '<td class="score ' + cls + '" style="' + curStyle + '">' + display + '</td>';
});
const bestModel = realAgent ? (realAgent.best_model || a.model_short) : a.model_short;
const bestScore = realAgent ? Math.round(realAgent.best_score || 0) : Math.round(a.fit_score || 0);
h += '<td>' + esc(bestModel) + '</td><td style="font-weight:700">' + bestScore + '</td></tr>';
});
t.innerHTML = h + '</tbody>';
}`;
// 2. Add loadRealFitData script after dashboard load
const loadRealFitData = `
// Load real-fit report for cross-model evaluation
try {
const rfRes = await fetch('data/real-fit-report.json');
if (rfRes.ok) window.realFitData = await rfRes.json();
} catch(e) { console.warn('real-fit-report.json not loaded:', e.message); }
`;
let html = fs.readFileSync(INDEX, 'utf-8');
// Patch A: replace renderHeatmap function
const oldPattern = /\/\/ Render Heatmap[\s\S]*?function renderHeatmap\(\)\s*\{[^}]*\{[^}]*\}[^}]*\}/;
const oldMatch = html.match(oldPattern);
if (oldMatch) {
html = html.substring(0, oldMatch.index) + '// Render Heatmap (real-fit enabled)\n' + newRenderHeatmap + html.substring(oldMatch.index + oldMatch[0].length);
console.log('Patched renderHeatmap');
} else {
console.log('Pattern A not found, trying fallback...');
// Fallback: find and replace the specific renderHeatmap block
const start = html.indexOf('function renderHeatmap() {');
if (start !== -1) {
let brace = 0, end = start;
for (let i = start; i < html.length; i++) {
if (html[i] === '{') brace++;
else if (html[i] === '}') { brace--; if (brace === 0) { end = i + 1; break; } }
}
html = html.substring(0, start) + newRenderHeatmap + '\n' + html.substring(end);
console.log('Patched renderHeatmap (fallback)');
}
}
// Patch B: insert real-fit loading after dashboard load
const dashLoadPattern = /window\.dashboardData = await dashRes\.json\(\);/;
if (dashLoadPattern.test(html)) {
html = html.replace(dashLoadPattern, 'window.dashboardData = await dashRes.json();\n' + loadRealFitData.trim());
console.log('Patched init() to load real-fit data');
}
fs.writeFileSync(INDEX, html);
console.log('Done — ' + (fs.statSync(INDEX).size / 1024).toFixed(1) + ' KB');