From 9e06b15d3d4f64d49121bb85dfbd82979eeb171f Mon Sep 17 00:00:00 2001 From: AndyMik90 Date: Tue, 17 Feb 2026 15:35:33 +0100 Subject: [PATCH] fix: address PR #1847 review findings - Reuse SKIP_DIRS from context.constants instead of duplicating exclusion list - Fix exception types in write error handlers (TypeError/ValueError, not JSONDecodeError) - Add warning log when path validation bypassed due to exhausted retries - Use existing safeReadFileSync helper for attempt_history reads Co-Authored-By: Claude Opus 4.6 --- apps/backend/agents/coder.py | 33 ++++++------------- .../ipc-handlers/task/execution-handlers.ts | 9 +++-- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/apps/backend/agents/coder.py b/apps/backend/agents/coder.py index b29643da..de44991a 100644 --- a/apps/backend/agents/coder.py +++ b/apps/backend/agents/coder.py @@ -13,6 +13,7 @@ import re from datetime import datetime, timedelta from pathlib import Path +from context.constants import SKIP_DIRS from core.client import create_client from core.file_utils import write_json_atomic from linear_updater import ( @@ -99,27 +100,8 @@ logger = logging.getLogger(__name__) # FILE VALIDATION UTILITIES # ============================================================================= -# Directories to exclude from file path search -_EXCLUDE_DIRS = frozenset( - { - "node_modules", - ".git", - "dist", - "build", - ".venv", - "__pycache__", - ".next", - ".nuxt", - ".auto-claude", - "coverage", - ".tox", - ".idea", - ".vscode", - "vendor", - "target", - "out", - } -) +# Directories to exclude from file path search — extends context.constants.SKIP_DIRS +_EXCLUDE_DIRS = frozenset(SKIP_DIRS | {".auto-claude", ".tox", "out"}) def _build_file_index( @@ -393,7 +375,7 @@ def _auto_correct_subtask_files( logger.info( f"Persisted {len(corrections)} path correction(s) to implementation_plan.json" ) - except OSError as e: + except (OSError, TypeError, ValueError) as e: logger.warning(f"Failed to persist path corrections: {e}") return still_missing @@ -474,7 +456,7 @@ def _validate_plan_file_paths(spec_dir: Path, project_dir: Path) -> str | None: try: write_json_atomic(plan_file, plan) logger.info(f"Persisted {corrections_made} post-plan path correction(s)") - except OSError as e: + except (OSError, TypeError, ValueError) as e: logger.warning(f"Failed to persist post-plan corrections: {e}") if not all_missing: @@ -1240,6 +1222,11 @@ async def run_autonomous_agent( first_run = True status = "continue" else: + if path_issues: + logger.warning( + f"Plan has uncorrectable file paths after " + f"{planning_validation_failures} retries - proceeding anyway" + ) plan_validated = True planning_retry_context = None else: diff --git a/apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts index ebf6b1ad..734e8b3a 100644 --- a/apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts +++ b/apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts @@ -1072,8 +1072,10 @@ export function registerTaskExecutionHandlers( for (const dir of specDirsToClean) { const attemptHistoryPath = path.join(dir, 'memory', 'attempt_history.json'); + const historyContent = safeReadFileSync(attemptHistoryPath); + if (!historyContent) continue; + try { - const historyContent = readFileSync(attemptHistoryPath, 'utf-8'); const history = JSON.parse(historyContent); // Collect stuck subtask IDs before clearing @@ -1103,10 +1105,7 @@ export function registerTaskExecutionHandlers( writeFileAtomicSync(attemptHistoryPath, JSON.stringify(history, null, 2)); console.log(`[Recovery] Cleared attempt_history.json at: ${dir} (reset ${stuckIds.size} stuck entries)`); } catch (historyErr) { - // File might not exist - that's fine, no stuck markers to clear - if ((historyErr as NodeJS.ErrnoException).code !== 'ENOENT') { - console.warn(`[Recovery] Could not clear attempt_history at ${dir}:`, historyErr); - } + console.warn(`[Recovery] Could not parse attempt_history at ${dir}:`, historyErr); } } }