1- import os
21import json
3- from typing import List , Optional
2+
3+ from typing import List , Optional , Any , Union
44from pydantic import BaseModel , Field , field_validator
55
66
7+ class AgentResponse (BaseModel ):
8+ thoughts : str = Field (
9+ ..., description = "Your internal reasoning and analysis of the situation."
10+ )
11+ plan : List [str ] = Field (
12+ ..., description = "A step-by-step checklist of what you are about to do."
13+ )
14+ action_taken : str = Field (
15+ ..., description = "Summary of the actual tool calls or actions performed."
16+ )
17+ final_output : str = Field (..., description = "The response to the user." )
18+
19+
20+ class StepResult (BaseModel ):
21+ """Generic container for agent steps."""
22+
23+ thoughts : str
24+ plan : List [str ]
25+ output : Any
26+
27+
28+ class PlanStepResult (BaseModel ):
29+ thoughts : str
30+ plan : List [str ]
31+ output : Union ["ImplementationPlan" , "Clarification" , "Task" , str ]
32+
33+
34+ class TaskStepResult (BaseModel ):
35+ thoughts : str
36+ plan : List [str ]
37+ output : "Task"
38+
39+
740class Task (BaseModel ):
841 id : int = Field (..., description = "Unique identifier for the task, e.g. 1, 2, 3" )
942 description : str = Field (
@@ -12,20 +45,19 @@ class Task(BaseModel):
1245 acceptance_criteria : List [str ] = Field (
1346 ..., description = "List of testable conditions for completion"
1447 )
15- passes : bool = Field (
16- default = False , description = "Flag indicating if the task is complete"
17- )
1848 dependencies : Optional [List [int ]] = Field (
1949 default = None , description = "List of other task IDs this depends on"
2050 )
2151 notes : Optional [str ] = Field (
22- default = None , description = "Additional notes or learnings from the agent"
52+ default = None ,
53+ description = "Learnings and findings from the agent from their work on this task" ,
2354 )
24- priority : Optional [ str ] = Field (
25- default = None , description = "Priority level: high, medium, low "
55+ attempt_count : int = Field (
56+ default = 0 , description = "Number of attempts made to complete this task "
2657 )
27- execution_history : List [str ] = Field (
28- default_factory = list , description = "Log of tool calls and execution steps"
58+ status : str = Field (
59+ default = "pending" ,
60+ description = "Status: pending, in_progress, implemented, verified, failed" ,
2961 )
3062
3163 @field_validator ("dependencies" , mode = "before" )
@@ -64,62 +96,92 @@ def ensure_list_of_strings(cls, v):
6496 return [v ]
6597
6698
67- class PRD (BaseModel ):
68- project : str = Field (
69- ...,
70- description = "The name of the project. This will also be used as the folder in the workspace. (Always lowercase)" ,
71- )
72- workspace : Optional [str ] = Field (
73- default = os .environ .get ("REPOSITORY_MANAGER_WORKSPACE" , "/documents" ),
74- description = "The workspace location of the project" ,
75- )
99+ class ImplementationPlan (BaseModel ):
76100 summary : str = Field (
77- default = "" , description = "High-level summary of the project/feature"
78- )
79- description : str = Field (
80- default = "" , description = "Detailed description of the project/feature"
101+ default = "" , description = "High-level summary of the implementation plan"
81102 )
103+ description : str = Field (default = "" , description = "Detailed description of the plan" )
82104 guardrails : List [str ] = Field (
83105 default_factory = list , description = "Global rules or constraints"
84106 )
85- stories : List [Task ] = Field (..., description = "List of tasks/stories " )
107+ tasks : List [Task ] = Field (..., description = "List of tasks to implement " )
86108 iteration_count : int = Field (
87109 default = 0 , description = "Number of iterations completed"
88110 )
89111
90- @field_validator ("stories " , mode = "before" )
91- def ensure_list_stories (cls , v ):
112+ @field_validator ("tasks " , mode = "before" )
113+ def ensure_list_tasks (cls , v ):
92114 if isinstance (v , list ):
93115 return v
94116 return [v ]
95117
96- @field_validator ("project" , mode = "before" )
97- def ensure_project_lowercase (cls , v ):
98- if isinstance (v , str ):
99- return v .lower ()
100- else :
101- return str (v ).lower ()
102-
103118 def is_complete (self ) -> bool :
104- """Check if all tasks are marked as passed."""
105- return all (task .passes for task in self .stories )
106-
107- def get_next_task (self ) -> Optional [Task ]:
108- """Get the next undone task that has all dependencies satisfied."""
109- for task in self .stories :
110- if not task .passes :
111- if task .dependencies is None or all (
112- self .stories [dep - 1 ].passes
113- for dep in task .dependencies
114- if dep - 1 < len (self .stories )
115- ):
116- return task
117- return None
118-
119-
120- class ElicitationRequest (BaseModel ):
119+ """Check if all tasks are marked as verified."""
120+ return all (task .status == "verified" for task in self .tasks )
121+
122+ def get_next_tasks (self ) -> List [Task ]:
123+ """Get all runnable tasks that have dependencies satisfied."""
124+ runnable = []
125+ completed_ids = {t .id for t in self .tasks if t .status == "verified" }
126+
127+ for task in self .tasks :
128+ if task .status not in ["verified" , "in_progress" , "implemented" ]:
129+ # Check dependencies
130+ deps_met = True
131+ if task .dependencies :
132+ for dep_id in task .dependencies :
133+ if dep_id not in completed_ids :
134+ deps_met = False
135+ break
136+ if deps_met :
137+ runnable .append (task )
138+ return runnable
139+
140+ def to_markdown (self ) -> str :
141+ """Generate a markdown representation of the implementation plan."""
142+ md = []
143+ md .append (f"# Implementation Plan - { self .iteration_count } Iterations\n " )
144+ md .append (f"**Summary:** { self .summary } \n " )
145+ md .append (f"**Description:** { self .description } \n " )
146+
147+ if self .guardrails :
148+ md .append ("## Guardrails" )
149+ for g in self .guardrails :
150+ md .append (f"- { g } " )
151+ md .append ("" )
152+
153+ md .append ("## Tasks" )
154+ for task in self .tasks :
155+ status_icon = {
156+ "pending" : "⏳" ,
157+ "in_progress" : "🚧" ,
158+ "implemented" : "✅" ,
159+ "verified" : "🏁" ,
160+ "failed" : "❌" ,
161+ }.get (task .status , "❓" )
162+
163+ md .append (f"### { status_icon } Task { task .id } : { task .description } " )
164+ md .append (f"**Status:** { task .status } | **Attempts:** { task .attempt_count } " )
165+
166+ if task .dependencies :
167+ md .append (f"**Dependencies:** { task .dependencies } " )
168+
169+ if task .acceptance_criteria :
170+ md .append ("**Acceptance Criteria:**" )
171+ for ac in task .acceptance_criteria :
172+ md .append (f"- { ac } " )
173+
174+ if task .notes :
175+ md .append (f"\n **Notes:**\n { task .notes } " )
176+
177+ md .append ("\n ---" )
178+
179+ return "\n " .join (md )
180+
181+
182+ class Clarification (BaseModel ):
121183 """
122- Represents a request for more information from the user (Product Manager -> User).
184+ Represents a request for clarification from the user (Architect -> User).
123185 """
124186
125187 question : str = Field (..., description = "The question to ask the user." )
0 commit comments