- 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
99 lines
4.5 KiB
JavaScript
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 => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[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');
|