diff --git a/core/agents/code_monkey.py b/core/agents/code_monkey.py index 46ee2f6f7..72eac0d33 100644 --- a/core/agents/code_monkey.py +++ b/core/agents/code_monkey.py @@ -31,25 +31,6 @@ async def run(self) -> AgentResponse: else: return await self.implement_changes() - def _get_task_convo(self) -> AgentConvo: - # FIXME: Current prompts reuse task breakdown / iteration messages so we have to resort to this - task = self.current_state.current_task - current_task_index = self.current_state.tasks.index(task) - - convo = AgentConvo(self).template( - "breakdown", - task=task, - iteration=None, - current_task_index=current_task_index, - ) - # TODO: We currently show last iteration to the code monkey; we might need to show the task - # breakdown and all the iterations instead? To think about when refactoring prompts - if self.current_state.iterations: - convo.assistant(self.current_state.iterations[-1]["description"]) - else: - convo.assistant(self.current_state.current_task["instructions"]) - return convo - async def implement_changes(self) -> AgentResponse: file_name = self.step["save_file"]["path"] @@ -73,12 +54,23 @@ async def implement_changes(self) -> AgentResponse: feedback = None iterations = self.current_state.iterations + user_feedback = None + user_feedback_qa = None llm = self.get_llm() - convo = self._get_task_convo().template( + if iterations: + instructions = iterations[-1]["description"] + user_feedback = iterations[-1]["user_feedback"] + user_feedback_qa = iterations[-1]["user_feedback_qa"] + else: + instructions = self.current_state.current_task["instructions"] + + convo = AgentConvo(self).template( "implement_changes", file_name=file_name, file_content=file_content, - instructions=iterations[-1]["description"] if iterations else task["instructions"], + instructions=instructions, + user_feedback=user_feedback, + user_feedback_qa=user_feedback_qa, ) if feedback: convo.assistant(f"```\n{self.prev_response.data['new_content']}\n```\n").template( diff --git a/core/agents/tech_lead.py b/core/agents/tech_lead.py index e8cb953e3..e4bf4f16d 100644 --- a/core/agents/tech_lead.py +++ b/core/agents/tech_lead.py @@ -27,7 +27,7 @@ class DevelopmentPlan(BaseModel): class UpdatedDevelopmentPlan(BaseModel): - updated_current_task: Task = Field( + updated_current_epic: Task = Field( description="Updated detailed description of what was implemented while working on the current development task." ) plan: list[Task] = Field(description="List of unfinished development tasks.") @@ -198,8 +198,8 @@ async def update_epic(self) -> AgentResponse: parser=JSONParser(UpdatedDevelopmentPlan), temperature=0, ) - log.debug(f"Reworded last task as: {response.updated_current_task.description}") - finished_tasks[-1]["description"] = response.updated_current_task.description + log.debug(f"Reworded last task as: {response.updated_current_epic.description}") + finished_tasks[-1]["description"] = response.updated_current_epic.description self.next_state.tasks = finished_tasks + [ { diff --git a/core/prompts/code-monkey/implement_changes.prompt b/core/prompts/code-monkey/implement_changes.prompt index 1d8187aa5..fcd1d3aee 100644 --- a/core/prompts/code-monkey/implement_changes.prompt +++ b/core/prompts/code-monkey/implement_changes.prompt @@ -1,56 +1,39 @@ +You are working on a project and your job is to implement new code changes based on given instructions. +Now you have to implement ALL changes that are related to `{{ file_name }}` described in development instructions listed below. +Make sure you don't make any mistakes, especially ones that could affect rest of project. Your changes will be reviewed by very detailed reviewer. Because of that, it is extremely important that you are STRICTLY following ALL the following rules while implementing changes: + +{% include "partials/coding_rules.prompt" %} + +You are currently working on this task: +``` +{{ state.current_task.description }} +``` + +{% include "partials/user_feedback.prompt" %} + +Here are development instructions and now you have to focus only on changes in `{{ file_name }}`: +---start_of_development_instructions--- + +{{ instructions }} + +---end_of_development_instructions--- + {% if rework_feedback is defined %} -You previously made changes to file `{{ file_name }}`, according to the instructions described in the previous message. +You previously made changes to file `{{ file_name }}` but not all changes were accepted, and the reviewer provided feedback on the changes that you must rework: +{{ rework_feedback}} +Please update the file accordingly and output the full new version of the file. + The reviewer accepted some of your changes, and the file now looks like this: ``` {{ file_content }} ``` {% elif file_content %} -I need to modify file `{{ file_name }}` that currently looks like this: +Here is how `{{ file_name }}` looks like currently: ``` {{ file_content }} ``` {% else %} -I need to create a new file `{{ file_name }}`: +You need to create a new file `{{ file_name }}`. {% endif %} -**IMPORTANT** -{% if rework_feedback is defined %} -But not all changes were accepted, and the reviewer provided feedback on the changes that you must rework: -{{ rework_feedback}} -Please update the file accordingly and output the full new version of the file. -{% else %} -I want you to implement changes described in previous message, that starts with `{{ " ".join(instructions.split()[:5]) }}` and ends with `{{ " ".join(instructions.split()[-5:]) }}`. -{% endif %} -Make sure you don't make any mistakes, especially ones that could affect rest of project. Your changes will {% if rework_feedback is defined %}again {% endif %}be reviewed by very detailed reviewer. Because of that, it is extremely important that you are STRICTLY following ALL the following rules while implementing changes: - -**IMPORTANT** Output format -You must output the COMPLETE NEW VERSION of this file in following format: ------------------------format---------------------------- -``` -the full contents of the updated file, without skipping over any content -``` -------------------------end_of_format--------------------------- - -**IMPORTANT** Comprehensive Codebase Insight -It's crucial to grasp the full scope of the codebase related to your tasks to avert mistakes. Check the initial conversation message for a list of files. Pay a lot of attention to files that are directly included in the file you are currently modifying or that are importing your file. -Consider these examples to guide your approach and thought process: ------------------------start_of_examples---------------------------- -- UI components or templates: Instead of placing scripts directly on specific pages, integrating them in the section or as reusable partials enhances application-wide consistency and reusability. -- Database operations: Be careful not to execute an action, like password hashing, both in a routing function and a model's pre('save') hook, which could lead to redundancy and errors. -- Adding backend logic: Prior to creating new functions, verify if an equivalent function exists in the codebase that you could import and use, preventing unnecessary code duplication and keeping the project efficient. ------------------------end_of_examples---------------------------- - -**IMPORTANT** Coding principles -Write high-quality code, first organize it logically with clear, meaningful names for variables, functions, and classes. Aim for simplicity and adhere to the DRY (Don't Repeat Yourself) principle to avoid code duplication. Ensure your codebase is structured and modular for easy navigation and updates. - -**IMPORTANT** If the instructions have comments like `// ..add code here...` or `# placeholder for code`, instead of copying the comment, interpret the instructions and output the relevant code. - -**IMPORTANT** Your reply MUST NOT omit any code in the new implementation or substitute anything with comments like `// .. rest of the code goes here ..` or `# insert existing code here`, because I will overwrite the existing file with the content you provide. Output ONLY the content for this file, without additional explanation, suggestions or notes. Your output MUST start with ``` and MUST end with ``` and include only the complete file contents. - -**IMPORTANT** When working with configuration files (e.g. config.json, .env,...), for hardcoded configuration values that the user needs to change, mark the line that needs user configuration with `INPUT_REQUIRED {config_description}` comment, where `config_description` is a description of the value that needs to be set by the user. Use appropriate syntax for comments in the file you're saving (for example `// INPUT_REQUIRED {config_description}` in JavaScript). NEVER ask the user to write code or provide implementation, even if the instructions suggest it! If the file type doesn't support comments (eg JSON), don't add any. - -**IMPORTANT**: Logging -Whenever you write code, make sure to log code execution so that when a developer looks at the CLI output, they can understand what is happening on the server. If the description above mentions the exact code that needs to be added but doesn't contain enough logs, you need to add the logs handlers inside that code yourself. - -**IMPORTANT**: Error handling -Whenever you write code, make sure to add error handling for all edge cases you can think of because this app will be used in production so there shouldn't be any crashes. Whenever you log the error, you **MUST** log the entire error message and trace and not only the error message. If the description above mentions the exact code that needs to be added but doesn't contain enough error handlers, you need to add the error handlers inside that code yourself. +{% include "partials/files_list.prompt" %} diff --git a/core/prompts/partials/coding_rules.prompt b/core/prompts/partials/coding_rules.prompt new file mode 100644 index 000000000..b1eca9cb9 --- /dev/null +++ b/core/prompts/partials/coding_rules.prompt @@ -0,0 +1,39 @@ +# RULES FOR IMPLEMENTING CODE CHANGES +---start_of_coding_rules--- + +## Rule 1: Scope of your coding task +You must implement everything mentioned in the instructions that is related to this file. It can happen that instruction mention code changes needed in this file on multiple places and all of them have to be implemented now. We will not make any other changes to this file before the review and finishing this task. + +## Rule 2: Output format +You must output the COMPLETE NEW VERSION of this file in following format: +---format--- +``` +the full contents of the updated file, without skipping over any content +``` +---end_of_format--- + +## Rule 3: Comprehensive Codebase Insight +It's crucial to grasp the full scope of the codebase related to your tasks to avert mistakes. Check the initial conversation message for a list of files. Pay a lot of attention to files that are directly included in the file you are currently modifying or that are importing your file. +Consider these examples to guide your approach and thought process: +---start_of_examples--- +- UI components or templates: Instead of placing scripts directly on specific pages, integrating them in the section or as reusable partials enhances application-wide consistency and reusability. +- Database operations: Be careful not to execute an action, like password hashing, both in a routing function and a model's pre('save') hook, which could lead to redundancy and errors. +- Adding backend logic: Prior to creating new functions, verify if an equivalent function exists in the codebase that you could import and use, preventing unnecessary code duplication and keeping the project efficient. +---end_of_examples--- + +## Rule 4: Coding principles +Write high-quality code, first organize it logically with clear, meaningful names for variables, functions, and classes. Aim for simplicity and adhere to the DRY (Don't Repeat Yourself) principle to avoid code duplication. Ensure your codebase is structured and modular for easy navigation and updates. + +If the instructions have comments like `// ..add code here...` or `# placeholder for code`, instead of copying the comment, interpret the instructions and output the relevant code. + +Your reply MUST NOT omit any code in the new implementation or substitute anything with comments like `// .. rest of the code goes here ..` or `# insert existing code here`, because I will overwrite the existing file with the content you provide. Output ONLY the content for this file, without additional explanation, suggestions or notes. Your output MUST start with ``` and MUST end with ``` and include only the complete file contents. + +When working with configuration files (e.g. config.json, .env,...), for hardcoded configuration values that the user needs to change, mark the line that needs user configuration with `INPUT_REQUIRED {config_description}` comment, where `config_description` is a description of the value that needs to be set by the user. Use appropriate syntax for comments in the file you're saving (for example `// INPUT_REQUIRED {config_description}` in JavaScript). NEVER ask the user to write code or provide implementation, even if the instructions suggest it! If the file type doesn't support comments (eg JSON), don't add any. + +## Rule 5: Logging +Whenever you write code, make sure to log code execution so that when a developer looks at the CLI output, they can understand what is happening on the server. If the description above mentions the exact code that needs to be added but doesn't contain enough logs, you need to add the logs handlers inside that code yourself. + +## Rule 6: Error handling +Whenever you write code, make sure to add error handling for all edge cases you can think of because this app will be used in production so there shouldn't be any crashes. Whenever you log the error, you **MUST** log the entire error message and trace and not only the error message. If the description above mentions the exact code that needs to be added but doesn't contain enough error handlers, you need to add the error handlers inside that code yourself. + +---end_of_coding_rules--- diff --git a/core/prompts/partials/project_tasks.prompt b/core/prompts/partials/project_tasks.prompt index f4f60a75d..58b0524f0 100644 --- a/core/prompts/partials/project_tasks.prompt +++ b/core/prompts/partials/project_tasks.prompt @@ -1,67 +1,27 @@ -Before we go into the coding part, I want you to split the development process of creating this {{ task_type }} into smaller tasks so that it is easier to develop, debug and make the {{ task_type }} work. +{# This is actually creation of tasks and not epics. Reason why this prompt uses word "epic" instead of "task" is that LLM gives very detailed description and creates very big plan if we ask him to create tasks. When asked to create epics he focuses on much bigger picture and gives high level description which is what we want. #} +# Rules for creating epics +---start_of_rules_for_creating_epics--- -Each task needs to be related only to the development of this {{ task_type }} and nothing else - once the {{ task_type }} is fully working, that is it. There shouldn't be a task for researching, deployment, writing documentation, testing or anything that is not writing the actual code. +## Rule #1 +Every epic must have only coding involved. There should never be a epic that is only testing or ensuring something works. There shouldn't be a epic for researching, deployment, writing documentation, testing or anything that is not writing the actual code. Testing if app works will be done as part of each epic. -**IMPORTANT** -As an experienced tech lead you always follow rules on how to create tasks. Dividing project into tasks is extremely important job and you have to do it very carefully. +## Rule #2 +This rule applies to epic scope. +Each epic must be deliverable that can be verified by non technical user. Each epic must have frontend interface, backend implementation, and a way for non technical user to test epic. Do not use words "backend" and "frontend" in epic descriptions. All details mentioned in project description must be fully implemented once all epics are finished. -Now, based on the project details provided{% if task_type == 'feature' %} and new feature description{% endif %}, think task by task and create the entire development plan{% if task_type == 'feature' %} for new feature{% elif task_type == 'app' %}. {% if state.files %}Continue from the existing code listed above{% else %}Start from the project setup{% endif %} and specify each task until the moment when the entire app should be fully working{% if state.files %}. You should not reimplement what's already done - just continue from the implementation already there{% endif %}{% endif %} while strictly following these rules: +## Rule #3 +This rule applies to the number of epics you will create. +Every app should have different number of epics depending on complexity. Think epic by epic and create the minimum number of epics that are needed to develop this app. +Simple apps should have only 1 epic. +Medium complexity apps should have 2-5 epics. +Very complex apps should have 4-8 epics. -Rule #1 -There should never be a task that is only testing or ensuring something works, every task must have coding involved. Have this in mind for every task, but it is extremely important for last task of project. Testing if {{ task_type }} works will be done as part of each task. +## Rule #4 +This rule applies to writing epic 'description'. +Every epic must have a clear, high level, and short 1 sentence 'description'. It must be very clear so that even non technical users who are reviewing it and just moved to this project can understand what is goal for the epic. -Rule #2 -This rule applies to the complexity of tasks. -You have to make sure the project is not split into tasks that are too small or simple for no reason but also not too big or complex so that they are hard to develop, debug and review. -Have in mind that project already has workspace folder created and only system dependencies installed. You don't have to create tasks for that. -Here are examples of poorly created tasks: +## Rule #5 +This rule applies to order of epics. +Epics will be executed in same order that you output them. You must order them in a logical way so that epics that depend on other functionalities are implemented in later stage. -**too simple tasks** -- Set up a Node.js project and install all necessary dependencies. -- Establish a MongoDB database connection using Mongoose with the IP '127.0.0.1'. - -**too complex tasks** -- Set up Node.js project with /home, /profile, /register and /login routes that will have user authentication, connection to MongoDB with user schemas, mailing of new users and frontend with nice design. - -You must to avoid creating tasks that are too simple or too complex. You have to aim to create tasks that are medium complexity. Here are examples of tasks that are good: - -**good tasks** -- Set up a Node.js project, install all necessary dependencies and set up an express server with a simple route to `/ping` that returns the status 200. -- Establish a MongoDB database connection and implement the message schema using Mongoose for persistent storage of messages. - -Rule #3 -This rule applies to the number of tasks you will create. -Every {{ task_type }} should have different number of tasks depending on complexity. Think task by task and create the minimum number of tasks that are relevant for this specific {{ task_type }}. -{% if task_type == 'feature' %} If the feature is small, it is ok to have only 1 task.{% endif %} -Here are some examples of apps with different complexity that can give you guidance on how many tasks you should create: - -Example #1: -app description: "I want to create an app that will just say 'Hello World' when I open it on my localhost:3000." -number of tasks: 1 - -Example #2: -app description: "Create a node.js app that enables users to register and log into the app. On frontend it should have /home (shows user data), /register and /login. It should use sessions to keep user logged in." -number of tasks: 2-4 - -Example #3: -app description: "A cool online shoe store, with a sleek look. In terms of data models, there are shoes, categories and user profiles. For web pages: product listing, details, shopping cart. It must look cool and jazzy." -number of tasks: 5-15 - -Rule #4 -This rule applies to writing task 'description'. -Every task must have a clear and very detailed (must be minimum of 4 sentences but can be more) 'description'. It must be very clear so that even developers who just moved to this project can execute them without additional questions. It is not enough to just write something like "Create a route for /home". You have to describe what needs to be done in that route, what data needs to be returned, what should be the status code, etc. Give as many details as possible and make sure no information is missing that could be needed for this task. -Here is an example of good and bad task description: - -**bad task** -{ - "description": "Create a route for /dashboard" -} - -**good task** -{ - "description": "In 'route.js' add a route for /dashboard that returns the status 200. Route should be accessible only for logged in users. In 'middlewares.js' there should be a check if user is logged in using session. If user is not logged in, it should redirect to /login. If user is logged in, it should return the user data. User data should be fetched from database in 'users' collection using the user id from session." -} - -Rule #5 -When creating and naming new files, ensure the file naming (camelCase, kebab-case, underscore_case, etc) is consistent with the best practices and coding style of the language. -Pay attention to file paths: if the command or argument is a file or folder from the project, use paths relative to the project root (for example, use `somedir/somefile` instead of `/somedir/somefile`). +---end_of_rules_for_creating_epics--- diff --git a/core/prompts/partials/user_feedback.prompt b/core/prompts/partials/user_feedback.prompt new file mode 100644 index 000000000..f8926ad37 --- /dev/null +++ b/core/prompts/partials/user_feedback.prompt @@ -0,0 +1,15 @@ +{% if user_feedback %} +User who was using the app "{{ state.branch.project.name }}" sent you this feedback: +``` +{{ user_feedback }} +``` +{% endif %} +{% if user_feedback_qa %} +Feedback was not clear enough so you asked user for additional information and got this response: +``` +{% for row in user_feedback_qa %} +Q: {{ row.question }} +A: {{ row.answer }} +{% endfor %} +``` +{% endif %} \ No newline at end of file diff --git a/core/prompts/tech-lead/plan.prompt b/core/prompts/tech-lead/plan.prompt index 84a5cade1..a46ea0857 100644 --- a/core/prompts/tech-lead/plan.prompt +++ b/core/prompts/tech-lead/plan.prompt @@ -21,5 +21,8 @@ Finally, here is the description of new feature that needs to be added to the ap {% if epic.complexity and epic.complexity == 'simple' %} This is very low complexity {{ task_type }} and because of that, you have to create ONLY one task that is sufficient to fully implement it. {% else %} +Before we go into the coding part, your job is to split the development process of creating this app into smaller epics. +Now, based on the project details provided{% if task_type == 'feature' %} and new feature description{% endif %}, think epic by epic and create the entire development plan{% if task_type == 'feature' %} for new feature{% elif task_type == 'app' %}. {% if state.files %}Continue from the existing code listed above{% else %}Start from the project setup{% endif %} and specify each epic until the moment when the entire app should be fully working{% if state.files %}. You should not reimplement what's already done - just continue from the implementation already there{% endif %}{% endif %} while strictly following these rules: + {% include "partials/project_tasks.prompt" %} {% endif %} diff --git a/core/prompts/tech-lead/update_plan.prompt b/core/prompts/tech-lead/update_plan.prompt index ca8ff1fa0..d1a50f2dd 100644 --- a/core/prompts/tech-lead/update_plan.prompt +++ b/core/prompts/tech-lead/update_plan.prompt @@ -2,34 +2,35 @@ You are working on an app called "{{ state.branch.project.name }}". {% include "partials/project_details.prompt" %} -Development plan for that {{ task_type }} was created and the {{ task_type }} was then broken down to smaller tasks so that it's easier for development. +{# This is actually updating of tasks and not epics. Reason why this prompt uses word "epic" instead of "task" is that LLM gives very detailed description and creates very big plan if we ask him to create tasks. When asked to create epics he focuses on much bigger picture and gives high level description which is what we want. #} +Development plan for that {{ task_type }} was created and the {{ task_type }} was then broken down to smaller epics so that it's easier for development. -Here are tasks that are finished so far: +Here are epics that are finished so far: ``` {% for task in finished_tasks %} -- Task #{{ loop.index }} -Description: {{ task }} +- Epic #{{ loop.index }} +Description: {{ task.description }} {% endfor %} ``` -Here are tasks that still have to be implemented: +Here are epics that still have to be implemented: ``` {% for task in state.unfinished_tasks %} -- Task #{{ finished_tasks|length + loop.index }} -Description: {{ task }} +- Epic #{{ finished_tasks|length + loop.index }} +Description: {{ task.description }} {% endfor %} ``` {% if finished_tasks %} -This is the last task you were working on: +This is the last epic you were working on: ``` {{ finished_tasks[-1].description }} ``` {% endif %} -While working on that last task, you were iterating based on user feedbacks for this {{ task_type }}. Here is list of all iterations: +While working on that last epic, you were iterating based on user feedbacks for this {{ task_type }}. Here is list of all iterations: ``` {% for iteration in state.iterations %} - Iteration #{{ loop.index }}: @@ -40,20 +41,21 @@ Developer solution: {{ iteration.description }} ``` {% if modified_files|length > 0 %} -Here are files that were modified during this task implementation: +Here are files that were modified during this epic implementation: ---start_of_current_files--- {% for file in modified_files %} **{{ file.path }}** ({{ file.content.content.splitlines()|length }} lines of code): ``` -{{ file.content }} +{{ file.content.content }} ``` {% endfor %} ---end_of_current_files--- {% endif %} +{% include "partials/project_tasks.prompt" %} -You need to think step by step what was done in last task and update development plan if needed. All iterations that were mentioned were executed and finished successfully and that needs to be reflected in updated development plan. +You need to think step by step what was done in last epic and update development plan if needed. All iterations that were mentioned were executed and finished successfully and that needs to be reflected in updated development plan. As output you have to give 2 things: -1. Reword/update current task, "updated_current_task", if needed, based on what is implemented so far. Consider current task description, all iterations that were implemented during this task and all changes that were made to the code. +1. Reword/update current epic, "updated_current_epic", ONLY IF NECESSARY, based on what is implemented so far. Consider current epic description, all iterations that were implemented during this epic and all changes that were made to the code. -2. Give me updated list of tasks that still have to be implemented. Take into consideration all tasks in current development plan, previous tasks that were finished and everything that was implemented in this task. There should be minimum possible number of tasks that still have to be executed to finish the app. You must list only tasks that need implementation and were not done in scope of previous tasks or during iterations on current task. Do not create new tasks, only remove tasks from list of tasks that still have to be implemented in case they were implemented during current task. +2. Give me updated list of epics that still have to be implemented. Take into consideration all epics in current development plan, previous epics that were finished and everything that was implemented in this epic. There should be minimum possible number of epics that still have to be executed to finish the app. You must list only epics that need implementation and were not done in scope of previous epics or during iterations on current epic. Do not create new epics, only remove epics from list of epics that still have to be implemented in case they were implemented during current epic. diff --git a/core/prompts/troubleshooter/iteration.prompt b/core/prompts/troubleshooter/iteration.prompt index 5c7cf74bc..902409d8b 100644 --- a/core/prompts/troubleshooter/iteration.prompt +++ b/core/prompts/troubleshooter/iteration.prompt @@ -18,21 +18,8 @@ You are currently working on, and have to focus only on, this task: A part of the app is already finished. {% include "partials/files_list.prompt" %} -{% if user_feedback %} -User who was using the app "{{ state.branch.project.name }}" sent you this feedback: -``` -{{ user_feedback }} -``` -{% endif %} -{% if user_feedback_qa %} -Feedback was not clear enough so you asked user for additional information and got this response: -``` -{% for row in user_feedback_qa %} -Q: {{ row.question }} -A: {{ row.answer }} -{% endfor %} -``` -{% endif %} +{% include "partials/user_feedback.prompt" %} + {% if next_solution_to_try is not none %} Focus on solving this issue in the following way: ``` diff --git a/tests/agents/test_tech_lead.py b/tests/agents/test_tech_lead.py index c1e25d0a7..30a3cc1a3 100644 --- a/tests/agents/test_tech_lead.py +++ b/tests/agents/test_tech_lead.py @@ -122,7 +122,7 @@ async def test_update_epic(agentcontext): tl = TechLead(sm, ui) tl.get_llm = mock_get_llm( return_value=UpdatedDevelopmentPlan( - updated_current_task=Task(description="Updated Just Finished"), + updated_current_epic=Task(description="Updated Just Finished"), plan=[Task(description="Alternative Future Task")], ) )