From cea19611839dbe628f3a95e5c1b82478bcb76154 Mon Sep 17 00:00:00 2001 From: jaakko Date: Tue, 7 Apr 2026 10:13:15 +0300 Subject: [PATCH] Testaaja: staattinen analyysi + strukturoitu LLM-arviointi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- network-poc/static/index.html | 63 ++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/network-poc/static/index.html b/network-poc/static/index.html index 7b1e2c7..c7bcbbf 100644 --- a/network-poc/static/index.html +++ b/network-poc/static/index.html @@ -2499,17 +2499,70 @@ IMPORTANT: Keep the code SHORT. Max ~50 lines. No comments, no docstrings. Write .map(([name, code]) => `--- ${name} ---\n${code}`) .join('\n\n'); - termLog(`\n[${fileList.length + 2}] Testaaja — arviointi`); + // Staattinen analyysi ennen LLM-arviointia + termLog(`\n[${fileList.length + 2}] Testaaja — staattinen analyysi + arviointi`); 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(` Staattinen analyysi (${staticIssues.length} huomautusta):`); + for (const issue of staticIssues) { + termLog(` ${esc(issue)}`); + } + } else { + termLog(' Staattinen analyysi: ei huomautuksia'); + } + 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}`; - 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); // 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[${fileList.length + 3}] Koodari — korjaukset`); pipelineStep('coder', 'Korjaukset', 'active', review); const fixPrompt = `Fix the issues found in the review.