Testaaja: staattinen analyysi + strukturoitu LLM-arviointi
Staattinen analyysi selaimessa (ennen LLM:ää): - Käyttämättömät importit - Puuttuvat importit (FastAPI, Session) - Tyhjät funktiot LLM-arviointi 5 kohdalla (esimerkkivastauksineen): 1. Imports, 2. Database, 3. Endpoints, 4. Error handling, 5. Security Korjausluuppi käynnistyy jos ✗ löytyy tai staattinen analyysi huomauttaa. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2499,17 +2499,70 @@ IMPORTANT: Keep the code SHORT. Max ~50 lines. No comments, no docstrings. Write
|
|||||||
.map(([name, code]) => `--- ${name} ---\n${code}`)
|
.map(([name, code]) => `--- ${name} ---\n${code}`)
|
||||||
.join('\n\n');
|
.join('\n\n');
|
||||||
|
|
||||||
termLog(`\n<span style="color:#58a6ff;font-weight:bold">[${fileList.length + 2}] Testaaja</span> — arviointi`);
|
// Staattinen analyysi ennen LLM-arviointia
|
||||||
|
termLog(`\n<span style="color:#58a6ff;font-weight:bold">[${fileList.length + 2}] Testaaja</span> — staattinen analyysi + arviointi`);
|
||||||
pipelineStep('tester', 'Review', 'active', `${Object.keys(generatedFiles).length} tiedostoa`);
|
pipelineStep('tester', 'Review', 'active', `${Object.keys(generatedFiles).length} tiedostoa`);
|
||||||
const reviewPrompt = `Review this project. List bugs or issues. Be brief.
|
|
||||||
If the code is correct, say "LGTM".
|
// Yksinkertainen staattinen tarkistus selaimessa
|
||||||
|
const staticIssues = [];
|
||||||
|
for (const [name, code] of Object.entries(generatedFiles)) {
|
||||||
|
if (!name.endsWith('.py')) continue;
|
||||||
|
const lines = (code || '').split('\n');
|
||||||
|
// Tarkista importit
|
||||||
|
const imports = lines.filter(l => l.match(/^(from|import)\s/));
|
||||||
|
const usedNames = code.replace(/^(from|import)\s.*/gm, '');
|
||||||
|
for (const imp of imports) {
|
||||||
|
const match = imp.match(/import\s+(\w+)|from\s+\S+\s+import\s+(.+)/);
|
||||||
|
if (match) {
|
||||||
|
const names = (match[1] || match[2]).split(',').map(n => n.trim().split(' as ').pop().trim());
|
||||||
|
for (const n of names) {
|
||||||
|
if (n && !usedNames.includes(n) && n !== '*') {
|
||||||
|
staticIssues.push(`${name}: käyttämätön import '${n}'`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Tarkista puuttuvat importit
|
||||||
|
if (code.includes('FastAPI') && !imports.some(i => i.includes('FastAPI'))) {
|
||||||
|
staticIssues.push(`${name}: käyttää FastAPI mutta ei importtaa sitä`);
|
||||||
|
}
|
||||||
|
if (code.includes('Session') && !imports.some(i => i.includes('Session'))) {
|
||||||
|
staticIssues.push(`${name}: käyttää Session mutta ei importtaa sitä`);
|
||||||
|
}
|
||||||
|
// Tarkista tyhjät funktiot
|
||||||
|
const emptyFuncs = code.match(/def \w+\([^)]*\):\s*\n\s*(pass|\.\.\.)/g);
|
||||||
|
if (emptyFuncs) staticIssues.push(`${name}: ${emptyFuncs.length} tyhjää funktiota`);
|
||||||
|
}
|
||||||
|
if (staticIssues.length > 0) {
|
||||||
|
termLog(` <span style="color:#d29922">Staattinen analyysi (${staticIssues.length} huomautusta):</span>`);
|
||||||
|
for (const issue of staticIssues) {
|
||||||
|
termLog(` <span style="color:#d29922">⚠</span> ${esc(issue)}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
termLog(' <span style="color:#3fb950">Staattinen analyysi: ei huomautuksia</span>');
|
||||||
|
}
|
||||||
|
const reviewPrompt = `Review this project code. Check EVERY item and report result:
|
||||||
|
|
||||||
|
1. Imports: ✓/✗ — are all imports valid and available?
|
||||||
|
2. Database: ✓/✗ — is the DB setup correct (engine, session, models)?
|
||||||
|
3. Endpoints: ✓/✗ — do all routes have correct parameters and return types?
|
||||||
|
4. Error handling: ✓/✗ — are edge cases handled (404, validation)?
|
||||||
|
5. Security: ✓/✗ — any SQL injection, missing auth, or data exposure?
|
||||||
|
|
||||||
|
EXAMPLE output:
|
||||||
|
1. Imports: ✓ — all imports are valid
|
||||||
|
2. Database: ✗ — missing Base.metadata.create_all(engine) call
|
||||||
|
3. Endpoints: ✓ — GET/POST/DELETE routes are correct
|
||||||
|
4. Error handling: ✗ — no 404 when todo not found
|
||||||
|
5. Security: ✓ — using ORM, no raw SQL
|
||||||
|
|
||||||
${allCode}`;
|
${allCode}`;
|
||||||
const review = await kpnRun(agentPrompts.tester.model, reviewPrompt, false, 200);
|
const review = await kpnRun(agentPrompts.tester.model, reviewPrompt, false, 300);
|
||||||
pipelineStep('tester', 'Review', 'done', `${Object.keys(generatedFiles).length} tiedostoa`, review);
|
pipelineStep('tester', 'Review', 'done', `${Object.keys(generatedFiles).length} tiedostoa`, review);
|
||||||
|
|
||||||
// Vaihe 4: Korjausluuppi — jos testaaja löysi ongelmia
|
// Vaihe 4: Korjausluuppi — jos testaaja löysi ongelmia
|
||||||
if (review && !review.toLowerCase().includes('lgtm') && !review.toLowerCase().includes('looks good')) {
|
const hasIssues = review && (review.includes('✗') || staticIssues.length > 0);
|
||||||
|
if (hasIssues) {
|
||||||
termLog(`\n<span style="color:#d29922;font-weight:bold">[${fileList.length + 3}] Koodari</span> — korjaukset`);
|
termLog(`\n<span style="color:#d29922;font-weight:bold">[${fileList.length + 3}] Koodari</span> — korjaukset`);
|
||||||
pipelineStep('coder', 'Korjaukset', 'active', review);
|
pipelineStep('coder', 'Korjaukset', 'active', review);
|
||||||
const fixPrompt = `Fix the issues found in the review.
|
const fixPrompt = `Fix the issues found in the review.
|
||||||
|
|||||||
Reference in New Issue
Block a user