From 27da64d77815020056d40d9932d3bf7cb1ebbf42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sondre=20Engebr=C3=A5ten?= Date: Sat, 14 Feb 2026 19:36:49 +0100 Subject: [PATCH] fix(issues): include all fix approaches in task creation + i18n specialist labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task creation from investigation reports now includes root cause context, ALL fix approaches with pros/cons/complexity, gotchas, and patterns to follow — not just the recommended approach. This gives the coder agent full context to choose the best strategy. Also fixes i18n violation: specialist labels in GeneralSettings now use translation keys instead of hardcoded English strings from models.ts. Co-Authored-By: Claude Opus 4.6 --- .../github/services/parallel_agent_base.py | 4 +- .../github/investigation-handlers.ts | 168 +++++++++++++----- .../components/settings/GeneralSettings.tsx | 5 +- .../src/shared/i18n/locales/en/settings.json | 18 +- .../src/shared/i18n/locales/fr/settings.json | 18 +- 5 files changed, 165 insertions(+), 48 deletions(-) diff --git a/apps/backend/runners/github/services/parallel_agent_base.py b/apps/backend/runners/github/services/parallel_agent_base.py index 4eb6db37..7fcba2dd 100644 --- a/apps/backend/runners/github/services/parallel_agent_base.py +++ b/apps/backend/runners/github/services/parallel_agent_base.py @@ -200,7 +200,9 @@ class ParallelAgentOrchestrator: model, effective_thinking ) # Override effort_level if explicitly provided (e.g., investigation - # agents always use "high" effort regardless of thinking level) + # agents always use "high" effort regardless of thinking level). + # Only applies to adaptive models (Opus 4.6+) where thinking_kwargs + # includes effort_level; non-adaptive models silently skip this. if effort_level and "effort_level" in thinking_kwargs: thinking_kwargs["effort_level"] = effort_level diff --git a/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts index b1ded0fd..a1480b11 100644 --- a/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts +++ b/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts @@ -713,6 +713,127 @@ function getInvestigationSettings(projectId: string): InvestigationSettings { return createDefaultSettings(); } +/** + * Build a comprehensive task description from an investigation report. + * Includes root cause, ALL fix approaches with pros/cons, gotchas, and + * patterns to follow — so the AI coder agent has full context. + */ +function buildTaskDescriptionFromReport( + issueNumber: number, + reportData: Record, +): string { + const summary = (reportData.ai_summary as string) || `Investigation of issue #${issueNumber}`; + const fixAdvice = reportData.fix_advice as { + approaches?: Array<{ + description?: string; + complexity?: string; + files_affected?: string[]; + pros?: string[]; + cons?: string[]; + }>; + recommended_approach?: number; + gotchas?: string[]; + patterns_to_follow?: Array<{ file?: string; description?: string }>; + } | undefined; + const rootCause = reportData.root_cause as { + identified_root_cause?: string; + confidence?: string; + evidence?: string; + code_paths?: Array<{ file?: string; description?: string }>; + } | undefined; + + const sections: string[] = [ + `# GitHub Issue #${issueNumber}`, + '', + '## Summary', + summary, + ]; + + // Root cause context for the coder agent + if (rootCause?.identified_root_cause) { + sections.push( + '', + '## Root Cause', + `**Confidence:** ${rootCause.confidence ?? 'unknown'}`, + '', + rootCause.identified_root_cause, + ); + if (rootCause.code_paths?.length) { + sections.push( + '', + '### Code Paths', + ...rootCause.code_paths.map( + (cp) => `- \`${cp.file}\` — ${cp.description ?? ''}`, + ), + ); + } + if (rootCause.evidence) { + sections.push('', '### Evidence', rootCause.evidence); + } + } + + // All fix approaches so the agent can choose the best strategy + if (fixAdvice?.approaches?.length) { + const recIdx = fixAdvice.recommended_approach ?? 0; + sections.push('', '## Fix Approaches'); + sections.push( + '', + `The investigation identified ${fixAdvice.approaches.length} approach(es). ` + + `Approach ${recIdx + 1} is recommended, but evaluate all options and choose the best strategy.`, + ); + + for (const [i, approach] of fixAdvice.approaches.entries()) { + const isRecommended = i === recIdx; + sections.push( + '', + `### Approach ${i + 1}: ${approach.description ?? 'Unnamed'}${isRecommended ? ' (Recommended)' : ''}`, + `**Complexity:** ${approach.complexity ?? 'unknown'}`, + ); + if (approach.files_affected?.length) { + sections.push( + '', + '**Files to Modify:**', + ...approach.files_affected.map((f) => `- \`${f}\``), + ); + } + if (approach.pros?.length) { + sections.push( + '', + '**Pros:**', + ...approach.pros.map((p) => `- ${p}`), + ); + } + if (approach.cons?.length) { + sections.push( + '', + '**Cons:**', + ...approach.cons.map((c) => `- ${c}`), + ); + } + } + } + + // Gotchas and patterns + if (fixAdvice?.gotchas?.length) { + sections.push( + '', + '## Gotchas', + ...fixAdvice.gotchas.map((g) => `- ${g}`), + ); + } + if (fixAdvice?.patterns_to_follow?.length) { + sections.push( + '', + '## Patterns to Follow', + ...fixAdvice.patterns_to_follow.map( + (p) => `- \`${p.file}\` — ${p.description ?? ''}`, + ), + ); + } + + return sections.join('\n'); +} + /** * Auto-create a task from a completed investigation report. * Mirrors the logic in the GITHUB_INVESTIGATION_CREATE_TASK handler. @@ -737,26 +858,8 @@ async function autoCreateTaskFromInvestigation( if (!fs.existsSync(reportPath)) return null; const reportData = JSON.parse(fs.readFileSync(reportPath, 'utf-8')); - const summary = reportData.ai_summary || `Investigation of issue #${issueNumber}`; - const fixAdvice = reportData.fix_advice; - const taskDescription = [ - `# GitHub Issue #${issueNumber}`, - '', - `## Summary`, - summary, - '', - fixAdvice?.approaches?.length - ? [ - '## Suggested Approach', - fixAdvice.approaches[fixAdvice.recommended_approach ?? 0]?.description || '', - '', - '### Files to Modify', - ...(fixAdvice.approaches[fixAdvice.recommended_approach ?? 0]?.files_affected?.map( - (f: string) => `- ${f}`, - ) || []), - ].join('\n') - : '', - ].join('\n'); + const summary = (reportData.ai_summary as string) || `Investigation of issue #${issueNumber}`; + const taskDescription = buildTaskDescriptionFromReport(issueNumber, reportData); const config = getGitHubConfig(project); const githubUrl = config @@ -1473,28 +1576,9 @@ export function registerInvestigationHandlers( const reportData = JSON.parse(fs.readFileSync(reportPath, 'utf-8')); - // Build task description from investigation report - // Report fields use snake_case (Pydantic model_dump output) - const summary = reportData.ai_summary || `Investigation of issue #${issueNumber}`; - const fixAdvice = reportData.fix_advice; - const taskDescription = [ - `# GitHub Issue #${issueNumber}`, - '', - `## Summary`, - summary, - '', - fixAdvice?.approaches?.length - ? [ - '## Suggested Approach', - fixAdvice.approaches[fixAdvice.recommended_approach ?? 0]?.description || '', - '', - '### Files to Modify', - ...(fixAdvice.approaches[fixAdvice.recommended_approach ?? 0]?.files_affected?.map( - (f: string) => `- ${f}`, - ) || []), - ].join('\n') - : '', - ].join('\n'); + // Build task description from investigation report with ALL fix approaches + const summary = (reportData.ai_summary as string) || `Investigation of issue #${issueNumber}`; + const taskDescription = buildTaskDescriptionFromReport(issueNumber, reportData); const config = getGitHubConfig(project); const githubUrl = config diff --git a/apps/frontend/src/renderer/components/settings/GeneralSettings.tsx b/apps/frontend/src/renderer/components/settings/GeneralSettings.tsx index da8a3db2..a4b62599 100644 --- a/apps/frontend/src/renderer/components/settings/GeneralSettings.tsx +++ b/apps/frontend/src/renderer/components/settings/GeneralSettings.tsx @@ -15,7 +15,6 @@ import { DEFAULT_INVESTIGATION_MODELS, DEFAULT_INVESTIGATION_THINKING, INVESTIGATION_SPECIALIST_KEYS, - INVESTIGATION_SPECIALIST_LABELS } from '../../../shared/constants'; import type { AppSettings, @@ -267,10 +266,10 @@ export function GeneralSettings({ settings, onSettingsChange, section }: General
- {INVESTIGATION_SPECIALIST_LABELS[specialist].description} + {t(`general.investigationAgents.${specialist}.description`)}
diff --git a/apps/frontend/src/shared/i18n/locales/en/settings.json b/apps/frontend/src/shared/i18n/locales/en/settings.json index fe604057..70ddf3d7 100644 --- a/apps/frontend/src/shared/i18n/locales/en/settings.json +++ b/apps/frontend/src/shared/i18n/locales/en/settings.json @@ -204,7 +204,23 @@ "featureModelSettingsDescription": "Model and thinking level for Insights, Ideation, and Roadmap", "investigationAgents": { "title": "GitHub Issues", - "description": "Issue investigation agents" + "description": "Issue investigation agents", + "root_cause": { + "label": "Root Cause Agent", + "description": "Traces the bug to its source code" + }, + "impact": { + "label": "Impact Agent", + "description": "Assesses blast radius and severity" + }, + "fix_advisor": { + "label": "Fix Advisor Agent", + "description": "Suggests concrete fix approaches" + }, + "reproducer": { + "label": "Reproducer Agent", + "description": "Designs reproduction steps and tests" + } }, "model": "Model", "thinkingLevel": "Thinking Level", diff --git a/apps/frontend/src/shared/i18n/locales/fr/settings.json b/apps/frontend/src/shared/i18n/locales/fr/settings.json index 3581e936..ad1af113 100644 --- a/apps/frontend/src/shared/i18n/locales/fr/settings.json +++ b/apps/frontend/src/shared/i18n/locales/fr/settings.json @@ -204,7 +204,23 @@ "featureModelSettingsDescription": "Modèle et niveau de réflexion pour Insights, Idéation et Roadmap", "investigationAgents": { "title": "GitHub Issues", - "description": "Agents d'investigation des issues" + "description": "Agents d'investigation des issues", + "root_cause": { + "label": "Agent Cause Racine", + "description": "Trace le bug jusqu'à son code source" + }, + "impact": { + "label": "Agent Impact", + "description": "Évalue le rayon d'impact et la sévérité" + }, + "fix_advisor": { + "label": "Agent Correctif", + "description": "Propose des approches de correction concrètes" + }, + "reproducer": { + "label": "Agent Reproducteur", + "description": "Conçoit les étapes de reproduction et les tests" + } }, "model": "Modèle", "thinkingLevel": "Niveau de réflexion",