├── .DS_Store ├── .cursor └── rules │ ├── claude-3-7-sonnet-reasoning.mdc │ ├── deepseek-reasoner.mdc │ ├── final-analysis-docs.mdc │ ├── google-gemini-api-v2.mdc │ ├── phase-1-docs.mdc │ ├── phase-2-docs.mdc │ ├── phase-3-docs.mdc │ ├── phase-5-docs.mdc │ └── tavily-search-tool.mdc ├── .cursorignore ├── .cursorrules ├── .gitignore ├── .vscode └── settings.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── config ├── __init__.py ├── agents.py ├── exclusions.py └── prompts │ ├── __init__.py │ ├── final_analysis_prompt.py │ ├── phase_1_prompts.py │ ├── phase_2_prompts.py │ ├── phase_3_prompts.py │ ├── phase_4_prompts.py │ └── phase_5_prompts.py ├── core ├── __init__.py ├── agent_tools │ ├── tavily.py │ └── tool_manager.py ├── agents │ ├── .DS_Store │ ├── __init__.py │ ├── anthropic.py │ ├── base.py │ ├── deepseek.py │ ├── factory.py │ ├── gemini.py │ └── openai.py ├── analysis │ ├── __init__.py │ ├── final_analysis.py │ ├── phase_1.py │ ├── phase_2.py │ ├── phase_3.py │ ├── phase_4.py │ └── phase_5.py ├── types │ ├── __init__.py │ ├── agent_config.py │ ├── models.py │ └── tool_config.py └── utils │ ├── .DS_Store │ ├── file_creation │ ├── cursorignore.py │ └── phases_output.py │ └── tools │ ├── .cursorrules │ ├── agent_parser.py │ ├── clean_cursorrules.py │ ├── file_retriever.py │ ├── model_config_helper.py │ └── tree_generator.py ├── main.py ├── requirements.txt └── tests ├── .DS_Store ├── final_analysis_test ├── fa_test_input.json ├── output │ ├── cursor_rules.md │ └── final_analysis_results.json ├── run_test.py ├── test_date.py └── test_final_analysis.py ├── phase_1_test ├── output │ └── phase1_results.json └── run_test.py ├── phase_2_test ├── output │ ├── analysis_plan.xml │ └── phase2_results.json ├── run_test.py └── test2_input.json ├── phase_3_test ├── debug_parser.py ├── output │ └── phase3_results.json ├── run_test.py ├── test3_input.json └── test3_input.xml ├── phase_4_test ├── output │ ├── analysis.md │ └── phase4_results.json ├── run_test.py └── test4_input.json ├── phase_5_test ├── output │ ├── consolidated_report.md │ └── phase5_results.json ├── run_test.py └── test5_input.json ├── test_env.py ├── tests_input ├── .DS_Store ├── .cursorignore ├── .cursorrules ├── README.md ├── index.html ├── main.py └── requirements.txt └── utils ├── clean_cr_test.py ├── inputs └── .cursorrules └── run_tree_generator.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlyyCooper/cursorrules-architect/d3341bec543e5ba24cacc2caf33383e98c657e2d/.DS_Store -------------------------------------------------------------------------------- /.cursor/rules/deepseek-reasoner.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: core/agents/deepseek.py,core/agents/base.py 4 | alwaysApply: false 5 | --- 6 | Reasoning Model (deepseek-reasoner) 7 | deepseek-reasoner is a reasoning model developed by DeepSeek. Before delivering the final answer, the model first generates a Chain of Thought (CoT) to enhance the accuracy of its responses. Our API provides users with access to the CoT content generated by deepseek-reasoner, enabling them to view, display, and distill it. 8 | 9 | When using deepseek-reasoner, please upgrade the OpenAI SDK first to support the new parameters. 10 | 11 | pip3 install -U openai 12 | 13 | API Parameters 14 | Input: 15 | 16 | max_tokens:The maximum length of the final response after the CoT output is completed, defaulting to 4K, with a maximum of 8K. Note that the CoT output can reach up to 32K tokens, and the parameter to control the CoT length (reasoning_effort) will be available soon. 17 | Output: 18 | 19 | reasoning_content:The content of the CoT,which is at the same level as content in the output structure. See API Example for details 20 | contentThe content of the final answer 21 | Context Length:The API supports a maximum context length of 64K, and the length of the output reasoning_content is not counted within the 64K context length. 22 | 23 | Supported Features:Chat Completion、Chat Prefix Completion (Beta) 24 | 25 | Not Supported Features:Function Call、Json Output、FIM (Beta) 26 | 27 | Not Supported Parameters:temperature、top_p、presence_penalty、frequency_penalty、logprobs、top_logprobs. Please note that to ensure compatibility with existing software, setting temperature、top_p、presence_penalty、frequency_penalty will not trigger an error but will also have no effect. Setting logprobs、top_logprobs will trigger an error. 28 | 29 | Multi-round Conversation 30 | In each round of the conversation, the model outputs the CoT (reasoning_content) and the final answer (content). In the next round of the conversation, the CoT from previous rounds is not concatenated into the context, as illustrated in the following diagram: 31 | 32 | 33 | Please note that if the reasoning_content field is included in the sequence of input messages, the API will return a 400 error. Therefore, you should remove the reasoning_content field from the API response before making the API request, as demonstrated in the API example. 34 | 35 | API Example 36 | The following code, using Python as an example, demonstrates how to access the CoT and the final answer, as well as how to conduct multi-round conversations: 37 | 38 | NoStreaming 39 | Streaming 40 | from openai import OpenAI 41 | client = OpenAI(api_key="", base_url="https://api.deepseek.com") 42 | 43 | # Round 1 44 | messages = [{"role": "user", "content": "9.11 and 9.8, which is greater?"}] 45 | response = client.chat.completions.create( 46 | model="deepseek-reasoner", 47 | messages=messages 48 | ) 49 | 50 | reasoning_content = response.choices[0].message.reasoning_content 51 | content = response.choices[0].message.content 52 | 53 | # Round 2 54 | messages.append({'role': 'assistant', 'content': content}) 55 | messages.append({'role': 'user', 'content': "How many Rs are there in the word 'strawberry'?"}) 56 | response = client.chat.completions.create( 57 | model="deepseek-reasoner", 58 | messages=messages 59 | ) 60 | # ... 61 | 62 | -------------------------------------------------------------------------------- /.cursor/rules/final-analysis-docs.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: core/analysis/final_analysis.py,config/prompts/final_analysis_prompt.py,config/agents.py,tests/final_analysis_test/run_test.py 4 | alwaysApply: false 5 | --- 6 | The Final Analysis phase is the culmination of the entire project analysis pipeline. It takes the consolidated report from Phase 5 and transforms it into actionable Cursor rules for the Cursor IDE. Here's what it does: 7 | 8 | 1. It uses an AI model (configured to be gpt-4.1 Precise by default in `agents.py`) to analyze the consolidated report from Phase 5. 9 | 10 | 2. The `FinalAnalysis` class initializes the appropriate architect via `get_architect_for_phase("final")` and then calls its `final_analysis` method with the consolidated report and a formatted prompt. 11 | 12 | 3. The prompt (defined in `final_analysis_prompt.py`) follows the CRS-1 (Cursor Rules Specification) format and instructs the model to create a tailored system prompt that will: 13 | - Establish an identity for the AI assistant 14 | - Define technical constraints and dependencies 15 | - Provide imperative directives (requirements) 16 | - Create a knowledge framework with documentation, patterns, and best practices 17 | - Include implementation examples 18 | - Warn about negative patterns to avoid 19 | - Establish knowledge evolution mechanisms 20 | 21 | 4. The output from this phase is saved as a `.cursorrules` file in the project root directory, which the Cursor IDE can then use to provide context-aware assistance when working with the codebase. 22 | 23 | 5. The report is structured to help the AI assistant in Cursor understand the project's architecture, dependencies, patterns, and best practices so it can provide more relevant and accurate suggestions when coding. 24 | 25 | The Final Analysis phase essentially creates a specialized AI assistant persona tailored to the specific codebase that developers can interact with in the Cursor IDE. 26 | -------------------------------------------------------------------------------- /.cursor/rules/google-gemini-api-v2.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: true 5 | --- 6 | ## Google Gemini API Notes 7 | 8 | ### Text Generation 9 | 10 | The Gemini API can generate text output in response to various inputs, including text, images, video, and audio. This guide shows you how to generate text using text and image inputs. It also covers streaming, chat, and system instructions. 11 | 12 | #### Text Input 13 | 14 | The simplest way to generate text using the Gemini API is to provide the model with a single text-only input, as shown in this example: 15 | 16 | ```python 17 | from google import genai 18 | 19 | client = genai.Client(api_key="GEMINI_API_KEY") 20 | 21 | response = client.models.generate_content( 22 | model="gemini-2.0-flash", 23 | contents=["How does AI work?"] 24 | ) 25 | print(response.text) 26 | ``` 27 | 28 | #### Streaming Output 29 | 30 | By default, the model returns a response after completing the entire text generation process. You can achieve faster interactions by using streaming to return instances of `GenerateContentResponse` as they're generated. 31 | 32 | ```python 33 | from google import genai 34 | 35 | client = genai.Client(api_key="GEMINI_API_KEY") 36 | 37 | response = client.models.generate_content_stream( 38 | model="gemini-2.0-flash", 39 | contents=["Explain how AI works"] 40 | ) 41 | for chunk in response: 42 | print(chunk.text, end="") 43 | ``` 44 | 45 | #### Multi-turn Conversations 46 | 47 | The Gemini SDK lets you collect multiple rounds of questions and responses into a chat. The chat format enables users to step incrementally toward answers and to get help with multipart problems. This SDK implementation of chat provides an interface to keep track of conversation history, but behind the scenes it uses the same `generateContent` method to create the response. 48 | 49 | The following code example shows a basic chat implementation: 50 | 51 | ```python 52 | from google import genai 53 | 54 | client = genai.Client(api_key="GEMINI_API_KEY") 55 | chat = client.chats.create(model="gemini-2.0-flash") 56 | 57 | response = chat.send_message("I have 2 dogs in my house.") 58 | print(response.text) 59 | 60 | response = chat.send_message("How many paws are in my house?") 61 | print(response.text) 62 | 63 | # Print chat history 64 | for message in chat.get_history(): 65 | print(f'role - {message.role}',end=": ") 66 | print(message.parts[0].text) 67 | ``` 68 | 69 | You can also use streaming with chat, as shown in the following example: 70 | 71 | ```python 72 | from google import genai 73 | 74 | client = genai.Client(api_key="GEMINI_API_KEY") 75 | chat = client.chats.create(model="gemini-2.0-flash") 76 | 77 | response = chat.send_message_stream("I have 2 dogs in my house.") 78 | for chunk in response: 79 | print(chunk.text, end="") 80 | print() # Add a newline after the first streamed response 81 | 82 | response = chat.send_message_stream("How many paws are in my house?") 83 | for chunk in response: 84 | print(chunk.text, end="") 85 | print() # Add a newline after the second streamed response 86 | 87 | # Print chat history 88 | for message in chat.get_history(): 89 | print(f'role - {message.role}', end=": ") 90 | print(message.parts[0].text) 91 | ``` 92 | 93 | #### System Instructions 94 | 95 | System instructions let you steer the behavior of a model based on your specific use case. When you provide system instructions, you give the model additional context to help it understand the task and generate more customized responses. The model should adhere to the system instructions over the full interaction with the user, enabling you to specify product-level behavior separate from the prompts provided by end users. 96 | 97 | You can set system instructions when you initialize your model: 98 | 99 | ```python 100 | from google import genai 101 | from google.genai import types 102 | 103 | client = genai.Client(api_key="GEMINI_API_KEY") 104 | 105 | response = client.models.generate_content( 106 | model="gemini-2.0-flash", 107 | config=types.GenerateContentConfig( 108 | system_instruction="You are a cat. Your name is Neko."), 109 | contents="Hello there" 110 | ) 111 | 112 | print(response.text) 113 | ``` 114 | 115 | ### Use Gemini Thinking 116 | 117 | Gemini 2.5 Pro Experimental and Gemini 2.0 Flash Thinking Experimental are models that use an internal "thinking process" during response generation. This process contributes to their improved reasoning capabilities and allows them to solve complex tasks. This guide shows you how to use Gemini models with thinking capabilities. 118 | 119 | *Try Gemini 2.5 Pro Experimental in Google AI Studio* 120 | 121 | #### Use Thinking Models 122 | 123 | Models with thinking capabilities are available in Google AI Studio and through the Gemini API. Note that the thinking process is visible within Google AI Studio but is not provided as part of the API output. 124 | 125 | ##### Send a Basic Request 126 | 127 | ```python 128 | from google import genai 129 | 130 | client = genai.Client(api_key="GEMINI_API_KEY") 131 | prompt = "Explain the concept of Occam's Razor and provide a simple, everyday example." 132 | response = client.models.generate_content( 133 | model="gemini-2.5-pro-exp-03-25", # or gemini-2.0-flash-thinking-exp 134 | contents=prompt 135 | ) 136 | 137 | print(response.text) 138 | ``` 139 | 140 | ##### Multi-turn Thinking Conversations 141 | 142 | To take the previous chat history into account, you can use multi-turn conversations. 143 | 144 | With the SDKs, you can create a chat session to manage the state of the conversation. *Note: The example below uses `asyncio`.* 145 | 146 | ```python 147 | import asyncio 148 | from google import genai 149 | 150 | async def run_async_chat(): 151 | client = genai.Client(api_key='GEMINI_API_KEY') 152 | 153 | chat = client.aio.chats.create( 154 | model='gemini-2.5-pro-exp-03-25', # or gemini-2.0-flash-thinking-exp 155 | ) 156 | response = await chat.send_message('What is your name?') 157 | print(response.text) 158 | response = await chat.send_message('What did you just say before this?') 159 | print(response.text) 160 | 161 | # To run the async function: 162 | # asyncio.run(run_async_chat()) 163 | ``` -------------------------------------------------------------------------------- /.cursor/rules/phase-1-docs.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: config/prompts/phase_1_prompts.py,core/analysis/phase_1.py,config/agents.py,tests/phase_1_test/run_test.py 4 | alwaysApply: false 5 | --- 6 | I'll explain what Phase 1 (Initial Discovery) does in the CursorRules Architect project. 7 | 8 | Phase 1 is the first stage of the project analysis pipeline, focused on initial exploration and discovery. It serves as the foundation for later analysis phases by gathering key information about the project's structure and technologies. 9 | 10 | The process has three main components: 11 | 12 | 1. **Three Specialized Agents**: 13 | - **Structure Agent**: Analyzes directory/file organization, maps project layout, and identifies key architectural components 14 | - **Dependency Agent**: Investigates packages and libraries, determines version requirements, and researches compatibility issues 15 | - **Tech Stack Agent**: Identifies frameworks and technologies used, gathers documentation, and notes current best practices 16 | 17 | 2. **Implementation Details**: 18 | - Runs the three agents concurrently using asyncio 19 | - Each agent analyzes the same project tree and package information 20 | - Returns structured findings from each agent's analysis 21 | 22 | 3. **Workflow**: 23 | - `main.py` creates the project tree and passes it to Phase 1 24 | - `phase_1.py` initializes the three agents and runs them concurrently 25 | - Each agent has specific prompts defined in `phase_1_prompts.py` 26 | - The agent configurations (model, reasoning mode) come from `config/agents.py` 27 | - Results are collected and returned as a dictionary for Phase 2 to use 28 | 29 | The output of Phase 1 is a comprehensive overview of the project's structure, dependencies, and technology stack - essential information that later phases will use for deeper analysis. 30 | 31 | Phase 1 is not hardcoded to use any specific model - it's configurable through the `config/agents.py` file. 32 | 33 | Looking at the code: 34 | 35 | 1. In `phase_1.py`, it doesn't directly import the AnthropicArchitect, but instead uses: 36 | ```python 37 | from config.agents import get_architect_for_phase 38 | ``` 39 | 40 | 2. In the initialization of Phase1Analysis, it creates architects using this factory function: 41 | ```python 42 | self.architects = [ 43 | get_architect_for_phase("phase1", name=STRUCTURE_AGENT_PROMPT["name"], ...), 44 | get_architect_for_phase("phase1", name=DEPENDENCY_AGENT_PROMPT["name"], ...), 45 | get_architect_for_phase("phase1", name=TECH_STACK_AGENT_PROMPT["name"], ...) 46 | ] 47 | ``` 48 | 49 | 3. The `get_architect_for_phase` function in `agents.py` looks up the model configuration for "phase1" from the `MODEL_CONFIG` dictionary: 50 | ```python 51 | # Default model configuration 52 | MODEL_CONFIG = { 53 | # Phase 1: Initial Discovery 54 | "phase1": CLAUDE_BASIC, 55 | # ... other phases ... 56 | } 57 | ``` 58 | 59 | 4. While the default is `CLAUDE_BASIC`, this is just a configuration that can be changed. The `get_architect_for_phase` function supports creating architects from multiple providers: 60 | - AnthropicArchitect 61 | - OpenAIArchitect 62 | - DeepSeekArchitect 63 | - GeminiArchitect 64 | 65 | So Phase 1 is configured to use Claude by default, but the architecture allows you to easily switch to OpenAI, DeepSeek, or Gemini models by just changing the `MODEL_CONFIG` dictionary in `agents.py`. 66 | -------------------------------------------------------------------------------- /.cursor/rules/phase-2-docs.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: config/prompts/phase_2_prompts.py,core/analysis/phase_2.py,config/agents.py,tests/phase_2_test/run_test.py 4 | alwaysApply: false 5 | --- 6 | Phase 2 (Methodical Planning) is the second stage in the project analysis pipeline. Here's what it does: 7 | 8 | 1. **Purpose:** 9 | Phase 2 creates a detailed analysis plan based on the findings from Phase 1. It strategically plans how to analyze the project by creating specialized agents and assigning files to each agent. 10 | 11 | 2. **Implementation:** 12 | - Takes the Phase 1 results and project structure as input 13 | - Generates a structured analysis plan with agent definitions and file assignments 14 | 15 | 3. **Key Components:** 16 | - **Agent Creation:** Defines 3-5 specialized agents tailored to the project's needs 17 | - **File Assignment:** Assigns each file in the project to the most appropriate agent 18 | - **Reasoning:** Provides the rationale behind the agent creation and file assignments 19 | 20 | 4. **Technical Flow:** 21 | 1. `Phase2Analysis` class initializes with the specified model (defaults to "o1") 22 | 2. The `run` method formats a prompt using Phase 1 results and the project tree 23 | 3. It calls the `OpenAIAgent.create_analysis_plan()` method to generate the plan 24 | 4. It uses `parse_agents_from_phase2()` to extract structured agent definitions 25 | 5. Returns a dictionary with the complete plan and token usage metrics 26 | 27 | 5. **Output Format:** 28 | The output is structured XML containing: 29 | ```xml 30 | Explanation of approach 31 | 32 | 33 | Agent role description 34 | 35 | path/to/file1 36 | path/to/file2 37 | 38 | 39 | 40 | 41 | ``` 42 | 43 | 6. **Configuration:** 44 | Like Phase 1, the model used is configurable through the `MODEL_CONFIG` dictionary in `agents.py`. By default, it uses OpenAI's O1 model with high reasoning. 45 | 46 | This phase is critical because it creates the blueprint for how the deeper analysis in Phase 3 will be conducted, ensuring each file is analyzed by an agent with the right expertise. 47 | -------------------------------------------------------------------------------- /.cursor/rules/phase-3-docs.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: core/analysis/phase_3.py,core/utils/tools/agent_parser.py,core/utils/tools/file_retriever.py,tests/phase_3_test/run_test.py 4 | alwaysApply: false 5 | --- 6 | Phase 3 (Deep Analysis) is the third stage in the project analysis pipeline. Here's how it works: 7 | 8 | 1. **Purpose:** 9 | Phase 3 performs deep, detailed analysis of the project's codebase based on the agent assignments created in Phase 2. Each specialized agent analyzes specific files according to its expertise. 10 | 11 | 2. **Key Components:** 12 | - **Dynamic Agent Creation:** Creates specialized analysis agents based on Phase 2's output 13 | - **File Content Retrieval:** Retrieves and formats the actual contents of assigned files 14 | - **In-depth Analysis:** Each agent analyzes its assigned files in detail 15 | - **Concurrent Execution:** Runs all agent analyses in parallel using asyncio 16 | 17 | 3. **Technical Flow:** 18 | 1. Phase3Analysis reads the agent definitions from Phase 2's output 19 | 2. It creates AnthropicArchitect instances for each agent using `get_architect_for_phase` 20 | 3. For each agent, it: 21 | - Retrieves the contents of all files assigned to that agent 22 | - Creates a custom prompt that includes the tree structure, assigned files, and file contents 23 | - Formats a context object with all the necessary information 24 | 4. It runs all agents concurrently using asyncio.gather 25 | 5. It collects and processes the results from each agent 26 | 27 | 4. **Agent Parser Integration:** 28 | - Uses the `agent_parser.py` module to extract agent definitions from Phase 2's XML output 29 | - The parser handles both well-formed XML and provides fallback extraction using regex 30 | - It extracts agent names, descriptions, and file assignments to build the appropriate contexts 31 | 32 | 5. **File Retriever Integration:** 33 | - Uses `file_retriever.py` to read the actual file contents 34 | - Formats the content with file paths for context 35 | - Handles different encodings and exclusion patterns 36 | - Filters to only include files assigned to each specific agent 37 | 38 | 6. **Fallback Mechanism:** 39 | - If no valid agent definitions can be extracted from Phase 2, it uses a set of predefined fallback agents: 40 | - Code Analysis Agent 41 | - Dependency Mapping Agent 42 | - Architecture Agent 43 | 44 | 7. **Model Configuration:** 45 | Like previous phases, the model used is configurable in `agents.py`. By default, it uses Claude 3.7 Sonnet. 46 | 47 | 8. **Output Format:** 48 | The output is a structured dictionary containing: 49 | ```json 50 | { 51 | "phase": "Deep Analysis", 52 | "findings": [ 53 | { 54 | "agent": "Agent Name", 55 | "findings": "Detailed analysis of assigned files..." 56 | }, 57 | // More agent findings 58 | ] 59 | } 60 | ``` 61 | 62 | Phase 3 is critical because it provides the in-depth analysis of the code itself, going beyond the structural and dependency analysis of earlier phases to examine implementation details, patterns, and architectural decisions. 63 | 64 | ## Fallback Mechanism 65 | 66 | Phase 3 uses both formats, but in different ways: 67 | 68 | 1. **Input from Phase 2:** 69 | - It expects a dictionary (JSON-like structure) as the input from Phase 2, specifically the `analysis_plan` parameter in the `run` method 70 | - This dictionary should contain an `agents` field with the agent definitions 71 | 72 | 2. **XML Processing:** 73 | - The `agent_parser.py` module can parse XML-formatted text that's contained within the Phase 2 output 74 | - If the Phase 2 output contains an XML string in the `plan` field, the `parse_agents_from_phase2` function will extract agent definitions from it 75 | - It first tries to parse it as proper XML using ElementTree 76 | - If XML parsing fails, it falls back to regex-based extraction 77 | 78 | So the answer is that Phase 3 primarily expects a JSON/dictionary structure as input, but it's designed to handle XML strings contained within that JSON structure. This flexibility allows it to work with different output formats from Phase 2. 79 | 80 | Looking at the code: 81 | ```python 82 | # In Phase3Analysis.run() 83 | agent_definitions = analysis_plan.get("agents", []) 84 | ``` 85 | 86 | This shows that it expects a dictionary input with an "agents" field. However, if that's missing, it has fallback mechanisms to parse XML from the text output of Phase 2. 87 | 88 | -------------------------------------------------------------------------------- /.cursor/rules/phase-5-docs.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: config/prompts/phase_5_prompts.py,config/agents.py,core/analysis/phase_5.py,tests/phase_5_test/run_test.py 4 | alwaysApply: false 5 | --- 6 | Phase 5 (Consolidation) is the final phase before the Final Analysis. It takes all the results from the previous phases (1-4) and consolidates them into a comprehensive, cohesive report. 7 | 8 | Looking at the implementation: 9 | 10 | 1. The `Phase5Analysis` class initializes with a model configured in `config/agents.py` (by default, DeepSeek Reasoner). 11 | 12 | 2. When `run()` is called, it: 13 | - Takes all previous results as input 14 | - Formats a prompt using `format_phase5_prompt()` 15 | - Passes this to the configured AI model 16 | - Returns a consolidated report 17 | 18 | 3. The prompt instructs the model to: 19 | - Combine all agent findings 20 | - Organize by component/module 21 | - Create comprehensive documentation 22 | - Highlight key discoveries 23 | - Prepare a final report 24 | 25 | The consolidated output becomes the foundation for the Final Analysis phase, which creates the actual Cursor rules. 26 | 27 | This phase is crucial as it transforms all the individual analyses from different agents and phases into a single, coherent document that captures the project's architecture, dependencies, and technical patterns. 28 | -------------------------------------------------------------------------------- /.cursorignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | __pycache__ 3 | __pycache__/ 4 | .git 5 | .gitattributes 6 | .gitignore 7 | .next 8 | package-lock.json 9 | .venv 10 | .venv/ 11 | .DS_STORE 12 | LICENSE 13 | .svg 14 | .pytest_cache 15 | .DS_Store 16 | .turbo 17 | dist 18 | public 19 | public/ 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Environment variables 2 | .env 3 | .env.local 4 | .env.*.local 5 | 6 | # Python 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | *.so 11 | .Python 12 | env/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # Project specific 30 | project_tree_* 31 | our-notes/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.cursorrules": "markdown" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to CursorRules Architect V2 2 | 3 | Thank you for considering contributing to CursorRules Architect! Your help is greatly appreciated. This guide explains how you can contribute to the project. 4 | 5 | ## Table of Contents 6 | 7 | - [Code of Conduct](#code-of-conduct) 8 | - [Getting Started](#getting-started) 9 | - [How to Contribute](#how-to-contribute) 10 | - [Reporting Bugs](#reporting-bugs) 11 | - [Suggesting Features](#suggesting-features) 12 | - [Submitting Changes](#submitting-changes) 13 | - [Git Workflow](#git-workflow) 14 | - [Code Standards](#code-standards) 15 | - [Commit Messages](#commit-messages) 16 | - [Pull Request Guidelines](#pull-request-guidelines) 17 | - [Development Setup](#development-setup) 18 | - [Prerequisites](#prerequisites) 19 | - [Installing Dependencies](#installing-dependencies) 20 | - [Setting Up API Keys](#setting-up-api-keys) 21 | - [Running the Project](#running-the-project) 22 | - [Testing](#testing) 23 | - [Important Notes](#important-notes) 24 | - [Supported Models](#supported-models) 25 | - [Model Configuration](#model-configuration) 26 | - [Model Usage Restrictions](#model-usage-restrictions) 27 | 28 | ## Code of Conduct 29 | 30 | By participating in this project, you agree to abide by the [Code of Conduct](CODE_OF_CONDUCT.md). Be respectful and considerate in all interactions. 31 | 32 | ## Getting Started 33 | 34 | To get started with development, you'll need to set up your local environment. 35 | 36 | ### Prerequisites 37 | 38 | - Python 3.8 or higher 39 | - API keys for at least one of the following providers: 40 | - OpenAI API key with access to `o1`, `o3-mini`, or `gpt-4.1` 41 | - Anthropic API key with access to `claude-3-7-sonnet-20250219` 42 | - DeepSeek API key with access to DeepSeek Reasoner 43 | - Git 44 | 45 | ### Installing Dependencies 46 | 47 | Clone the repository: 48 | 49 | ```bash 50 | git clone https://github.com/SlyyCooper/cursorrules-architect.git 51 | cd cursorrules-architect 52 | ``` 53 | 54 | Create a virtual environment and activate it: 55 | 56 | ```bash 57 | python -m venv venv 58 | source venv/bin/activate # On Windows use `venv\Scripts\activate` 59 | ``` 60 | 61 | Install the required packages: 62 | 63 | ```bash 64 | pip install -r requirements.txt 65 | ``` 66 | 67 | ### Setting Up API Keys 68 | 69 | Set your API keys as environment variables: 70 | 71 | ```bash 72 | # Linux/macOS 73 | export OPENAI_API_KEY='your-openai-api-key' 74 | export ANTHROPIC_API_KEY='your-anthropic-api-key' 75 | export DEEPSEEK_API_KEY='your-deepseek-api-key' 76 | 77 | # Windows Command Prompt 78 | set OPENAI_API_KEY=your-openai-api-key 79 | set ANTHROPIC_API_KEY=your-anthropic-api-key 80 | set DEEPSEEK_API_KEY=your-deepseek-api-key 81 | 82 | # Windows PowerShell 83 | $env:OPENAI_API_KEY='your-openai-api-key' 84 | $env:ANTHROPIC_API_KEY='your-anthropic-api-key' 85 | $env:DEEPSEEK_API_KEY='your-deepseek-api-key' 86 | ``` 87 | 88 | Alternatively, create a `.env` file in the project root: 89 | 90 | ``` 91 | ANTHROPIC_API_KEY=your-anthropic-api-key 92 | OPENAI_API_KEY=your-openai-api-key 93 | DEEPSEEK_API_KEY=your-deepseek-api-key 94 | ``` 95 | 96 | **Important:** Ensure that your API keys have access to the required models. You can configure which models to use in `config/agents.py`. 97 | 98 | ## How to Contribute 99 | 100 | Contributions can be in the form of bug reports, feature suggestions, or code changes. 101 | 102 | ### Reporting Bugs 103 | 104 | If you encounter any bugs, please open an issue on GitHub with detailed information: 105 | 106 | - Steps to reproduce the issue 107 | - Expected and actual results 108 | - Any relevant error messages or logs 109 | - Your environment details (OS, Python version, package versions) 110 | 111 | ### Suggesting Features 112 | 113 | We welcome feature suggestions! Please open an issue with: 114 | 115 | - A clear and descriptive title 116 | - A detailed description of the feature 117 | - Any proposed implementation details 118 | 119 | ### Submitting Changes 120 | 121 | #### Git Workflow 122 | 123 | 1. **Fork the Repository** on GitHub. 124 | 2. **Clone Your Fork**: 125 | 126 | ```bash 127 | git clone https://github.com/your-username/cursorrules-architect.git 128 | cd cursorrules-architect 129 | ``` 130 | 131 | 3. **Create a Feature Branch**: 132 | 133 | ```bash 134 | git checkout -b feature/YourFeature 135 | ``` 136 | 137 | 4. **Make Your Changes** and commit them. 138 | 139 | 5. **Push to Your Branch**: 140 | 141 | ```bash 142 | git push origin feature/YourFeature 143 | ``` 144 | 145 | 6. **Open a Pull Request** on the original repository. 146 | 147 | #### Code Standards 148 | 149 | - **Python Style**: Follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) guidelines. 150 | - **Typing**: Use type hints where appropriate. 151 | - **Imports**: Organize imports according to [PEP 8](https://www.python.org/dev/peps/pep-0008/#imports). 152 | - **Documentation**: Include docstrings for functions, classes, and modules. 153 | - **Architecture**: Follow the existing architectural patterns: 154 | - Use the `BaseArchitect` abstract class for new AI model providers 155 | - Keep prompts and logic separated 156 | - Ensure compatibility with the phase-based approach 157 | 158 | #### Commit Messages 159 | 160 | - Use descriptive commit messages. 161 | - Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification when possible. 162 | 163 | #### Pull Request Guidelines 164 | 165 | - Ensure your code passes all tests. 166 | - Address any merge conflicts. 167 | - Provide a clear description of your changes in the pull request. 168 | - If adding support for new models or providers, include documentation and examples. 169 | 170 | ## Development Setup 171 | 172 | ### Running the Project 173 | 174 | You can run the main script using: 175 | 176 | ```bash 177 | python main.py -p /path/to/your/project 178 | ``` 179 | 180 | To use the new architecture (recommended): 181 | 182 | ```bash 183 | python main.py -p /path/to/your/project -n 184 | ``` 185 | 186 | ### Testing 187 | 188 | When adding new features or modifying existing ones, consider adding appropriate test cases. To run specific tests: 189 | 190 | ```bash 191 | # Test a specific component 192 | python -m unittest tests/test_your_component.py 193 | 194 | # Run all tests 195 | python -m unittest discover tests 196 | ``` 197 | 198 | ## Important Notes 199 | 200 | ### Supported Models 201 | 202 | CursorRules Architect V2 supports multiple AI models: 203 | 204 | - **Anthropic**: 205 | - `claude-3-7-sonnet-20250219` (with or without reasoning) 206 | 207 | - **OpenAI**: 208 | - `o1` (with low/medium/high reasoning) 209 | - `o3-mini` (with low/medium/high reasoning) 210 | - `gpt-4.1` (with temperature control) 211 | 212 | - **DeepSeek**: 213 | - DeepSeek Reasoner (always with reasoning enabled) 214 | 215 | ### Model Configuration 216 | 217 | You can configure which models are used for each phase by modifying the `MODEL_CONFIG` dictionary in `config/agents.py`. For example: 218 | 219 | ```python 220 | MODEL_CONFIG = { 221 | "phase1": CLAUDE_WITH_REASONING, # Use Claude with reasoning for Phase 1 222 | "phase2": O1_HIGH, # Use OpenAI's o1 with high reasoning for Phase 2 223 | # etc. 224 | } 225 | ``` 226 | 227 | ### Model Usage Restrictions 228 | 229 | Be mindful of API usage costs when developing and testing. Consider using mock responses or lower token budgets during development. 230 | 231 | ## Questions? 232 | 233 | If you have any questions or need assistance, feel free to open an issue or reach out to the maintainers. 234 | 235 | We look forward to your contributions! 236 | 237 | 238 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 SlyyCooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | config package 3 | 4 | This package contains configuration settings for the project analyzer. 5 | """ -------------------------------------------------------------------------------- /config/agents.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/agents.py 3 | 4 | This module provides configurations for AI models used in different phases of analysis. 5 | It allows users to easily configure which models to use for each phase by updating 6 | the `MODEL_CONFIG` dictionary. 7 | 8 | Users can specify a different model for each phase and whether to use reasoning. 9 | """ 10 | 11 | from core.types.models import ( 12 | ModelConfig, 13 | CLAUDE_BASIC, 14 | CLAUDE_WITH_REASONING, 15 | O1_HIGH, 16 | O1_MEDIUM, 17 | O1_LOW, 18 | O3_MINI_HIGH, 19 | O3_MINI_MEDIUM, 20 | O3_MINI_LOW, 21 | GPT4_1_DEFAULT, 22 | GPT4_1_CREATIVE, 23 | GPT4_1_PRECISE, 24 | DEEPSEEK_REASONER, 25 | GEMINI_BASIC, 26 | GEMINI_WITH_REASONING 27 | ) 28 | 29 | # ==================================================== 30 | # Phase Model Configuration 31 | # Define which model to use for each phase. 32 | # ==================================================== 33 | 34 | # Default model configuration 35 | MODEL_CONFIG = { 36 | # Phase 1: Initial Discovery 37 | "phase1": GPT4_1_PRECISE, 38 | 39 | # Phase 2: Methodical Planning 40 | "phase2": GEMINI_BASIC, 41 | 42 | # Phase 3: Deep Analysis 43 | "phase3": GEMINI_BASIC, 44 | 45 | # Phase 4: Synthesis 46 | "phase4": GEMINI_BASIC, 47 | 48 | # Phase 5: Consolidation 49 | "phase5": GEMINI_BASIC, 50 | 51 | # Final Analysis 52 | "final": GEMINI_BASIC, 53 | } 54 | -------------------------------------------------------------------------------- /config/exclusions.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/exclusions.py 3 | 4 | This module contains exclusion settings for the project analyzer. 5 | It defines sets of directories, files, and extensions that should be 6 | excluded from the project tree structure and analysis. 7 | """ 8 | 9 | # ---------------------------------------------------------------------- 10 | # ---[ Excluded Files and Directories Configuration ]--- 11 | # ---------------------------------------------------------------------- 12 | 13 | # These sets define directories, files, and file extensions to exclude 14 | # from the tree structure. This helps to keep the tree clean and 15 | # focused on relevant project files. 16 | 17 | EXCLUDED_DIRS = { 18 | 'node_modules', '.next', '.git', 'venv', '__pycache__', '_pycache_', 19 | 'dist', 'build', '.vscode', '.idea', 'coverage', 20 | '.pytest_cache', '.mypy_cache', 'env', '.env', '.venv', 21 | 'site-packages' 22 | } 23 | 24 | EXCLUDED_FILES = { 25 | 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 26 | '.DS_Store', '.env', '.env.local', '.gitignore', 27 | 'README.md', 'LICENSE', '.eslintrc', '.prettierrc', 28 | 'tsconfig.json', 'requirements.txt', 'poetry.lock', 29 | 'Pipfile.lock', '.gitattributes', '.gitconfig', '.gitmodules', 30 | } 31 | 32 | EXCLUDED_EXTENSIONS = { 33 | '.jpg', '.jpeg', '.png', '.gif', '.ico', 34 | '.svg', '.mp4', '.mp3', '.pdf', '.zip', 35 | '.woff', '.woff2', '.ttf', '.eot', 36 | '.pyc', '.pyo', '.pyd', '.so', '.pkl', '.pickle', 37 | '.db', '.sqlite', '.log', '.cache' 38 | } 39 | -------------------------------------------------------------------------------- /config/prompts/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/prompts package 3 | 4 | This package contains prompt templates for different phases of the project analysis. 5 | """ 6 | 7 | # Import all prompt modules for easy access 8 | from config.prompts.phase_1_prompts import * 9 | from config.prompts.phase_2_prompts import * 10 | # phase_3_prompts removed - now implemented directly in phase_3.py 11 | from config.prompts.phase_4_prompts import * 12 | from config.prompts.phase_5_prompts import * 13 | from config.prompts.final_analysis_prompt import * -------------------------------------------------------------------------------- /config/prompts/phase_1_prompts.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/prompts/phase_1_prompts.py 3 | 4 | This module contains the prompts used by Phase 1 (Initial Discovery) agents. 5 | Centralizing prompts here makes it easier to edit and maintain them without 6 | modifying the core logic of the agents. 7 | """ 8 | 9 | # Base prompt template for all Phase 1 agents 10 | PHASE_1_BASE_PROMPT = """You are a {agent_name}, responsible for {agent_role}. 11 | 12 | Your specific responsibilities are: 13 | {agent_responsibilities} 14 | 15 | Analyze this project context and provide a detailed report focused on your domain: 16 | 17 | {context} 18 | 19 | Format your response as a structured report with clear sections and findings.""" 20 | 21 | # Specific prompts for each agent in Phase 1 22 | 23 | # Structure Agent prompt 24 | STRUCTURE_AGENT_PROMPT = { 25 | "name": "Structure Agent", 26 | "role": "analyzing directory and file organization", 27 | "responsibilities": [ 28 | "Analyze directory and file organization", 29 | "Map project layout and file relationships", 30 | "Identify key architectural components" 31 | ] 32 | } 33 | 34 | # Dependency Agent prompt 35 | DEPENDENCY_AGENT_PROMPT = { 36 | "name": "Dependency Agent", 37 | "role": "investigating packages and libraries", 38 | "responsibilities": [ 39 | "Investigate all packages and libraries", 40 | "Determine version requirements", 41 | "Research compatibility issues" 42 | ] 43 | } 44 | 45 | # Tech Stack Agent prompt 46 | TECH_STACK_AGENT_PROMPT = { 47 | "name": "Tech Stack Agent", 48 | "role": "identifying frameworks and technologies", 49 | "responsibilities": [ 50 | "Identify all frameworks and technologies", 51 | "Gather latest documentation for each", 52 | "Note current best practices and updates" 53 | ] 54 | } 55 | 56 | # Function to format a prompt for a specific agent 57 | def format_agent_prompt(agent_config, context): 58 | """ 59 | Format a prompt for a specific agent using the base template. 60 | 61 | Args: 62 | agent_config: Dictionary containing agent name, role, and responsibilities 63 | context: Dictionary containing the context for analysis 64 | 65 | Returns: 66 | Formatted prompt string 67 | """ 68 | return PHASE_1_BASE_PROMPT.format( 69 | agent_name=agent_config["name"], 70 | agent_role=agent_config["role"], 71 | agent_responsibilities="\n".join(f"- {r}" for r in agent_config["responsibilities"]), 72 | context=context 73 | ) 74 | 75 | # List of all Phase 1 agent configurations 76 | PHASE_1_AGENTS = [ 77 | STRUCTURE_AGENT_PROMPT, 78 | DEPENDENCY_AGENT_PROMPT, 79 | TECH_STACK_AGENT_PROMPT 80 | ] 81 | -------------------------------------------------------------------------------- /config/prompts/phase_2_prompts.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/prompts/phase_2_prompts.py 3 | 4 | This module contains the prompts used by Phase 2 (Methodical Planning). 5 | Centralizing prompts here makes it easier to edit and maintain them without 6 | modifying the core logic of the agents. 7 | """ 8 | 9 | import json 10 | from typing import Dict, List 11 | 12 | # Base prompt template for Phase 2 (Methodical Planning) 13 | PHASE_2_PROMPT = """You are a project documentation planner tasked with processing the ... from the given ... in order to: 14 | 15 | 1. Create a listing of a team of 3 to 5 agents that would be the best fit to analyze the contents of each file shown within the project structure. 16 | 17 | 2. Assign each file to the applicable agent you created until all files have been assigned. 18 | 19 | # Approach 20 | 21 | - Agent Creation: Identify roles and expertise suitable for the project's needs. 22 | 23 | - File Assignment: Distribute files based on agent expertise to ensure efficient analysis. 24 | 25 | --- 26 | 27 | {project_structure} 28 | 29 | --- 30 | 31 | 32 | {phase1_results} 33 | 34 | 35 | --- 36 | 37 | # OUTPUT REQUIREMENTS 38 | # 1. Use valid XML format with proper closing tags **NOT IN A CODE BLOCK** 39 | # 2. DO NOT use special characters like &, <, > in agent names or descriptions 40 | # 3. Use only alphanumeric characters and spaces in names 41 | # 4. Keep agent IDs exactly as shown: agent_1, agent_2, agent_3) 42 | 43 | --- 44 | 45 | ## OUTPUT FORMAT 46 | 47 | 48 | Describe your approach or reasoning here. 49 | 50 | 51 | 52 | 53 | Brief description of this agent's role and expertise. 54 | 55 | [File path 1] 56 | [File path 2] 57 | 58 | 59 | 60 | 61 | 62 | Brief description of this agent's role and expertise. 63 | 64 | [File path 3] 65 | [File path 4] 66 | 67 | 68 | 69 | 70 | 71 | Brief description of this agent's role and expertise. 72 | 73 | [File path 5] 74 | [File path 6] 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | """ 83 | 84 | def format_phase2_prompt(phase1_results: Dict, project_structure: List[str] = None) -> str: 85 | """ 86 | Format the Phase 2 prompt with the Phase 1 results and project structure. 87 | 88 | Args: 89 | phase1_results: Dictionary containing the results from Phase 1 90 | project_structure: List of strings representing the project tree structure 91 | 92 | Returns: 93 | Formatted prompt string 94 | """ 95 | # Format the project structure 96 | if project_structure is None: 97 | project_structure = ["No project structure provided"] 98 | 99 | structure_str = "\n".join(project_structure) 100 | 101 | return PHASE_2_PROMPT.format( 102 | phase1_results=json.dumps(phase1_results, indent=2), 103 | project_structure=structure_str 104 | ) 105 | -------------------------------------------------------------------------------- /config/prompts/phase_3_prompts.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/prompts/phase_3_prompts.py 3 | 4 | This module provides prompt templates for Phase 3 (Deep Analysis) of the project analysis. 5 | It defines functions to format prompts for the dynamic agents based on their assignments. 6 | """ 7 | 8 | from typing import Dict 9 | 10 | def format_phase3_prompt(context: Dict) -> str: 11 | """ 12 | Format the prompt for a Phase 3 analysis agent. 13 | 14 | Args: 15 | context: Dictionary containing agent information and analysis context 16 | 17 | Returns: 18 | Formatted prompt string 19 | """ 20 | # Extract required context elements with defaults 21 | agent_name = context.get("agent_name", "Analysis Agent") 22 | agent_role = context.get("agent_role", "analyzing code files") 23 | 24 | # Format the tree structure 25 | tree_structure = context.get("tree_structure", []) 26 | if isinstance(tree_structure, list): 27 | tree_structure = "\n".join(tree_structure) 28 | 29 | # Format assigned files 30 | assigned_files = context.get("assigned_files", []) 31 | if isinstance(assigned_files, list): 32 | assigned_files = "\n".join(f"- {file}" for file in assigned_files) 33 | 34 | # Format file contents 35 | file_contents = context.get("file_contents", {}) 36 | if isinstance(file_contents, dict): 37 | formatted_contents = [] 38 | for path, content in file_contents.items(): 39 | formatted_contents.append(f"\n{content}\n") 40 | 41 | file_content_str = "\n\n".join(formatted_contents) 42 | else: 43 | file_content_str = str(file_contents) 44 | 45 | # Return a formatted prompt 46 | return f"""You are {agent_name}, responsible for {agent_role}. 47 | 48 | Your task is to perform a deep analysis of the code files assigned to you in this project. 49 | 50 | TREE STRUCTURE: 51 | {tree_structure} 52 | 53 | ASSIGNED FILES: 54 | {assigned_files} 55 | 56 | FILE CONTENTS: 57 | {file_content_str} 58 | 59 | Analyze the code following these guidelines: 60 | 1. Focus on understanding the purpose and functionality of each file 61 | 2. Identify key patterns and design decisions 62 | 3. Note any potential issues, optimizations, or improvements 63 | 4. Pay attention to relationships between different components 64 | 5. Summarize your findings in a clear, structured format 65 | 66 | Format your response as a structured report with clear sections and findings for each file.""" -------------------------------------------------------------------------------- /config/prompts/phase_4_prompts.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/prompts/phase_4_prompts.py 3 | 4 | This module contains the prompts used by Phase 4 (Synthesis). 5 | Centralizing prompts here makes it easier to edit and maintain them without 6 | modifying the core logic of the agents. 7 | """ 8 | 9 | import json 10 | from typing import Dict 11 | 12 | # Prompt template for Phase 4 (Synthesis) 13 | PHASE_4_PROMPT = """Review and synthesize these agent findings: 14 | 15 | Analysis Results: 16 | {phase3_results} 17 | 18 | Provide: 19 | 1. Deep analysis of all findings 20 | 2. Methodical processing of new information 21 | 3. Updated analysis directions 22 | 4. Refined instructions for agents 23 | 5. Areas needing deeper investigation""" 24 | 25 | def format_phase4_prompt(phase3_results: Dict) -> str: 26 | """ 27 | Format the Phase 4 prompt with the Phase 3 results. 28 | 29 | Args: 30 | phase3_results: Dictionary containing the results from Phase 3 31 | 32 | Returns: 33 | Formatted prompt string 34 | """ 35 | return PHASE_4_PROMPT.format( 36 | phase3_results=json.dumps(phase3_results, indent=2) 37 | ) 38 | -------------------------------------------------------------------------------- /config/prompts/phase_5_prompts.py: -------------------------------------------------------------------------------- 1 | """ 2 | config/prompts/phase_5_prompts.py 3 | 4 | This module contains the prompt templates used in Phase 5 (Consolidation) of the project analysis. 5 | These prompts are used by the Anthropic agent to generate the final report. 6 | """ 7 | 8 | import json 9 | from typing import Dict 10 | 11 | # Prompt for the Report Agent (Claude) 12 | PHASE_5_PROMPT = """As the Report Agent, create a comprehensive final report from all analysis phases: 13 | 14 | Analysis Results: 15 | {results} 16 | 17 | Your tasks: 18 | 1. Combine all agent findings 19 | 2. Organize by component/module 20 | 3. Create comprehensive documentation 21 | 4. Highlight key discoveries 22 | 5. Prepare final report""" 23 | 24 | def format_phase5_prompt(results: Dict) -> str: 25 | """ 26 | Format the Phase 5 prompt with the results from all previous phases. 27 | 28 | Args: 29 | results: Dictionary containing the results from all previous phases 30 | 31 | Returns: 32 | Formatted prompt string 33 | """ 34 | return PHASE_5_PROMPT.format(results=json.dumps(results, indent=2)) 35 | -------------------------------------------------------------------------------- /core/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | core package 3 | 4 | This package contains the core functionality of the project analyzer. 5 | """ -------------------------------------------------------------------------------- /core/agent_tools/tavily.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlyyCooper/cursorrules-architect/d3341bec543e5ba24cacc2caf33383e98c657e2d/core/agent_tools/tavily.py -------------------------------------------------------------------------------- /core/agent_tools/tool_manager.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlyyCooper/cursorrules-architect/d3341bec543e5ba24cacc2caf33383e98c657e2d/core/agent_tools/tool_manager.py -------------------------------------------------------------------------------- /core/agents/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlyyCooper/cursorrules-architect/d3341bec543e5ba24cacc2caf33383e98c657e2d/core/agents/.DS_Store -------------------------------------------------------------------------------- /core/agents/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/agents package 3 | 4 | This package contains agent classes for interacting with different AI models. 5 | """ 6 | 7 | from .factory import get_architect_for_phase -------------------------------------------------------------------------------- /core/agents/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/agents/base.py 3 | 4 | This module provides the base Architect class for interacting with AI models. 5 | It defines the abstract base class that all specific model implementations will inherit from. 6 | 7 | This module serves as the foundation for all model interactions in the CursorRules Architect system. 8 | """ 9 | 10 | # ==================================================== 11 | # Importing Required Libraries 12 | # This section imports all the necessary libraries needed for the script. 13 | # ==================================================== 14 | 15 | from abc import ABC, abstractmethod 16 | import logging 17 | from enum import Enum 18 | from typing import Dict, List, Any, Optional, Union 19 | 20 | # ==================================================== 21 | # Type Definitions 22 | # This section defines types used throughout the module. 23 | # ==================================================== 24 | 25 | class ReasoningMode(Enum): 26 | """Enum for specifying the reasoning mode for a model.""" 27 | # General modes (primarily for Anthropic) 28 | ENABLED = "enabled" 29 | DISABLED = "disabled" 30 | 31 | # OpenAI-specific reasoning effort levels (for O1 and O3-mini) 32 | LOW = "low" 33 | MEDIUM = "medium" 34 | HIGH = "high" 35 | 36 | # For temperature-based models like gpt-4.1, use TEMPERATURE mode 37 | # and specify the actual temperature value separately 38 | TEMPERATURE = "temperature" 39 | 40 | class ModelProvider(Enum): 41 | """Enum for specifying the model provider.""" 42 | ANTHROPIC = "anthropic" 43 | OPENAI = "openai" 44 | DEEPSEEK = "deepseek" 45 | GEMINI = "gemini" 46 | 47 | # ==================================================== 48 | # Get Logger 49 | # Set up logger to track events and issues. 50 | # ==================================================== 51 | 52 | logger = logging.getLogger("project_extractor") 53 | 54 | # ==================================================== 55 | # BaseArchitect Class Definition 56 | # This class defines the BaseArchitect, which serves as the abstract base class 57 | # for all AI model implementations. 58 | # ==================================================== 59 | 60 | class BaseArchitect(ABC): 61 | """ 62 | Abstract base class for all Architect implementations. 63 | 64 | This class defines the common interface that all model-specific Architect 65 | classes must implement, providing a uniform way to interact with different 66 | AI models. 67 | """ 68 | 69 | def __init__( 70 | self, 71 | provider: ModelProvider, 72 | model_name: str, 73 | reasoning: ReasoningMode = ReasoningMode.DISABLED, 74 | temperature: Optional[float] = None, 75 | name: Optional[str] = None, 76 | role: Optional[str] = None, 77 | responsibilities: Optional[List[str]] = None 78 | ): 79 | """ 80 | Initialize a BaseArchitect instance. 81 | 82 | Args: 83 | provider: The model provider (Anthropic or OpenAI) 84 | model_name: Name of the model to use 85 | reasoning: Reasoning mode to use (if supported by the model) 86 | temperature: Temperature value for temperature-based models 87 | name: Optional name for the architect (for specialized roles) 88 | role: Optional role description 89 | responsibilities: Optional list of responsibilities 90 | """ 91 | self.provider = provider 92 | self.model_name = model_name 93 | self.reasoning = reasoning 94 | self.temperature = temperature 95 | self.name = name 96 | self.role = role 97 | self.responsibilities = responsibilities or [] 98 | 99 | @abstractmethod 100 | async def analyze(self, context: Dict[str, Any]) -> Dict[str, Any]: 101 | """ 102 | Run analysis using the AI model. 103 | 104 | Args: 105 | context: Dictionary containing the context for analysis 106 | 107 | Returns: 108 | Dictionary containing the analysis results or error information 109 | """ 110 | pass 111 | 112 | @abstractmethod 113 | async def create_analysis_plan(self, phase1_results: Dict, prompt: Optional[str] = None) -> Dict: 114 | """ 115 | Create an analysis plan based on Phase 1 results. 116 | 117 | Args: 118 | phase1_results: Dictionary containing the results from Phase 1 119 | prompt: Optional custom prompt to use 120 | 121 | Returns: 122 | Dictionary containing the analysis plan 123 | """ 124 | pass 125 | 126 | @abstractmethod 127 | async def synthesize_findings(self, phase3_results: Dict, prompt: Optional[str] = None) -> Dict: 128 | """ 129 | Synthesize findings from Phase 3. 130 | 131 | Args: 132 | phase3_results: Dictionary containing the results from Phase 3 133 | prompt: Optional custom prompt to use 134 | 135 | Returns: 136 | Dictionary containing the synthesis 137 | """ 138 | pass 139 | 140 | @abstractmethod 141 | async def final_analysis(self, consolidated_report: Dict, prompt: Optional[str] = None) -> Dict: 142 | """ 143 | Perform final analysis on the consolidated report. 144 | 145 | Args: 146 | consolidated_report: Dictionary containing the consolidated report 147 | prompt: Optional custom prompt to use 148 | 149 | Returns: 150 | Dictionary containing the final analysis 151 | """ 152 | pass 153 | 154 | @abstractmethod 155 | async def consolidate_results(self, all_results: Dict, prompt: Optional[str] = None) -> Dict: 156 | """ 157 | Consolidate results from all previous phases. 158 | 159 | Args: 160 | all_results: Dictionary containing all phase results 161 | prompt: Optional custom prompt to use 162 | 163 | Returns: 164 | Dictionary containing the consolidated report 165 | """ 166 | pass 167 | -------------------------------------------------------------------------------- /core/agents/factory.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/agents/factory.py 3 | 4 | This module provides a factory function for creating the appropriate architect 5 | instances based on configuration for different phases of analysis. 6 | 7 | It serves as a central hub for instantiating the right architect implementation 8 | based on the model configuration defined in config/agents.py. 9 | """ 10 | 11 | from typing import Any, Dict 12 | from .base import ModelProvider, ReasoningMode 13 | from .anthropic import AnthropicArchitect 14 | from .openai import OpenAIArchitect 15 | from .deepseek import DeepSeekArchitect 16 | from .gemini import GeminiArchitect 17 | 18 | def get_architect_for_phase(phase: str, **kwargs) -> Any: 19 | """ 20 | Get the appropriate architect instance for a phase based on configuration. 21 | 22 | Args: 23 | phase: The phase to get an architect for (e.g., "phase1", "phase2") 24 | **kwargs: Additional keyword arguments to pass to the architect constructor 25 | 26 | Returns: 27 | An instance of the appropriate architect class for the specified phase 28 | """ 29 | # Import here to avoid circular imports 30 | from config.agents import MODEL_CONFIG 31 | 32 | # Get model configuration for the phase 33 | config = MODEL_CONFIG.get(phase) 34 | if not config: 35 | raise ValueError(f"No model configuration found for phase '{phase}'") 36 | 37 | # Create the appropriate architect instance 38 | if config.provider == ModelProvider.ANTHROPIC: 39 | return AnthropicArchitect( 40 | model_name=config.model_name, 41 | reasoning=config.reasoning, 42 | **kwargs 43 | ) 44 | elif config.provider == ModelProvider.OPENAI: 45 | return OpenAIArchitect( 46 | model_name=config.model_name, 47 | reasoning=config.reasoning, 48 | temperature=config.temperature, 49 | **kwargs 50 | ) 51 | elif config.provider == ModelProvider.DEEPSEEK: 52 | # DeepSeek Reasoner has fixed parameters 53 | return DeepSeekArchitect( 54 | **kwargs # Only pass the kwargs, other params are fixed in DeepSeekArchitect 55 | ) 56 | elif config.provider == ModelProvider.GEMINI: 57 | return GeminiArchitect( 58 | model_name=config.model_name, 59 | reasoning=config.reasoning, 60 | **kwargs 61 | ) 62 | else: 63 | raise ValueError(f"Unknown model provider: {config.provider}") -------------------------------------------------------------------------------- /core/analysis/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/analysis package 3 | 4 | This package contains modules for different phases of the project analysis. 5 | """ 6 | 7 | # Import all phase analysis classes for easier access 8 | from core.analysis.phase_1 import Phase1Analysis 9 | from core.analysis.phase_2 import Phase2Analysis 10 | from core.analysis.phase_3 import Phase3Analysis 11 | from core.analysis.phase_4 import Phase4Analysis 12 | from core.analysis.phase_5 import Phase5Analysis 13 | from core.analysis.final_analysis import FinalAnalysis 14 | 15 | # Export all classes for cleaner imports 16 | __all__ = [ 17 | 'Phase1Analysis', 18 | 'Phase2Analysis', 19 | 'Phase3Analysis', 20 | 'Phase4Analysis', 21 | 'Phase5Analysis', 22 | 'FinalAnalysis' 23 | ] -------------------------------------------------------------------------------- /core/analysis/final_analysis.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/analysis/final_analysis.py 3 | 4 | This module provides functionality for the Final Analysis phase of the project analysis. 5 | It defines the methods needed for performing the final analysis on the consolidated report. 6 | """ 7 | 8 | # ==================================================== 9 | # Importing Required Libraries 10 | # This section imports all the necessary libraries and modules needed for this phase. 11 | # ==================================================== 12 | 13 | import logging # Used for logging events and errors. 14 | from typing import Dict, List # Used for type hinting. 15 | from core.agents.openai import OpenAIAgent # Custom class for interacting with OpenAI models. 16 | from config.prompts.final_analysis_prompt import format_final_analysis_prompt # Function to format the final analysis prompt. 17 | from core.agents import get_architect_for_phase # Import for dynamic model configuration 18 | 19 | # ==================================================== 20 | # Logger Setup 21 | # This section sets up the logger for the module. 22 | # ==================================================== 23 | 24 | # Get logger 25 | logger = logging.getLogger("project_extractor") 26 | 27 | # ==================================================== 28 | # Final Analysis Class 29 | # This class handles the final analysis phase (Phase 6) of the project. 30 | # It uses AI agents to analyze the consolidated report and provide insights. 31 | # ==================================================== 32 | 33 | class FinalAnalysis: 34 | """ 35 | Class responsible for the Final Analysis phase of the project analysis. 36 | 37 | This phase uses a model configured in config/agents.py to perform a final analysis on the 38 | consolidated report from Phase 5, providing architectural patterns, 39 | system structure mapping, and improvement recommendations. 40 | """ 41 | 42 | # ==================================================== 43 | # Initialization (__init__) 44 | # This method sets up the initial state of the FinalAnalysis class. 45 | # ==================================================== 46 | 47 | def __init__(self): 48 | """ 49 | Initialize the Final Analysis with the architect from configuration. 50 | """ 51 | # Use the factory function to get the appropriate architect based on configuration 52 | self.architect = get_architect_for_phase("final") 53 | 54 | # ==================================================== 55 | # Run Method 56 | # This method executes the final analysis phase. 57 | # ==================================================== 58 | 59 | async def run(self, consolidated_report: Dict, project_structure: List[str] = None) -> Dict: 60 | """ 61 | Run the Final Analysis Phase using the configured model. 62 | 63 | Args: 64 | consolidated_report: Dictionary containing the consolidated report from Phase 5. 65 | project_structure: List of strings representing the project directory tree. 66 | 67 | Returns: 68 | Dictionary containing the final analysis and token usage. 69 | """ 70 | try: 71 | # Format the prompt using the template from the prompts file. 72 | prompt = format_final_analysis_prompt(consolidated_report, project_structure) 73 | 74 | logger.info("[bold]Final Analysis:[/bold] Creating Cursor rules from consolidated report") 75 | 76 | # Use the architect to perform the final analysis with the formatted prompt. 77 | result = await self.architect.final_analysis(consolidated_report, prompt) 78 | 79 | logger.info("[bold green]Final Analysis:[/bold green] Rules creation completed successfully") 80 | 81 | return result 82 | except Exception as e: 83 | # Log any errors that occur during the analysis. 84 | logger.error(f"[bold red]Error in Final Analysis:[/bold red] {str(e)}") 85 | return {"error": str(e)} # Return the error message. 86 | -------------------------------------------------------------------------------- /core/analysis/phase_1.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/analysis/phase_1.py 3 | 4 | This module provides functionality for Phase 1 (Initial Discovery) of the project analysis. 5 | It defines the agents and methods needed for the initial exploration of the project. 6 | """ 7 | 8 | # ==================================================== 9 | # Importing Required Libraries 10 | # This section imports all the necessary libraries and modules needed for this phase. 11 | # ==================================================== 12 | 13 | import asyncio # For running asynchronous tasks concurrently. 14 | import json # For handling JSON data. 15 | from typing import Dict, List # For type hinting. 16 | from core.agents.anthropic import AnthropicArchitect # The AnthropicArchitect class for interacting with the Anthropic API. 17 | from config.prompts.phase_1_prompts import ( # Prompts used for configuring the agents in Phase 1. 18 | PHASE_1_BASE_PROMPT, 19 | STRUCTURE_AGENT_PROMPT, 20 | DEPENDENCY_AGENT_PROMPT, 21 | TECH_STACK_AGENT_PROMPT, 22 | ) 23 | from core.agents import get_architect_for_phase # Function to get the appropriate architect for a phase 24 | import logging # For logging information about the execution 25 | from rich import print 26 | 27 | # ==================================================== 28 | # Phase 1 Analysis Class 29 | # This class handles the initial discovery phase of the project analysis. 30 | # ==================================================== 31 | 32 | class Phase1Analysis: 33 | """ 34 | Class responsible for Phase 1 (Initial Discovery) of the project analysis. 35 | 36 | This phase uses Anthropic models to perform initial exploration of the project, 37 | analyzing directory structure, dependencies, and technology stack. 38 | """ 39 | 40 | # ---------------------------------------------------- 41 | # Initialization 42 | # Sets up the agents required for the initial discovery. 43 | # ---------------------------------------------------- 44 | def __init__(self): 45 | """ 46 | Initialize the Phase 1 analysis with the required architects. 47 | """ 48 | # Use the Architect architecture 49 | self.architects = [ 50 | get_architect_for_phase( 51 | "phase1", 52 | name=STRUCTURE_AGENT_PROMPT["name"], 53 | role=STRUCTURE_AGENT_PROMPT["role"], 54 | responsibilities=STRUCTURE_AGENT_PROMPT["responsibilities"], 55 | prompt_template=PHASE_1_BASE_PROMPT 56 | ), 57 | get_architect_for_phase( 58 | "phase1", 59 | name=DEPENDENCY_AGENT_PROMPT["name"], 60 | role=DEPENDENCY_AGENT_PROMPT["role"], 61 | responsibilities=DEPENDENCY_AGENT_PROMPT["responsibilities"], 62 | prompt_template=PHASE_1_BASE_PROMPT 63 | ), 64 | get_architect_for_phase( 65 | "phase1", 66 | name=TECH_STACK_AGENT_PROMPT["name"], 67 | role=TECH_STACK_AGENT_PROMPT["role"], 68 | responsibilities=TECH_STACK_AGENT_PROMPT["responsibilities"], 69 | prompt_template=PHASE_1_BASE_PROMPT 70 | ) 71 | ] 72 | 73 | # ---------------------------------------------------- 74 | # Run Method 75 | # Executes the Initial Discovery phase. 76 | # ---------------------------------------------------- 77 | async def run(self, tree: List[str], package_info: Dict) -> Dict: 78 | """ 79 | Run the Initial Discovery Phase. 80 | 81 | Args: 82 | tree: List of strings representing the project directory tree 83 | package_info: Dictionary containing information about project dependencies 84 | 85 | Returns: 86 | Dictionary containing the results of the phase 87 | """ 88 | # Create a context object with the tree structure and package information. 89 | context = { 90 | "tree_structure": tree, 91 | "package_info": package_info 92 | } 93 | 94 | logging.info("[bold]Phase 1:[/bold] Starting analysis with 3 agents") 95 | 96 | # Use the Architect architecture - create a dictionary to map each architect to its index 97 | architect_indices = {architect: i for i, architect in enumerate(self.architects)} 98 | 99 | # Run each architect in parallel with its own context 100 | async def run_architect_with_logging(architect, ctx): 101 | agent_num = architect_indices[architect] + 1 102 | logging.info(f"[bold cyan]Agent {agent_num}:[/bold cyan] {architect.name} starting analysis") 103 | result = await architect.analyze(ctx) 104 | logging.info(f"[bold green]Agent {agent_num}:[/bold green] {architect.name} completed analysis") 105 | return result 106 | 107 | architect_tasks = [run_architect_with_logging(architect, context) for architect in self.architects] 108 | results = await asyncio.gather(*architect_tasks) 109 | 110 | logging.info("[bold green]Phase 1:[/bold green] All agents have completed their analysis") 111 | 112 | # Return the results with phase information. 113 | return { 114 | "phase": "Initial Discovery", 115 | "findings": results 116 | } 117 | -------------------------------------------------------------------------------- /core/analysis/phase_2.py: -------------------------------------------------------------------------------- 1 | # core/analysis/phase_2.py 2 | """ 3 | This module provides functionality for Phase 2 (Methodical Planning) of the project analysis. 4 | It defines the methods needed for creating a detailed analysis plan based on Phase 1 results. 5 | """ 6 | 7 | # ==================================================== 8 | # Import Statements 9 | # This section imports necessary modules and functions for the script. 10 | # ==================================================== 11 | 12 | import logging # Used for logging messages 13 | from typing import Dict, List # Used for type hinting, making code more readable 14 | from core.agents.openai import OpenAIAgent # The OpenAI agent class 15 | from config.prompts.phase_2_prompts import PHASE_2_PROMPT, format_phase2_prompt # Prompts for Phase 2 16 | from core.utils.tools.agent_parser import parse_agents_from_phase2, extract_agent_fallback # Function to parse agent definitions 17 | from core.agents import get_architect_for_phase # Added import for dynamic model configuration 18 | 19 | # ==================================================== 20 | # Logger Initialization 21 | # Get the logger for this module. 22 | # ==================================================== 23 | logger = logging.getLogger("project_extractor") 24 | 25 | # ==================================================== 26 | # Phase 2 Analysis Class 27 | # This class handles the methodical planning phase. 28 | # ==================================================== 29 | 30 | class Phase2Analysis: 31 | """ 32 | Class responsible for Phase 2 (Methodical Planning) of the project analysis. 33 | 34 | This phase uses a model configured in config/agents.py to create a detailed 35 | analysis plan based on the findings from Phase 1. 36 | """ 37 | 38 | # ==================================================== 39 | # Initialization 40 | # Sets up the Phase 2 analysis. 41 | # ==================================================== 42 | def __init__(self): 43 | """ 44 | Initialize the Phase 2 analysis with the architect from configuration. 45 | """ 46 | # Use the factory function to get the appropriate architect based on configuration 47 | self.architect = get_architect_for_phase("phase2") 48 | 49 | # ==================================================== 50 | # Run Method 51 | # Executes the methodical planning phase. 52 | # ==================================================== 53 | async def run(self, phase1_results: Dict, tree: List[str] = None) -> Dict: 54 | """ 55 | Run the Methodical Planning Phase using the configured model. 56 | 57 | Args: 58 | phase1_results: Dictionary containing the results from Phase 1 59 | tree: List of strings representing the project directory tree 60 | 61 | Returns: 62 | Dictionary containing the analysis plan and token usage 63 | """ 64 | try: 65 | # ==================================================== 66 | # Prompt Formatting 67 | # Format the prompt using the template. 68 | # ==================================================== 69 | prompt = format_phase2_prompt(phase1_results, tree) 70 | 71 | logger.info("[bold]Phase 2:[/bold] Creating analysis plan using configured model") 72 | 73 | # ==================================================== 74 | # Analysis Plan Creation 75 | # Use the architect to create an analysis plan. 76 | # ==================================================== 77 | analysis_plan_response = await self.architect.create_analysis_plan(phase1_results, prompt) 78 | 79 | # ==================================================== 80 | # Error Handling 81 | # Check for errors and return if any. 82 | # ==================================================== 83 | if "error" in analysis_plan_response and analysis_plan_response["error"]: 84 | logger.error(f"[bold red]Error:[/bold red] {analysis_plan_response['error']}") 85 | return analysis_plan_response 86 | 87 | # ==================================================== 88 | # Plan Extraction and Agent Parsing 89 | # Get the plan and parse agent definitions. 90 | # ==================================================== 91 | plan_text = analysis_plan_response.get("plan", "") # Extract the raw plan text 92 | 93 | # Try parsing agents from the plan text 94 | logger.info("[bold]Phase 2:[/bold] Parsing agent definitions from plan") 95 | agents = parse_agents_from_phase2(plan_text) # Parse the agent definitions from plan text 96 | 97 | if agents: 98 | logger.info(f"[bold green]Success:[/bold green] Found {len(agents)} agents in the analysis plan") 99 | for i, agent in enumerate(agents): 100 | files_count = len(agent.get('file_assignments', [])) 101 | logger.info(f" [bold cyan]Agent {i+1}:[/bold cyan] {agent.get('name', 'Unknown')} with {files_count} files") 102 | # If no agents found, try the fallback approach directly 103 | else: 104 | logger.info("[bold yellow]Warning:[/bold yellow] No agents found from standard parsing, trying fallback") 105 | try: 106 | fallback_agents = extract_agent_fallback(plan_text) 107 | if fallback_agents: 108 | logger.info(f"[bold green]Success:[/bold green] Fallback found {len(fallback_agents)} agents") 109 | agents = fallback_agents 110 | else: 111 | logger.warning("[bold yellow]Warning:[/bold yellow] Fallback parsing couldn't find any agents") 112 | except Exception as e: 113 | logger.error(f"[bold red]Error:[/bold red] Fallback parsing failed: {str(e)}") 114 | 115 | # Add the agents to the response dictionary 116 | analysis_plan_response["agents"] = agents 117 | 118 | return analysis_plan_response 119 | except Exception as e: 120 | logger.error(f"[bold red]Error:[/bold red] in Phase 2: {str(e)}") 121 | return {"error": str(e)} 122 | -------------------------------------------------------------------------------- /core/analysis/phase_4.py: -------------------------------------------------------------------------------- 1 | # core/analysis/phase_4.py 2 | """ 3 | This module provides functionality for Phase 4 (Synthesis) of the project analysis. 4 | It defines the methods needed for synthesizing the findings from Phase 3. 5 | """ 6 | 7 | # ==================================================== 8 | # Import Statements 9 | # This section imports necessary modules and functions for the script. 10 | # ==================================================== 11 | 12 | import logging # Used for logging messages 13 | from typing import Dict # Used for type hinting, making code more readable 14 | from core.agents.openai import OpenAIAgent # The OpenAI agent class 15 | from config.prompts.phase_4_prompts import PHASE_4_PROMPT, format_phase4_prompt # Prompts for Phase 4 16 | from core.agents import get_architect_for_phase # Added import for dynamic model configuration 17 | 18 | # ==================================================== 19 | # Logger Initialization 20 | # Get the logger for this module. 21 | # ==================================================== 22 | 23 | # Get logger 24 | logger = logging.getLogger("project_extractor") 25 | 26 | # ==================================================== 27 | # Phase 4 Analysis Class 28 | # This class handles the Phase 4 (Synthesis) of the project analysis. 29 | # ==================================================== 30 | 31 | class Phase4Analysis: 32 | """ 33 | Class responsible for Phase 4 (Synthesis) of the project analysis. 34 | 35 | This phase uses a model configured in config/agents.py to synthesize the findings from Phase 3, 36 | providing a deeper analysis and updated directions. 37 | """ 38 | 39 | # ==================================================== 40 | # Initialization Method 41 | # Sets up the Phase 4 analysis with the OpenAI agent. 42 | # ==================================================== 43 | def __init__(self): 44 | """ 45 | Initialize the Phase 4 analysis with the architect from configuration. 46 | """ 47 | # Use the factory function to get the appropriate architect based on configuration 48 | self.architect = get_architect_for_phase("phase4") 49 | 50 | # ==================================================== 51 | # Run Method 52 | # Executes the Synthesis Phase using the configured model. 53 | # ==================================================== 54 | async def run(self, phase3_results: Dict) -> Dict: 55 | """ 56 | Run the Synthesis Phase using the configured model. 57 | 58 | Args: 59 | phase3_results: Dictionary containing the results from Phase 3 60 | 61 | Returns: 62 | Dictionary containing the synthesis and token usage 63 | """ 64 | try: 65 | # Format the prompt using the template from the prompts file 66 | prompt = format_phase4_prompt(phase3_results) 67 | 68 | logger.info("[bold]Phase 4:[/bold] Synthesizing findings from all analysis agents") 69 | 70 | # Use the architect to synthesize findings from Phase 3 71 | result = await self.architect.synthesize_findings(phase3_results, prompt) 72 | 73 | logger.info("[bold green]Phase 4:[/bold green] Synthesis completed successfully") 74 | 75 | return result 76 | except Exception as e: 77 | logger.error(f"[bold red]Error in Phase 4:[/bold red] {str(e)}") 78 | return {"error": str(e)} 79 | -------------------------------------------------------------------------------- /core/analysis/phase_5.py: -------------------------------------------------------------------------------- 1 | # core/analysis/phase_5.py 2 | # ============================================================================= 3 | # Phase 5: Consolidation 4 | # This file contains the code for Phase 5 of the project analysis, which 5 | # consolidates the results from all previous phases into a single report. 6 | # ============================================================================= 7 | 8 | # ============================================================================= 9 | # Import Statements 10 | # These lines import necessary modules and functions for this phase. 11 | # - json: For handling JSON data. 12 | # - logging: For logging events and errors. 13 | # - Dict: For type hinting dictionaries. 14 | # - Anthropic: The Anthropic API client. 15 | # - PHASE_5_PROMPT, format_phase5_prompt: Specific prompt and formatting 16 | # function for Phase 5 from the config.prompts module. 17 | # ============================================================================= 18 | import json 19 | import logging 20 | from typing import Dict 21 | from anthropic import Anthropic 22 | from config.prompts.phase_5_prompts import PHASE_5_PROMPT, format_phase5_prompt 23 | from core.agents import get_architect_for_phase 24 | 25 | # ============================================================================= 26 | # Initialize the Anthropic Client and Logger 27 | # This section initializes the Anthropic client for API calls and sets up 28 | # logging to track the process. 29 | # ============================================================================= 30 | anthropic_client = Anthropic() 31 | logger = logging.getLogger("project_extractor") 32 | 33 | # ============================================================================= 34 | # Phase 5 Analysis Class 35 | # This class handles the consolidation of results from all previous phases. 36 | # ============================================================================= 37 | class Phase5Analysis: 38 | """ 39 | Class responsible for Phase 5 (Consolidation) of the project analysis. 40 | 41 | This phase uses a model configured in config/agents.py to consolidate 42 | the results from all previous phases into a comprehensive final report. 43 | """ 44 | 45 | # ========================================================================= 46 | # Initialization Method 47 | # Sets up the Phase 5 analysis with the model from configuration. 48 | # ========================================================================= 49 | def __init__(self): 50 | """ 51 | Initialize the Phase 5 analysis with the architect from configuration. 52 | """ 53 | # Use the factory function to get the appropriate architect based on configuration 54 | self.architect = get_architect_for_phase("phase5") 55 | 56 | # ========================================================================= 57 | # Run Method 58 | # Executes the consolidation phase using the configured model. 59 | # ========================================================================= 60 | async def run(self, all_results: Dict) -> Dict: 61 | """ 62 | Run the Consolidation Phase using the configured model. 63 | 64 | Args: 65 | all_results: Dictionary containing the results from all previous phases 66 | 67 | Returns: 68 | Dictionary containing the consolidated report 69 | """ 70 | try: 71 | # Format the prompt using the template from the prompts file 72 | prompt = format_phase5_prompt(all_results) 73 | 74 | logger.info("[bold]Phase 5:[/bold] Consolidating results from all previous phases") 75 | 76 | # Use the architect to consolidate results 77 | result = await self.architect.consolidate_results(all_results, prompt) 78 | 79 | logger.info("[bold green]Phase 5:[/bold green] Consolidation completed successfully") 80 | 81 | # Return the result, ensuring it has the expected format 82 | if "report" not in result and "error" not in result: 83 | if "phase" in result and isinstance(result.get("phase"), str): 84 | return result # Already in the expected format 85 | else: 86 | # Extract findings if available 87 | findings = result.get("findings", "No consolidated report generated") 88 | return { 89 | "phase": "Consolidation", 90 | "report": findings if isinstance(findings, str) else json.dumps(findings) 91 | } 92 | return result 93 | except Exception as e: 94 | logger.error(f"[bold red]Error in Phase 5:[/bold red] {str(e)}") 95 | return { 96 | "phase": "Consolidation", 97 | "error": str(e) 98 | } 99 | -------------------------------------------------------------------------------- /core/types/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/types package 3 | 4 | This package contains type definitions for various components of the project. 5 | """ 6 | 7 | from .agent_config import AgentConfig 8 | from .models import ( 9 | ModelConfig, 10 | # Predefined model configurations 11 | CLAUDE_BASIC, 12 | CLAUDE_WITH_REASONING, 13 | O1_HIGH, 14 | O1_MEDIUM, 15 | O1_LOW, 16 | O3_MINI_HIGH, 17 | O3_MINI_MEDIUM, 18 | O3_MINI_LOW, 19 | GPT4_1_DEFAULT, 20 | GPT4_1_CREATIVE, 21 | GPT4_1_PRECISE, 22 | DEEPSEEK_REASONER, 23 | GEMINI_BASIC, 24 | GEMINI_WITH_REASONING 25 | ) -------------------------------------------------------------------------------- /core/types/agent_config.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | from typing_extensions import TypedDict 3 | 4 | 5 | class AgentConfig(TypedDict): 6 | PHASE_1_AGENTS: str 7 | PHASE_2_AGENTS: str 8 | PHASE_3_AGENTS: str 9 | PHASE_4_AGENTS: str 10 | PHASE_5_AGENTS: str -------------------------------------------------------------------------------- /core/types/models.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/types/models.py 3 | 4 | This module defines the model configuration types and predefined model configurations 5 | used throughout the CursorRules Architect system. 6 | """ 7 | 8 | from typing import Dict, Any, NamedTuple, Optional 9 | from core.agents.base import ModelProvider, ReasoningMode 10 | 11 | # ==================================================== 12 | # Model Configuration Types 13 | # This section defines types for model configuration. 14 | # ==================================================== 15 | 16 | class ModelConfig(NamedTuple): 17 | """Configuration for a specific AI model.""" 18 | provider: ModelProvider 19 | model_name: str 20 | reasoning: ReasoningMode = ReasoningMode.DISABLED 21 | temperature: Optional[float] = None # For temperature-based models like gpt-4.1 22 | 23 | # ==================================================== 24 | # Predefined Model Configurations 25 | # These are shorthand configurations that can be referenced in the MODEL_CONFIG. 26 | # ==================================================== 27 | 28 | CLAUDE_BASIC = ModelConfig( 29 | provider=ModelProvider.ANTHROPIC, 30 | model_name="claude-3-7-sonnet-20250219", 31 | reasoning=ReasoningMode.DISABLED 32 | ) 33 | 34 | CLAUDE_WITH_REASONING = ModelConfig( 35 | provider=ModelProvider.ANTHROPIC, 36 | model_name="claude-3-7-sonnet-20250219", 37 | reasoning=ReasoningMode.ENABLED 38 | ) 39 | 40 | # O1 configurations with different reasoning levels 41 | O1_HIGH = ModelConfig( 42 | provider=ModelProvider.OPENAI, 43 | model_name="o1", 44 | reasoning=ReasoningMode.HIGH 45 | ) 46 | 47 | O1_MEDIUM = ModelConfig( 48 | provider=ModelProvider.OPENAI, 49 | model_name="o1", 50 | reasoning=ReasoningMode.MEDIUM 51 | ) 52 | 53 | O1_LOW = ModelConfig( 54 | provider=ModelProvider.OPENAI, 55 | model_name="o1", 56 | reasoning=ReasoningMode.LOW 57 | ) 58 | 59 | # O3-mini configurations with different reasoning levels 60 | O3_MINI_HIGH = ModelConfig( 61 | provider=ModelProvider.OPENAI, 62 | model_name="o3-mini", 63 | reasoning=ReasoningMode.HIGH 64 | ) 65 | 66 | O3_MINI_MEDIUM = ModelConfig( 67 | provider=ModelProvider.OPENAI, 68 | model_name="o3-mini", 69 | reasoning=ReasoningMode.MEDIUM 70 | ) 71 | 72 | O3_MINI_LOW = ModelConfig( 73 | provider=ModelProvider.OPENAI, 74 | model_name="o3-mini", 75 | reasoning=ReasoningMode.LOW 76 | ) 77 | 78 | # gpt-4.1 configurations with different temperature values 79 | GPT4_1_DEFAULT = ModelConfig( 80 | provider=ModelProvider.OPENAI, 81 | model_name="gpt-4.1", 82 | reasoning=ReasoningMode.TEMPERATURE, 83 | temperature=0.7 # Default temperature 84 | ) 85 | 86 | GPT4_1_CREATIVE = ModelConfig( 87 | provider=ModelProvider.OPENAI, 88 | model_name="gpt-4.1", 89 | reasoning=ReasoningMode.TEMPERATURE, 90 | temperature=0.9 # Higher temperature for more creative outputs 91 | ) 92 | 93 | GPT4_1_PRECISE = ModelConfig( 94 | provider=ModelProvider.OPENAI, 95 | model_name="gpt-4.1", 96 | reasoning=ReasoningMode.TEMPERATURE, 97 | temperature=0.2 # Lower temperature for more precise/deterministic outputs 98 | ) 99 | 100 | # DeepSeek configurations 101 | DEEPSEEK_REASONER = ModelConfig( 102 | provider=ModelProvider.DEEPSEEK, 103 | model_name="deepseek-reasoner", 104 | reasoning=ReasoningMode.ENABLED # Always enabled for reasoner 105 | ) 106 | 107 | # Gemini configurations 108 | GEMINI_BASIC = ModelConfig( 109 | provider=ModelProvider.GEMINI, 110 | model_name="gemini-2.5-flash-preview-04-17", 111 | reasoning=ReasoningMode.DISABLED 112 | ) 113 | 114 | GEMINI_WITH_REASONING = ModelConfig( 115 | provider=ModelProvider.GEMINI, 116 | model_name="gemini-2.5-pro-preview-03-25", 117 | reasoning=ReasoningMode.ENABLED 118 | ) -------------------------------------------------------------------------------- /core/types/tool_config.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlyyCooper/cursorrules-architect/d3341bec543e5ba24cacc2caf33383e98c657e2d/core/types/tool_config.py -------------------------------------------------------------------------------- /core/utils/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlyyCooper/cursorrules-architect/d3341bec543e5ba24cacc2caf33383e98c657e2d/core/utils/.DS_Store -------------------------------------------------------------------------------- /core/utils/file_creation/phases_output.py: -------------------------------------------------------------------------------- 1 | """ 2 | utils/file_creation/phases_output.py 3 | 4 | This module provides functionality for saving the outputs of analysis phases 5 | to separate files. It handles the creation of output directories and formatting 6 | of the output files. 7 | 8 | This module is used by the main analysis process to save results in a structured way. 9 | """ 10 | 11 | # ==================================================== 12 | # Importing Necessary Libraries 13 | # This section imports external libraries that are used in the code. 14 | # These libraries add extra functionalities that Python doesn't have by default. 15 | # ==================================================== 16 | 17 | import json # Used for working with JSON data 18 | from pathlib import Path # Used for interacting with file paths in a more object-oriented way 19 | from typing import Dict, Any # Used for type hinting, which makes the code easier to understand 20 | import os # Used for creating directories 21 | 22 | 23 | # ==================================================== 24 | # Function to Save Phase Outputs 25 | # This is the main function that takes the analysis results and saves them into separate files. 26 | # ==================================================== 27 | 28 | def save_phase_outputs(directory: Path, analysis_data: dict) -> None: 29 | """ 30 | Save the outputs of each phase to separate markdown files. 31 | 32 | Args: 33 | directory: Path to the project directory 34 | analysis_data: Dictionary containing the results from all phases 35 | """ 36 | # Import the MODEL_CONFIG to get model information for each phase 37 | from config.agents import MODEL_CONFIG 38 | from main import get_model_config_name 39 | 40 | # Get model configuration names 41 | phase1_model = get_model_config_name(MODEL_CONFIG['phase1']) 42 | phase2_model = get_model_config_name(MODEL_CONFIG['phase2']) 43 | phase3_model = get_model_config_name(MODEL_CONFIG['phase3']) 44 | phase4_model = get_model_config_name(MODEL_CONFIG['phase4']) 45 | phase5_model = get_model_config_name(MODEL_CONFIG['phase5']) 46 | final_model = get_model_config_name(MODEL_CONFIG['final']) 47 | 48 | # Create the phases_output directory if it doesn't exist 49 | output_dir = directory / "phases_output" 50 | os.makedirs(output_dir, exist_ok=True) 51 | 52 | # Helper function to ensure values are strings 53 | def ensure_string(value: Any) -> str: 54 | """ 55 | Ensure that the value is a string. 56 | 57 | Args: 58 | value: The value to convert to a string 59 | 60 | Returns: 61 | String representation of the value 62 | """ 63 | if isinstance(value, str): 64 | return value 65 | elif isinstance(value, dict) or isinstance(value, list): 66 | return json.dumps(value, indent=2) 67 | else: 68 | return str(value) 69 | 70 | # Phase 1: Initial Discovery 71 | with open(output_dir / "phase1_discovery.md", "w", encoding="utf-8") as f: 72 | f.write(f"# Phase 1: Initial Discovery (Config: {phase1_model})\n\n") 73 | f.write("## Agent Findings\n\n") 74 | f.write("```json\n") 75 | f.write(json.dumps(analysis_data["phase1"], indent=2)) # Write the Phase 1 results as JSON 76 | f.write("\n```\n") 77 | 78 | # Phase 2: Methodical Planning 79 | with open(output_dir / "phase2_planning.md", "w", encoding="utf-8") as f: 80 | f.write(f"# Phase 2: Methodical Planning (Config: {phase2_model})\n\n") 81 | plan_data = analysis_data["phase2"].get("plan", "Error in planning phase") 82 | f.write(ensure_string(plan_data)) # Ensure we're writing a string 83 | 84 | # Phase 3: Deep Analysis 85 | with open(output_dir / "phase3_analysis.md", "w", encoding="utf-8") as f: 86 | f.write(f"# Phase 3: Deep Analysis (Config: {phase3_model})\n\n") 87 | f.write("```json\n") 88 | f.write(json.dumps(analysis_data["phase3"], indent=2)) # Write the Phase 3 results as JSON 89 | f.write("\n```\n") 90 | 91 | # Phase 4: Synthesis 92 | with open(output_dir / "phase4_synthesis.md", "w", encoding="utf-8") as f: 93 | f.write(f"# Phase 4: Synthesis (Config: {phase4_model})\n\n") 94 | analysis_data_phase4 = analysis_data["phase4"].get("analysis", "Error in synthesis phase") 95 | f.write(ensure_string(analysis_data_phase4)) # Ensure we're writing a string 96 | 97 | # Phase 5: Consolidation 98 | with open(output_dir / "phase5_consolidation.md", "w", encoding="utf-8") as f: 99 | f.write(f"# Phase 5: Consolidation (Config: {phase5_model})\n\n") 100 | report_data = analysis_data["consolidated_report"].get("report", "Error in consolidation phase") 101 | f.write(ensure_string(report_data)) # Ensure we're writing a string 102 | 103 | # Final Analysis - Save to both markdown file and .cursorrules file 104 | final_analysis_data = analysis_data["final_analysis"].get("analysis", "Error in final analysis phase") 105 | 106 | # Save to markdown file in phases_output directory 107 | with open(output_dir / "final_analysis.md", "w", encoding="utf-8") as f: 108 | f.write(f"# Final Analysis (Config: {final_model})\n\n") 109 | f.write(ensure_string(final_analysis_data)) # Ensure we're writing a string 110 | 111 | # Save to .cursorrules file in project root directory with project tree 112 | # Define directories to exclude from the tree 113 | exclude_dirs = ["phases_output", "__pycache__", ".git", ".vscode", ".cursor"] 114 | 115 | # Get the project tree without the excluded directories 116 | from core.utils.tools.tree_generator import generate_tree, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_PATTERNS 117 | 118 | # Create a custom set of exclude directories by combining defaults with our additions 119 | custom_exclude_dirs = DEFAULT_EXCLUDE_DIRS.union(set(exclude_dirs)) 120 | 121 | # Generate a tree with our custom exclusions 122 | tree = generate_tree( 123 | directory, 124 | exclude_dirs=custom_exclude_dirs, 125 | exclude_patterns=DEFAULT_EXCLUDE_PATTERNS 126 | ) 127 | 128 | # Add delimiters and format for inclusion in the .cursorrules file 129 | tree_section = [ 130 | "\n", 131 | ] 132 | tree_section.extend(tree) 133 | tree_section.append("") 134 | 135 | # Write final analysis and tree to .cursorrules file 136 | with open(directory / ".cursorrules", "w", encoding="utf-8") as f: 137 | f.write(ensure_string(final_analysis_data)) # Save the final analysis 138 | f.write("\n\n") # Add spacing 139 | f.write("# Project Directory Structure\n") # Section header 140 | f.write("---\n\n") # Section divider 141 | f.write('\n'.join(tree_section)) # Append the tree structure 142 | 143 | # ==================================================== 144 | # Create metrics file 145 | # This section creates a metrics file that summarizes key information 146 | # from the entire analysis, including metrics like total time and token usage. 147 | # ==================================================== 148 | with open(output_dir / "metrics.md", "w", encoding="utf-8") as f: 149 | f.write("# CursorRules Architect Metrics\n\n") 150 | f.write(f"Project: {directory}\n") 151 | f.write("=" * 50 + "\n\n") 152 | f.write("## Analysis Metrics\n\n") 153 | f.write(f"- Time taken: {analysis_data['metrics']['time']:.2f} seconds\n") # Write the total time 154 | 155 | f.write("\n## Model Configurations Used\n\n") 156 | f.write(f"- Phase 1: Initial Discovery - {phase1_model}\n") 157 | f.write(f"- Phase 2: Methodical Planning - {phase2_model}\n") 158 | f.write(f"- Phase 3: Deep Analysis - {phase3_model}\n") 159 | f.write(f"- Phase 4: Synthesis - {phase4_model}\n") 160 | f.write(f"- Phase 5: Consolidation - {phase5_model}\n") 161 | f.write(f"- Final Analysis - {final_model}\n") 162 | 163 | f.write("\n## Generated Files\n\n") 164 | f.write("- `.cursorrules` - Contains the final analysis for Cursor IDE\n") 165 | f.write("- `.cursorignore` - Contains patterns of files to ignore in Cursor IDE\n") 166 | f.write(f"- `phase1_discovery.md` - Results from Initial Discovery (Config: {phase1_model})\n") 167 | f.write(f"- `phase2_planning.md` - Results from Methodical Planning (Config: {phase2_model})\n") 168 | f.write(f"- `phase3_analysis.md` - Results from Deep Analysis (Config: {phase3_model})\n") 169 | f.write(f"- `phase4_synthesis.md` - Results from Synthesis (Config: {phase4_model})\n") 170 | f.write(f"- `phase5_consolidation.md` - Results from Consolidation (Config: {phase5_model})\n") 171 | f.write(f"- `final_analysis.md` - Copy of the final analysis (Config: {final_model})\n\n") 172 | f.write("See individual phase files for detailed outputs.") 173 | -------------------------------------------------------------------------------- /core/utils/tools/.cursorrules: -------------------------------------------------------------------------------- 1 | ```cursorrules 2 | 1. IDENTITY ESTABLISHMENT 3 | You are an advanced Python developer specializing in a multi-phase code analysis system. You oversee the “agent_parser.py,” “file_retriever.py,” and “tree_generator.py” modules to form a robust, modular pipeline for analyzing and visualizing project structures. 4 | 5 | 2. TEMPORAL FRAMEWORK 6 | It is the year 2025 and you are implementing brand-new concurrency capabilities along with modernized XML parsing strategies—significantly more advanced than those in your 2023 training data. 7 | 8 | 3. TECHNICAL CONSTRAINTS 9 | # Technical Environment 10 | - Python environment (3.9+) utilizing “pathlib” and “concurrent.futures” for concurrency 11 | - Project features a multi-phase analysis pipeline with specialized modules: 12 | 1) “agent_parser.py” for XML-based agent definitions 13 | 2) “file_retriever.py” for content and encoding retrieval 14 | 3) “tree_generator.py” for visual directory structures 15 | 16 | # Dependencies 17 | - xml.etree.ElementTree (built-in, advanced error handling required) 18 | - concurrent.futures (ThreadPoolExecutor recommended) 19 | - Logging framework of your choice (must support configurable logging levels) 20 | 21 | # Configuration 22 | - All shared settings and exclusion patterns must be centralized to avoid duplication 23 | - Maximum default file limit: 500 24 | - Default concurrency workers: 4 25 | 26 | 4. IMPERATIVE DIRECTIVES 27 | # Your Requirements: 28 | 1. ALWAYS centralize configuration. No hard-coded exclusions or file limits scattered throughout the code. 29 | 2. Use concurrency—particularly ThreadPoolExecutor—for file retrieval tasks involving large codebases. 30 | 3. Standardize error handling with clear, logged exceptions. Avoid silent catches. 31 | 4. Implement robust XML parsing with proper sanitization—never rely purely on regex for agent definitions. 32 | 5. Maintain modular design. Keep each phase (Discovery, Planning, Analysis, Synthesis, Consolidation) logically separated. 33 | 6. Document new learnings or corrections in the designated knowledge evolution file (see Section 8). 34 | 35 | 5. KNOWLEDGE FRAMEWORK 36 | 37 | # 5.1 Technology Documentation 38 | ## Python Concurrency 39 | Python’s “concurrent.futures” module allows parallel execution of tasks using ThreadPoolExecutor or ProcessPoolExecutor. For I/O-bound tasks—like reading multiple files concurrently—ThreadPoolExecutor is preferred. 40 | 41 | ## XML Parsing 42 | Use robust libraries (xml.etree.ElementTree, xml.sax.saxutils) to parse, escape, or sanitize XML data. Fallback to regex-based methods ONLY when standard XML parsing fails—and log these events. 43 | 44 | ## Directory & File Operations 45 | The “pathlib” library is used for path manipulations and directory traversal. Generating an ASCII-like tree requires recursion or iterative scanning over directories. Exclusion patterns should come from a centralized config class. 46 | 47 | # 5.2 Implementation Patterns 48 | 1. Multi-Phase Architecture: 49 | - Each phase (Discovery → Planning → Analysis → Synthesis → Consolidation) refines the context for the next. 50 | - Keep pipeline data (e.g., discovered paths, agent responsibilities) well-defined and typed. 51 | 52 | 2. Defensive Programming: 53 | - Use try/except blocks around I/O operations and XML parsing. 54 | - Log all errors consistently without masking them. 55 | 56 | 3. Configuration Manager: 57 | - Provide default fallback values for exclusions, encoding attempts, file limits, and concurrency workers. 58 | 59 | # 5.3 Best Practices 60 | - DRY up repeated code for exclusions, error handling, and concurrency structures. 61 | - Use type annotations for all function signatures to clarify data shapes. 62 | - Keep a consistent code style (PEP 8). 63 | - Perform partial or full concurrency based on codebase size and hardware. 64 | - Validate and escape untrusted XML content to prevent injection attacks. 65 | 66 | 6. IMPLEMENTATION EXAMPLES 67 | 68 | ## Centralized Configuration 69 | ```python 70 | # config_manager.py 71 | class ConfigManager: 72 | DEFAULT_EXCLUSIONS = [ 73 | "__pycache__", 74 | ".git", 75 | "node_modules" 76 | ] 77 | 78 | DEFAULT_ENCODING_ATTEMPTS = [ 79 | "utf-8", 80 | "latin-1", 81 | "cp1252" 82 | ] 83 | 84 | MAX_FILES = 500 85 | DEFAULT_CONCURRENCY_WORKERS = 4 86 | 87 | @classmethod 88 | def get_exclusions(cls): 89 | return cls.DEFAULT_EXCLUSIONS 90 | 91 | @classmethod 92 | def get_encoding_fallbacks(cls): 93 | return cls.DEFAULT_ENCODING_ATTEMPTS 94 | ``` 95 | 96 | Expected Output: 97 | Use “ConfigManager” across all modules to avoid repeating identical exclusion or encoding lists. 98 | 99 | ## XML Parsing with Fallback 100 | ```python 101 | # agent_parser.py 102 | import xml.sax.saxutils 103 | from xml.etree import ElementTree as ET 104 | 105 | def parse_agent_xml(xml_content): 106 | try: 107 | root = ET.fromstring(xml_content) 108 | agents = [] 109 | for agent_elem in root.findall(".//agent"): 110 | agent = { 111 | "id": agent_elem.get("id"), 112 | "name": agent_elem.findtext("name"), 113 | "description": agent_elem.findtext("description"), 114 | "file_assignments": [ 115 | path.text for path in agent_elem.findall("file_assignments/file_path") 116 | ] 117 | } 118 | agents.append(agent) 119 | return agents 120 | except ET.ParseError as exc: 121 | logger.warning(f"XML parsing failed: {str(exc)}; attempting fallback.") 122 | return parse_agent_xml_fallback(xml_content) 123 | ``` 124 | 125 | Expected Output: 126 | An agents list loaded from well-formed XML. If parsing fails, fallback occurs, but usage is carefully logged. 127 | 128 | ## Concurrent File Retrieval 129 | ```python 130 | # file_retriever.py 131 | import concurrent.futures 132 | from pathlib import Path 133 | from config_manager import ConfigManager 134 | 135 | def retrieve_files_concurrent(directory): 136 | file_paths = list_files( 137 | directory, 138 | exclusions=ConfigManager.get_exclusions() 139 | ) 140 | results = [] 141 | 142 | with concurrent.futures.ThreadPoolExecutor( 143 | max_workers=ConfigManager.DEFAULT_CONCURRENCY_WORKERS 144 | ) as executor: 145 | future_to_path = { 146 | executor.submit(read_file_with_fallback, p): p 147 | for p in file_paths 148 | } 149 | for future in concurrent.futures.as_completed(future_to_path): 150 | path = future_to_path[future] 151 | try: 152 | content = future.result() 153 | if content: 154 | results.append((path, content)) 155 | except Exception as exc: 156 | logger.error(f"Error reading {path}: {str(exc)}") 157 | return results 158 | ``` 159 | 160 | Expected Output: 161 | A list of (Path, Content) tuples processed in parallel, with logs for errors. 162 | 163 | 7. NEGATIVE PATTERNS 164 | 165 | # What NOT to do: 166 | 167 | ## Unsecured XML Parsing 168 | - Relying solely on “regex” for sanitizing or parsing XML. 169 | - Not escaping untrusted content, leading to injection vulnerabilities. 170 | 171 | ## Configuration Sprawl 172 | - Hard-coding file exclusions or concurrency limits in multiple modules. 173 | - Failing to update references when defaults change. 174 | 175 | ## Inconsistent Error Handling 176 | - Swallowing exceptions without logging. 177 | - Using bare “except:” with no additional context or re-raise logic. 178 | 179 | 8. KNOWLEDGE EVOLUTION MECHANISM 180 | # Knowledge Evolution: 181 | 182 | As you discover improved concurrency strategies, advanced XML libraries, or better error handling patterns, record them in: 183 | “phases_output/knowledge_evolution.md” 184 | using the format below: 185 | 186 | ## [Category] 187 | - [Old pattern] → [New pattern] 188 | - [Incorrect assumption] → [Correct information] 189 | 190 | Example: 191 | - “Regex-based XML sanitization” → “Proper xml.etree.ElementTree usage” 192 | - “Manual concurrency for loops” → “ThreadPoolExecutor with dynamic worker allocation” 193 | ``` 194 | 195 | 196 | # Project Directory Structure 197 | --- 198 | 199 | 200 | 201 | File Type Key: 202 | ------------ 203 | 🐍 : Python 204 | 📁 : Directory 205 | 📝 : Markdown 206 | 207 | ├── 📁 phases_output 208 | │ ├── 📝 final_analysis.md 209 | │ ├── 📝 phase1_discovery.md 210 | │ ├── 📝 phase2_planning.md 211 | │ ├── 📝 phase3_analysis.md 212 | │ ├── 📝 phase4_synthesis.md 213 | │ └── 📝 phase5_consolidation.md 214 | ├── 🐍 agent_parser.py 215 | ├── 🐍 file_retriever.py 216 | └── 🐍 tree_generator.py 217 | -------------------------------------------------------------------------------- /core/utils/tools/clean_cursorrules.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | core/utils/tools/clean_cursorrules.py 4 | 5 | This module provides functionality for cleaning .cursorrules files by removing 6 | any text before the first occurrence of "You are...". 7 | 8 | This ensures that cursor rules files start with the proper system prompt format. 9 | """ 10 | 11 | # ==================================================== 12 | # Importing Required Libraries 13 | # ==================================================== 14 | 15 | import os 16 | import re 17 | from pathlib import Path 18 | from typing import Tuple, Optional 19 | 20 | # ==================================================== 21 | # Constants 22 | # ==================================================== 23 | CURSORRULES_FILE = ".cursorrules" # Default name for the .cursorrules file 24 | START_PATTERN = re.compile(r'\bYou are\b', re.IGNORECASE) # Pattern to find "You are" text 25 | 26 | 27 | # ==================================================== 28 | # Function: clean_cursorrules_file 29 | # This function cleans a .cursorrules file by removing any text 30 | # before the first occurrence of "You are..." 31 | # ==================================================== 32 | def clean_cursorrules_file(file_path: str) -> Tuple[bool, str]: 33 | """ 34 | Clean a .cursorrules file by removing any text before "You are...". 35 | 36 | Args: 37 | file_path: Path to the .cursorrules file 38 | 39 | Returns: 40 | Tuple[bool, str]: Success status and message 41 | """ 42 | try: 43 | # Check if file exists 44 | if not os.path.isfile(file_path): 45 | return False, f"File not found: {file_path}" 46 | 47 | # Read file content 48 | with open(file_path, 'r', encoding='utf-8') as f: 49 | content = f.read() 50 | 51 | # Find first occurrence of "You are" 52 | match = START_PATTERN.search(content) 53 | if not match: 54 | return False, f"Pattern 'You are' not found in {file_path}" 55 | 56 | # Get the cleaned content starting from "You are" 57 | cleaned_content = content[match.start():] 58 | 59 | # Write the cleaned content back to the file 60 | with open(file_path, 'w', encoding='utf-8') as f: 61 | f.write(cleaned_content) 62 | 63 | return True, f"Successfully cleaned {file_path}" 64 | 65 | except Exception as e: 66 | return False, f"Error cleaning {file_path}: {str(e)}" 67 | 68 | 69 | # ==================================================== 70 | # Function: clean_cursorrules 71 | # This function finds and cleans a .cursorrules file in the specified directory 72 | # ==================================================== 73 | def clean_cursorrules(directory: Optional[str] = None) -> Tuple[bool, str]: 74 | """ 75 | Find and clean a .cursorrules file in the specified directory. 76 | 77 | Args: 78 | directory: Optional directory path where to find the file. If None, uses current directory. 79 | 80 | Returns: 81 | Tuple[bool, str]: Success status and message 82 | """ 83 | # Determine the full path for the .cursorrules file 84 | if directory: 85 | cursorrules_path = os.path.join(directory, CURSORRULES_FILE) 86 | else: 87 | cursorrules_path = CURSORRULES_FILE 88 | 89 | return clean_cursorrules_file(cursorrules_path) 90 | -------------------------------------------------------------------------------- /core/utils/tools/model_config_helper.py: -------------------------------------------------------------------------------- 1 | """ 2 | core/utils/tools/model_config_helper.py 3 | 4 | This module provides utility functions for working with model configurations, 5 | including functions to identify and display model configuration names. 6 | """ 7 | 8 | import inspect 9 | from typing import Dict, Any, Union 10 | from config.agents import MODEL_CONFIG 11 | import core.types.models as models_module 12 | 13 | def get_model_config_name(config_entry): 14 | """ 15 | Find the variable name for a model configuration in models.py or agents.py 16 | 17 | Args: 18 | config_entry: A ModelConfig object or dict with model configuration info 19 | 20 | Returns: 21 | str: The configuration name (like "GPT4_1_CREATIVE" or "CLAUDE_WITH_REASONING") 22 | """ 23 | # First check if it's one of the predefined phase configs 24 | for phase, config in MODEL_CONFIG.items(): 25 | if isinstance(config_entry, dict): 26 | if (config.provider == config_entry.get("provider") and 27 | config.model_name == config_entry.get("model_name") and 28 | config.reasoning == config_entry.get("reasoning") and 29 | config.temperature == config_entry.get("temperature")): 30 | # Instead of returning the phase name, continue looking for the actual config name 31 | pass 32 | elif config is config_entry: 33 | # Direct object identity match (for when passing MODEL_CONFIG['phase1'] directly) 34 | # First check in models_module to find predefined configs 35 | for name, value in inspect.getmembers(models_module): 36 | if name.isupper() and value is config: 37 | return name 38 | 39 | # If not found, check in agents_module (backwards compatibility) 40 | import config.agents as agents_module 41 | for name, value in inspect.getmembers(agents_module): 42 | if name.isupper() and value is config: 43 | return name 44 | 45 | # Check all variables in the core.types.models module 46 | for name, value in inspect.getmembers(models_module): 47 | if name.isupper() and value is not None and hasattr(value, "provider") and hasattr(value, "model_name"): 48 | if isinstance(config_entry, dict): 49 | if (value.provider == config_entry.get("provider") and 50 | value.model_name == config_entry.get("model_name") and 51 | value.reasoning == config_entry.get("reasoning") and 52 | value.temperature == config_entry.get("temperature")): 53 | return name 54 | elif (value.provider == getattr(config_entry, "provider", None) and 55 | value.model_name == getattr(config_entry, "model_name", None) and 56 | value.reasoning == getattr(config_entry, "reasoning", None) and 57 | value.temperature == getattr(config_entry, "temperature", None)): 58 | return name 59 | 60 | # If not found in models_module, check in agents_module (backwards compatibility) 61 | import config.agents as agents_module 62 | for name, value in inspect.getmembers(agents_module): 63 | if name.isupper() and hasattr(value, "provider") and hasattr(value, "model_name"): 64 | if isinstance(config_entry, dict): 65 | if (value.provider == config_entry.get("provider") and 66 | value.model_name == config_entry.get("model_name") and 67 | value.reasoning == config_entry.get("reasoning") and 68 | value.temperature == config_entry.get("temperature")): 69 | return name 70 | elif (value.provider == getattr(config_entry, "provider", None) and 71 | value.model_name == getattr(config_entry, "model_name", None) and 72 | value.reasoning == getattr(config_entry, "reasoning", None) and 73 | value.temperature == getattr(config_entry, "temperature", None)): 74 | return name 75 | 76 | # Return the model name if no match is found 77 | if isinstance(config_entry, dict): 78 | provider = config_entry.get("provider", "unknown") 79 | model_name = config_entry.get("model_name", "unknown") 80 | provider_name = provider.name if hasattr(provider, "name") else provider 81 | return f"{provider_name}_{model_name}" 82 | else: 83 | provider_name = config_entry.provider.name if hasattr(config_entry, "provider") else "unknown" 84 | model_name = getattr(config_entry, "model_name", "unknown") 85 | return f"{provider_name}_{model_name}" -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | anthropic 2 | typer[all] 3 | rich 4 | pathlib 5 | pydantic 6 | beautifulsoup4 7 | lxml 8 | openai 9 | google-genai 10 | python-dotenv 11 | tavily-python -------------------------------------------------------------------------------- /tests/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SlyyCooper/cursorrules-architect/d3341bec543e5ba24cacc2caf33383e98c657e2d/tests/.DS_Store -------------------------------------------------------------------------------- /tests/final_analysis_test/fa_test_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "phase": "Consolidation", 3 | "report": "**Final Technical Report: Flight Simulator System Analysis** \n**Prepared by: Report Agent** \n**Date: [Insert Date]** \n\n---\n\n# **Executive Summary** \nThe analysis reveals a flight simulator system in early development with significant technical debt but strong foundational potential. Key risks include critical security vulnerabilities, incomplete core features, and unclear architectural boundaries. Strategic priorities should focus on: \n1. Immediate security remediation \n2. Dependency management standardization \n3. Architectural decision formalization \n4. Core simulation feature completion \n\n---\n\n# **Detailed System Findings** \n\n## **1. Core Architecture Analysis** \n```mermaid\ngraph TD\n A[Flask Server] -->|Serves| B(index.html)\n A -->|Potentially Manages| C[3D Physics]\n B -->|Requires| D[Three.js]\n B -->|Missing| E[Flight Control JS]\n A -->|Security Risk| F[Unrestricted File Access]\n```\n\n**Frontend Components** \n- **HTML Structure**: Basic template exists but lacks: \n - Three.js initialization code \n - Control input handling system \n - Aircraft state management logic \n- **UI Elements**: Partially implemented control panel with truncated instructions \n\n**Backend Components** \n- **Flask Server**: \n - Serves static files with path traversal vulnerability (CWE-22) \n - Runs in debug mode without production hardening \n - No API endpoints or WebSocket implementation \n\n---\n\n# **Critical Discoveries** \n\n| Category | Risk Level | Impact Summary |\n|------------------------|------------|----------------------------------|\n| Security Vulnerabilities | Critical | Unrestricted file access, debug mode exposure |\n| Architectural Gaps | High | No clear client/server boundaries |\n| Dependency Management | High | Unversioned Python/JS dependencies |\n| Feature Completion | Medium | Missing physics engine & 3D rendering logic |\n\n---\n\n# **Strategic Roadmap** \n\n## **Phase 1: Security & Foundation (Weeks 1-2)** \n1. **Security Implementation** \n - [ ] File access whitelisting \n - [ ] Environment-specific configurations \n ```python\n # Sample security implementation\n app = Flask(__name__)\n if os.environ.get('ENV') == 'production':\n app.config['DEBUG'] = False\n app.config['ALLOWED_EXTENSIONS'] = {'html', 'js', 'css'}\n ```\n\n2. **Dependency Management** \n - Create `requirements.txt` with Flask==2.0.1 \n - Establish Three.js r128 baseline \n\n## **Phase 2: Architectural Definition (Weeks 3-4)** \n1. **Component Inventory** \n ```json\n {\n \"missing_components\": [\n \"WebGL Renderer Initialization\",\n \"Aircraft Mesh Loader\",\n \"Flight Dynamics Calculator\",\n \"Control Input Handler\"\n ]\n }\n ```\n\n2. **Protocol Decisions Required** \n - Client/Server communication method (WebSocket vs REST) \n - Physics computation location (Browser vs Server) \n\n## **Phase 3: Feature Implementation (Weeks 5-8)** \n1. Three.js Integration Path \n ```javascript\n // Required initialization sequence\n const scene = new THREE.Scene();\n const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);\n const renderer = new THREE.WebGLRenderer();\n ```\n\n2. Flight Control System \n - Axis control mapping \n - Aerodynamic force calculations \n\n---\n\n# **Technical Debt Assessment** \n\n**Immediate Risks** \n1. Path traversal vulnerability in file serving \n2. Missing input validation layers \n3. Unprotected developer endpoints \n\n**Long-Term Risks** \n1. Unversioned dependencies \n2. Undocumented architecture \n3. Untested WebGL compatibility \n\n---\n\n# **Agent Task Allocation** \n\n| Agent Type | Priority Tasks | Deliverables |\n|--------------------|-----------------------------------------|---------------------------------------|\n| **Structure Agent** | Reverse-engineer DOM interactions | Component inventory JSON |\n| **Dependency Agent**| Security hardening checklist | Vulnerability matrix |\n| **Tech Stack Agent**| Compatibility verification | Version support matrix |\n\n---\n\n# **Next-Step Recommendations** \n1. **Immediate Actions** \n - Disable debug mode and implement file access restrictions \n - Create version-locked requirements.txt \n\n2. **Architectural Planning** \n - Conduct ADR workshop for: \n - Physics engine selection \n - Network protocol standardization \n\n3. **Development Sprints** \n - Week 1: Three.js rendering prototype \n - Week 2: Flight control input system \n - Week 3: Server-side security audit \n\n---\n\n**Conclusion** \nThis system demonstrates potential as a web-based flight simulator but requires focused effort to address security flaws and architectural ambiguity. A phased approach balancing immediate risk mitigation with parallel feature development will maximize progress while maintaining system stability. Regular architectural reviews and test-driven development are recommended to ensure long-term viability. \n\n**Approvals** \n[ ] Technical Lead \n[ ] Security Officer \n[ ] Project Sponsor \n\n--- \n**END OF REPORT**", 4 | "reasoning": "Okay, I need to create a comprehensive final report from the analysis phases provided. Let me start by understanding the input. The user provided the Analysis Results, which include phase1 to phase4. However, phase1, phase2, and phase3 are empty, so all the relevant data is in phase4. The main content is the \"analysis\" and \"reasoning\" sections under phase4.\n\nFirst, my task is to combine all agent findings. Since only phase4 has data, I'll focus on that. The analysis section has several parts: Consolidated Technical Assessment, Information Processing Framework, Revised Investigation Priorities, Enhanced Agent Instructions, Critical Investigation Areas, and Next-Step Recommendations. The reasoning section is a detailed explanation of how the analysis was derived.\n\nThe user wants the final report organized by component/module. Looking at the analysis, the components mentioned include the Flask server (backend), HTML frontend, Three.js integration, security aspects, dependency management, and architectural considerations. I should structure the report around these components.\n\nNext, I need to create comprehensive documentation. This means ensuring each section is detailed, with clear explanations and possibly visual aids like the mermaid diagram provided. The report should highlight key discoveries such as security vulnerabilities, missing components, and architectural gaps.\n\nI should start by outlining the report structure. The example response includes sections like Executive Summary, Detailed Findings, Strategic Roadmap, etc. I can follow a similar structure but ensure it's tailored to the provided analysis.\n\nLooking at the \"analysis\" content, the Consolidated Technical Assessment has a mermaid diagram and key findings. I need to present that clearly. The Information Processing Framework includes a prioritization matrix and knowledge graph additions. The Revised Investigation Priorities list four main areas. The Enhanced Agent Instructions give specific tasks for different agents. Critical Investigation Areas outline technical debt and unknowns. Next-Step Recommendations are listed at the end.\n\nI need to make sure each of these parts is included in the report under appropriate sections. For example, the key findings from the Consolidated Technical Assessment would go into Detailed Findings. The prioritization matrix and knowledge graph could be part of an Analysis Framework section. The investigation priorities and agent instructions would fit into Strategic Roadmap or Recommendations.\n\nHighlighting key discoveries is essential. The security vulnerabilities (debug mode, file access), missing Three.js integration, dependency issues, and architectural uncertainties are critical points. These should be emphasized in the Executive Summary and Detailed Findings.\n\nThe final report needs to be professional and comprehensive, suitable for stakeholders. I should avoid markdown in the thinking process but in the final answer, use appropriate formatting as per the user's example.\n\nWait, the user's example response uses markdown for headings, tables, code blocks, etc. So I should follow that format. Let me check the structure again:\n\n- Title\n- Executive Summary\n- Detailed Findings (organized by component)\n- Analysis Framework (prioritization matrix, knowledge graph)\n- Strategic Roadmap (investigation priorities, agent instructions)\n- Critical Investigation Areas\n- Next-Step Recommendations\n- Conclusion\n\nI need to ensure all the information from the analysis is covered. For instance, the Enhanced Agent Instructions section has specific tasks for Structure, Dependency, and Tech Stack Agents. These should be part of the Strategic Roadmap or a separate section on Agent Task Allocations.\n\nAlso, the reasoning section provides context on how the analysis was derived, which might be useful in explaining the key discoveries or in the Executive Summary.\n\nLet me start drafting each section step by step, making sure to translate the analysis content into the report structure while maintaining clarity and comprehensiveness." 5 | } -------------------------------------------------------------------------------- /tests/final_analysis_test/output/cursor_rules.md: -------------------------------------------------------------------------------- 1 | Based on the provided project structure and report, I will create a tailored `.cursorrules` file in the CRS-1 format. This file will guide the AI assistant in the Cursor IDE to effectively assist in the development of the flight simulator system. The rules will incorporate the project's current state, technical constraints, and strategic priorities. 2 | 3 | ### CRS-1 Cursor Rules File 4 | 5 | ``` 6 | 1. IDENTITY ESTABLISHMENT 7 | 8 | You are an expert web-based flight simulator development assistant specializing in Flask and Three.js integration. 9 | 10 | 2. TEMPORAL FRAMEWORK 11 | 12 | It is March 2025 and you are developing with the latest web technologies to enhance the flight simulator's capabilities. 13 | 14 | 3. TECHNICAL CONSTRAINTS 15 | 16 | # Technical Environment 17 | - Development is conducted on a Linux-based server environment. 18 | - The system is designed to run on modern web browsers with WebGL support. 19 | 20 | # Dependencies 21 | - Flask: 2.0.1 22 | - Three.js: r128 23 | - Python: 3.9 24 | 25 | # Configuration 26 | - Flask server must not run in debug mode in production. 27 | - Static file serving must implement path traversal protection. 28 | 29 | 4. IMPERATIVE DIRECTIVES 30 | 31 | # Your Requirements: 32 | 1. Implement security measures to prevent unrestricted file access. 33 | 2. Ensure all dependencies are version-locked and documented in `requirements.txt`. 34 | 3. Develop clear client/server boundaries with defined communication protocols. 35 | 4. Integrate Three.js for 3D rendering and flight dynamics visualization. 36 | 37 | 5. KNOWLEDGE FRAMEWORK 38 | 39 | # Security Practices 40 | ## File Access 41 | - Implement file access whitelisting to prevent path traversal vulnerabilities. 42 | 43 | ## Environment Configuration 44 | - Use environment-specific configurations to disable debug mode in production. 45 | 46 | # Three.js Integration 47 | ## Initialization 48 | - Ensure proper initialization of WebGL renderer and scene setup. 49 | 50 | ## Flight Dynamics 51 | - Develop aerodynamic force calculations and axis control mapping. 52 | 53 | 6. IMPLEMENTATION EXAMPLES 54 | 55 | ## Flask Security Configuration 56 | 57 | ```python 58 | app = Flask(__name__) 59 | if os.environ.get('ENV') == 'production': 60 | app.config['DEBUG'] = False 61 | app.config['ALLOWED_EXTENSIONS'] = {'html', 'js', 'css'} 62 | ``` 63 | 64 | ### Output: 65 | 66 | This configuration ensures the Flask server runs securely in production. 67 | 68 | ## Three.js Scene Setup 69 | 70 | ```javascript 71 | const scene = new THREE.Scene(); 72 | const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 73 | const renderer = new THREE.WebGLRenderer(); 74 | ``` 75 | 76 | ### Output: 77 | 78 | This setup initializes the 3D scene for rendering flight simulations. 79 | 80 | 7. NEGATIVE PATTERNS 81 | 82 | # What NOT to do: 83 | 84 | ## Security Oversights 85 | - Do not run the Flask server in debug mode in production environments. 86 | - Avoid serving files without proper access restrictions. 87 | 88 | ## Dependency Management 89 | - Do not use unversioned dependencies; always specify versions in `requirements.txt`. 90 | 91 | 8. KNOWLEDGE EVOLUTION MECHANISM 92 | 93 | # Knowledge Evolution: 94 | 95 | As you learn new patterns or encounter corrections, document them in `.cursor/rules/lessons-learned-and-new-knowledge.mdc` using the following format: 96 | 97 | ## Security Enhancements 98 | - Debug mode enabled in production → Debug mode disabled with environment-specific settings 99 | 100 | ## Three.js Integration 101 | - Missing WebGL initialization → Proper WebGL renderer and scene setup 102 | ``` 103 | 104 | ### Domain-Specific Adaptations 105 | 106 | Given the project's focus on web-based flight simulation, the cursor rules emphasize security practices, Three.js integration, and dependency management. The rules are structured to guide the AI in addressing the project's current technical debt and architectural gaps while ensuring secure and efficient development practices. -------------------------------------------------------------------------------- /tests/final_analysis_test/output/final_analysis_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "analysis": "Based on the provided project structure and report, I will create a tailored `.cursorrules` file in the CRS-1 format. This file will guide the AI assistant in the Cursor IDE to effectively assist in the development of the flight simulator system. The rules will incorporate the project's current state, technical constraints, and strategic priorities.\n\n### CRS-1 Cursor Rules File\n\n```\n1. IDENTITY ESTABLISHMENT\n\nYou are an expert web-based flight simulator development assistant specializing in Flask and Three.js integration.\n\n2. TEMPORAL FRAMEWORK\n\nIt is March 2025 and you are developing with the latest web technologies to enhance the flight simulator's capabilities.\n\n3. TECHNICAL CONSTRAINTS\n\n# Technical Environment\n- Development is conducted on a Linux-based server environment.\n- The system is designed to run on modern web browsers with WebGL support.\n\n# Dependencies\n- Flask: 2.0.1\n- Three.js: r128\n- Python: 3.9\n\n# Configuration\n- Flask server must not run in debug mode in production.\n- Static file serving must implement path traversal protection.\n\n4. IMPERATIVE DIRECTIVES\n\n# Your Requirements:\n1. Implement security measures to prevent unrestricted file access.\n2. Ensure all dependencies are version-locked and documented in `requirements.txt`.\n3. Develop clear client/server boundaries with defined communication protocols.\n4. Integrate Three.js for 3D rendering and flight dynamics visualization.\n\n5. KNOWLEDGE FRAMEWORK\n\n# Security Practices\n## File Access\n- Implement file access whitelisting to prevent path traversal vulnerabilities.\n\n## Environment Configuration\n- Use environment-specific configurations to disable debug mode in production.\n\n# Three.js Integration\n## Initialization\n- Ensure proper initialization of WebGL renderer and scene setup.\n\n## Flight Dynamics\n- Develop aerodynamic force calculations and axis control mapping.\n\n6. IMPLEMENTATION EXAMPLES\n\n## Flask Security Configuration\n\n```python\napp = Flask(__name__)\nif os.environ.get('ENV') == 'production':\n app.config['DEBUG'] = False\n app.config['ALLOWED_EXTENSIONS'] = {'html', 'js', 'css'}\n```\n\n### Output:\n\nThis configuration ensures the Flask server runs securely in production.\n\n## Three.js Scene Setup\n\n```javascript\nconst scene = new THREE.Scene();\nconst camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);\nconst renderer = new THREE.WebGLRenderer();\n```\n\n### Output:\n\nThis setup initializes the 3D scene for rendering flight simulations.\n\n7. NEGATIVE PATTERNS\n\n# What NOT to do:\n\n## Security Oversights\n- Do not run the Flask server in debug mode in production environments.\n- Avoid serving files without proper access restrictions.\n\n## Dependency Management\n- Do not use unversioned dependencies; always specify versions in `requirements.txt`.\n\n8. KNOWLEDGE EVOLUTION MECHANISM\n\n# Knowledge Evolution:\n\nAs you learn new patterns or encounter corrections, document them in `.cursor/rules/lessons-learned-and-new-knowledge.mdc` using the following format:\n\n## Security Enhancements\n- Debug mode enabled in production \u2192 Debug mode disabled with environment-specific settings\n\n## Three.js Integration\n- Missing WebGL initialization \u2192 Proper WebGL renderer and scene setup\n```\n\n### Domain-Specific Adaptations\n\nGiven the project's focus on web-based flight simulation, the cursor rules emphasize security practices, Three.js integration, and dependency management. The rules are structured to guide the AI in addressing the project's current technical debt and architectural gaps while ensuring secure and efficient development practices." 3 | } -------------------------------------------------------------------------------- /tests/final_analysis_test/run_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | tests/final_analysis_test/run_test.py 4 | 5 | This script tests the Final Analysis functionality by using the Phase 5 6 | output as input and generating final cursor rules. 7 | """ 8 | 9 | import sys 10 | import os 11 | import json 12 | import asyncio 13 | from pathlib import Path 14 | 15 | # Add the project root to the Python path to allow importing from the project 16 | sys.path.insert(0, str(Path(__file__).parent.parent.parent)) 17 | 18 | from core.analysis.final_analysis import FinalAnalysis 19 | from core.utils.tools.tree_generator import get_project_tree 20 | 21 | async def run_final_analysis_test(): 22 | """ 23 | Run Final Analysis using the Phase 5 results and generate cursor rules. 24 | """ 25 | # Path to the output directory 26 | output_dir = Path(__file__).parent / "output" 27 | os.makedirs(output_dir, exist_ok=True) 28 | 29 | # Path to the test input directory (for generating a sample project tree) 30 | test_input_dir = Path(__file__).parent.parent / "tests_input" 31 | 32 | # Load Phase 5 results from the test input 33 | phase5_file = Path(__file__).parent / "fa_test_input.json" 34 | with open(phase5_file, "r") as f: 35 | phase5_results = json.load(f) 36 | 37 | # Generate a sample project tree 38 | print(f"Generating project tree for: {test_input_dir}") 39 | tree = get_project_tree(test_input_dir) 40 | 41 | # Remove delimiters for analysis if they exist 42 | if len(tree) >= 2 and tree[0] == "<@tree_generator.py project_structure>" and tree[-1] == "": 43 | tree = tree[1:-1] 44 | 45 | # Initialize Final Analysis 46 | print("Initializing Final Analysis...") 47 | final_analysis = FinalAnalysis() 48 | 49 | # Run Final Analysis 50 | print("Running Final Analysis...") 51 | results = await final_analysis.run(phase5_results, tree) 52 | 53 | # Save the complete results 54 | output_file = output_dir / "final_analysis_results.json" 55 | print(f"Saving results to: {output_file}") 56 | with open(output_file, "w") as f: 57 | json.dump(results, f, indent=2) 58 | 59 | # Also save just the analysis text if available 60 | if "analysis" in results: 61 | rules_file = output_dir / "cursor_rules.md" 62 | print(f"Saving cursor rules to: {rules_file}") 63 | with open(rules_file, "w") as f: 64 | f.write(results["analysis"]) 65 | 66 | print("Final Analysis test completed successfully!") 67 | return results 68 | 69 | if __name__ == "__main__": 70 | results = asyncio.run(run_final_analysis_test()) 71 | print("\nFinal Analysis Results Summary:") 72 | if "analysis" in results: 73 | print(f"Cursor rules length: {len(results['analysis'])} characters") 74 | else: 75 | print(f"Response keys: {list(results.keys())}") 76 | -------------------------------------------------------------------------------- /tests/final_analysis_test/test_date.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests/final_analysis/test_temporal_framework.py 3 | 4 | This script tests the dynamic insertion of the current month and year into the final analysis prompt. 5 | """ 6 | 7 | import sys 8 | import os 9 | from datetime import datetime 10 | 11 | # Add the project root to the Python path 12 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) 13 | 14 | from config.prompts.final_analysis_prompt import format_final_analysis_prompt 15 | 16 | def test_temporal_framework(): 17 | """Test that the current month and year are properly inserted into the prompt.""" 18 | # Get current month and year for comparison 19 | current_date = datetime.now() 20 | current_month = current_date.strftime("%B") # Full month name 21 | current_year = current_date.year 22 | 23 | # Create a simple consolidated report 24 | consolidated_report = { 25 | "test": "This is a test report" 26 | } 27 | 28 | # Format the prompt 29 | prompt = format_final_analysis_prompt(consolidated_report) 30 | 31 | # Check if the current month and year are in the prompt 32 | expected_format = f"It is {current_month} {current_year} and [temporal context]" 33 | expected_example = f"It is {current_month} {current_year} and you are developing with the brand new {current_year}" 34 | 35 | if expected_format in prompt: 36 | print(f"✅ Format section successfully updated with '{expected_format}'") 37 | else: 38 | print(f"❌ Format section not updated correctly. Expected '{expected_format}'") 39 | 40 | if expected_example in prompt: 41 | print(f"✅ Example section successfully updated with '{expected_example}'") 42 | else: 43 | print(f"❌ Example section not updated correctly. Expected '{expected_example}'") 44 | 45 | # Print the relevant sections for visual inspection 46 | print("\nRelevant sections from the prompt:") 47 | lines = prompt.split('\n') 48 | for i, line in enumerate(lines): 49 | if "It is" in line and (current_month in line or str(current_year) in line): 50 | start = max(0, i - 5) 51 | end = min(len(lines), i + 5) 52 | print("\n".join(lines[start:end])) 53 | print("-" * 50) 54 | 55 | if __name__ == "__main__": 56 | test_temporal_framework() -------------------------------------------------------------------------------- /tests/final_analysis_test/test_final_analysis.py: -------------------------------------------------------------------------------- 1 | """ 2 | tests/final_analysis/test_final_analysis.py 3 | 4 | This script tests the Final Analysis phase of the CursorRules Architect. 5 | It verifies that the Final Analysis works correctly with different model configurations. 6 | """ 7 | 8 | import sys 9 | import os 10 | import asyncio 11 | import json 12 | from typing import Dict 13 | from datetime import datetime 14 | 15 | # Add the project root to the Python path 16 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) 17 | 18 | from core.analysis.final_analysis import FinalAnalysis 19 | from core.types.models import ( 20 | CLAUDE_WITH_REASONING, 21 | O1_HIGH, 22 | GPT4_1_DEFAULT as GPT4_1, 23 | O3_MINI_HIGH, 24 | ModelConfig 25 | ) 26 | from config.agents import MODEL_CONFIG 27 | from core.agents import get_architect_for_phase 28 | from core.agents.base import ModelProvider, ReasoningMode 29 | 30 | # Sample consolidated report for testing 31 | SAMPLE_CONSOLIDATED_REPORT = { 32 | "project_name": "Test Project", 33 | "analysis_date": datetime.now().strftime("%Y-%m-%d"), 34 | "phases": { 35 | "phase1": { 36 | "structure": { 37 | "findings": "The project has a clear structure with modules X, Y, Z." 38 | }, 39 | "dependency": { 40 | "findings": "The project uses libraries A, B, C." 41 | }, 42 | "tech_stack": { 43 | "findings": "The project is built with Python using Framework D." 44 | } 45 | }, 46 | "phase4": { 47 | "analysis": "The project follows a clear architectural pattern with good separation of concerns." 48 | }, 49 | "phase5": { 50 | "consolidated_findings": "This is a well-structured project with clear architecture." 51 | } 52 | } 53 | } 54 | 55 | # Sample project structure for testing 56 | SAMPLE_PROJECT_STRUCTURE = [ 57 | ".", 58 | "├── main.py", 59 | "├── config/", 60 | "│ ├── __init__.py", 61 | "│ └── settings.py", 62 | "├── core/", 63 | "│ ├── __init__.py", 64 | "│ ├── models.py", 65 | "│ └── utils.py", 66 | "└── tests/", 67 | " ├── __init__.py", 68 | " └── test_main.py" 69 | ] 70 | 71 | async def test_model_config(model_config: ModelConfig, model_name: str): 72 | """Test the final analysis with a specific model configuration.""" 73 | print(f"\n\nTesting with {model_name}: {model_config.provider.value} - {model_config.model_name}") 74 | print("-" * 50) 75 | 76 | # Override the MODEL_CONFIG for this test 77 | import config.agents 78 | original_config = config.agents.MODEL_CONFIG.get("final") 79 | config.agents.MODEL_CONFIG["final"] = model_config 80 | 81 | try: 82 | # Initialize the FinalAnalysis class 83 | final_analysis = FinalAnalysis() 84 | 85 | # Run the final analysis 86 | start_time = datetime.now() 87 | result = await final_analysis.run(SAMPLE_CONSOLIDATED_REPORT, SAMPLE_PROJECT_STRUCTURE) 88 | end_time = datetime.now() 89 | 90 | # Check if the result is valid 91 | if "status" in result and result["status"] == "error": 92 | print(f"❌ ERROR: {result.get('error', 'Unknown error')}") 93 | return False 94 | 95 | # Check if the result contains the expected keys 96 | expected_keys = ["output", "tokens_used"] 97 | if all(key in result for key in expected_keys): 98 | print(f"✅ PASSED: The final analysis returned the expected keys") 99 | else: 100 | print(f"❌ FAILED: The final analysis did not return all expected keys. Got: {list(result.keys())}") 101 | return False 102 | 103 | # Print some information about the result 104 | print(f"Time taken: {end_time - start_time}") 105 | print(f"Tokens used: {result.get('tokens_used', 'Not available')}") 106 | 107 | # Print a sample of the output 108 | output_sample = result.get("output", "")[:200] + "..." if result.get("output") else "No output" 109 | print(f"Output sample: {output_sample}") 110 | 111 | return True 112 | except Exception as e: 113 | print(f"❌ EXCEPTION: {str(e)}") 114 | return False 115 | finally: 116 | # Restore the original configuration 117 | config.agents.MODEL_CONFIG["final"] = original_config 118 | 119 | async def run_all_tests(): 120 | """Run tests with all available model configurations.""" 121 | # Tests to run 122 | models_to_test = [ 123 | ("CLAUDE_WITH_REASONING", CLAUDE_WITH_REASONING), 124 | ("O1_HIGH", O1_HIGH), 125 | ("GPT4_1", GPT4_1), 126 | ("O3_MINI_HIGH", O3_MINI_HIGH) 127 | ] 128 | 129 | # Current model from MODEL_CONFIG 130 | current_model = MODEL_CONFIG.get("final") 131 | current_model_name = "DEFAULT_CONFIG" 132 | 133 | # Also test the current model from MODEL_CONFIG 134 | if current_model: 135 | models_to_test.append((current_model_name, current_model)) 136 | 137 | # Run all tests 138 | results = {} 139 | for model_name, model_config in models_to_test: 140 | results[model_name] = await test_model_config(model_config, model_name) 141 | 142 | # Print summary 143 | print("\n\nTest Summary:") 144 | print("=" * 50) 145 | for model_name, result in results.items(): 146 | status = "PASSED" if result else "FAILED" 147 | print(f"{model_name}: {status}") 148 | 149 | # Calculate overall status 150 | overall_status = all(results.values()) 151 | print(f"\nOverall status: {'PASSED' if overall_status else 'FAILED'}") 152 | 153 | if __name__ == "__main__": 154 | asyncio.run(run_all_tests()) -------------------------------------------------------------------------------- /tests/phase_1_test/run_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | tests/phase_1_test/run_test.py 4 | 5 | This script tests Phase 1 (Initial Discovery) functionality by running it on the test input 6 | and saving the output to the specified directory. 7 | """ 8 | 9 | import sys 10 | import os 11 | import json 12 | import asyncio 13 | from pathlib import Path 14 | 15 | # Add the project root to the Python path to allow importing from the project 16 | sys.path.insert(0, str(Path(__file__).parent.parent.parent)) 17 | 18 | from core.analysis.phase_1 import Phase1Analysis 19 | from core.utils.tools.tree_generator import get_project_tree 20 | 21 | async def run_phase1_test(): 22 | """ 23 | Run Phase 1 analysis on the test input and save the results to the output directory. 24 | """ 25 | # Path to the test input directory 26 | test_input_dir = Path(__file__).parent.parent / "tests_input" 27 | 28 | # Path to the output directory 29 | output_dir = Path(__file__).parent / "output" 30 | os.makedirs(output_dir, exist_ok=True) 31 | 32 | # Generate project tree 33 | print(f"Generating project tree for: {test_input_dir}") 34 | tree = get_project_tree(test_input_dir) 35 | 36 | # Remove delimiters for analysis if they exist 37 | if len(tree) >= 2 and tree[0] == "<@tree_generator.py project_structure>" and tree[-1] == "": 38 | tree = tree[1:-1] 39 | 40 | # Package info (simplified for test) 41 | package_info = {"dependencies": {"flask": "latest"}} 42 | 43 | # Initialize Phase 1 44 | print("Initializing Phase 1 Analysis...") 45 | phase1 = Phase1Analysis() 46 | 47 | # Run Phase 1 analysis 48 | print("Running Phase 1 Analysis...") 49 | results = await phase1.run(tree, package_info) 50 | 51 | # Save the results 52 | output_file = output_dir / "phase1_results.json" 53 | print(f"Saving results to: {output_file}") 54 | with open(output_file, "w") as f: 55 | json.dump(results, f, indent=2) 56 | 57 | print("Phase 1 test completed successfully!") 58 | return results 59 | 60 | if __name__ == "__main__": 61 | results = asyncio.run(run_phase1_test()) 62 | print("\nPhase 1 Results Summary:") 63 | print(f"Number of findings: {len(results.get('findings', []))}") 64 | -------------------------------------------------------------------------------- /tests/phase_2_test/output/analysis_plan.xml: -------------------------------------------------------------------------------- 1 | 2 | Based on the provided project structure and initial findings, the project consists of a Python backend file (`main.py`), an HTML frontend file (`index.html`), and two configuration/utility text files (`.cursorignore`, `.cursorrules`). The initial findings highlight expertise needed in backend development (Python Flask), frontend structure (HTML), and understanding project configuration/metadata. To effectively analyze these files, a team of three specialized agents is proposed: one for backend logic, one for frontend presentation, and one for handling configuration and ignore rules. This team size is within the requested range of 3-5 and covers all distinct file types present. Files are assigned to agents based on the primary technology or purpose of the file. 3 | 4 | 5 | 6 | 7 | Specialized in analyzing Python code, backend logic, server-side frameworks like Flask, and API implementations. 8 | 9 | main.py 10 | 11 | 12 | 13 | 14 | Specialized in analyzing HTML structure, web page layout, frontend technologies, and templating. 15 | 16 | index.html 17 | 18 | 19 | 20 | 21 | Specialized in analyzing project configuration files, ignore lists, rules files, and general text-based metadata. 22 | 23 | .cursorignore 24 | .cursorrules 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/phase_2_test/output/phase2_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "plan": "\nBased on the provided project structure and initial findings, the project consists of a Python backend file (`main.py`), an HTML frontend file (`index.html`), and two configuration/utility text files (`.cursorignore`, `.cursorrules`). The initial findings highlight expertise needed in backend development (Python Flask), frontend structure (HTML), and understanding project configuration/metadata. To effectively analyze these files, a team of three specialized agents is proposed: one for backend logic, one for frontend presentation, and one for handling configuration and ignore rules. This team size is within the requested range of 3-5 and covers all distinct file types present. Files are assigned to agents based on the primary technology or purpose of the file.\n\n\n\n\nSpecialized in analyzing Python code, backend logic, server-side frameworks like Flask, and API implementations.\n\nmain.py\n\n\n\n\nSpecialized in analyzing HTML structure, web page layout, frontend technologies, and templating.\n\nindex.html\n\n\n\n\nSpecialized in analyzing project configuration files, ignore lists, rules files, and general text-based metadata.\n\n.cursorignore\n.cursorrules\n\n\n", 3 | "error": null, 4 | "agents": [ 5 | { 6 | "id": "agent_1", 7 | "name": "Backend Agent", 8 | "description": "Specialized in analyzing Python code, backend logic, server-side frameworks like Flask, and API implementations.", 9 | "expertise": [], 10 | "responsibilities": [], 11 | "file_assignments": [ 12 | "main.py" 13 | ] 14 | }, 15 | { 16 | "id": "agent_2", 17 | "name": "Frontend Agent", 18 | "description": "Specialized in analyzing HTML structure, web page layout, frontend technologies, and templating.", 19 | "expertise": [], 20 | "responsibilities": [], 21 | "file_assignments": [ 22 | "index.html" 23 | ] 24 | }, 25 | { 26 | "id": "agent_3", 27 | "name": "Config Agent", 28 | "description": "Specialized in analyzing project configuration files, ignore lists, rules files, and general text-based metadata.", 29 | "expertise": [], 30 | "responsibilities": [], 31 | "file_assignments": [ 32 | ".cursorignore", 33 | ".cursorrules" 34 | ] 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /tests/phase_2_test/run_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | tests/phase_2/run_test.py 4 | 5 | This script tests Phase 2 (Methodical Planning) functionality by using the Phase 1 6 | output as input and generating a detailed analysis plan. 7 | """ 8 | 9 | import sys 10 | import os 11 | import json 12 | import asyncio 13 | from pathlib import Path 14 | 15 | # Add the project root to the Python path to allow importing from the project 16 | sys.path.insert(0, str(Path(__file__).parent.parent.parent)) 17 | 18 | from core.analysis.phase_2 import Phase2Analysis 19 | from core.utils.tools.tree_generator import get_project_tree 20 | 21 | async def run_phase2_test(): 22 | """ 23 | Run Phase 2 analysis using the Phase 1 results and generate an analysis plan. 24 | """ 25 | # Path to the test input directory 26 | test_input_dir = Path(__file__).parent.parent / "tests_input" 27 | 28 | # Path to the output directory 29 | output_dir = Path(__file__).parent / "output" 30 | os.makedirs(output_dir, exist_ok=True) 31 | 32 | # Load Phase 1 results from the test input 33 | phase1_file = Path(__file__).parent / "test2_input.json" 34 | with open(phase1_file, "r") as f: 35 | phase1_results = json.load(f) 36 | 37 | # Generate project tree 38 | print(f"Generating project tree for: {test_input_dir}") 39 | tree = get_project_tree(test_input_dir) 40 | 41 | # Remove delimiters for analysis if they exist 42 | if len(tree) >= 2 and tree[0] == "<@tree_generator.py project_structure>" and tree[-1] == "": 43 | tree = tree[1:-1] 44 | 45 | # Initialize Phase 2 Analysis 46 | print("Initializing Phase 2 Analysis...") 47 | phase2 = Phase2Analysis() # Uses the model specified in agents.py 48 | 49 | # Run Phase 2 analysis 50 | print("Running Phase 2 Analysis...") 51 | results = await phase2.run(phase1_results, tree) 52 | 53 | # Add diagnostic output 54 | print(f"Raw results keys: {list(results.keys())}") 55 | print(f"Agents found: {len(results.get('agents', []))}") 56 | if 'agents' in results: 57 | for i, agent in enumerate(results['agents']): 58 | print(f" Agent {i+1}: {agent.get('name', 'Unknown')} with {len(agent.get('file_assignments', []))} files") 59 | 60 | # Save the complete results 61 | output_file = output_dir / "phase2_results.json" 62 | print(f"Saving complete results to: {output_file}") 63 | with open(output_file, "w") as f: 64 | json.dump(results, f, indent=2) 65 | 66 | # Save just the analysis plan text 67 | plan_file = output_dir / "analysis_plan.xml" 68 | print(f"Saving analysis plan to: {plan_file}") 69 | with open(plan_file, "w") as f: 70 | f.write(results.get("plan", "")) 71 | 72 | print("Phase 2 test completed successfully!") 73 | return results 74 | 75 | if __name__ == "__main__": 76 | results = asyncio.run(run_phase2_test()) 77 | print("\nPhase 2 Results Summary:") 78 | print(f"Analysis plan created with {len(results.get('agents', []))} agents") 79 | -------------------------------------------------------------------------------- /tests/phase_2_test/test2_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "phase": "Initial Discovery", 3 | "findings": [ 4 | { 5 | "agent": "Structure Agent", 6 | "findings": "# Structure Agent Report: Project Analysis\n\n## Directory and File Organization\n\nThe project has a minimal structure with only two files at the root level:\n- `index.html` (HTML file)\n- `main.py` (Python file)\n\nThis indicates a very simple project organization with no subdirectories or complex hierarchy.\n\n## Project Layout Map\n\n```\n/\n\u251c\u2500\u2500 index.html # Frontend HTML file\n\u2514\u2500\u2500 main.py # Python backend file\n```\n\n## Key Architectural Components\n\n1. **Frontend Component**:\n - `index.html`: Likely serves as the main web interface for the application.\n\n2. **Backend Component**:\n - `main.py`: Python file that likely contains the server-side logic.\n - The presence of Flask as a dependency suggests this is a web application using the Flask framework.\n\n## Architecture Analysis\n\nThis appears to be a simple web application following a basic client-server architecture:\n- The frontend is represented by a single HTML file (`index.html`)\n- The backend is powered by Flask (as indicated in the dependencies) through `main.py`\n\nThis is a common pattern for small Flask web applications where:\n- `main.py` typically contains the Flask application setup and route definitions\n- `index.html` serves as the template that Flask renders to users\n\n## Recommendations\n\n1. As the project grows, consider organizing files into separate directories:\n - `/templates` for HTML files\n - `/static` for CSS, JavaScript, and other assets\n - `/routes` or `/views` for route handlers if the application becomes more complex\n\n2. Consider adding a requirements.txt or Pipfile to better manage Python dependencies beyond just Flask.\n\n3. If functionality expands, implementing a modular structure would improve maintainability." 7 | }, 8 | { 9 | "agent": "Dependency Agent", 10 | "findings": "# Dependency Analysis Report\n\n## Overview\nI've analyzed the provided project structure and dependencies. This appears to be a simple Flask web application with minimal structure consisting of a Python file (`main.py`) and an HTML file (`index.html`).\n\n## Dependencies Identified\n\n### Core Dependencies\n1. **Flask**\n - Current Specification: \"latest\" (not recommended for production)\n - Latest Version: 2.3.3 (as of my last update)\n - Recommended Version: Specify exact version like \"2.3.3\" for reproducible builds\n\n## Dependency Management Concerns\n\n### Pinned Version Recommendations\n- **Issue**: Using \"latest\" for Flask is problematic for reproducible builds and can lead to unexpected breaking changes\n- **Recommendation**: Pin the Flask version to a specific version (e.g., \"2.3.3\")\n- **Best Practice**: Add a `requirements.txt` file to properly document and manage Python dependencies\n\n### Missing Dependencies\nThe project may require additional dependencies depending on what functionality is implemented in `main.py`:\n- If using a database: `flask-sqlalchemy` might be needed\n- If handling forms: `flask-wtf` might be beneficial\n- For environment management: `python-dotenv` is recommended\n\n## Compatibility Considerations\n\n### Python Version\n- No Python version specified\n- **Recommendation**: Specify Python version requirement (Flask 2.3.x requires Python 3.8+)\n\n### Flask Version Compatibility\n- Flask 2.0+ has breaking changes from 1.x versions\n- **Recommendation**: If this is an existing project migrating to newer Flask, review the Flask migration guide\n\n## Security Recommendations\n\n- Regularly audit dependencies for security vulnerabilities\n- Consider adding dependency scanning to development workflow\n- Use a tool like `pip-audit` or GitHub's Dependabot for automated vulnerability checks\n\n## Suggested Dependency Configuration\n\n```\n# requirements.txt\nFlask==2.3.3\npython-dotenv==1.0.0\n```\n\n## Next Steps\n\n1. Create a proper `requirements.txt` file with pinned versions\n2. Consider adding a virtual environment (venv) configuration\n3. Specify the required Python version in a `runtime.txt` or similar file\n4. Implement dependency scanning in your development workflow\n\nThe project appears to have a minimal dependency footprint, which is good for maintenance, but proper version specification would improve deployment reliability." 11 | }, 12 | { 13 | "agent": "Tech Stack Agent", 14 | "findings": "# Tech Stack Analysis Report\n\n## Identified Technologies & Frameworks\n\n### Backend Technologies\n1. **Python**\n - General-purpose programming language identified from `main.py`\n - Used as the primary backend language for this project\n\n2. **Flask**\n - Python web framework identified from dependencies\n - Version: Latest\n\n### Frontend Technologies\n1. **HTML**\n - Markup language identified from `index.html`\n - Used for structuring web content\n\n## Documentation Resources\n\n### Python\n- **Latest Documentation**: [Python Documentation](https://docs.python.org/3/)\n- **Current Version**: 3.12 (as of latest stable release)\n- **Key Resource**: [Python Standard Library](https://docs.python.org/3/library/index.html)\n\n### Flask\n- **Latest Documentation**: [Flask Documentation](https://flask.palletsprojects.com/en/latest/)\n- **Current Version**: 2.3.x (as of this analysis)\n- **Quick Start**: [Flask Quickstart Guide](https://flask.palletsprojects.com/en/latest/quickstart/)\n- **API Reference**: [Flask API](https://flask.palletsprojects.com/en/latest/api/)\n\n### HTML\n- **Latest Documentation**: [MDN HTML Reference](https://developer.mozilla.org/en-US/docs/Web/HTML)\n- **Living Standard**: [HTML Living Standard](https://html.spec.whatwg.org/)\n\n## Current Best Practices & Updates\n\n### Python Best Practices\n- Use virtual environments for dependency management (venv, pipenv, or poetry)\n- Follow PEP 8 style guidelines for code formatting\n- Consider using type hints (introduced in Python 3.5+) for better code clarity\n- Leverage async features for I/O bound operations (with asyncio)\n\n### Flask Best Practices\n- **Application Factory Pattern**: Structure Flask apps using the application factory pattern for better testing and configuration\n- **Blueprints**: Use Flask blueprints for organizing larger applications\n- **Security Updates**: Keep dependencies updated to avoid security vulnerabilities\n- **RESTful API Design**: Consider Flask-RESTful or Flask-RESTX for API development\n- **Database Integration**: Flask-SQLAlchemy is recommended for database integration\n- **Environment Variables**: Use python-dotenv for environment variable management\n\n### HTML Best Practices\n- Ensure proper semantic markup\n- Maintain accessibility standards (WCAG)\n- Use responsive design principles\n- Consider implementing HTML5 features for modern browsers\n\n## Recommendations\n\n1. **Dependency Management**: Implement a requirements.txt or Pipfile to properly specify versions of dependencies\n2. **Static Files Organization**: Consider adding a static directory for CSS and JavaScript files\n3. **Templates Folder**: Implement a templates directory for Flask template organization\n4. **Version Pinning**: Specify exact versions of dependencies rather than using \"latest\" to ensure consistency\n\n## Technology Update Notes\n\n- Flask has been moving toward async support in recent versions\n- Python's async capabilities continue to improve with each release\n- Consider evaluating frontend frameworks if the project expands beyond basic HTML" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /tests/phase_3_test/debug_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import json 4 | import logging 5 | import sys 6 | from pathlib import Path 7 | import re 8 | 9 | # Configure logging 10 | logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') 11 | logger = logging.getLogger("debug") 12 | 13 | # Add the project root to path 14 | sys.path.insert(0, str(Path(__file__).resolve().parent)) 15 | 16 | # Import the parsing function 17 | from core.utils.tools.agent_parser import parse_agents_from_phase2, extract_xml_content, clean_and_fix_xml, extract_agent_fallback 18 | 19 | def print_full_content(content): 20 | """Print the full content for debugging""" 21 | print("\n==== FULL CONTENT ====") 22 | print(content) 23 | print("==== END OF CONTENT ====\n") 24 | 25 | def test_parse(): 26 | # Load the phase2_results.json file 27 | file_path = 'tests/phase_2_test/output/phase2_results.json' 28 | logger.info(f"Reading file: {file_path}") 29 | 30 | try: 31 | with open(file_path, 'r') as f: 32 | data = json.load(f) 33 | 34 | logger.info(f"JSON loaded successfully with keys: {list(data.keys())}") 35 | plan_content = data.get("plan", "") 36 | 37 | # Print the first 200 chars of the plan content 38 | logger.info(f"Plan content starts with: {plan_content[:200]}...") 39 | 40 | # Check if the plan contains agent definitions 41 | agent_count = len(re.findall(r']*>.*?', plan_content, re.DOTALL) 47 | logger.info(f"Direct regex found {len(agent_blocks)} agent blocks") 48 | 49 | # Try fallback extraction 50 | logger.info("Attempting fallback extraction method...") 51 | agents_fallback = extract_agent_fallback(plan_content) 52 | logger.info(f"Fallback extraction found {len(agents_fallback)} agents") 53 | 54 | for i, agent in enumerate(agents_fallback): 55 | logger.info(f" - Agent {i+1}: {agent.get('name')} with {len(agent.get('file_assignments', []))} files") 56 | 57 | # Try the full parse_agents_from_phase2 function 58 | logger.info("Attempting full parsing...") 59 | agents = parse_agents_from_phase2(plan_content) 60 | logger.info(f"Full parsing found {len(agents)} agents") 61 | 62 | for i, agent in enumerate(agents): 63 | logger.info(f" - Agent {i+1}: {agent.get('name')} with {len(agent.get('file_assignments', []))} files") 64 | 65 | except Exception as e: 66 | logger.error(f"Error: {str(e)}") 67 | import traceback 68 | traceback.print_exc() 69 | 70 | if __name__ == "__main__": 71 | test_parse() -------------------------------------------------------------------------------- /tests/phase_3_test/run_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | tests/phase_3_test/run_test.py 4 | 5 | This script tests Phase 3 (Deep Analysis) functionality by using the Phase 2 output 6 | as input and running deep analysis on the test codebase files. 7 | """ 8 | 9 | import sys 10 | import os 11 | import json 12 | import asyncio 13 | from pathlib import Path 14 | 15 | # Add the project root to the Python path to allow importing from the project 16 | sys.path.insert(0, str(Path(__file__).parent.parent.parent)) 17 | 18 | from core.analysis.phase_3 import Phase3Analysis 19 | from core.utils.tools.tree_generator import get_project_tree 20 | 21 | async def run_phase3_test(): 22 | """ 23 | Run Phase 3 analysis using the Phase 2 results on the test input files. 24 | """ 25 | # Path to the test input directory 26 | test_input_dir = Path(__file__).parent.parent / "tests_input" 27 | 28 | # Path to the output directory 29 | output_dir = Path(__file__).parent / "output" 30 | os.makedirs(output_dir, exist_ok=True) 31 | 32 | # Load Phase 2 results from the test input JSON 33 | phase2_file = Path(__file__).parent / "test3_input.json" 34 | with open(phase2_file, "r") as f: 35 | phase2_results = json.load(f) 36 | 37 | # Generate project tree 38 | print(f"Generating project tree for: {test_input_dir}") 39 | tree = get_project_tree(test_input_dir) 40 | 41 | # Remove delimiters for analysis if they exist 42 | if len(tree) >= 2 and tree[0] == "<@tree_generator.py project_structure>" and tree[-1] == "": 43 | tree = tree[1:-1] 44 | 45 | # Initialize Phase 3 Analysis 46 | print("Initializing Phase 3 Analysis...") 47 | phase3 = Phase3Analysis() 48 | 49 | # Run Phase 3 analysis 50 | print("Running Phase 3 Analysis...") 51 | results = await phase3.run(phase2_results, tree, test_input_dir) 52 | 53 | # Save the complete results 54 | output_file = output_dir / "phase3_results.json" 55 | print(f"Saving results to: {output_file}") 56 | with open(output_file, "w") as f: 57 | json.dump(results, f, indent=2) 58 | 59 | print("Phase 3 test completed successfully!") 60 | return results 61 | 62 | if __name__ == "__main__": 63 | results = asyncio.run(run_phase3_test()) 64 | print("\nPhase 3 Results Summary:") 65 | print(f"Number of agents: {len(results.get('findings', []))}") 66 | -------------------------------------------------------------------------------- /tests/phase_3_test/test3_input.json: -------------------------------------------------------------------------------- 1 | { 2 | "plan": "\nI created three agents based on the expertise indicated in the initial findings (Structure, Dependencies, and Tech Stack). Each file is assigned to the agent(s) whose expertise aligns with the file's contents. This ensures that both the HTML file and the Python file receive the right attention for structure, dependencies, and overall technology considerations.\n\n\n\n\nFocuses on analyzing the organization and layout of project files and directories.\n\nindex.html\n\n\n\n\nSpecializes in reviewing and managing project dependencies for the Python backend.\n\nmain.py\n\n\n\n\nEvaluates the programming languages and frameworks used in the project.\n\nmain.py\n\n\n", 3 | "reasoning_tokens": 3264, 4 | "agents": [ 5 | { 6 | "id": "agent_1", 7 | "name": "Structure Agent", 8 | "description": "Focuses on analyzing the organization and layout of project files and directories.", 9 | "expertise": [], 10 | "responsibilities": [], 11 | "file_assignments": [ 12 | "index.html" 13 | ] 14 | }, 15 | { 16 | "id": "agent_2", 17 | "name": "Dependency Agent", 18 | "description": "Specializes in reviewing and managing project dependencies for the Python backend.", 19 | "expertise": [], 20 | "responsibilities": [], 21 | "file_assignments": [ 22 | "main.py" 23 | ] 24 | }, 25 | { 26 | "id": "agent_3", 27 | "name": "Tech Stack Agent", 28 | "description": "Evaluates the programming languages and frameworks used in the project.", 29 | "expertise": [], 30 | "responsibilities": [], 31 | "file_assignments": [ 32 | "main.py" 33 | ] 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /tests/phase_3_test/test3_input.xml: -------------------------------------------------------------------------------- 1 | 2 | I created three agents based on the expertise indicated in the initial findings (Structure, Dependencies, and Tech Stack). Each file is assigned to the agent(s) whose expertise aligns with the file's contents. This ensures that both the HTML file and the Python file receive the right attention for structure, dependencies, and overall technology considerations. 3 | 4 | 5 | 6 | 7 | Focuses on analyzing the organization and layout of project files and directories. 8 | 9 | index.html 10 | 11 | 12 | 13 | 14 | Specializes in reviewing and managing project dependencies for the Python backend. 15 | 16 | main.py 17 | 18 | 19 | 20 | 21 | Evaluates the programming languages and frameworks used in the project. 22 | 23 | main.py 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/phase_4_test/output/analysis.md: -------------------------------------------------------------------------------- 1 | Okay, here is a synthesized review of the agent findings, followed by the requested elements. 2 | 3 | **Synthesized Review and Analysis** 4 | 5 | Based on the reports from the Structure, Dependency, and Tech Stack Agents, the "Flight Simulator Project" appears to be a basic web application consisting of a simple Python/Flask backend serving static files for a planned Three.js-based frontend simulator. 6 | 7 | 1. **Deep Analysis of All Findings:** 8 | 9 | * **Project Goal & Structure:** The project aims to be a "Pure Three.js Flight Simulator" displayed in a web browser. It follows a client-server architecture, albeit a very simple one. `index.html` is the declared frontend entry point, and a Flask application (`main.py`, inferred from context) acts as the backend web server. 10 | * **Frontend State (`index.html`):** The Structure Agent reveals that the `index.html` file provides the basic HTML structure, minimal CSS for layout (full-screen canvas, info panel), and a partial definition of user controls (W/S for throttle, Up/Down for pitch, Left/Right arrows cut off). Crucially, it is an *incomplete* skeleton. It *lacks* any inclusion or reference to the Three.js library and, more significantly, the actual JavaScript code that would implement the 3D rendering and simulator logic. There is no visible link or script tag connecting it to the Python backend beyond the assumption that the backend serves this file. 11 | * **Backend State (`main.py` - inferred):** The Dependency and Tech Stack Agents focus on the server component, identifying it as a Python application using the Flask framework. Its primary function is to serve static files from the directory where the script runs. It's configured to run on port 5000, accessible externally (`0.0.0.0`), and is in Flask's debug mode. The server handles the root route (`/`) by serving `index.html` and a generic route (`/`) to serve other files. 12 | * **Relationship between Frontend and Backend:** The current analysis suggests a minimal relationship: the Flask server simply delivers the static frontend files (`index.html`, presumably others like CSS and eventually JavaScript). There's no indication of backend logic supporting the simulator itself (e.g., physics calculations, state management, networking), implying the simulator is intended to be primarily frontend-driven using JavaScript and Three.js. 13 | * **Missing Core Functionality:** The most significant finding across the reports, particularly when viewed together, is the *absence of the actual simulator implementation code*. The HTML is set up for a Three.js sim, but the necessary JavaScript and Three.js library itself are missing from the analyzed HTML. The Python server is configured only for static serving, not dynamic simulator support. 14 | * **Backend Issues:** Both Dependency and Tech Stack Agents highlight significant issues with the current backend implementation: 15 | * **Security:** The static file serving route has a bypassed or incomplete security check, potentially allowing access to sensitive files in the script's directory. Running with `debug=True` in production is also a security risk. 16 | * **Production Readiness:** The Flask built-in server is not suitable for production loads. Debug mode should be off. There's no robust error handling or use of environment variables for configuration. 17 | * **Dependency Management:** There's no `requirements.txt` or similar file to specify Python dependencies (Flask version), making setup and reproducibility difficult. 18 | 19 | 2. **Methodical Processing of New Information:** 20 | 21 | * The Structure Agent's finding of an incomplete HTML file (`index.html`) designed for Three.js initially raised questions about where the actual code resides and its connection to the Python file. 22 | * The Dependency and Tech Stack Agents provided crucial context by identifying the Python file's role as a *static file server*. 23 | * Combining these findings clarifies the intended architecture: The Python server's role is primarily hosting. The missing simulator logic is expected to be a separate frontend component (likely JavaScript using Three.js) that the server *serves*. 24 | * This synthesis highlights that the project, *as currently represented by the analyzed files*, is more of a *scaffold* for a flight simulator (basic HTML/CSS UI structure and a simple server to host it) rather than a functional simulator itself. 25 | * The backend analysis also introduces critical non-functional requirements and issues (security, dependency management, production readiness) that the initial look at the HTML didn't reveal. 26 | 27 | 3. **Updated Analysis Directions:** 28 | 29 | * **Locate and Analyze Frontend Code:** The most critical next step is to find and analyze the JavaScript files, especially those implementing the Three.js logic and handling user input (controls described in HTML). 30 | * **Verify File Serving:** Confirm which specific files the Flask server is intended to serve (e.g., are there JS or CSS files not mentioned explicitly?). 31 | * **Investigate Backend Interaction:** Determine if there's *any* planned or implemented dynamic interaction between the frontend (JS) and the backend (Python/Flask) beyond static file serving. Could the Python backend eventually handle things like scoring, multi-player state, or serving dynamic data? 32 | * **Complete Control Scheme Analysis:** Find the full description or implementation of the control scheme mentioned in `index.html`. 33 | * **Review Security and Production Readiness:** Perform a focused security review of the Flask application, specifically around static file serving vulnerabilities. Analyze its readiness for deployment. 34 | * **Identify All Project Files:** Ensure all files within the project scope are identified to avoid missing components. 35 | 36 | 4. **Refined Instructions for Agents:** 37 | 38 | * **General:** When analyzing a project identified as a web application, always look for the interplay between frontend assets (HTML, CSS, JS) and backend code (Python/Flask). Prioritize finding the main application logic files (likely JavaScript for a frontend sim). If multiple file types are present, ensure agents analyze all relevant types and report on how they connect. 39 | * **Structure Agent:** 40 | * Analyze *all* frontend files found (HTML, CSS, JS). 41 | * In HTML, identify all `