get rid of tech debt system

This commit is contained in:
AI Christianson 2024-12-11 22:50:59 -05:00
parent c1bcc000a7
commit 92e1a25bca
4 changed files with 9 additions and 268 deletions

View File

@ -14,11 +14,10 @@ from ra_aid.tools import (
ask_expert, run_shell_command, run_programming_task, ask_expert, run_shell_command, run_programming_task,
emit_research_notes, emit_plan, emit_related_files, emit_task, emit_research_notes, emit_plan, emit_related_files, emit_task,
emit_expert_context, get_memory_value, emit_key_facts, delete_key_facts, emit_expert_context, get_memory_value, emit_key_facts, delete_key_facts,
emit_key_snippets, delete_key_snippets, note_tech_debt, emit_key_snippets, delete_key_snippets,
request_implementation, read_file_tool, emit_research_subtask, request_implementation, read_file_tool, emit_research_subtask,
fuzzy_find_project_files, ripgrep_search, list_directory_tree fuzzy_find_project_files, ripgrep_search, list_directory_tree
) )
from ra_aid.tools.note_tech_debt import BORDER_STYLE, TECH_DEBT_NOTE_EMOJI
from ra_aid.tools.memory import _global_memory, get_related_files from ra_aid.tools.memory import _global_memory, get_related_files
from ra_aid import print_agent_output, print_stage_header, print_task_header from ra_aid import print_agent_output, print_stage_header, print_task_header
from ra_aid.prompts import ( from ra_aid.prompts import (
@ -56,16 +55,6 @@ Examples:
action='store_true', action='store_true',
help='Skip interactive approval for shell commands' help='Skip interactive approval for shell commands'
) )
parser.add_argument(
'--review-tech-debt',
action='store_true',
help='Review existing technical debt notes'
)
parser.add_argument(
'--clear-tech-debt',
action='store_true',
help='Clear all technical debt notes'
)
return parser.parse_args() return parser.parse_args()
# Create console instance # Create console instance
@ -80,9 +69,9 @@ planning_memory = MemorySaver()
implementation_memory = MemorySaver() implementation_memory = MemorySaver()
# Define tool sets for each stage # Define tool sets for each stage
research_tools = [list_directory_tree, emit_research_subtask, run_shell_command, emit_expert_context, ask_expert, emit_research_notes, emit_related_files, emit_key_facts, delete_key_facts, emit_key_snippets, delete_key_snippets, note_tech_debt, request_implementation, read_file_tool, fuzzy_find_project_files, ripgrep_search] research_tools = [list_directory_tree, emit_research_subtask, run_shell_command, emit_expert_context, ask_expert, emit_research_notes, emit_related_files, emit_key_facts, delete_key_facts, emit_key_snippets, delete_key_snippets, request_implementation, read_file_tool, fuzzy_find_project_files, ripgrep_search]
planning_tools = [list_directory_tree, emit_expert_context, ask_expert, emit_plan, emit_task, emit_related_files, emit_key_facts, delete_key_facts, emit_key_snippets, delete_key_snippets, note_tech_debt, read_file_tool, fuzzy_find_project_files, ripgrep_search] planning_tools = [list_directory_tree, emit_expert_context, ask_expert, emit_plan, emit_task, emit_related_files, emit_key_facts, delete_key_facts, emit_key_snippets, delete_key_snippets, read_file_tool, fuzzy_find_project_files, ripgrep_search]
implementation_tools = [list_directory_tree, run_shell_command, emit_expert_context, ask_expert, run_programming_task, emit_related_files, emit_key_facts, delete_key_facts, emit_key_snippets, delete_key_snippets, note_tech_debt, read_file_tool, fuzzy_find_project_files, ripgrep_search] implementation_tools = [list_directory_tree, run_shell_command, emit_expert_context, ask_expert, run_programming_task, emit_related_files, emit_key_facts, delete_key_facts, emit_key_snippets, delete_key_snippets, read_file_tool, fuzzy_find_project_files, ripgrep_search]
# Create stage-specific agents with individual memory objects # Create stage-specific agents with individual memory objects
research_agent = create_react_agent(model, research_tools, checkpointer=research_memory) research_agent = create_react_agent(model, research_tools, checkpointer=research_memory)
@ -249,22 +238,6 @@ def run_research_subtasks(base_task: str, config: dict):
subtask_prompt = f"Research Subtask: {subtask}\n\n{RESEARCH_PROMPT}" subtask_prompt = f"Research Subtask: {subtask}\n\n{RESEARCH_PROMPT}"
run_agent_with_retry(subtask_agent, subtask_prompt, config) run_agent_with_retry(subtask_agent, subtask_prompt, config)
def check_tech_debt_notes() -> bool:
"""Check if any tech debt notes exist.
Returns:
bool: True if tech debt notes exist, False otherwise
"""
tech_debt_dir = '.ra-aid/tech-debt'
tech_debt_files = glob.glob(os.path.join(tech_debt_dir, '*.md'))
return len(tech_debt_files) > 0
def clear_tech_debt_notes() -> None:
"""Clear all technical debt notes."""
tech_debt_dir = '.ra-aid/tech-debt'
if os.path.exists(tech_debt_dir):
shutil.rmtree(tech_debt_dir)
os.makedirs(tech_debt_dir) # Recreate empty directory
def validate_environment(): def validate_environment():
"""Validate required environment variables and dependencies.""" """Validate required environment variables and dependencies."""
@ -286,76 +259,6 @@ def validate_environment():
print(f"- {error}", file=sys.stderr) print(f"- {error}", file=sys.stderr)
sys.exit(1) sys.exit(1)
def review_tech_debt() -> None:
"""Review any technical debt notes collected during execution."""
tech_debt_dir = '.ra-aid/tech-debt'
tech_debt_files = glob.glob(os.path.join(tech_debt_dir, '*.md'))
if not tech_debt_files:
console.print(Panel(
"[bold]No technical debt notes found.[/]",
border_style=BORDER_STYLE,
title=f"{TECH_DEBT_NOTE_EMOJI} Tech Debt"
))
return
print_stage_header("Technical Debt Review")
# Read the contents of all tech debt notes
tech_debt_contents = []
for file_path in tech_debt_files:
with open(file_path, 'r') as file:
content = file.read()
tech_debt_contents.append("\n")
tech_debt_contents.append(content)
# Create dedicated memory and agent for tech debt review
tech_debt_memory = MemorySaver()
# Define tools for tech debt review agent - minimal set needed for analysis
# tech_debt_tools = [
# emit_expert_context, ask_expert, read_file_tool,
# list_directory_tree, fuzzy_find_project_files, ripgrep_search,
# ]
tech_debt_tools = []
# Create fresh agent for tech debt review
tech_debt_agent = create_react_agent(
model,
tech_debt_tools,
checkpointer=tech_debt_memory
)
# Analyze the tech debt notes
prompt = f"""Review the following technical debt notes collected during program execution:
{chr(10).join(tech_debt_contents)}
Please provide a brief, focused analysis:
1. Group similar issues if any
2. Highlight high-impact items
3. Suggest a rough priority order
Keep the response concise and actionable.
Remember that the user doesn't know the note ids. You'll have to reiterate the key information of the issues in whole.
We want to prioritize items that are the highest impact relative to the level of effort required to fix them.
"""
# Stream and print the analysis
while True:
try:
for chunk in tech_debt_agent.stream(
{"messages": [HumanMessage(content=prompt)]},
{"configurable": {"thread_id": "tech-debt"}, "recursion_limit": 100}
):
print_agent_output(chunk)
break
except ChatAnthropic.InternalServerError as e:
print(f"Encountered Anthropic Internal Server Error: {e}. Retrying...")
continue
# Exit immediately after tech debt review
sys.exit(0)
def main(): def main():
"""Main entry point for the ra-aid command line tool.""" """Main entry point for the ra-aid command line tool."""
@ -364,33 +267,11 @@ def main():
validate_environment() validate_environment()
args = parse_arguments() args = parse_arguments()
# Validate message is provided when needed # Validate message is provided
if not (args.message or args.review_tech_debt or args.clear_tech_debt): if not args.message:
print("Error: --message is required unless reviewing or clearing tech debt", file=sys.stderr) print("Error: --message is required", file=sys.stderr)
sys.exit(1) sys.exit(1)
# Handle clear tech debt request early
if args.clear_tech_debt:
clear_tech_debt_notes()
console.print(Panel(
"[bold]Technical debt notes cleared.[/]",
border_style="bright_blue",
title="📝 Tech Debt"
))
return
# Handle tech debt review request
if args.review_tech_debt:
if check_tech_debt_notes():
review_tech_debt()
else:
console.print(Panel(
"[bold]No technical debt notes found.[/]",
border_style="bright_blue",
title="📝 Tech Debt"
))
return
base_task = args.message base_task = args.message
config = { config = {
"configurable": { "configurable": {
@ -448,15 +329,7 @@ Be very thorough in your research and emit lots of snippets, key facts. If you t
except TaskCompletedException: except TaskCompletedException:
sys.exit(0) sys.exit(0)
finally: finally:
# Show tech debt notification only when appropriate pass
if (check_tech_debt_notes() and
not getattr(args, 'review_tech_debt', False) and
not getattr(args, 'clear_tech_debt', False)):
console.print(Panel(
"[bold]Technical debt notes exist.[/]\n[dim italic]Use --review-tech-debt to review them.[/]",
border_style=BORDER_STYLE,
title=f"{TECH_DEBT_NOTE_EMOJI} Tech Debt"
))
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -93,18 +93,6 @@ Thoroughness and Completeness
Carefully report what you found, including all directories and files. Carefully report what you found, including all directories and files.
Do not move on until you are certain you have a complete picture of the codebase structure. Do not move on until you are certain you have a complete picture of the codebase structure.
Technical Debt Detection:
While exploring the codebase, use note_tech_debt to record any technical issues you discover, such as:
- Inconsistencies in code organization or naming
- Apparent dead or duplicated code
- Out-of-date dependencies or documentation
- Anti-patterns or code smells
- Confusing or poorly documented sections
When calling note_tech_debt, include:
- Clear description of the issue
- Specific file location where the issue was found
Focus on observation only - do not suggest fixes
Decision on Implementation Decision on Implementation
After completing your factual enumeration and description, decide: After completing your factual enumeration and description, decide:
@ -156,15 +144,6 @@ Guidelines:
Therefore, use as few tasks as needed, but no fewer. Therefore, use as few tasks as needed, but no fewer.
Keep tasks organized as semantic divisions of the overall work, rather than a series of steps. Keep tasks organized as semantic divisions of the overall work, rather than a series of steps.
Technical Debt Management:
While analyzing implementation approaches, use note_tech_debt to record discovered issues:
- Architectural inconsistencies that need future attention
- Technical limitations that may need addressing
- Dependencies that could cause future problems
- Potential scalability or maintenance concerns
- API design issues or inconsistencies
This helps maintain a record of technical concerns while staying focused on the current task.
When planning the implementation: When planning the implementation:
Break the overall work into sub-tasks that are as detailed as necessary, but no more. Break the overall work into sub-tasks that are as detailed as necessary, but no more.
Each sub-task should be clear and unambiguous, and should fully describe what needs to be done, including: Each sub-task should be clear and unambiguous, and should fully describe what needs to be done, including:
@ -243,14 +222,6 @@ Important Notes:
- Use delete_key_facts to remove facts that become outdated, irrelevant, or duplicated. - Use delete_key_facts to remove facts that become outdated, irrelevant, or duplicated.
- Use emit_key_snippets to manage code sections before and after modifications in batches. - Use emit_key_snippets to manage code sections before and after modifications in batches.
- Regularly remove outdated snippets with delete_key_snippets. - Regularly remove outdated snippets with delete_key_snippets.
- While implementing, use note_tech_debt to record technical issues you encounter:
* Code organization problems requiring refactoring
* Areas needing better error handling or validation
* Performance concerns that should be addressed
* Security considerations for future hardening
* Testing gaps or coverage issues
Record these observations without deviating from your current task.
Instructions: Instructions:
1. Review the provided base task, plan, and key facts. 1. Review the provided base task, plan, and key facts.
2. Implement only the specified task: 2. Implement only the specified task:

View File

@ -5,7 +5,6 @@ from .read_file import read_file_tool
from .fuzzy_find import fuzzy_find_project_files from .fuzzy_find import fuzzy_find_project_files
from .list_directory import list_directory_tree from .list_directory import list_directory_tree
from .ripgrep import ripgrep_search from .ripgrep import ripgrep_search
from .note_tech_debt import note_tech_debt
from .memory import ( from .memory import (
emit_research_notes, emit_plan, emit_task, get_memory_value, emit_key_facts, emit_research_notes, emit_plan, emit_task, get_memory_value, emit_key_facts,
request_implementation, skip_implementation, delete_key_facts, emit_research_subtask, request_implementation, skip_implementation, delete_key_facts, emit_research_subtask,
@ -32,6 +31,5 @@ __all__ = [
'run_shell_command', 'run_shell_command',
'skip_implementation', 'skip_implementation',
'emit_research_subtask', 'emit_research_subtask',
'ripgrep_search', 'ripgrep_search'
'note_tech_debt'
] ]

View File

@ -1,101 +0,0 @@
from pathlib import Path
from typing import Dict, Optional, Any
import os
import glob
from langchain_core.tools import tool
from rich.console import Console
from rich.panel import Panel
# Rich styling constants for tech debt UI
BORDER_STYLE = "bright_blue"
TECH_DEBT_NOTE_EMOJI = "📝"
TECH_DEBT_CLEANUP_EMOJI = "🧹"
MAX_NOTES = 10 # Maximum number of tech debt notes before cleanup warning
console = Console()
@tool
def note_tech_debt(
description: str,
location: Optional[str] = None
) -> Dict[str, Any]:
"""Record a technical debt note for later review.
Creates a markdown file in .ra-aid/tech-debt/ containing the technical debt note.
The system maintains a limit of MAX_NOTES (10) tech debt notes before triggering
cleanup procedures. When this limit is reached, a cleanup agent is spawned to
analyze and suggest notes for removal.
Args:
description: Description of the technical debt issue
location: Optional file/location reference where the tech debt was found
Returns:
Dict containing:
- success: Boolean indicating if note was saved
- note_path: Path to the created note file
- note_number: Sequential number of the note
- cleanup_needed: Boolean indicating if note limit was reached
"""
# Ensure base directory exists
base_dir = Path('.ra-aid/tech-debt')
base_dir.mkdir(parents=True, exist_ok=True)
# Find existing notes and determine next note number
existing_notes = glob.glob(str(base_dir / '*.md'))
next_num = 1
cleanup_needed = False
if existing_notes:
# Extract note numbers from filenames and find highest number
numbers = [int(Path(note).stem) for note in existing_notes]
next_num = max(numbers) + 1
# Check if we've hit the note limit that triggers cleanup
if len(existing_notes) >= MAX_NOTES:
cleanup_needed = True
console.print(
Panel(
f"""[bold]Tech Debt Threshold Reached[/bold]
Current Count: {len(existing_notes)} notes
Maximum Limit: {MAX_NOTES} notes
Status: Spawning cleanup/triage agent
[dim italic]The cleanup agent will analyze note contents and suggest which ones to purge.[/dim italic]
""",
title=f"{TECH_DEBT_CLEANUP_EMOJI} Tech Debt Cleanup",
border_style=BORDER_STYLE
)
)
# Create note path
note_path = base_dir / f'{next_num}.md'
# Format note content
content = [f'# Technical Debt Note {next_num}\n']
content.append('## Description\n')
content.append(f'{description}\n')
if location:
content.append('\n## Location\n')
content.append(f'{location}\n')
# Write note file
note_path.write_text(''.join(content))
# Display status panel
console.print(
Panel(
f"Created Tech Debt Note #{next_num} at {note_path}",
title=f"{TECH_DEBT_NOTE_EMOJI} Tech Debt Note",
border_style=BORDER_STYLE
)
)
return {
'success': True,
'note_path': str(note_path),
'note_number': next_num,
'cleanup_needed': cleanup_needed
}