get rid of tech debt system
This commit is contained in:
parent
c1bcc000a7
commit
92e1a25bca
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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'
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue