From 91242c2f48c398019c06c23fbbd0f8827e15374d Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 5 Mar 2026 10:47:38 +0400 Subject: [PATCH 1/2] auto-claude: subtask-1-3 - Add roadmap tool constants to models.py Added TOOL_REORDER_FEATURES constant following existing pattern for Auto-Code MCP tools. This constant defines the tool name used by the reorder_features roadmap management tool. Co-Authored-By: Claude Sonnet 4.5 --- apps/backend/agents/tools_pkg/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/backend/agents/tools_pkg/models.py b/apps/backend/agents/tools_pkg/models.py index ebd5c752..95942913 100644 --- a/apps/backend/agents/tools_pkg/models.py +++ b/apps/backend/agents/tools_pkg/models.py @@ -42,6 +42,9 @@ TOOL_SEARCH_TEAM_DOCS = "mcp__auto-claude__search_team_docs" TOOL_GET_TEAM_DOCS = "mcp__auto-claude__get_team_docs" +# Roadmap management tools +TOOL_REORDER_FEATURES = "mcp__auto-claude__reorder_features" + # Background task management tools TOOL_START_BACKGROUND = "mcp__auto-claude__start_background_command" TOOL_GET_TASK_STATUS = "mcp__auto-claude__get_task_status" From 0e8673ee78fc2d1c73b632e0d13dd87b295900ac Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 5 Mar 2026 10:59:40 +0400 Subject: [PATCH 2/2] auto-claude: subtask-1-4 - Update auto_claude_tools.py exports Added TOOL_REORDER_FEATURES to the exports in auto_claude_tools.py to make it available for agent use. Co-Authored-By: Claude Sonnet 4.5 --- apps/backend/agents/tools_pkg/registry.py | 2 + .../agents/tools_pkg/tools/__init__.py | 2 + .../backend/agents/tools_pkg/tools/roadmap.py | 183 ++++++++++++++++++ apps/backend/auto_claude_tools.py | 2 + 4 files changed, 189 insertions(+) create mode 100644 apps/backend/agents/tools_pkg/tools/roadmap.py diff --git a/apps/backend/agents/tools_pkg/registry.py b/apps/backend/agents/tools_pkg/registry.py index ff5c619a..a6ff9da9 100644 --- a/apps/backend/agents/tools_pkg/registry.py +++ b/apps/backend/agents/tools_pkg/registry.py @@ -22,6 +22,7 @@ create_memory_tools, create_progress_tools, create_qa_tools, + create_roadmap_tools, create_statistics_tools, create_subtask_tools, ) @@ -52,6 +53,7 @@ def create_all_tools(spec_dir: Path, project_dir: Path) -> list: all_tools.extend(create_background_task_tools(spec_dir, project_dir)) all_tools.extend(create_debugging_tools(spec_dir, project_dir)) all_tools.extend(create_knowledge_base_tools(spec_dir, project_dir)) + all_tools.extend(create_roadmap_tools(spec_dir, project_dir)) return all_tools diff --git a/apps/backend/agents/tools_pkg/tools/__init__.py b/apps/backend/agents/tools_pkg/tools/__init__.py index fa123a2f..b43d33a6 100644 --- a/apps/backend/agents/tools_pkg/tools/__init__.py +++ b/apps/backend/agents/tools_pkg/tools/__init__.py @@ -11,6 +11,7 @@ from .memory import create_memory_tools from .progress import create_progress_tools from .qa import create_qa_tools +from .roadmap import create_roadmap_tools from .statistics import create_statistics_tools from .subtask import create_subtask_tools @@ -23,4 +24,5 @@ "create_background_task_tools", "create_debugging_tools", "create_knowledge_base_tools", + "create_roadmap_tools", ] diff --git a/apps/backend/agents/tools_pkg/tools/roadmap.py b/apps/backend/agents/tools_pkg/tools/roadmap.py new file mode 100644 index 00000000..8d0bc332 --- /dev/null +++ b/apps/backend/agents/tools_pkg/tools/roadmap.py @@ -0,0 +1,183 @@ +""" +Roadmap Tools +============= + +Tools for managing roadmap features, including reordering within phases. +""" + +import json +from pathlib import Path +from typing import Any + +try: + from claude_agent_sdk import tool + + SDK_TOOLS_AVAILABLE = True +except ImportError: + SDK_TOOLS_AVAILABLE = False + tool = None + + +def create_roadmap_tools(spec_dir: Path, project_dir: Path) -> list: + """ + Create roadmap management tools. + + Args: + spec_dir: Path to the spec directory + project_dir: Path to the project root + + Returns: + List of roadmap tool functions + """ + if not SDK_TOOLS_AVAILABLE: + return [] + + tools = [] + + # ------------------------------------------------------------------------- + # Tool: reorder_features + # ------------------------------------------------------------------------- + @tool( + "reorder_features", + "Reorder roadmap features within a specific phase. Updates the features array to reflect the new order.", + { + "type": "object", + "properties": { + "phase_id": { + "type": "string", + "description": "The ID of the phase containing the features to reorder", + }, + "feature_ids": { + "type": "array", + "items": {"type": "string"}, + "description": "Array of feature IDs in the desired new order", + }, + }, + "required": ["phase_id", "feature_ids"], + }, + ) + async def reorder_features(args: dict[str, Any]) -> dict[str, Any]: + """Reorder features within a phase in the roadmap.""" + roadmap_file = project_dir / ".auto-claude" / "roadmap" / "roadmap.json" + + if not roadmap_file.exists(): + return { + "content": [ + { + "type": "text", + "text": "Error: Roadmap file not found. Generate a roadmap first.", + } + ] + } + + try: + phase_id = args.get("phase_id") + feature_ids = args.get("feature_ids", []) + + if not phase_id: + return { + "content": [{"type": "text", "text": "Error: phase_id is required"}] + } + + if not feature_ids: + return { + "content": [ + {"type": "text", "text": "Error: feature_ids array is required"} + ] + } + + # Read roadmap + with open(roadmap_file, encoding="utf-8") as f: + roadmap = json.load(f) + + # Validate phase exists + phases = roadmap.get("phases", []) + phase_exists = any(p.get("id") == phase_id for p in phases) + if not phase_exists: + return { + "content": [ + { + "type": "text", + "text": f"Error: Phase '{phase_id}' not found in roadmap", + } + ] + } + + # Get all features + all_features = roadmap.get("features", []) + + # Separate features by phase + phase_features = [f for f in all_features if f.get("phase_id") == phase_id] + other_features = [f for f in all_features if f.get("phase_id") != phase_id] + + # Validate all feature IDs exist in the phase + existing_feature_ids = {f.get("id") for f in phase_features} + for fid in feature_ids: + if fid not in existing_feature_ids: + return { + "content": [ + { + "type": "text", + "text": f"Error: Feature '{fid}' not found in phase '{phase_id}'", + } + ] + } + + # Create feature lookup + feature_map = {f.get("id"): f for f in phase_features} + + # Reorder phase features according to feature_ids + reordered_phase_features = [] + for fid in feature_ids: + if fid in feature_map: + reordered_phase_features.append(feature_map[fid]) + + # Combine: other phases first, then reordered phase features + updated_features = other_features + reordered_phase_features + + # Update roadmap + roadmap["features"] = updated_features + + # Update timestamp if metadata exists + if "metadata" in roadmap: + from datetime import datetime + + roadmap["metadata"]["updated_at"] = datetime.utcnow().isoformat() + "Z" + + # Write back to file + with open(roadmap_file, "w", encoding="utf-8") as f: + json.dump(roadmap, f, indent=2) + + # Build success message + feature_titles = [ + f"{fid}: {feature_map[fid].get('title', 'Unknown')}" + for fid in feature_ids + if fid in feature_map + ] + + result = f"""Successfully reordered {len(feature_ids)} features in phase '{phase_id}' + +New order: +{chr(10).join(f" {i + 1}. {title}" for i, title in enumerate(feature_titles))} + +Roadmap file updated: {roadmap_file.relative_to(project_dir)}""" + + return {"content": [{"type": "text", "text": result}]} + + except json.JSONDecodeError as e: + return { + "content": [ + { + "type": "text", + "text": f"Error: Failed to parse roadmap JSON: {e}", + } + ] + } + except Exception as e: + return { + "content": [{"type": "text", "text": f"Error reordering features: {e}"}] + } + + tools.append(reorder_features) + + return tools diff --git a/apps/backend/auto_claude_tools.py b/apps/backend/auto_claude_tools.py index a15fe4c6..8f436ed4 100644 --- a/apps/backend/auto_claude_tools.py +++ b/apps/backend/auto_claude_tools.py @@ -13,6 +13,7 @@ TOOL_GET_SPEC_STATISTICS, TOOL_RECORD_DISCOVERY, TOOL_RECORD_GOTCHA, + TOOL_REORDER_FEATURES, TOOL_UPDATE_QA_STATUS, TOOL_UPDATE_SUBTASK_STATUS, is_electron_mcp_enabled, @@ -35,6 +36,7 @@ "TOOL_GET_BUILD_PROGRESS", "TOOL_RECORD_DISCOVERY", "TOOL_RECORD_GOTCHA", + "TOOL_REORDER_FEATURES", "TOOL_GET_SESSION_CONTEXT", "TOOL_GET_SPEC_STATISTICS", "TOOL_UPDATE_QA_STATUS",