- Fix BatchProcessor constructor to avoid server blocking during startup - Add comprehensive integration tests for all modular combinations - Enhance CLAUDE.md documentation with new test commands - Update SelectiveLayers configuration for better LLM allocation - Add AutoReporter system for test automation - Include production workflow validation tests 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
407 lines
20 KiB
HTML
407 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Auto-Rapport TI - 9/18/2025, 2:28:42 PM</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
|
|
.container { max-width: 1000px; margin: 0 auto; }
|
|
.header { background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; margin-bottom: 20px; }
|
|
.stat-card { background: white; padding: 15px; border-radius: 8px; text-align: center; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
.stat-value { font-size: 1.8em; font-weight: bold; color: #2196F3; }
|
|
.stat-label { color: #666; margin-top: 5px; font-size: 14px; }
|
|
.test-list { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
.test-item { padding: 10px; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; align-items: center; cursor: pointer; transition: background-color 0.2s; }
|
|
.test-item:hover { background: #f8f9fa; }
|
|
.test-item.clickable { border-left: 4px solid #4CAF50; }
|
|
.test-status { width: 12px; height: 12px; border-radius: 50%; margin-right: 10px; }
|
|
.status-passed { background: #4CAF50; }
|
|
.status-failed { background: #f44336; }
|
|
.llm-section { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-top: 20px; }
|
|
.llm-call { background: #f9f9f9; padding: 10px; margin: 5px 0; border-radius: 4px; display: flex; justify-content: space-between; cursor: pointer; transition: background-color 0.2s; }
|
|
.llm-call:hover { background: #e8f4f8; }
|
|
.llm-call.clickable { border-left: 4px solid #2196F3; }
|
|
.phases-section { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-top: 20px; }
|
|
.phase-timeline { display: flex; flex-direction: column; gap: 10px; }
|
|
.phase-item { background: #f8f9fa; padding: 12px; border-radius: 6px; border-left: 4px solid #9C27B0; display: flex; justify-content: space-between; align-items: center; }
|
|
.phase-item.completed { border-left-color: #4CAF50; background: #f1f8e9; }
|
|
.phase-item.started { border-left-color: #FF9800; background: #fff3e0; }
|
|
.phase-number { width: 30px; height: 30px; border-radius: 50%; background: #9C27B0; color: white; display: flex; align-items: center; justify-content: center; font-weight: bold; margin-right: 12px; }
|
|
.phase-number.completed { background: #4CAF50; }
|
|
.phase-number.started { background: #FF9800; }
|
|
|
|
/* Modal styles */
|
|
.modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); }
|
|
#llmModal { z-index: 1100; } /* LLM modal au-dessus du test modal */
|
|
.modal-content { background-color: white; margin: 5% auto; padding: 20px; border-radius: 8px; width: 90%; max-width: 800px; max-height: 80vh; overflow-y: auto; }
|
|
.close { color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer; }
|
|
.close:hover { color: black; }
|
|
.prompt-section, .response-section { margin: 15px 0; }
|
|
.prompt-section h4, .response-section h4 { color: #333; border-bottom: 2px solid #2196F3; padding-bottom: 5px; }
|
|
.prompt-content, .response-content { background: #f5f5f5; padding: 15px; border-radius: 4px; white-space: pre-wrap; font-family: monospace; font-size: 14px; max-height: 300px; overflow-y: auto; }
|
|
.response-content { background: #f0f8ff; }
|
|
|
|
/* Test details modal styles */
|
|
.test-details-section { margin: 15px 0; }
|
|
.test-details-section h4 { color: #333; border-bottom: 2px solid #4CAF50; padding-bottom: 5px; }
|
|
.test-llm-list { background: #f8f9fa; padding: 10px; border-radius: 4px; margin-top: 10px; }
|
|
.test-llm-item { background: white; margin: 5px 0; padding: 8px; border-radius: 3px; display: flex; justify-content: space-between; cursor: pointer; border: 1px solid #ddd; }
|
|
.test-llm-item:hover { background: #e8f4f8; }
|
|
.test-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; margin: 10px 0; }
|
|
.test-stat { background: #f0f0f0; padding: 8px; border-radius: 4px; text-align: center; }
|
|
.test-stat-value { font-weight: bold; color: #2196F3; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>📊 Auto-Rapport Tests d'Intégration</h1>
|
|
<p>Généré automatiquement le 9/18/2025, 2:28:42 PM</p>
|
|
</div>
|
|
|
|
<div class="stats">
|
|
<div class="stat-card">
|
|
<div class="stat-value">1</div>
|
|
<div class="stat-label">Tests</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value" style="color: #4CAF50">0</div>
|
|
<div class="stat-label">Réussis</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value" style="color: #f44336">1</div>
|
|
<div class="stat-label">Échoués</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">0</div>
|
|
<div class="stat-label">LLM Calls</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">29s</div>
|
|
<div class="stat-label">Durée</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-list">
|
|
<h3>Résultats des Tests</h3>
|
|
|
|
<div class="test-item clickable" onclick="openTestModal(0)">
|
|
<div style="display: flex; align-items: center;">
|
|
<span class="test-status status-failed"></span>
|
|
<div>
|
|
<div><strong>Main.handleModularWorkflowWithData()(data=[object Object], config=[object Object], modularWorkflow=true, compatibilityMode=true, selectiveStack=standardEnhancement, adversarialMode=light, humanSimulationMode=none, patternBreakingMode=none, source=test_integration) FAILED</strong></div>
|
|
<div style="font-size: 12px; color: #666;">
|
|
0 LLM calls • 0s durée LLM
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div style="text-align: right;">
|
|
<div style="color: #f44336; font-weight: bold;">
|
|
✗ ÉCHOUÉ
|
|
</div>
|
|
<div style="font-size: 10px; color: #2196F3; margin-top: 2px;">
|
|
🔍 Cliquer pour détails
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="llm-section">
|
|
<h3>Appels LLM (0)</h3>
|
|
|
|
</div>
|
|
|
|
<!-- Modal pour afficher les détails LLM -->
|
|
<div id="llmModal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" onclick="closeModal()">×</span>
|
|
<h2 id="modalTitle">Détails de l'appel LLM</h2>
|
|
|
|
<div class="prompt-section">
|
|
<h4>🔍 Prompt envoyé</h4>
|
|
<div id="promptContent" class="prompt-content">Aucun prompt capturé</div>
|
|
</div>
|
|
|
|
<div class="response-section">
|
|
<h4>📥 Réponse reçue</h4>
|
|
<div id="responseContent" class="response-content">Aucune réponse capturée</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal pour afficher les détails de test -->
|
|
<div id="testModal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" onclick="closeTestModal()">×</span>
|
|
<h2 id="testModalTitle">Détails du test</h2>
|
|
|
|
<div class="test-details-section">
|
|
<h4>📊 Statistiques</h4>
|
|
<div id="testStats" class="test-stats">
|
|
<!-- Stats will be populated here -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-details-section">
|
|
<h4>🚀 Appels LLM associés</h4>
|
|
<div id="testLLMCalls" class="test-llm-list">
|
|
<!-- LLM calls will be listed here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal pour afficher les détails de phase -->
|
|
<div id="phaseModal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" onclick="closePhaseModal()">×</span>
|
|
<h2 id="phaseModalTitle">Détails de la phase</h2>
|
|
|
|
<div class="test-details-section">
|
|
<h4>📊 Métriques de la phase</h4>
|
|
<div id="phaseMetrics" class="test-stats">
|
|
<!-- Metrics will be populated here -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-details-section">
|
|
<h4>🚀 Appels LLM de cette phase</h4>
|
|
<div id="phaseLLMCalls" class="test-llm-list">
|
|
<!-- Phase LLM calls will be listed here -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-details-section">
|
|
<h4>⏱️ Timeline</h4>
|
|
<div id="phaseTimeline" style="background: #f8f9fa; padding: 10px; border-radius: 4px;">
|
|
<!-- Timeline will be populated here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const llmCalls = [];
|
|
const testResults = [{"name":"Main.handleModularWorkflowWithData()(data=[object Object], config=[object Object], modularWorkflow=true, compatibilityMode=true, selectiveStack=standardEnhancement, adversarialMode=light, humanSimulationMode=none, patternBreakingMode=none, source=test_integration) FAILED","status":"failed","duration":78.5,"timestamp":1758176907581,"llmCallsCount":0}];
|
|
const phases = [];
|
|
|
|
function openModal(index) {
|
|
const call = llmCalls[index];
|
|
if (!call) return;
|
|
|
|
const modal = document.getElementById('llmModal');
|
|
const title = document.getElementById('modalTitle');
|
|
const promptContent = document.getElementById('promptContent');
|
|
const responseContent = document.getElementById('responseContent');
|
|
|
|
title.textContent = `${call.provider.toUpperCase()} (${call.model}) - ${call.testContext}`;
|
|
|
|
promptContent.textContent = call.prompt || 'Aucun prompt capturé';
|
|
responseContent.textContent = call.response || 'Aucune réponse capturée';
|
|
|
|
modal.style.display = 'block';
|
|
}
|
|
|
|
function closeModal() {
|
|
document.getElementById('llmModal').style.display = 'none';
|
|
}
|
|
|
|
function openTestModal(index) {
|
|
const test = testResults[index];
|
|
if (!test) return;
|
|
|
|
const modal = document.getElementById('testModal');
|
|
const title = document.getElementById('testModalTitle');
|
|
const statsDiv = document.getElementById('testStats');
|
|
const llmCallsDiv = document.getElementById('testLLMCalls');
|
|
|
|
title.textContent = `Test: ${test.name}`;
|
|
|
|
// Get LLM calls for this test
|
|
const testLLMCalls = llmCalls.filter(call => call.testContext === test.name);
|
|
const totalDuration = testLLMCalls.reduce((sum, call) => sum + call.duration, 0);
|
|
const totalTokensIn = testLLMCalls.reduce((sum, call) => sum + (call.tokens?.prompt || 0), 0);
|
|
const totalTokensOut = testLLMCalls.reduce((sum, call) => sum + (call.tokens?.response || 0), 0);
|
|
|
|
// Populate stats
|
|
statsDiv.innerHTML = `
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${test.status === 'passed' ? '✓' : '✗'}</div>
|
|
<div>Statut</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${testLLMCalls.length}</div>
|
|
<div>LLM Calls</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${Math.round(totalDuration/1000)}s</div>
|
|
<div>Durée LLM</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${totalTokensIn}</div>
|
|
<div>Tokens Input</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${totalTokensOut}</div>
|
|
<div>Tokens Output</div>
|
|
</div>
|
|
`;
|
|
|
|
// Populate LLM calls
|
|
if (testLLMCalls.length > 0) {
|
|
llmCallsDiv.innerHTML = testLLMCalls.map((call, callIndex) => {
|
|
const globalIndex = llmCalls.findIndex(c => c === call);
|
|
return `
|
|
<div class="test-llm-item" onclick="openModal(${globalIndex})">
|
|
<div>
|
|
<strong>${call.provider.toUpperCase()}</strong> (${call.model})
|
|
<div style="font-size: 11px; color: #666; margin-top: 2px;">
|
|
${new Date(call.timestamp).toLocaleTimeString()}
|
|
</div>
|
|
</div>
|
|
<div style="text-align: right;">
|
|
<div>${call.duration}ms</div>
|
|
<div style="font-size: 11px; color: #666;">
|
|
${call.tokens?.prompt || 0}→${call.tokens?.response || 0} tokens
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
} else {
|
|
llmCallsDiv.innerHTML = '<div style="color: #666; text-align: center; padding: 20px;">Aucun appel LLM pour ce test</div>';
|
|
}
|
|
|
|
modal.style.display = 'block';
|
|
}
|
|
|
|
function closeTestModal() {
|
|
document.getElementById('testModal').style.display = 'none';
|
|
}
|
|
|
|
function openPhaseModal(index) {
|
|
const phase = phases[index];
|
|
if (!phase) return;
|
|
|
|
const modal = document.getElementById('phaseModal');
|
|
const title = document.getElementById('phaseModalTitle');
|
|
const metricsDiv = document.getElementById('phaseMetrics');
|
|
const llmCallsDiv = document.getElementById('phaseLLMCalls');
|
|
const timelineDiv = document.getElementById('phaseTimeline');
|
|
|
|
title.textContent = `Phase ${phase.number}/4: ${phase.name}`;
|
|
|
|
// Populate metrics
|
|
const metrics = phase.metrics || {};
|
|
metricsDiv.innerHTML = `
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${phase.status === 'completed' ? '✓' : '⏳'}</div>
|
|
<div>Statut</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${metrics.totalElements || 0}</div>
|
|
<div>Éléments</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${metrics.modifications || 0}</div>
|
|
<div>Modifications</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${metrics.processed || 0}/${metrics.total || 0}</div>
|
|
<div>Traités</div>
|
|
</div>
|
|
<div class="test-stat">
|
|
<div class="test-stat-value">${phase.duration ? Math.round(phase.duration) + 'ms' : 'N/A'}</div>
|
|
<div>Durée</div>
|
|
</div>
|
|
`;
|
|
|
|
// Get LLM calls for this phase (by timestamp range)
|
|
const phaseStart = new Date(phase.timestamp);
|
|
const phaseEnd = phase.endTimestamp ? new Date(phase.endTimestamp) : new Date();
|
|
const phaseLLMCalls = llmCalls.filter(call => {
|
|
const callTime = new Date(call.timestamp);
|
|
return callTime >= phaseStart && callTime <= phaseEnd;
|
|
});
|
|
|
|
// Populate LLM calls
|
|
if (phaseLLMCalls.length > 0) {
|
|
llmCallsDiv.innerHTML = phaseLLMCalls.map((call, callIndex) => {
|
|
const globalIndex = llmCalls.findIndex(c => c === call);
|
|
return `
|
|
<div class="test-llm-item" onclick="openModal(${globalIndex})">
|
|
<div>
|
|
<strong>${call.provider.toUpperCase()}</strong> (${call.model})
|
|
<div style="font-size: 11px; color: #666; margin-top: 2px;">
|
|
${new Date(call.timestamp).toLocaleTimeString()}
|
|
</div>
|
|
</div>
|
|
<div style="text-align: right;">
|
|
<div>${call.duration}ms</div>
|
|
<div style="font-size: 11px; color: #666;">
|
|
${call.promptTokens || 0}→${call.responseTokens || 0} tokens
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
} else {
|
|
llmCallsDiv.innerHTML = '<div style="color: #666; text-align: center; padding: 20px;">Aucun appel LLM pour cette phase</div>';
|
|
}
|
|
|
|
// Populate timeline
|
|
timelineDiv.innerHTML = `
|
|
<div style="margin-bottom: 10px;">
|
|
<strong>🚀 Début:</strong> ${new Date(phase.timestamp).toLocaleTimeString()}
|
|
</div>
|
|
${phase.endTimestamp ? `
|
|
<div style="margin-bottom: 10px;">
|
|
<strong>✅ Fin:</strong> ${new Date(phase.endTimestamp).toLocaleTimeString()}
|
|
</div>
|
|
<div style="margin-bottom: 10px;">
|
|
<strong>⏱️ Durée:</strong> ${phase.duration ? Math.round(phase.duration) + 'ms' : 'N/A'}
|
|
</div>
|
|
` : '<div style="color: #FF9800;"><strong>⏳ En cours...</strong></div>'}
|
|
<div>
|
|
<strong>🧪 Test:</strong> ${phase.testContext || 'unknown'}
|
|
</div>
|
|
`;
|
|
|
|
modal.style.display = 'block';
|
|
}
|
|
|
|
function closePhaseModal() {
|
|
document.getElementById('phaseModal').style.display = 'none';
|
|
}
|
|
|
|
// Fermer modal en cliquant à l'extérieur
|
|
window.onclick = function(event) {
|
|
const llmModal = document.getElementById('llmModal');
|
|
const testModal = document.getElementById('testModal');
|
|
const phaseModal = document.getElementById('phaseModal');
|
|
if (event.target === llmModal) {
|
|
closeModal();
|
|
}
|
|
if (event.target === testModal) {
|
|
closeTestModal();
|
|
}
|
|
if (event.target === phaseModal) {
|
|
closePhaseModal();
|
|
}
|
|
}
|
|
|
|
// Fermer modal avec Escape
|
|
document.addEventListener('keydown', function(event) {
|
|
if (event.key === 'Escape') {
|
|
closeModal();
|
|
closeTestModal();
|
|
closePhaseModal();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |