fix(issues): include all fix approaches in task creation + i18n specialist labels

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 <[email protected]>
This commit is contained in:
Sondre Engebråten
2026-02-14 19:36:49 +01:00
co-authored by Claude Opus 4.6
parent 5c942468d7
commit 27da64d778
5 changed files with 165 additions and 48 deletions
@@ -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
@@ -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, unknown>,
): 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
@@ -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
<div key={specialist} className="space-y-2">
<div className="flex items-center justify-between">
<Label className="text-xs font-medium text-foreground">
{INVESTIGATION_SPECIALIST_LABELS[specialist].label}
{t(`general.investigationAgents.${specialist}.label`)}
</Label>
<span className="text-xs text-muted-foreground">
{INVESTIGATION_SPECIALIST_LABELS[specialist].description}
{t(`general.investigationAgents.${specialist}.description`)}
</span>
</div>
<div className="grid grid-cols-2 gap-3 max-w-md">
@@ -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",
@@ -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",