26725286d5
This commit adds a new phase configuration module that manages model and thinking level settings for different execution phases. It reads configurations from `task_metadata.json` and provides resolved model IDs for various phases, including spec creation, planning, coding, and QA. Key changes include: - New `phase_config.py` file to handle model ID mappings and thinking budgets. - Updates to agent files (`coder.py`, `planner.py`, `loop.py`) to utilize phase-specific models and thinking levels. - Modifications to the CLI and UI components to support per-phase configuration, enhancing the user experience for task creation and editing. The new structure allows for optimized model selection and thinking depth based on the phase, improving overall task execution efficiency. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
176 lines
6.8 KiB
Python
176 lines
6.8 KiB
Python
"""
|
|
Planning and Validation Phase Implementations
|
|
==============================================
|
|
|
|
Phases for implementation planning and final validation.
|
|
"""
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from task_logger import LogEntryType, LogPhase
|
|
|
|
from .. import writer
|
|
from .models import MAX_RETRIES, PhaseResult
|
|
|
|
if TYPE_CHECKING:
|
|
pass
|
|
|
|
|
|
class PlanningPhaseMixin:
|
|
"""Mixin for planning and validation phase methods."""
|
|
|
|
async def phase_planning(self) -> PhaseResult:
|
|
"""Create the implementation plan."""
|
|
from ..validate_pkg.auto_fix import auto_fix_plan
|
|
|
|
plan_file = self.spec_dir / "implementation_plan.json"
|
|
|
|
if plan_file.exists():
|
|
result = self.spec_validator.validate_implementation_plan()
|
|
if result.valid:
|
|
self.ui.print_status(
|
|
"implementation_plan.json already exists and is valid", "success"
|
|
)
|
|
return PhaseResult("planning", True, [str(plan_file)], [], 0)
|
|
self.ui.print_status("Plan exists but invalid, regenerating...", "warning")
|
|
|
|
errors = []
|
|
|
|
# Try Python script first (deterministic)
|
|
self.ui.print_status("Trying planner.py (deterministic)...", "progress")
|
|
success, output = self._run_script(
|
|
"planner.py", ["--spec-dir", str(self.spec_dir)]
|
|
)
|
|
|
|
if success and plan_file.exists():
|
|
result = self.spec_validator.validate_implementation_plan()
|
|
if result.valid:
|
|
self.ui.print_status(
|
|
"Created valid implementation_plan.json via script", "success"
|
|
)
|
|
stats = writer.get_plan_stats(self.spec_dir)
|
|
if stats:
|
|
self.task_logger.log(
|
|
f"Implementation plan created with {stats.get('total_subtasks', 0)} subtasks",
|
|
LogEntryType.SUCCESS,
|
|
LogPhase.PLANNING,
|
|
)
|
|
return PhaseResult("planning", True, [str(plan_file)], [], 0)
|
|
else:
|
|
if auto_fix_plan(self.spec_dir):
|
|
result = self.spec_validator.validate_implementation_plan()
|
|
if result.valid:
|
|
self.ui.print_status(
|
|
"Auto-fixed implementation_plan.json", "success"
|
|
)
|
|
return PhaseResult("planning", True, [str(plan_file)], [], 0)
|
|
errors.append(f"Script output invalid: {result.errors}")
|
|
|
|
# Fall back to agent
|
|
self.ui.print_status("Falling back to planner agent...", "progress")
|
|
for attempt in range(MAX_RETRIES):
|
|
self.ui.print_status(
|
|
f"Running planner agent (attempt {attempt + 1})...", "progress"
|
|
)
|
|
|
|
success, output = await self.run_agent_fn(
|
|
"planner.md",
|
|
phase_name="planning",
|
|
)
|
|
|
|
if success and plan_file.exists():
|
|
result = self.spec_validator.validate_implementation_plan()
|
|
if result.valid:
|
|
self.ui.print_status(
|
|
"Created valid implementation_plan.json via agent", "success"
|
|
)
|
|
return PhaseResult("planning", True, [str(plan_file)], [], attempt)
|
|
else:
|
|
if auto_fix_plan(self.spec_dir):
|
|
result = self.spec_validator.validate_implementation_plan()
|
|
if result.valid:
|
|
self.ui.print_status(
|
|
"Auto-fixed implementation_plan.json", "success"
|
|
)
|
|
return PhaseResult(
|
|
"planning", True, [str(plan_file)], [], attempt
|
|
)
|
|
errors.append(f"Agent attempt {attempt + 1}: {result.errors}")
|
|
self.ui.print_status("Plan created but invalid", "error")
|
|
else:
|
|
errors.append(f"Agent attempt {attempt + 1}: Did not create plan file")
|
|
|
|
return PhaseResult("planning", False, [], errors, MAX_RETRIES)
|
|
|
|
async def phase_validation(self) -> PhaseResult:
|
|
"""Final validation of all spec files with auto-fix retry."""
|
|
for attempt in range(MAX_RETRIES):
|
|
results = self.spec_validator.validate_all()
|
|
all_valid = all(r.valid for r in results)
|
|
|
|
for result in results:
|
|
if result.valid:
|
|
self.ui.print_status(f"{result.checkpoint}: PASS", "success")
|
|
else:
|
|
self.ui.print_status(f"{result.checkpoint}: FAIL", "error")
|
|
for err in result.errors:
|
|
print(f" {self.ui.muted('Error:')} {err}")
|
|
|
|
if all_valid:
|
|
print()
|
|
self.ui.print_status("All validation checks passed", "success")
|
|
return PhaseResult("validation", True, [], [], attempt)
|
|
|
|
# If not valid, try to auto-fix with AI agent
|
|
if attempt < MAX_RETRIES - 1:
|
|
print()
|
|
self.ui.print_status(
|
|
f"Attempting auto-fix (attempt {attempt + 1}/{MAX_RETRIES - 1})...",
|
|
"progress",
|
|
)
|
|
|
|
# Collect all errors for the fixer agent
|
|
error_details = []
|
|
for result in results:
|
|
if not result.valid:
|
|
error_details.append(
|
|
f"**{result.checkpoint}** validation failed:"
|
|
)
|
|
for err in result.errors:
|
|
error_details.append(f" - {err}")
|
|
if result.fixes:
|
|
error_details.append(" Suggested fixes:")
|
|
for fix in result.fixes:
|
|
error_details.append(f" - {fix}")
|
|
|
|
context_str = f"""
|
|
**Spec Directory**: {self.spec_dir}
|
|
|
|
## Validation Errors to Fix
|
|
|
|
{chr(10).join(error_details)}
|
|
|
|
## Files in Spec Directory
|
|
|
|
The following files exist in the spec directory:
|
|
- context.json
|
|
- requirements.json
|
|
- spec.md
|
|
- implementation_plan.json
|
|
- project_index.json (if exists)
|
|
|
|
Read the failed files, understand the errors, and fix them.
|
|
"""
|
|
success, output = await self.run_agent_fn(
|
|
"validation_fixer.md",
|
|
additional_context=context_str,
|
|
phase_name="validation",
|
|
)
|
|
|
|
if not success:
|
|
self.ui.print_status("Auto-fix agent failed", "warning")
|
|
|
|
# All retries exhausted
|
|
errors = [f"{r.checkpoint}: {err}" for r in results for err in r.errors]
|
|
return PhaseResult("validation", False, [], errors, MAX_RETRIES)
|