@@ -88,18 +88,33 @@ def _build_system_prompt(self) -> str:
8888- Ensure proper TypeScript typing (no 'any' types)
8989"""
9090
91- async def execute_task (self , task : Task , project_id : int = 1 ) -> Dict [str , Any ]:
91+ async def execute_task (self , task : Dict [ str , Any ] , project_id : int = 1 ) -> Dict [str , Any ]:
9292 """
9393 Execute frontend task: generate React component.
9494
9595 Args:
96- task: Task to execute with component specification
96+ task: Task dictionary with id, project_id, task_number, title, description, etc.
9797 project_id: Project ID for WebSocket broadcasts
9898
9999 Returns:
100100 Execution result with status and output
101101 """
102- self .current_task = task
102+ # Extract commonly used fields from task dict
103+ task_id = task ["id" ]
104+ task_title = task ["title" ]
105+ task_description = task ["description" ]
106+
107+ # Create Task object for self.current_task (used by blocker creation)
108+ self .current_task = Task (
109+ id = task_id ,
110+ project_id = task .get ("project_id" ),
111+ issue_id = task .get ("issue_id" ),
112+ task_number = task .get ("task_number" , "" ),
113+ parent_issue_number = task .get ("parent_issue_number" , "" ),
114+ title = task_title ,
115+ description = task_description ,
116+ assigned_to = task .get ("assigned_to" ),
117+ )
103118
104119 try :
105120 # Broadcast task started
@@ -110,18 +125,18 @@ async def execute_task(self, task: Task, project_id: int = 1) -> Dict[str, Any]:
110125 await broadcast_task_status (
111126 self .websocket_manager ,
112127 project_id ,
113- task . id ,
128+ task_id ,
114129 "in_progress" ,
115130 agent_id = self .agent_id ,
116131 progress = 0 ,
117132 )
118133 except Exception as e :
119134 logger .debug (f"Failed to broadcast task status: { e } " )
120135
121- logger .info (f"Frontend agent { self .agent_id } executing task { task . id } : { task . title } " )
136+ logger .info (f"Frontend agent { self .agent_id } executing task { task_id } : { task_title } " )
122137
123138 # Parse task description for component spec
124- component_spec = self ._parse_component_spec (task . description )
139+ component_spec = self ._parse_component_spec (task_description )
125140
126141 # Generate component code
127142 component_code = await self ._generate_react_component (component_spec )
@@ -151,29 +166,29 @@ async def execute_task(self, task: Task, project_id: int = 1) -> Dict[str, Any]:
151166 await broadcast_task_status (
152167 self .websocket_manager ,
153168 project_id ,
154- task . id ,
169+ task_id ,
155170 "completed" ,
156171 agent_id = self .agent_id ,
157172 progress = 100 ,
158173 )
159174 except Exception as e :
160175 logger .debug (f"Failed to broadcast task status: { e } " )
161176
162- logger .info (f"Frontend agent { self .agent_id } completed task { task . id } " )
177+ logger .info (f"Frontend agent { self .agent_id } completed task { task_id } " )
163178
164179 # T076: Auto-commit task changes after successful completion
165180 if hasattr (self , "git_workflow" ) and self .git_workflow and file_paths :
166181 try :
167182 # Convert file_paths dict to list of paths
168183 files_modified = [path for path in file_paths .values ()]
169184
170- # Convert Task object to dict for git_workflow
185+ # Task is already a dict, extract fields for git_workflow
171186 task_dict = {
172- "id" : task . id ,
173- "project_id" : task .project_id ,
174- "task_number" : task .task_number ,
175- "title" : task . title ,
176- "description" : task . description ,
187+ "id" : task_id ,
188+ "project_id" : task .get ( " project_id" ) ,
189+ "task_number" : task .get ( " task_number" , "" ) ,
190+ "title" : task_title ,
191+ "description" : task_description ,
177192 }
178193
179194 commit_sha = self .git_workflow .commit_task_changes (
@@ -182,11 +197,11 @@ async def execute_task(self, task: Task, project_id: int = 1) -> Dict[str, Any]:
182197
183198 # T082: Record commit SHA in database
184199 if commit_sha and self .db :
185- self .db .update_task_commit_sha (task . id , commit_sha )
186- logger .info (f"Task { task . id } committed with SHA: { commit_sha [:7 ]} " )
200+ self .db .update_task_commit_sha (task_id , commit_sha )
201+ logger .info (f"Task { task_id } committed with SHA: { commit_sha [:7 ]} " )
187202 except Exception as e :
188203 # T080: Graceful degradation - log warning but don't block task completion
189- logger .warning (f"Auto-commit failed for task { task . id } (non-blocking): { e } " )
204+ logger .warning (f"Auto-commit failed for task { task_id } (non-blocking): { e } " )
190205
191206 return {
192207 "status" : "completed" ,
@@ -196,7 +211,7 @@ async def execute_task(self, task: Task, project_id: int = 1) -> Dict[str, Any]:
196211 }
197212
198213 except Exception as e :
199- logger .error (f"Frontend agent { self .agent_id } failed task { task . id } : { e } " )
214+ logger .error (f"Frontend agent { self .agent_id } failed task { task_id } : { e } " )
200215
201216 # Broadcast failure
202217 if self .websocket_manager :
@@ -206,12 +221,12 @@ async def execute_task(self, task: Task, project_id: int = 1) -> Dict[str, Any]:
206221 await broadcast_task_status (
207222 self .websocket_manager ,
208223 project_id ,
209- task . id ,
224+ task_id ,
210225 "failed" ,
211226 agent_id = self .agent_id ,
212227 )
213- except Exception as e :
214- logger .debug (f"Failed to broadcast task status: { e } " )
228+ except Exception as broadcast_err :
229+ logger .debug (f"Failed to broadcast task status: { broadcast_err } " )
215230
216231 return {"status" : "failed" , "output" : str (e ), "error" : str (e )}
217232
@@ -438,7 +453,7 @@ def _update_imports_exports(self, component_name: str, file_paths: Dict[str, str
438453 )
439454
440455 async def _run_and_check_linting (
441- self , task : Task , file_paths : Dict [str , str ], project_id : int
456+ self , task : Dict [ str , Any ] , file_paths : Dict [str , str ], project_id : int
442457 ) -> None :
443458 """
444459 Run linting on created files and create blocker if critical errors found (T112).
@@ -447,13 +462,14 @@ async def _run_and_check_linting(
447462 stores results in the database, and creates a blocker if critical errors are found.
448463
449464 Args:
450- task: Task object
465+ task: Task dictionary with id, project_id, task_number, title, description, etc.
451466 file_paths: Dict of created file paths
452467 project_id: Project ID for broadcasts
453468
454469 Raises:
455470 ValueError: If linting fails with critical errors (blocker created)
456471 """
472+ task_id = task ["id" ]
457473 if not file_paths :
458474 logger .debug ("No files created, skipping linting" )
459475 return
@@ -478,7 +494,7 @@ async def _run_and_check_linting(
478494 lint_runner = LintRunner (self .web_ui_root )
479495
480496 logger .info (
481- f"Running linting on { len (files_to_lint )} TypeScript files for task { task . id } "
497+ f"Running linting on { len (files_to_lint )} TypeScript files for task { task_id } "
482498 )
483499
484500 # Run linting
@@ -488,7 +504,7 @@ async def _run_and_check_linting(
488504 if self .db :
489505 for result in lint_results :
490506 self .db .create_lint_result (
491- task_id = task . id ,
507+ task_id = task_id ,
492508 linter = result .linter ,
493509 error_count = result .error_count ,
494510 warning_count = result .warning_count ,
@@ -508,10 +524,10 @@ async def _run_and_check_linting(
508524 blocker_type = "SYNC" ,
509525 title = f"Linting failed: { total_errors } critical errors" ,
510526 description = blocker_description ,
511- blocking_task_id = task . id ,
527+ blocking_task_id = task_id ,
512528 )
513529
514- logger .error (f"Task { task . id } blocked by { total_errors } lint errors" )
530+ logger .error (f"Task { task_id } blocked by { total_errors } lint errors" )
515531
516532 # Broadcast lint failure via WebSocket (T119)
517533 if self .websocket_manager :
@@ -523,7 +539,7 @@ async def _run_and_check_linting(
523539 project_id ,
524540 {
525541 "type" : "lint_failed" ,
526- "task_id" : task . id ,
542+ "task_id" : task_id ,
527543 "error_count" : total_errors ,
528544 "timestamp" : datetime .utcnow ().isoformat (),
529545 },
@@ -536,7 +552,7 @@ async def _run_and_check_linting(
536552 # Log warnings (non-blocking)
537553 total_warnings = sum (r .warning_count for r in lint_results )
538554 if total_warnings > 0 :
539- logger .warning (f"Task { task . id } : { total_warnings } lint warnings (non-blocking)" )
555+ logger .warning (f"Task { task_id } : { total_warnings } lint warnings (non-blocking)" )
540556
541557 # Broadcast lint success via WebSocket (T119)
542558 if self .websocket_manager :
@@ -548,7 +564,7 @@ async def _run_and_check_linting(
548564 project_id ,
549565 {
550566 "type" : "lint_completed" ,
551- "task_id" : task . id ,
567+ "task_id" : task_id ,
552568 "error_count" : 0 ,
553569 "warning_count" : total_warnings ,
554570 "timestamp" : datetime .utcnow ().isoformat (),
0 commit comments