"""Task decomposition engine - breaks large tasks into self-contained chunks.""" from dataclasses import dataclass, field @dataclass class TaskChunk: """A self-contained unit of work for a single Claude Code session.""" id: int title: str description: str files_to_read: list[str] = field(default_factory=list) files_to_modify: list[str] = field(default_factory=list) depends_on: list[int] = field(default_factory=list) verification: str = "" # how to verify this chunk is done status: str = "pending" # pending | done | skipped def prompt(self, codebase_summary: str, total_chunks: int) -> str: """Generate a ready-to-paste Claude Code prompt for this chunk.""" lines = [ f"# Task {self.id}/{total_chunks}: {self.title}", "", "## Context", codebase_summary, "", "## What to do", self.description, "", ] if self.files_to_read: lines.append("## Files to review first") for f in self.files_to_read: lines.append(f"- `{f}`") lines.append("") if self.files_to_modify: lines.append("## Files to create or modify") for f in self.files_to_modify: lines.append(f"- `{f}`") lines.append("") if self.depends_on: deps = ", ".join(f"Task {d}" for d in self.depends_on) lines.append(f"## Prerequisites") lines.append(f"This task depends on: {deps}. Those changes should already be committed.") lines.append("") if self.verification: lines.append("## Verification") lines.append(self.verification) lines.append("") lines.extend([ "## Instructions", "- Focus ONLY on this task. Do not refactor or change unrelated code.", "- Commit your changes when done with a clear commit message.", "- If you encounter issues that block this task, document them and move on.", ]) return "\n".join(lines) # --- Built-in decomposition strategies --- def decompose_by_component(task: str, files: list[str]) -> list[dict]: """Group files by directory (component/module) and create one chunk per group.""" from collections import defaultdict groups: dict[str, list[str]] = defaultdict(list) for f in files: parts = f.split("/") key = parts[0] if len(parts) > 1 else "root" groups[key].append(f) chunks = [] for i, (group, group_files) in enumerate(sorted(groups.items()), 1): chunks.append({ "id": i, "title": f"{task} - {group}", "description": f"Apply the following change to the `{group}` module/directory:\n\n{task}", "files_to_modify": group_files, }) return chunks def decompose_by_phase(task: str) -> list[dict]: """Break a task into standard software engineering phases.""" phases = [ ("Research & Plan", f"Analyze the codebase and create a detailed plan for: {task}\n\nOutput a PLAN.md file listing:\n- Files that need to change\n- The order of changes\n- Any risks or dependencies\n- Test strategy"), ("Core Implementation", f"Implement the core changes for: {task}\n\nFollow the plan in PLAN.md if it exists. Focus on the main logic, not tests or docs."), ("Tests", f"Write tests for the changes made in: {task}\n\nReview the implementation that was already committed and add appropriate tests."), ("Integration & Cleanup", f"Final integration pass for: {task}\n\nReview all changes made so far, fix any integration issues, update imports, and ensure everything works together. Run the existing test suite."), ] return [ { "id": i, "title": title, "description": desc, "depends_on": [i - 1] if i > 1 else [], } for i, (title, desc) in enumerate(phases, 1) ] STRATEGIES = { "component": decompose_by_component, "phase": decompose_by_phase, }