diff --git a/network-poc/frontend/src/pages/index.astro b/network-poc/frontend/src/pages/index.astro index 7e1671a..6fdc109 100644 --- a/network-poc/frontend/src/pages/index.astro +++ b/network-poc/frontend/src/pages/index.astro @@ -1418,20 +1418,71 @@ Blog → Author: name,email,bio(Text|None) / Post: title, content(Text), author_ let stepN = fileOrder.length + 2; - // === Vaihe 4: Mekaaninen QA-validointi === + // === Vaihe 4: Mekaaninen QA-validointi + korjaussilmukka === const qaAgent = agents.qa || Object.values(agents)[4]; - termLog(`\n[${stepN}] ${esc(qaAgent.name)} — validointi`); - highlightAgent('qa'); - explainStep('Validointi', `${qaAgent.name} ajaa mekaanisen koodivalidoinnin.`); + const MAX_FIX_ROUNDS = 2; + let mechIssues = validateProjectCode(files); + let fixRound = 0; - const mechIssues = validateProjectCode(files); - if (mechIssues.length > 0) { - termLog(` ⚠ ${mechIssues.length} ongelmaa (template-bugeja — korjattava):`); + while (mechIssues.length > 0 && fixRound < MAX_FIX_ROUNDS) { + fixRound++; + termLog(`\n[${stepN}] ${esc(qaAgent.name)} — validointi (kierros ${fixRound})`); + highlightAgent('qa'); + explainStep('Validointi', `${qaAgent.name} löysi ${mechIssues.length} ongelmaa — delegoidaan korjattavaksi.`); + termLog(` ⚠ ${mechIssues.length} ongelmaa:`); for (const issue of mechIssues) termLog(` ${esc(issue)}`); - } else { - termLog(` ✓ Kaikki tiedostot validoitu — 0 ongelmaa`); + promptLog.push({ step: promptLog.length, agentKey: 'qa', agentName: qaAgent.name, model: 'mekaaninen', label: `validointi #${fixRound}`, systemPrompt: '(mekaaninen validointi)', userPrompt: 'validateProjectCode(files)', response: mechIssues.join('\n') }); + stepN++; + + // Ryhmitellään ongelmat tiedostoittain + const issuesByFile = {}; + for (const issue of mechIssues) { + const m = issue.match(/^ISSUE:\s*(\S+?):/); + const fname = m ? m[1] : 'unknown'; + if (!issuesByFile[fname]) issuesByFile[fname] = []; + issuesByFile[fname].push(issue); + } + + // Delegoidaan korjaukset Coder-agentille tiedosto kerrallaan + for (const [fname, fIssues] of Object.entries(issuesByFile)) { + if (!files[fname]) continue; + const fixAgent = agents[agentMap[fname]] || cdr; + termLog(`\n[${stepN}] ${esc(fixAgent.name)} — korjaa ${esc(fname)} (${fIssues.length} ongelmaa)`); + highlightAgent(agentMap[fname] || 'coder'); + explainStep(`Korjaus: ${fname}`, `${fixAgent.name} korjaa validoinnin löytämät ongelmat.`); + + const fixPrompt = `Fix the following issues in this Python file. Return ONLY the complete corrected file, no explanations.\n\nISSUES:\n${fIssues.join('\n')}\n\nCURRENT FILE (${fname}):\n\`\`\`python\n${files[fname]}\`\`\``; + const fixResult = await kpnRun(fixAgent.model, fixPrompt, false, { ...fixAgent, prompt: 'You are a Python code fixer. Return ONLY the corrected Python file. No markdown fences, no explanations — just valid Python code.' }); + + if (fixResult) { + // Poistetaan markdown-koodiblokit jos LLM palauttaa ne + let cleaned = fixResult.replace(/^```(?:python)?\s*\n?/m, '').replace(/\n?```\s*$/m, '').trim() + '\n'; + files[fname] = cleaned; + termLog(` ✓ ${esc(fname)} korjattu`); + } else { + termLog(` ✗ ${esc(fname)} korjaus epäonnistui — pidetään alkuperäinen`); + } + promptLog.push({ step: promptLog.length, agentKey: agentMap[fname] || 'coder', agentName: fixAgent.name, model: fixAgent.model, label: `korjaus: ${fname}`, systemPrompt: '(code fixer)', userPrompt: fixPrompt, response: fixResult || '(epäonnistui)' }); + stepN++; + } + + // Validoidaan uudelleen + mechIssues = validateProjectCode(files); } - promptLog.push({ step: promptLog.length, agentKey: 'qa', agentName: qaAgent.name, model: 'mekaaninen', label: 'validointi', systemPrompt: '(mekaaninen validointi — ei LLM:ää)', userPrompt: 'validateProjectCode(files)', response: mechIssues.length === 0 ? 'OK — 0 issues' : mechIssues.join('\n') }); + + // Lopullinen validointitulos + termLog(`\n[${stepN}] ${esc(qaAgent.name)} — lopullinen validointi`); + highlightAgent('qa'); + if (mechIssues.length > 0) { + explainStep('Validointi', `${mechIssues.length} ongelmaa jäi korjaamatta ${MAX_FIX_ROUNDS} kierroksen jälkeen.`); + termLog(` ✗ ${mechIssues.length} ongelmaa jäljellä ${fixRound} korjauskierroksen jälkeen:`); + for (const issue of mechIssues) termLog(` ${esc(issue)}`); + } else { + const msg = fixRound > 0 ? `✓ Kaikki ongelmat korjattu (${fixRound} kierrosta)` : '✓ Kaikki tiedostot validoitu — 0 ongelmaa'; + explainStep('Validointi', msg); + termLog(` ${msg}`); + } + promptLog.push({ step: promptLog.length, agentKey: 'qa', agentName: qaAgent.name, model: 'mekaaninen', label: 'lopullinen validointi', systemPrompt: '(mekaaninen validointi)', userPrompt: 'validateProjectCode(files)', response: mechIssues.length === 0 ? `OK — korjattu ${fixRound} kierroksessa` : mechIssues.join('\n') }); stepN++; // Tarkkailija: yhteenveto + raportti + arvosana