Linting and test fixes

This commit is contained in:
AndyMik90
2025-12-16 21:53:01 +01:00
parent 11fcdf42f3
commit 140f11fccd
132 changed files with 529 additions and 2164 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from core.agent instead."""
from core.agent import *
from core.agent import * # noqa: F403
-1
View File
@@ -8,7 +8,6 @@ Handles session memory storage using dual-layer approach:
"""
import logging
import sys
from pathlib import Path
from debug import (
+1 -2
View File
@@ -6,7 +6,6 @@ Manages which tools are allowed for each agent type to prevent context
pollution and accidental misuse.
"""
from typing import List
from .models import (
BASE_READ_TOOLS,
@@ -22,7 +21,7 @@ from .models import (
)
def get_allowed_tools(agent_type: str) -> List[str]:
def get_allowed_tools(agent_type: str) -> list[str]:
"""
Get the list of allowed tools for a specific agent type.
+3 -1
View File
@@ -8,16 +8,18 @@ Code analysis and project scanning tools.
# Import from analyzers subpackage (these are the modular analyzers)
from .analyzers import (
ProjectAnalyzer as ModularProjectAnalyzer,
)
from .analyzers import (
ServiceAnalyzer,
analyze_project,
analyze_service,
)
from .ci_discovery import CIDiscovery
# Import from analysis module root (these are other analysis tools)
from .project_analyzer import ProjectAnalyzer
from .risk_classifier import RiskClassifier
from .security_scanner import SecurityScanner
from .ci_discovery import CIDiscovery
from .test_discovery import TestDiscovery
# insight_extractor is a module with functions, not a class, so don't import it here
@@ -292,7 +292,8 @@ class RouteDetector(BaseAnalyzer):
if pages_api.exists():
api_files = [f for f in pages_api.glob("**/*.{ts,js,tsx,jsx}") if self._should_include_file(f)]
for api_file in api_files:
if api_file.name.startswith('_'): continue
if api_file.name.startswith('_'):
continue
# Convert file path to route
relative_path = api_file.relative_to(pages_api)
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from analysis.analyzer instead."""
from analysis.analyzer import *
from analysis.analyzer import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from analysis.analyzers instead."""
from analysis.analyzers import *
from analysis.analyzers import * # noqa: F403
+6 -6
View File
@@ -1,12 +1,12 @@
"""Backward compatibility shim - import from analysis.ci_discovery instead."""
from analysis.ci_discovery import (
CIConfig,
CIWorkflow,
CIDiscovery,
discover_ci,
get_ci_test_commands,
get_ci_system,
HAS_YAML,
CIConfig,
CIDiscovery,
CIWorkflow,
discover_ci,
get_ci_system,
get_ci_test_commands,
)
__all__ = [
+6 -5
View File
@@ -8,7 +8,6 @@ CLI commands for building specs and handling the main build flow.
import asyncio
import sys
from pathlib import Path
from typing import Optional
# Ensure parent directory is in path for imports (before other imports)
_PARENT_DIR = Path(__file__).parent.parent
@@ -26,7 +25,6 @@ from ui import (
StatusManager,
bold,
box,
error,
highlight,
icon,
muted,
@@ -45,14 +43,17 @@ from workspace import (
setup_workspace,
)
from .input_handlers import collect_user_input_interactive, read_from_file, read_multiline_input
from .input_handlers import (
read_from_file,
read_multiline_input,
)
def handle_build_command(
project_dir: Path,
spec_dir: Path,
model: str,
max_iterations: Optional[int],
max_iterations: int | None,
verbose: bool,
force_isolated: bool,
force_direct: bool,
@@ -299,7 +300,7 @@ def _handle_build_interrupt(
worktree_manager,
working_dir: Path,
model: str,
max_iterations: Optional[int],
max_iterations: int | None,
verbose: bool,
) -> None:
"""
+1 -2
View File
@@ -9,7 +9,6 @@ import asyncio
import json
import sys
from pathlib import Path
from typing import Optional
# Ensure parent directory is in path for imports (before other imports)
_PARENT_DIR = Path(__file__).parent.parent
@@ -33,7 +32,7 @@ from ui import (
)
def collect_followup_task(spec_dir: Path, max_retries: int = 3) -> Optional[str]:
def collect_followup_task(spec_dir: Path, max_retries: int = 3) -> str | None:
"""
Collect a follow-up task description from the user.
+3 -4
View File
@@ -7,7 +7,6 @@ Reusable user input collection utilities for CLI commands.
import sys
from pathlib import Path
from typing import Optional
# Ensure parent directory is in path for imports (before other imports)
_PARENT_DIR = Path(__file__).parent.parent
@@ -31,7 +30,7 @@ def collect_user_input_interactive(
prompt_text: str,
allow_file: bool = True,
allow_paste: bool = True,
) -> Optional[str]:
) -> str | None:
"""
Collect user input through an interactive menu.
@@ -126,7 +125,7 @@ def collect_user_input_interactive(
return user_input
def read_from_file() -> Optional[str]:
def read_from_file() -> str | None:
"""
Read text content from a file path provided by the user.
@@ -171,7 +170,7 @@ def read_from_file() -> Optional[str]:
return None
def read_multiline_input(prompt_text: str) -> Optional[str]:
def read_multiline_input(prompt_text: str) -> str | None:
"""
Read multi-line input from the user.
+14 -5
View File
@@ -13,6 +13,7 @@ _PARENT_DIR = Path(__file__).parent.parent
if str(_PARENT_DIR) not in sys.path:
sys.path.insert(0, str(_PARENT_DIR))
from debug import debug_warning
from ui import (
Icons,
icon,
@@ -29,7 +30,15 @@ from .utils import print_banner
# Import debug utilities
try:
from debug import debug, debug_detailed, debug_verbose, debug_success, debug_error, debug_section, is_debug_enabled
from debug import (
debug,
debug_detailed,
debug_error,
debug_section,
debug_success,
debug_verbose,
is_debug_enabled,
)
except ImportError:
def debug(*args, **kwargs): pass
def debug_detailed(*args, **kwargs): pass
@@ -311,11 +320,11 @@ def handle_merge_preview_command(project_dir: Path, spec_name: str) -> dict:
project_dir=str(project_dir),
spec_name=spec_name)
from workspace import get_existing_build_worktree
from merge import MergeOrchestrator
from workspace import get_existing_build_worktree
worktree_path = get_existing_build_worktree(project_dir, spec_name)
debug(MODULE, f"Worktree lookup result",
debug(MODULE, "Worktree lookup result",
worktree_path=str(worktree_path) if worktree_path else None)
if not worktree_path:
@@ -358,7 +367,7 @@ def handle_merge_preview_command(project_dir: Path, spec_name: str) -> dict:
# Transform semantic conflicts to UI-friendly format
conflicts = []
for c in preview.get("conflicts", []):
debug_verbose(MODULE, f"Processing semantic conflict",
debug_verbose(MODULE, "Processing semantic conflict",
file=c.get("file", ""),
severity=c.get("severity", "unknown"))
conflicts.append({
@@ -419,7 +428,7 @@ def handle_merge_preview_command(project_dir: Path, spec_name: str) -> dict:
return result
except Exception as e:
debug_error(MODULE, f"Merge preview failed", error=str(e))
debug_error(MODULE, "Merge preview failed", error=str(e))
import traceback
debug_verbose(MODULE, "Exception traceback", traceback=traceback.format_exc())
return {
+1 -11
View File
@@ -1,6 +1,6 @@
"""Backward compatibility shim - import from core.client instead."""
import sys
import os
import sys
# Add auto-claude to path if not present
_auto_claude_dir = os.path.dirname(os.path.abspath(__file__))
@@ -12,13 +12,3 @@ def __getattr__(name):
"""Lazy import to avoid circular imports with auto_claude_tools."""
from core import client as _client
return getattr(_client, name)
# For wildcard imports, define __all__
__all__ = [
"create_claude_client",
"ClaudeClient",
"is_graphiti_mcp_enabled",
"get_graphiti_mcp_url",
"is_electron_mcp_enabled",
"get_electron_debug_port",
]
-1
View File
@@ -6,7 +6,6 @@ Handles serialization and deserialization of task context.
"""
import json
from dataclasses import asdict
from pathlib import Path
from .models import TaskContext
File diff suppressed because it is too large Load Diff
+61 -61
View File
@@ -26,85 +26,85 @@ _spec = importlib.util.spec_from_file_location("workspace_module", _workspace_fi
_workspace_module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_workspace_module)
merge_existing_build = _workspace_module.merge_existing_build
_run_parallel_merges = _workspace_module._run_parallel_merges
# TODO: _run_parallel_merges not yet implemented in workspace.py
# _run_parallel_merges = _workspace_module._run_parallel_merges
# Models and Enums
from .models import (
WorkspaceMode,
WorkspaceChoice,
ParallelMergeTask,
ParallelMergeResult,
MergeLock,
MergeLockError,
)
# Git Utilities
from .git_utils import (
has_uncommitted_changes,
get_current_branch,
get_existing_build_worktree,
get_file_content_from_ref,
get_changed_files_from_branch,
is_process_running,
is_binary_file,
is_lock_file,
validate_merged_syntax,
create_conflict_file_with_git,
# Export private names for backward compatibility
_is_process_running,
_is_binary_file,
_is_lock_file,
_validate_merged_syntax,
_get_file_content_from_ref,
_get_changed_files_from_branch,
_create_conflict_file_with_git,
# Constants
MAX_FILE_LINES_FOR_AI,
MAX_PARALLEL_AI_MERGES,
MAX_SYNTAX_FIX_RETRIES,
BINARY_EXTENSIONS,
LOCK_FILES,
MERGE_LOCK_TIMEOUT,
)
# Setup Functions
from .setup import (
choose_workspace,
copy_spec_to_worktree,
setup_workspace,
ensure_timeline_hook_installed,
initialize_timeline_tracking,
# Export private names for backward compatibility
_ensure_timeline_hook_installed,
_initialize_timeline_tracking,
)
# Display Functions
from .display import (
show_build_summary,
show_changed_files,
print_merge_success,
print_conflict_info,
_print_conflict_info,
# Export private names for backward compatibility
_print_merge_success,
_print_conflict_info,
print_conflict_info,
print_merge_success,
show_build_summary,
show_changed_files,
)
# Finalization Functions
from .finalization import (
check_existing_build,
cleanup_all_worktrees,
discard_existing_build,
finalize_workspace,
handle_workspace_choice,
review_existing_build,
discard_existing_build,
check_existing_build,
list_all_worktrees,
cleanup_all_worktrees,
review_existing_build,
)
# Git Utilities
from .git_utils import (
BINARY_EXTENSIONS,
LOCK_FILES,
# Constants
MAX_FILE_LINES_FOR_AI,
MAX_PARALLEL_AI_MERGES,
MAX_SYNTAX_FIX_RETRIES,
MERGE_LOCK_TIMEOUT,
_create_conflict_file_with_git,
_get_changed_files_from_branch,
_get_file_content_from_ref,
_is_binary_file,
_is_lock_file,
# Export private names for backward compatibility
_is_process_running,
_validate_merged_syntax,
create_conflict_file_with_git,
get_changed_files_from_branch,
get_current_branch,
get_existing_build_worktree,
get_file_content_from_ref,
has_uncommitted_changes,
is_binary_file,
is_lock_file,
is_process_running,
validate_merged_syntax,
)
from .models import (
MergeLock,
MergeLockError,
ParallelMergeResult,
ParallelMergeTask,
WorkspaceChoice,
WorkspaceMode,
)
# Setup Functions
from .setup import (
# Export private names for backward compatibility
_ensure_timeline_hook_installed,
_initialize_timeline_tracking,
choose_workspace,
copy_spec_to_worktree,
ensure_timeline_hook_installed,
initialize_timeline_tracking,
setup_workspace,
)
__all__ = [
# Merge Operations (from workspace.py)
'merge_existing_build',
'_run_parallel_merges', # Private but used by tests
# '_run_parallel_merges', # TODO: not yet implemented - Private but used by tests
# Models
'WorkspaceMode',
'WorkspaceChoice',
+3 -5
View File
@@ -6,8 +6,6 @@ Workspace Display
Functions for displaying workspace information and build summaries.
"""
from pathlib import Path
from typing import Optional
from ui import (
bold,
@@ -73,9 +71,9 @@ def show_changed_files(manager: WorktreeManager, spec_name: str) -> None:
print(f" {status} {filepath}")
def print_merge_success(no_commit: bool, stats: Optional[dict] = None) -> None:
def print_merge_success(no_commit: bool, stats: dict | None = None) -> None:
"""Print a success message after merge."""
from ui import box, icon, Icons, highlight
from ui import Icons, box, icon
if no_commit:
content = [
@@ -113,7 +111,7 @@ def print_merge_success(no_commit: bool, stats: Optional[dict] = None) -> None:
def print_conflict_info(result: dict) -> None:
"""Print information about conflicts that occurred during merge."""
from ui import warning, highlight, muted
from ui import highlight, muted, warning
conflicts = result.get("conflicts", [])
if not conflicts:
+3 -4
View File
@@ -8,7 +8,6 @@ Functions for finalizing workspaces and handling user choices after build comple
import sys
from pathlib import Path
from typing import Optional
from ui import (
Icons,
@@ -17,18 +16,18 @@ from ui import (
box,
highlight,
icon,
info,
muted,
print_status,
select_menu,
success,
warning,
info,
)
from worktree import WorktreeInfo, WorktreeManager
from .models import WorkspaceChoice
from .git_utils import get_existing_build_worktree
from .display import show_build_summary, show_changed_files
from .git_utils import get_existing_build_worktree
from .models import WorkspaceChoice
def finalize_workspace(
+3 -4
View File
@@ -9,7 +9,6 @@ Utility functions for git operations used in workspace management.
import json
import subprocess
from pathlib import Path
from typing import Optional
# Constants for merge limits
MAX_FILE_LINES_FOR_AI = 5000 # Skip AI for files larger than this
@@ -89,7 +88,7 @@ def get_existing_build_worktree(project_dir: Path, spec_name: str) -> Path | Non
return None
def get_file_content_from_ref(project_dir: Path, ref: str, file_path: str) -> Optional[str]:
def get_file_content_from_ref(project_dir: Path, ref: str, file_path: str) -> str | None:
"""Get file content from a git ref (branch, commit, etc.)."""
result = subprocess.run(
["git", "show", f"{ref}:{file_path}"],
@@ -265,9 +264,9 @@ def validate_merged_syntax(file_path: str, content: str, project_dir: Path) -> t
def create_conflict_file_with_git(
main_content: str,
worktree_content: str,
base_content: Optional[str],
base_content: str | None,
project_dir: Path,
) -> tuple[Optional[str], bool]:
) -> tuple[str | None, bool]:
"""
Use git merge-file to create a file with conflict markers.
+4 -5
View File
@@ -9,7 +9,6 @@ Data classes and enums for workspace management.
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
from typing import Optional
class WorkspaceMode(Enum):
@@ -34,7 +33,7 @@ class ParallelMergeTask:
file_path: str
main_content: str
worktree_content: str
base_content: Optional[str]
base_content: str | None
spec_name: str
@@ -42,9 +41,9 @@ class ParallelMergeTask:
class ParallelMergeResult:
"""Result of a parallel merge task."""
file_path: str
merged_content: Optional[str]
merged_content: str | None
success: bool
error: Optional[str] = None
error: str | None = None
was_auto_merged: bool = False # True if git auto-merged without AI
@@ -70,8 +69,8 @@ class MergeLock:
def __enter__(self):
"""Acquire the merge lock."""
import time
import os
import time
self.lock_dir.mkdir(parents=True, exist_ok=True)
+3 -4
View File
@@ -11,23 +11,22 @@ import shutil
import subprocess
import sys
from pathlib import Path
from typing import Optional
from merge import FileTimelineTracker
from ui import (
Icons,
MenuOption,
box,
icon,
muted,
print_status,
select_menu,
success,
muted,
)
from worktree import WorktreeManager
from merge import FileTimelineTracker
from .models import WorkspaceMode
from .git_utils import has_uncommitted_changes
from .models import WorkspaceMode
# Import debug utilities
try:
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from spec.critique instead."""
from spec.critique import *
from spec.critique import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from core.debug instead."""
from core.debug import *
from core.debug import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from integrations.graphiti.config instead."""
from integrations.graphiti.config import *
from integrations.graphiti.config import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from integrations.graphiti.providers_pkg instead."""
from integrations.graphiti.providers_pkg import *
from integrations.graphiti.providers_pkg import * # noqa: F403
+1 -1
View File
@@ -14,7 +14,7 @@ import json
from datetime import datetime
from pathlib import Path
from ui import Icons, print_key_value, print_status
from ui import print_key_value, print_status
from .types import IdeationPhaseResult
+2 -2
View File
@@ -1,3 +1,3 @@
"""Backward compatibility shim - import from implementation_plan package instead."""
from implementation_plan.main import *
from implementation_plan import *
from implementation_plan import * # noqa: F403
from implementation_plan.main import * # noqa: F403
+10 -10
View File
@@ -28,24 +28,24 @@ Usage:
# Re-export all public APIs from the package
from graphiti_providers import (
# Models
EMBEDDING_DIMENSIONS,
# Exceptions
ProviderError,
ProviderNotInstalled,
create_cross_encoder,
create_embedder,
# Factory functions
create_llm_client,
create_embedder,
create_cross_encoder,
# Models
EMBEDDING_DIMENSIONS,
get_expected_embedding_dim,
# Validators
validate_embedding_config,
test_llm_connection,
test_embedder_connection,
test_ollama_connection,
get_graph_hints,
# Utilities
is_graphiti_enabled,
get_graph_hints,
test_embedder_connection,
test_llm_connection,
test_ollama_connection,
# Validators
validate_embedding_config,
)
__all__ = [
@@ -23,28 +23,27 @@ Usage:
"""
# Core exceptions
# Cross-encoder / reranker
from .cross_encoder import create_cross_encoder
from .exceptions import ProviderError, ProviderNotInstalled
# Factory functions
from .factory import create_llm_client, create_embedder
# Cross-encoder / reranker
from .cross_encoder import create_cross_encoder
from .factory import create_embedder, create_llm_client
# Models and constants
from .models import EMBEDDING_DIMENSIONS, get_expected_embedding_dim
# Utilities
from .utils import get_graph_hints, is_graphiti_enabled
# Validators and health checks
from .validators import (
validate_embedding_config,
test_llm_connection,
test_embedder_connection,
test_llm_connection,
test_ollama_connection,
validate_embedding_config,
)
# Utilities
from .utils import is_graphiti_enabled, get_graph_hints
__all__ = [
# Exceptions
"ProviderError",
@@ -10,10 +10,10 @@ from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from graphiti_config import GraphitiConfig
from .openai_embedder import create_openai_embedder
from .voyage_embedder import create_voyage_embedder
from .azure_openai_embedder import create_azure_openai_embedder
from .ollama_embedder import create_ollama_embedder
from .openai_embedder import create_openai_embedder
from .voyage_embedder import create_voyage_embedder
__all__ = [
"create_openai_embedder",
@@ -11,6 +11,12 @@ from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from graphiti_config import GraphitiConfig
from .embedder_providers import (
create_azure_openai_embedder,
create_ollama_embedder,
create_openai_embedder,
create_voyage_embedder,
)
from .exceptions import ProviderError
from .llm_providers import (
create_anthropic_llm_client,
@@ -18,12 +24,6 @@ from .llm_providers import (
create_ollama_llm_client,
create_openai_llm_client,
)
from .embedder_providers import (
create_azure_openai_embedder,
create_ollama_embedder,
create_openai_embedder,
create_voyage_embedder,
)
logger = logging.getLogger(__name__)
@@ -10,10 +10,10 @@ from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from graphiti_config import GraphitiConfig
from .openai_llm import create_openai_llm_client
from .anthropic_llm import create_anthropic_llm_client
from .azure_openai_llm import create_azure_openai_llm_client
from .ollama_llm import create_ollama_llm_client
from .openai_llm import create_openai_llm_client
__all__ = [
"create_openai_llm_client",
+8 -8
View File
@@ -8,16 +8,16 @@ Integration with Linear issue tracking.
from .config import LinearConfig
from .integration import LinearManager
from .updater import (
LinearTaskState,
is_linear_enabled,
get_linear_api_key,
create_linear_task,
update_linear_status,
STATUS_TODO,
STATUS_CANCELED,
STATUS_DONE,
STATUS_IN_PROGRESS,
STATUS_IN_REVIEW,
STATUS_DONE,
STATUS_CANCELED,
STATUS_TODO,
LinearTaskState,
create_linear_task,
get_linear_api_key,
is_linear_enabled,
update_linear_status,
)
# Aliases for backward compatibility
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from integrations.linear.config instead."""
from integrations.linear.config import *
from integrations.linear.config import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from integrations.linear.integration instead."""
from integrations.linear.integration import *
from integrations.linear.integration import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from integrations.linear.updater instead."""
from integrations.linear.updater import *
from integrations.linear.updater import * # noqa: F403
+5 -6
View File
@@ -64,17 +64,13 @@ Public API:
"""
# Graphiti integration
# Codebase map
from .codebase_map import load_codebase_map, update_codebase_map
from .graphiti_helpers import is_graphiti_memory_enabled
# Directory management
from .paths import clear_memory, get_memory_dir, get_session_insights_dir
# Session insights
from .sessions import load_all_insights, save_session_insights
# Codebase map
from .codebase_map import load_codebase_map, update_codebase_map
# Patterns and gotchas
from .patterns import (
append_gotcha,
@@ -83,6 +79,9 @@ from .patterns import (
load_patterns,
)
# Session insights
from .sessions import load_all_insights, save_session_insights
# Summary utilities
from .summary import get_memory_summary
+5 -1
View File
@@ -12,7 +12,11 @@ from datetime import datetime, timezone
from pathlib import Path
from typing import Any
from .graphiti_helpers import is_graphiti_memory_enabled, run_async, save_to_graphiti_async
from .graphiti_helpers import (
is_graphiti_memory_enabled,
run_async,
save_to_graphiti_async,
)
from .paths import get_session_insights_dir
logger = logging.getLogger(__name__)
+30 -30
View File
@@ -23,51 +23,51 @@ Usage:
result = orchestrator.merge_task("task-001-feature")
"""
from .types import (
ChangeType,
SemanticChange,
FileAnalysis,
ConflictRegion,
ConflictSeverity,
MergeStrategy,
MergeResult,
MergeDecision,
TaskSnapshot,
FileEvolution,
)
from .models import MergeStats, TaskMergeRequest, MergeReport
from .semantic_analyzer import SemanticAnalyzer
from .conflict_detector import ConflictDetector
from .compatibility_rules import CompatibilityRule
from .auto_merger import AutoMerger
from .file_evolution import FileEvolutionTracker
from .ai_resolver import AIResolver, create_claude_resolver
from .auto_merger import AutoMerger
from .compatibility_rules import CompatibilityRule
from .conflict_detector import ConflictDetector
from .conflict_resolver import ConflictResolver
from .merge_pipeline import MergePipeline
from .git_utils import find_worktree, get_file_from_branch
from .file_evolution import FileEvolutionTracker
from .file_merger import (
apply_ai_merge,
apply_single_task_changes,
combine_non_conflicting_changes,
find_import_end,
extract_location_content,
apply_ai_merge,
find_import_end,
)
from .orchestrator import MergeOrchestrator
from .file_timeline import (
FileTimelineTracker,
FileTimeline,
MainBranchEvent,
BranchPoint,
WorktreeState,
TaskIntent,
TaskFileView,
FileTimeline,
FileTimelineTracker,
MainBranchEvent,
MergeContext,
TaskFileView,
TaskIntent,
WorktreeState,
)
from .git_utils import find_worktree, get_file_from_branch
from .merge_pipeline import MergePipeline
from .models import MergeReport, MergeStats, TaskMergeRequest
from .orchestrator import MergeOrchestrator
from .prompts import (
build_timeline_merge_prompt,
build_simple_merge_prompt,
build_timeline_merge_prompt,
optimize_prompt_for_length,
)
from .semantic_analyzer import SemanticAnalyzer
from .types import (
ChangeType,
ConflictRegion,
ConflictSeverity,
FileAnalysis,
FileEvolution,
MergeDecision,
MergeResult,
MergeStrategy,
SemanticChange,
TaskSnapshot,
)
__all__ = [
# Types
+2 -3
View File
@@ -11,10 +11,9 @@ responses and validating that content looks like code.
from __future__ import annotations
import re
from typing import Optional
def extract_code_block(response: str, language: str) -> Optional[str]:
def extract_code_block(response: str, language: str) -> str | None:
"""
Extract code block from AI response.
@@ -79,7 +78,7 @@ def extract_batch_code_blocks(
response: str,
location: str,
language: str,
) -> Optional[str]:
) -> str | None:
"""
Extract code block for a specific location from a batch response.
+2 -3
View File
@@ -11,8 +11,7 @@ resolution of conflicts using AI with minimal context.
from __future__ import annotations
import logging
import re
from typing import Callable, Optional
from collections.abc import Callable
from ..types import (
ConflictRegion,
@@ -57,7 +56,7 @@ class AIResolver:
def __init__(
self,
ai_call_fn: Optional[AICallFunction] = None,
ai_call_fn: AICallFunction | None = None,
max_context_tokens: int = MAX_CONTEXT_TOKENS,
):
"""
+4 -6
View File
@@ -8,8 +8,6 @@ Helper utilities for merge operations.
from __future__ import annotations
import re
from pathlib import Path
from typing import Optional
from ..types import ChangeType, SemanticChange
@@ -43,7 +41,7 @@ class MergeHelpers:
return False
@staticmethod
def extract_hook_call(change: SemanticChange) -> Optional[str]:
def extract_hook_call(change: SemanticChange) -> str | None:
"""Extract the hook call from a change."""
if change.content_after:
# Look for useXxx() pattern
@@ -59,7 +57,7 @@ class MergeHelpers:
return None
@staticmethod
def extract_jsx_wrapper(change: SemanticChange) -> Optional[tuple[str, str]]:
def extract_jsx_wrapper(change: SemanticChange) -> tuple[str, str] | None:
"""Extract JSX wrapper component and props."""
if change.content_after:
# Look for <ComponentName ...>
@@ -122,7 +120,7 @@ class MergeHelpers:
return content
@staticmethod
def find_function_insert_position(content: str, ext: str) -> Optional[int]:
def find_function_insert_position(content: str, ext: str) -> int | None:
"""Find the best position to insert new functions."""
lines = content.split("\n")
@@ -184,7 +182,7 @@ class MergeHelpers:
@staticmethod
def apply_content_change(
content: str,
old: Optional[str],
old: str | None,
new: str,
) -> str:
"""Apply a content change by replacing old with new."""
+4 -5
View File
@@ -25,7 +25,6 @@ import logging
import re
from dataclasses import dataclass
from pathlib import Path
from typing import Optional
from .types import (
ChangeType,
@@ -457,7 +456,7 @@ class AutoMerger:
return line.startswith("import ") or line.startswith("export ")
return False
def _extract_hook_call(self, change: SemanticChange) -> Optional[str]:
def _extract_hook_call(self, change: SemanticChange) -> str | None:
"""Extract the hook call from a change."""
if change.content_after:
# Look for useXxx() pattern
@@ -472,7 +471,7 @@ class AutoMerger:
return None
def _extract_jsx_wrapper(self, change: SemanticChange) -> Optional[tuple[str, str]]:
def _extract_jsx_wrapper(self, change: SemanticChange) -> tuple[str, str] | None:
"""Extract JSX wrapper component and props."""
if change.content_after:
# Look for <ComponentName ...>
@@ -534,7 +533,7 @@ class AutoMerger:
return content
def _find_function_insert_position(self, content: str, ext: str) -> Optional[int]:
def _find_function_insert_position(self, content: str, ext: str) -> int | None:
"""Find the best position to insert new functions."""
lines = content.split("\n")
@@ -595,7 +594,7 @@ class AutoMerger:
def _apply_content_change(
self,
content: str,
old: Optional[str],
old: str | None,
new: str,
) -> str:
"""Apply a content change by replacing old with new."""
+1 -2
View File
@@ -13,7 +13,6 @@ This module contains:
from __future__ import annotations
from dataclasses import dataclass
from typing import Optional
from .types import ChangeType, MergeStrategy
@@ -35,7 +34,7 @@ class CompatibilityRule:
change_type_a: ChangeType
change_type_b: ChangeType
compatible: bool
strategy: Optional[MergeStrategy] = None
strategy: MergeStrategy | None = None
reason: str = ""
bidirectional: bool = True
+3 -4
View File
@@ -15,7 +15,6 @@ from __future__ import annotations
import logging
from collections import defaultdict
from typing import Optional
from .compatibility_rules import CompatibilityRule
from .types import (
@@ -108,7 +107,7 @@ def analyze_location_conflict(
location: str,
task_changes: list[tuple[str, SemanticChange]],
rule_index: dict[tuple[ChangeType, ChangeType], CompatibilityRule],
) -> Optional[ConflictRegion]:
) -> ConflictRegion | None:
"""
Analyze changes at a specific location for conflicts.
@@ -134,7 +133,7 @@ def analyze_location_conflict(
# Check pairwise compatibility
all_compatible = True
final_strategy: Optional[MergeStrategy] = None
final_strategy: MergeStrategy | None = None
reasons = []
for i, (type_a, change_a) in enumerate(zip(change_types, changes)):
@@ -272,7 +271,7 @@ def analyze_compatibility(
change_a: SemanticChange,
change_b: SemanticChange,
rule_index: dict[tuple[ChangeType, ChangeType], CompatibilityRule],
) -> tuple[bool, Optional[MergeStrategy], str]:
) -> tuple[bool, MergeStrategy | None, str]:
"""
Analyze compatibility between two specific changes.
+3 -5
View File
@@ -23,7 +23,6 @@ The actual logic is organized into specialized modules:
from __future__ import annotations
import logging
from typing import Optional
from .compatibility_rules import (
CompatibilityRule,
@@ -31,7 +30,6 @@ from .compatibility_rules import (
index_rules,
)
from .conflict_analysis import (
analyze_compatibility,
detect_conflicts,
)
from .conflict_explanation import (
@@ -116,7 +114,7 @@ class ConflictDetector:
auto_mergeable = sum(1 for c in conflicts if c.can_auto_merge)
from .types import ConflictSeverity
critical = sum(1 for c in conflicts if c.severity == ConflictSeverity.CRITICAL)
debug_success(MODULE, f"Conflict detection complete",
debug_success(MODULE, "Conflict detection complete",
total_conflicts=len(conflicts),
auto_mergeable=auto_mergeable,
critical=critical)
@@ -149,8 +147,8 @@ class ConflictDetector:
def analyze_compatibility(
change_a: SemanticChange,
change_b: SemanticChange,
detector: Optional[ConflictDetector] = None,
) -> tuple[bool, Optional[MergeStrategy], str]:
detector: ConflictDetector | None = None,
) -> tuple[bool, MergeStrategy | None, str]:
"""
Analyze compatibility between two specific changes.
+1 -3
View File
@@ -12,8 +12,6 @@ This module provides functions to help users understand:
from __future__ import annotations
from typing import Optional
from .compatibility_rules import CompatibilityRule
from .types import ChangeType, ConflictRegion, MergeStrategy
@@ -51,7 +49,7 @@ def explain_conflict(conflict: ConflictRegion) -> str:
def get_compatible_pairs(
rules: list[CompatibilityRule],
) -> list[tuple[ChangeType, ChangeType, Optional[MergeStrategy]]]:
) -> list[tuple[ChangeType, ChangeType, MergeStrategy | None]]:
"""
Get all compatible change type pairs and their strategies.
+4 -5
View File
@@ -13,8 +13,10 @@ This module handles:
from __future__ import annotations
import logging
from typing import Optional
from .ai_resolver import AIResolver
from .auto_merger import AutoMerger, MergeContext
from .file_merger import apply_ai_merge, extract_location_content
from .types import (
ConflictRegion,
ConflictSeverity,
@@ -22,9 +24,6 @@ from .types import (
MergeResult,
TaskSnapshot,
)
from .auto_merger import AutoMerger, MergeContext
from .ai_resolver import AIResolver
from .file_merger import apply_ai_merge, extract_location_content
logger = logging.getLogger(__name__)
@@ -40,7 +39,7 @@ class ConflictResolver:
def __init__(
self,
auto_merger: AutoMerger,
ai_resolver: Optional[AIResolver] = None,
ai_resolver: AIResolver | None = None,
enable_ai: bool = True,
):
"""
+1 -1
View File
@@ -12,7 +12,7 @@ Components:
- tracker: Main FileEvolutionTracker class
"""
from .baseline_capture import BaselineCapture, DEFAULT_EXTENSIONS
from .baseline_capture import DEFAULT_EXTENSIONS, BaselineCapture
from .evolution_queries import EvolutionQueries
from .modification_tracker import ModificationTracker
from .storage import EvolutionStorage
@@ -14,7 +14,6 @@ import logging
import subprocess
from datetime import datetime
from pathlib import Path
from typing import Optional
from ..types import FileEvolution, TaskSnapshot, compute_content_hash
from .storage import EvolutionStorage
@@ -52,7 +51,7 @@ class BaselineCapture:
def __init__(
self,
storage: EvolutionStorage,
extensions: Optional[set[str]] = None,
extensions: set[str] | None = None,
):
"""
Initialize baseline capture.
@@ -119,7 +118,7 @@ class BaselineCapture:
def capture_baselines(
self,
task_id: str,
files: Optional[list[Path | str]],
files: list[Path | str] | None,
intent: str,
evolutions: dict[str, FileEvolution],
) -> dict[str, FileEvolution]:
@@ -15,7 +15,6 @@ from __future__ import annotations
import logging
import shutil
from pathlib import Path
from typing import Optional
from ..types import FileEvolution, TaskSnapshot
from .storage import EvolutionStorage
@@ -48,7 +47,7 @@ class EvolutionQueries:
self,
file_path: Path | str,
evolutions: dict[str, FileEvolution],
) -> Optional[FileEvolution]:
) -> FileEvolution | None:
"""
Get the complete evolution history for a file.
@@ -66,7 +65,7 @@ class EvolutionQueries:
self,
file_path: Path | str,
evolutions: dict[str, FileEvolution],
) -> Optional[str]:
) -> str | None:
"""
Get the baseline content for a file.
@@ -212,8 +211,8 @@ class EvolutionQueries:
self,
file_path: Path | str,
evolutions: dict[str, FileEvolution],
task_ids: Optional[list[str]] = None,
) -> Optional[dict]:
task_ids: list[str] | None = None,
) -> dict | None:
"""
Export evolution data for a file in a format suitable for merge.
@@ -14,7 +14,6 @@ import logging
import subprocess
from datetime import datetime
from pathlib import Path
from typing import Optional
from ..semantic_analyzer import SemanticAnalyzer
from ..types import FileEvolution, TaskSnapshot, compute_content_hash
@@ -44,7 +43,7 @@ class ModificationTracker:
def __init__(
self,
storage: EvolutionStorage,
semantic_analyzer: Optional[SemanticAnalyzer] = None,
semantic_analyzer: SemanticAnalyzer | None = None,
):
"""
Initialize modification tracker.
@@ -63,8 +62,8 @@ class ModificationTracker:
old_content: str,
new_content: str,
evolutions: dict[str, FileEvolution],
raw_diff: Optional[str] = None,
) -> Optional[TaskSnapshot]:
raw_diff: str | None = None,
) -> TaskSnapshot | None:
"""
Record a file modification by a task.
+2 -3
View File
@@ -13,7 +13,6 @@ from __future__ import annotations
import json
import logging
from pathlib import Path
from typing import Optional
from ..types import FileEvolution
@@ -125,7 +124,7 @@ class EvolutionStorage:
return str(baseline_path.relative_to(self.storage_dir))
def read_baseline_content(self, baseline_snapshot_path: str) -> Optional[str]:
def read_baseline_content(self, baseline_snapshot_path: str) -> str | None:
"""
Read baseline content from disk.
@@ -143,7 +142,7 @@ class EvolutionStorage:
logger.warning(f"Could not read baseline {baseline_snapshot_path}: {e}")
return None
def read_file_content(self, file_path: Path | str) -> Optional[str]:
def read_file_content(self, file_path: Path | str) -> str | None:
"""
Read file content from project directory.
+10 -11
View File
@@ -13,11 +13,10 @@ from __future__ import annotations
import logging
from pathlib import Path
from typing import Optional
from ..semantic_analyzer import SemanticAnalyzer
from ..types import FileEvolution, TaskSnapshot
from .baseline_capture import BaselineCapture, DEFAULT_EXTENSIONS
from .baseline_capture import DEFAULT_EXTENSIONS, BaselineCapture
from .evolution_queries import EvolutionQueries
from .modification_tracker import ModificationTracker
from .storage import EvolutionStorage
@@ -62,8 +61,8 @@ class FileEvolutionTracker:
def __init__(
self,
project_dir: Path,
storage_dir: Optional[Path] = None,
semantic_analyzer: Optional[SemanticAnalyzer] = None,
storage_dir: Path | None = None,
semantic_analyzer: SemanticAnalyzer | None = None,
):
"""
Initialize the file evolution tracker.
@@ -120,7 +119,7 @@ class FileEvolutionTracker:
def capture_baselines(
self,
task_id: str,
files: Optional[list[Path | str]] = None,
files: list[Path | str] | None = None,
intent: str = "",
) -> dict[str, FileEvolution]:
"""
@@ -152,8 +151,8 @@ class FileEvolutionTracker:
file_path: Path | str,
old_content: str,
new_content: str,
raw_diff: Optional[str] = None,
) -> Optional[TaskSnapshot]:
raw_diff: str | None = None,
) -> TaskSnapshot | None:
"""
Record a file modification by a task.
@@ -180,7 +179,7 @@ class FileEvolutionTracker:
self._save_evolutions()
return snapshot
def get_file_evolution(self, file_path: Path | str) -> Optional[FileEvolution]:
def get_file_evolution(self, file_path: Path | str) -> FileEvolution | None:
"""
Get the complete evolution history for a file.
@@ -192,7 +191,7 @@ class FileEvolutionTracker:
"""
return self.queries.get_file_evolution(file_path, self._evolutions)
def get_baseline_content(self, file_path: Path | str) -> Optional[str]:
def get_baseline_content(self, file_path: Path | str) -> str | None:
"""
Get the baseline content for a file.
@@ -296,8 +295,8 @@ class FileEvolutionTracker:
def export_for_merge(
self,
file_path: Path | str,
task_ids: Optional[list[str]] = None,
) -> Optional[dict]:
task_ids: list[str] | None = None,
) -> dict | None:
"""
Export evolution data for a file in a format suitable for merge.
-1
View File
@@ -15,7 +15,6 @@ from __future__ import annotations
import re
from pathlib import Path
from typing import Optional
from .types import ChangeType, SemanticChange, TaskSnapshot
+8 -8
View File
@@ -46,24 +46,24 @@ Architecture:
from __future__ import annotations
# Re-export helper classes (for advanced usage)
from .timeline_git import TimelineGitHelper
# Re-export all public models
from .timeline_models import (
MainBranchEvent,
BranchPoint,
WorktreeState,
TaskIntent,
TaskFileView,
FileTimeline,
MainBranchEvent,
MergeContext,
TaskFileView,
TaskIntent,
WorktreeState,
)
from .timeline_persistence import TimelinePersistence
# Re-export the main tracker service
from .timeline_tracker import FileTimelineTracker
# Re-export helper classes (for advanced usage)
from .timeline_git import TimelineGitHelper
from .timeline_persistence import TimelinePersistence
__all__ = [
# Main service
"FileTimelineTracker",
+2 -3
View File
@@ -14,10 +14,9 @@ from __future__ import annotations
import subprocess
from pathlib import Path
from typing import Optional
def find_worktree(project_dir: Path, task_id: str) -> Optional[Path]:
def find_worktree(project_dir: Path, task_id: str) -> Path | None:
"""
Find the worktree path for a task.
@@ -56,7 +55,7 @@ def find_worktree(project_dir: Path, task_id: str) -> Optional[Path]:
def get_file_from_branch(
project_dir: Path, file_path: str, branch: str
) -> Optional[str]:
) -> str | None:
"""
Get file content from a specific git branch.
+1 -2
View File
@@ -14,7 +14,6 @@ import stat
import sys
from pathlib import Path
HOOK_SCRIPT = '''#!/bin/bash
#
# Git post-commit hook for FileTimelineTracker
@@ -145,7 +144,7 @@ def uninstall_hook(project_path: Path) -> bool:
backup_path = git_dir / "hooks" / "post-commit.backup"
if backup_path.exists():
shutil.move(backup_path, hook_path)
print(f"Restored original hook from backup")
print("Restored original hook from backup")
else:
# Remove the hook entirely
hook_path.unlink()
+3 -4
View File
@@ -14,8 +14,10 @@ This module handles the pipeline for merging a single file:
from __future__ import annotations
import logging
from typing import Optional
from .conflict_detector import ConflictDetector
from .conflict_resolver import ConflictResolver
from .file_merger import apply_single_task_changes, combine_non_conflicting_changes
from .types import (
ChangeType,
FileAnalysis,
@@ -23,9 +25,6 @@ from .types import (
MergeResult,
TaskSnapshot,
)
from .conflict_detector import ConflictDetector
from .conflict_resolver import ConflictResolver
from .file_merger import apply_single_task_changes, combine_non_conflicting_changes
logger = logging.getLogger(__name__)
+3 -3
View File
@@ -16,7 +16,7 @@ import json
from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path
from typing import Any, Optional
from typing import Any
from .types import MergeResult
@@ -83,12 +83,12 @@ class MergeReport:
"""Complete report from a merge operation."""
started_at: datetime
completed_at: Optional[datetime] = None
completed_at: datetime | None = None
tasks_merged: list[str] = field(default_factory=list)
file_results: dict[str, MergeResult] = field(default_factory=dict)
stats: MergeStats = field(default_factory=MergeStats)
success: bool = True
error: Optional[str] = None
error: str | None = None
def to_dict(self) -> dict[str, Any]:
"""Convert to dictionary for serialization."""
+21 -20
View File
@@ -21,34 +21,35 @@ from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Any, Optional
from typing import Any
from .ai_resolver import AIResolver, create_claude_resolver
from .auto_merger import AutoMerger
from .conflict_detector import ConflictDetector
from .conflict_resolver import ConflictResolver
from .file_evolution import FileEvolutionTracker
from .git_utils import find_worktree, get_file_from_branch
from .merge_pipeline import MergePipeline
# Re-export models for backwards compatibility
from .models import MergeReport, MergeStats, TaskMergeRequest
from .semantic_analyzer import SemanticAnalyzer
from .types import (
ConflictRegion,
FileAnalysis,
MergeDecision,
)
# Re-export models for backwards compatibility
from .models import MergeReport, MergeStats, TaskMergeRequest
from .semantic_analyzer import SemanticAnalyzer
from .conflict_detector import ConflictDetector
from .auto_merger import AutoMerger
from .file_evolution import FileEvolutionTracker
from .ai_resolver import AIResolver, create_claude_resolver
from .conflict_resolver import ConflictResolver
from .merge_pipeline import MergePipeline
from .git_utils import find_worktree, get_file_from_branch
# Import debug utilities
try:
from debug import (
debug,
debug_detailed,
debug_verbose,
debug_success,
debug_error,
debug_warning,
debug_section,
debug_success,
debug_verbose,
debug_warning,
is_debug_enabled,
)
except ImportError:
@@ -114,9 +115,9 @@ class MergeOrchestrator:
def __init__(
self,
project_dir: Path,
storage_dir: Optional[Path] = None,
storage_dir: Path | None = None,
enable_ai: bool = True,
ai_resolver: Optional[AIResolver] = None,
ai_resolver: AIResolver | None = None,
dry_run: bool = False,
):
"""
@@ -159,8 +160,8 @@ class MergeOrchestrator:
self._ai_resolver_initialized = ai_resolver is not None
# Initialize conflict resolver and merge pipeline
self._conflict_resolver: Optional[ConflictResolver] = None
self._merge_pipeline: Optional[MergePipeline] = None
self._conflict_resolver: ConflictResolver | None = None
self._merge_pipeline: MergePipeline | None = None
# Merge output directory
self.merge_output_dir = self.storage_dir / "merge_output"
@@ -205,7 +206,7 @@ class MergeOrchestrator:
def merge_task(
self,
task_id: str,
worktree_path: Optional[Path] = None,
worktree_path: Path | None = None,
target_branch: str = "main",
) -> MergeReport:
"""
@@ -563,7 +564,7 @@ class MergeOrchestrator:
def write_merged_files(
self,
report: MergeReport,
output_dir: Optional[Path] = None,
output_dir: Path | None = None,
) -> list[Path]:
"""
Write merged files to disk.
+12 -10
View File
@@ -7,13 +7,14 @@ using the FileTimelineTracker's complete file evolution data.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .file_timeline import MergeContext, MainBranchEvent
from .file_timeline import MergeContext
def build_timeline_merge_prompt(context: "MergeContext") -> str:
def build_timeline_merge_prompt(context: MergeContext) -> str:
"""
Build a complete merge prompt using FileTimelineTracker context.
@@ -94,7 +95,7 @@ YOUR TASK:
return prompt
def _build_main_evolution_section(context: "MergeContext") -> str:
def _build_main_evolution_section(context: MergeContext) -> str:
"""Build the main branch evolution section of the prompt."""
if not context.main_evolution:
return f"""MAIN BRANCH EVOLUTION (0 commits since task branched)
@@ -124,7 +125,7 @@ No changes have been made to main branch since this task started.
return "\n".join(lines)
def _build_pending_tasks_section(context: "MergeContext") -> str:
def _build_pending_tasks_section(context: MergeContext) -> str:
"""Build the other pending tasks section."""
separator = "" * 79
if not context.other_pending_tasks:
@@ -150,7 +151,7 @@ No other tasks are pending for this file.
return "\n".join(lines)
def _build_compatibility_instructions(context: "MergeContext") -> str:
def _build_compatibility_instructions(context: MergeContext) -> str:
"""Build compatibility instructions based on pending tasks."""
if not context.other_pending_tasks:
return "- No other tasks pending for this file"
@@ -309,10 +310,10 @@ For EACH conflict, output the resolved code in this exact format:
resolved code here
```
{f"--- CONFLICT_2 RESOLVED ---" if len(conflicts) > 1 else ""}
{"--- CONFLICT_2 RESOLVED ---" if len(conflicts) > 1 else ""}
{f"```{language}" if len(conflicts) > 1 else ""}
{f"resolved code here" if len(conflicts) > 1 else ""}
{f"```" if len(conflicts) > 1 else ""}
{"resolved code here" if len(conflicts) > 1 else ""}
{"```" if len(conflicts) > 1 else ""}
(continue for each conflict)
'''
@@ -478,10 +479,10 @@ def extract_conflict_resolutions(response: str, conflicts: list[dict], language:
def optimize_prompt_for_length(
context: "MergeContext",
context: MergeContext,
max_content_chars: int = 50000,
max_evolution_events: int = 10,
) -> "MergeContext":
) -> MergeContext:
"""
Optimize a MergeContext for prompt length by trimming large content.
@@ -504,6 +505,7 @@ def optimize_prompt_for_length(
# Create a placeholder event for the middle
from datetime import datetime
from .file_timeline import MainBranchEvent
omitted_count = len(context.main_evolution) - max_evolution_events
@@ -4,7 +4,7 @@ JavaScript/TypeScript-specific semantic analysis using tree-sitter.
from __future__ import annotations
from typing import Callable, Optional
from collections.abc import Callable
from .models import ExtractedElement
@@ -20,7 +20,7 @@ def extract_js_elements(
get_text: Callable[[Node], str],
get_line: Callable[[int], int],
ext: str,
parent: Optional[str] = None,
parent: str | None = None,
) -> None:
"""
Extract structural elements from JavaScript/TypeScript AST.
@@ -5,7 +5,7 @@ Data models for semantic analysis.
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Optional
from typing import Any
@dataclass
@@ -17,7 +17,7 @@ class ExtractedElement:
start_line: int
end_line: int
content: str
parent: Optional[str] = None # For nested elements (methods in classes)
parent: str | None = None # For nested elements (methods in classes)
metadata: dict[str, Any] = None
def __post_init__(self):
@@ -4,7 +4,7 @@ Python-specific semantic analysis using tree-sitter.
from __future__ import annotations
from typing import Callable, Optional
from collections.abc import Callable
from .models import ExtractedElement
@@ -19,7 +19,7 @@ def extract_python_elements(
elements: dict[str, ExtractedElement],
get_text: Callable[[Node], str],
get_line: Callable[[int], int],
parent: Optional[str] = None,
parent: str | None = None,
) -> None:
"""
Extract structural elements from Python AST.
@@ -6,7 +6,6 @@ from __future__ import annotations
import difflib
import re
from typing import Optional
from ..types import ChangeType, FileAnalysis, SemanticChange
@@ -133,7 +132,7 @@ def analyze_with_regex(
return analysis
def get_import_pattern(ext: str) -> Optional[re.Pattern]:
def get_import_pattern(ext: str) -> re.Pattern | None:
"""
Get the import pattern for a file extension.
@@ -153,7 +152,7 @@ def get_import_pattern(ext: str) -> Optional[re.Pattern]:
return patterns.get(ext)
def get_function_pattern(ext: str) -> Optional[re.Pattern]:
def get_function_pattern(ext: str) -> re.Pattern | None:
"""
Get the function definition pattern for a file extension.
+5 -5
View File
@@ -15,7 +15,7 @@ from __future__ import annotations
import logging
from pathlib import Path
from typing import Any, Optional
from typing import Any
from .types import ChangeType, FileAnalysis
@@ -56,7 +56,7 @@ MODULE = "merge.semantic_analyzer"
# Try to import tree-sitter - it's optional but recommended
TREE_SITTER_AVAILABLE = False
try:
import tree_sitter
import tree_sitter # noqa: F401
from tree_sitter import Language, Node, Parser, Tree
TREE_SITTER_AVAILABLE = True
@@ -93,13 +93,13 @@ if TREE_SITTER_AVAILABLE:
pass
# Import our modular components
from .semantic_analysis.models import ExtractedElement
from .semantic_analysis.comparison import compare_elements
from .semantic_analysis.models import ExtractedElement
from .semantic_analysis.regex_analyzer import analyze_with_regex
if TREE_SITTER_AVAILABLE:
from .semantic_analysis.python_analyzer import extract_python_elements
from .semantic_analysis.js_analyzer import extract_js_elements
from .semantic_analysis.python_analyzer import extract_python_elements
class SemanticAnalyzer:
@@ -145,7 +145,7 @@ class SemanticAnalyzer:
file_path: str,
before: str,
after: str,
task_id: Optional[str] = None,
task_id: str | None = None,
) -> FileAnalysis:
"""
Analyze the semantic differences between two versions of a file.
+4 -5
View File
@@ -16,7 +16,6 @@ from __future__ import annotations
import logging
import subprocess
from pathlib import Path
from typing import Optional, List
logger = logging.getLogger(__name__)
@@ -61,7 +60,7 @@ class TimelineGitHelper:
except subprocess.CalledProcessError:
return "unknown"
def get_file_content_at_commit(self, file_path: str, commit_hash: str) -> Optional[str]:
def get_file_content_at_commit(self, file_path: str, commit_hash: str) -> str | None:
"""
Get file content at a specific commit.
@@ -85,7 +84,7 @@ class TimelineGitHelper:
except Exception:
return None
def get_files_changed_in_commit(self, commit_hash: str) -> List[str]:
def get_files_changed_in_commit(self, commit_hash: str) -> list[str]:
"""
Get list of files changed in a commit.
@@ -173,7 +172,7 @@ class TimelineGitHelper:
return worktree_path.read_text(encoding="utf-8")
return ""
def get_changed_files_in_worktree(self, worktree_path: Path) -> List[str]:
def get_changed_files_in_worktree(self, worktree_path: Path) -> list[str]:
"""
Get all changed files in a worktree vs main.
@@ -200,7 +199,7 @@ class TimelineGitHelper:
logger.error(f"Failed to get changed files in worktree: {e}")
return []
def get_branch_point(self, worktree_path: Path) -> Optional[str]:
def get_branch_point(self, worktree_path: Path) -> str | None:
"""
Get the branch point (merge-base with main) for a worktree.
+14 -14
View File
@@ -15,7 +15,7 @@ from __future__ import annotations
from dataclasses import dataclass, field
from datetime import datetime
from typing import Dict, List, Optional, Literal
from typing import Literal
@dataclass
@@ -35,14 +35,14 @@ class MainBranchEvent:
# Source of change
source: Literal['human', 'merged_task']
merged_from_task: Optional[str] = None # If source is 'merged_task'
merged_from_task: str | None = None # If source is 'merged_task'
# Intent/reason for change
commit_message: str = ""
# For richer context (optional)
author: Optional[str] = None
diff_summary: Optional[str] = None # e.g., "+15 -3 lines"
author: str | None = None
diff_summary: str | None = None # e.g., "+15 -3 lines"
def to_dict(self) -> dict:
return {
@@ -150,7 +150,7 @@ class TaskFileView:
branch_point: BranchPoint
# Current state in the task's worktree (None if not modified yet)
worktree_state: Optional[WorktreeState] = None
worktree_state: WorktreeState | None = None
# What the task intends to do
task_intent: TaskIntent = field(default_factory=lambda: TaskIntent("", ""))
@@ -160,7 +160,7 @@ class TaskFileView:
# Lifecycle status
status: Literal['active', 'merged', 'abandoned'] = 'active'
merged_at: Optional[datetime] = None
merged_at: datetime | None = None
def to_dict(self) -> dict:
return {
@@ -197,10 +197,10 @@ class FileTimeline:
file_path: str
# Main branch evolution - the authoritative history
main_branch_history: List[MainBranchEvent] = field(default_factory=list)
main_branch_history: list[MainBranchEvent] = field(default_factory=list)
# Each task's isolated view of this file
task_views: Dict[str, TaskFileView] = field(default_factory=dict)
task_views: dict[str, TaskFileView] = field(default_factory=dict)
# Metadata
created_at: datetime = field(default_factory=datetime.now)
@@ -221,15 +221,15 @@ class FileTimeline:
self.task_views[task_view.task_id] = task_view
self.last_updated = datetime.now()
def get_task_view(self, task_id: str) -> Optional[TaskFileView]:
def get_task_view(self, task_id: str) -> TaskFileView | None:
"""Get a task's view of this file."""
return self.task_views.get(task_id)
def get_active_tasks(self) -> List[TaskFileView]:
def get_active_tasks(self) -> list[TaskFileView]:
"""Get all tasks that are still active (not merged/abandoned)."""
return [tv for tv in self.task_views.values() if tv.status == 'active']
def get_events_since_commit(self, commit_hash: str) -> List[MainBranchEvent]:
def get_events_since_commit(self, commit_hash: str) -> list[MainBranchEvent]:
"""Get all main branch events since a given commit."""
events = []
found_commit = False
@@ -240,7 +240,7 @@ class FileTimeline:
found_commit = True
return events
def get_current_main_state(self) -> Optional[MainBranchEvent]:
def get_current_main_state(self) -> MainBranchEvent | None:
"""Get the most recent main branch event."""
if self.main_branch_history:
return self.main_branch_history[-1]
@@ -289,7 +289,7 @@ class MergeContext:
task_branch_point: BranchPoint
# What happened in main since task branched (ordered from oldest to newest)
main_evolution: List[MainBranchEvent]
main_evolution: list[MainBranchEvent]
# Task's changes
task_worktree_content: str
@@ -299,7 +299,7 @@ class MergeContext:
current_main_commit: str
# Other tasks that also touch this file (for forward-compatibility)
other_pending_tasks: List[Dict] # [{task_id, intent, branch_point, commits_behind}]
other_pending_tasks: list[dict] # [{task_id, intent, branch_point, commits_behind}]
# Metrics
total_commits_behind: int
+3 -3
View File
@@ -16,7 +16,7 @@ import json
import logging
from datetime import datetime
from pathlib import Path
from typing import Dict, TYPE_CHECKING
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .timeline_models import FileTimeline
@@ -52,7 +52,7 @@ class TimelinePersistence:
# Ensure storage directory exists
self.timelines_dir.mkdir(parents=True, exist_ok=True)
def load_all_timelines(self) -> Dict[str, "FileTimeline"]:
def load_all_timelines(self) -> dict[str, FileTimeline]:
"""
Load all timelines from disk on startup.
@@ -85,7 +85,7 @@ class TimelinePersistence:
return timelines
def save_timeline(self, file_path: str, timeline: "FileTimeline") -> None:
def save_timeline(self, file_path: str, timeline: FileTimeline) -> None:
"""
Save a single timeline to disk.
+17 -18
View File
@@ -15,18 +15,17 @@ from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional
from .timeline_git import TimelineGitHelper
from .timeline_models import (
BranchPoint,
FileTimeline,
MainBranchEvent,
BranchPoint,
WorktreeState,
TaskIntent,
TaskFileView,
MergeContext,
TaskFileView,
TaskIntent,
WorktreeState,
)
from .timeline_git import TimelineGitHelper
from .timeline_persistence import TimelinePersistence
logger = logging.getLogger(__name__)
@@ -49,7 +48,7 @@ class FileTimelineTracker:
This service is the "brain" of the intent-aware merge system.
"""
def __init__(self, project_path: Path, storage_path: Optional[Path] = None):
def __init__(self, project_path: Path, storage_path: Path | None = None):
"""
Initialize the file timeline tracker.
@@ -68,7 +67,7 @@ class FileTimelineTracker:
self.persistence = TimelinePersistence(self.storage_path)
# In-memory cache of timelines
self._timelines: Dict[str, FileTimeline] = {}
self._timelines: dict[str, FileTimeline] = {}
# Load existing timelines
self._timelines = self.persistence.load_all_timelines()
@@ -83,9 +82,9 @@ class FileTimelineTracker:
def on_task_start(
self,
task_id: str,
files_to_modify: List[str],
files_to_create: Optional[List[str]] = None,
branch_point_commit: Optional[str] = None,
files_to_modify: list[str],
files_to_create: list[str] | None = None,
branch_point_commit: str | None = None,
task_intent: str = "",
task_title: str = "",
) -> None:
@@ -303,7 +302,7 @@ class FileTimelineTracker:
# QUERY METHODS
# =========================================================================
def get_merge_context(self, task_id: str, file_path: str) -> Optional[MergeContext]:
def get_merge_context(self, task_id: str, file_path: str) -> MergeContext | None:
"""
Build complete merge context for AI resolver.
@@ -370,14 +369,14 @@ class FileTimelineTracker:
total_pending_tasks=len(other_tasks),
)
debug_success(MODULE, f"Built merge context",
debug_success(MODULE, "Built merge context",
commits_behind=task_view.commits_behind_main,
main_events=len(main_evolution),
other_tasks=len(other_tasks))
return context
def get_files_for_task(self, task_id: str) -> List[str]:
def get_files_for_task(self, task_id: str) -> list[str]:
"""
Return all files this task is tracking.
@@ -393,7 +392,7 @@ class FileTimelineTracker:
files.append(file_path)
return files
def get_pending_tasks_for_file(self, file_path: str) -> List[TaskFileView]:
def get_pending_tasks_for_file(self, file_path: str) -> list[TaskFileView]:
"""
Return all active tasks that modify this file.
@@ -408,7 +407,7 @@ class FileTimelineTracker:
return []
return timeline.get_active_tasks()
def get_task_drift(self, task_id: str) -> Dict[str, int]:
def get_task_drift(self, task_id: str) -> dict[str, int]:
"""
Return commits-behind-main for each file in task.
@@ -437,7 +436,7 @@ class FileTimelineTracker:
"""
return file_path in self._timelines
def get_timeline(self, file_path: str) -> Optional[FileTimeline]:
def get_timeline(self, file_path: str) -> FileTimeline | None:
"""
Get the timeline for a file.
@@ -533,7 +532,7 @@ class FileTimelineTracker:
task_view.commits_behind_main = drift
self._persist_timeline(file_path)
debug_success(MODULE, f"Initialized from worktree",
debug_success(MODULE, "Initialized from worktree",
files=len(changed_files),
branch_point=branch_point[:8])
+1 -2
View File
@@ -12,7 +12,6 @@ Usage:
"""
import argparse
import json
import sys
from pathlib import Path
@@ -46,7 +45,7 @@ def cmd_notify_commit(args):
print(f"[FileTimelineTracker] Processing commit: {commit_hash[:8]}")
tracker.on_main_branch_commit(commit_hash)
print(f"[FileTimelineTracker] Commit processed successfully")
print("[FileTimelineTracker] Commit processed successfully")
def cmd_show_timeline(args):
+9 -11
View File
@@ -11,12 +11,10 @@ enabling intelligent conflict detection and resolution.
from __future__ import annotations
import hashlib
import json
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from pathlib import Path
from typing import Any, Optional
from typing import Any
class ChangeType(Enum):
@@ -161,8 +159,8 @@ class SemanticChange:
location: str
line_start: int
line_end: int
content_before: Optional[str] = None
content_after: Optional[str] = None
content_before: str | None = None
content_after: str | None = None
metadata: dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> dict[str, Any]:
@@ -320,7 +318,7 @@ class ConflictRegion:
change_types: list[ChangeType]
severity: ConflictSeverity
can_auto_merge: bool
merge_strategy: Optional[MergeStrategy] = None
merge_strategy: MergeStrategy | None = None
reason: str = ""
def to_dict(self) -> dict[str, Any]:
@@ -373,11 +371,11 @@ class TaskSnapshot:
task_id: str
task_intent: str
started_at: datetime
completed_at: Optional[datetime] = None
completed_at: datetime | None = None
content_hash_before: str = ""
content_hash_after: str = ""
semantic_changes: list[SemanticChange] = field(default_factory=list)
raw_diff: Optional[str] = None
raw_diff: str | None = None
def to_dict(self) -> dict[str, Any]:
"""Convert to dictionary for serialization."""
@@ -454,7 +452,7 @@ class FileEvolution:
task_snapshots=[TaskSnapshot.from_dict(ts) for ts in data.get("task_snapshots", [])],
)
def get_task_snapshot(self, task_id: str) -> Optional[TaskSnapshot]:
def get_task_snapshot(self, task_id: str) -> TaskSnapshot | None:
"""Get a specific task's snapshot."""
for snapshot in self.task_snapshots:
if snapshot.task_id == task_id:
@@ -500,13 +498,13 @@ class MergeResult:
decision: MergeDecision
file_path: str
merged_content: Optional[str] = None
merged_content: str | None = None
conflicts_resolved: list[ConflictRegion] = field(default_factory=list)
conflicts_remaining: list[ConflictRegion] = field(default_factory=list)
ai_calls_made: int = 0
tokens_used: int = 0
explanation: str = ""
error: Optional[str] = None
error: str | None = None
def to_dict(self) -> dict[str, Any]:
"""Convert to dictionary for serialization."""
-1
View File
@@ -2,7 +2,6 @@
Utility functions for implementation planner.
"""
from pathlib import Path
from implementation_plan import Verification, VerificationType
+1 -1
View File
@@ -26,7 +26,7 @@ Usage:
from pathlib import Path
# Public API exports
from .models import PreImplementationChecklist, PredictedIssue
from .models import PredictedIssue, PreImplementationChecklist
from .predictor import BugPredictor
__all__ = [
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from core.progress instead."""
from core.progress import *
from core.progress import * # noqa: F403
+2 -3
View File
@@ -6,13 +6,12 @@ Core shell commands that are always safe regardless of project type.
These commands form the foundation of the security allowlist.
"""
from typing import Dict, Set
# =============================================================================
# BASE COMMANDS - Always safe regardless of project type
# =============================================================================
BASE_COMMANDS: Set[str] = {
BASE_COMMANDS: set[str] = {
# Core shell
"echo",
"printf",
@@ -153,7 +152,7 @@ BASE_COMMANDS: Set[str] = {
# VALIDATED COMMANDS - Need extra validation even when allowed
# =============================================================================
VALIDATED_COMMANDS: Dict[str, str] = {
VALIDATED_COMMANDS: dict[str, str] = {
"rm": "validate_rm",
"chmod": "validate_chmod",
"pkill": "validate_pkill",
@@ -5,13 +5,12 @@ Cloud Provider Commands Module
Commands for cloud provider CLIs and platform-specific tooling.
"""
from typing import Dict, Set
# =============================================================================
# CLOUD PROVIDER CLIs
# =============================================================================
CLOUD_COMMANDS: Dict[str, Set[str]] = {
CLOUD_COMMANDS: dict[str, set[str]] = {
"aws": {
"aws",
"sam",
@@ -5,13 +5,12 @@ Code Quality Commands Module
Commands for linters, formatters, security scanners, and code analysis tools.
"""
from typing import Dict, Set
# =============================================================================
# CODE QUALITY COMMANDS
# =============================================================================
CODE_QUALITY_COMMANDS: Dict[str, Set[str]] = {
CODE_QUALITY_COMMANDS: dict[str, set[str]] = {
"shellcheck": {"shellcheck"},
"hadolint": {"hadolint"},
"actionlint": {"actionlint"},
@@ -5,13 +5,12 @@ Database Commands Module
Commands for database clients, management tools, and ORMs.
"""
from typing import Dict, Set
# =============================================================================
# DATABASE COMMANDS
# =============================================================================
DATABASE_COMMANDS: Dict[str, Set[str]] = {
DATABASE_COMMANDS: dict[str, set[str]] = {
"postgresql": {
"psql",
"pg_dump",
@@ -6,13 +6,12 @@ Commands for web frameworks, testing frameworks, build tools,
and other framework-specific tooling across all ecosystems.
"""
from typing import Dict, Set
# =============================================================================
# FRAMEWORK-SPECIFIC COMMANDS
# =============================================================================
FRAMEWORK_COMMANDS: Dict[str, Set[str]] = {
FRAMEWORK_COMMANDS: dict[str, set[str]] = {
# Python web frameworks
"flask": {"flask", "gunicorn", "waitress", "gevent"},
"django": {"django-admin", "gunicorn", "daphne", "uvicorn"},
@@ -5,13 +5,12 @@ Infrastructure Commands Module
Commands for containerization, orchestration, IaC, and DevOps tooling.
"""
from typing import Dict, Set
# =============================================================================
# INFRASTRUCTURE/DEVOPS COMMANDS
# =============================================================================
INFRASTRUCTURE_COMMANDS: Dict[str, Set[str]] = {
INFRASTRUCTURE_COMMANDS: dict[str, set[str]] = {
"docker": {
"docker",
"docker-compose",
@@ -6,13 +6,12 @@ Programming language-specific commands including interpreters,
compilers, and language-specific tooling.
"""
from typing import Dict, Set
# =============================================================================
# LANGUAGE-SPECIFIC COMMANDS
# =============================================================================
LANGUAGE_COMMANDS: Dict[str, Set[str]] = {
LANGUAGE_COMMANDS: dict[str, set[str]] = {
"python": {
"python",
"python3",
@@ -5,13 +5,12 @@ Package Manager Commands Module
Commands for various package managers across different ecosystems.
"""
from typing import Dict, Set
# =============================================================================
# PACKAGE MANAGER COMMANDS
# =============================================================================
PACKAGE_MANAGER_COMMANDS: Dict[str, Set[str]] = {
PACKAGE_MANAGER_COMMANDS: dict[str, set[str]] = {
"npm": {"npm", "npx"},
"yarn": {"yarn"},
"pnpm": {"pnpm", "pnpx"},
@@ -5,13 +5,12 @@ Version Manager Commands Module
Commands for runtime version management tools.
"""
from typing import Dict, Set
# =============================================================================
# VERSION MANAGER COMMANDS
# =============================================================================
VERSION_MANAGER_COMMANDS: Dict[str, Set[str]] = {
VERSION_MANAGER_COMMANDS: dict[str, set[str]] = {
"asdf": {"asdf"},
"mise": {"mise"},
"nvm": {"nvm"},
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from prompts_pkg.prompt_generator instead."""
from prompts_pkg.prompt_generator import *
from prompts_pkg.prompt_generator import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from prompts_pkg.prompts instead."""
from prompts_pkg.prompts import *
from prompts_pkg.prompts import * # noqa: F403
+6 -6
View File
@@ -7,19 +7,19 @@ Prompt generation and templates for AI interactions.
# Import all functions from prompt_generator
from .prompt_generator import (
get_relative_spec_path,
generate_environment_context,
generate_subtask_prompt,
generate_planner_prompt,
load_subtask_context,
format_context_for_prompt,
generate_environment_context,
generate_planner_prompt,
generate_subtask_prompt,
get_relative_spec_path,
load_subtask_context,
)
# Import all functions from prompts
from .prompts import (
get_planner_prompt,
get_coding_prompt,
get_followup_planner_prompt,
get_planner_prompt,
is_first_run,
)
+22 -22
View File
@@ -1,38 +1,38 @@
"""Backward compatibility shim - import from qa package instead."""
from qa import (
ISSUE_SIMILARITY_THRESHOLD,
# Configuration
MAX_QA_ITERATIONS,
RECURRING_ISSUE_THRESHOLD,
ISSUE_SIMILARITY_THRESHOLD,
# Main loop
run_qa_validation_loop,
# Criteria & status
load_implementation_plan,
save_implementation_plan,
get_qa_signoff_status,
is_qa_approved,
is_qa_rejected,
is_fixes_applied,
get_qa_iteration_count,
should_run_qa,
should_run_fixes,
print_qa_status,
_issue_similarity,
_normalize_issue_key,
check_test_discovery,
create_manual_test_plan,
escalate_to_human,
# Report & tracking
get_iteration_history,
record_iteration,
has_recurring_issues,
get_qa_iteration_count,
get_qa_signoff_status,
get_recurring_issue_summary,
escalate_to_human,
create_manual_test_plan,
check_test_discovery,
has_recurring_issues,
is_fixes_applied,
is_no_test_project,
_normalize_issue_key,
_issue_similarity,
is_qa_approved,
is_qa_rejected,
# Criteria & status
load_implementation_plan,
load_qa_fixer_prompt,
# Agent sessions
load_qa_reviewer_prompt,
print_qa_status,
record_iteration,
run_qa_agent_session,
load_qa_fixer_prompt,
run_qa_fixer_session,
# Main loop
run_qa_validation_loop,
save_implementation_plan,
should_run_fixes,
should_run_qa,
)
__all__ = [
+1 -1
View File
@@ -1,8 +1,8 @@
"""Backward compatibility shim - import from services.recovery instead."""
from services.recovery import (
RecoveryManager,
FailureType,
RecoveryAction,
RecoveryManager,
check_and_recover,
get_recovery_context,
)
+1 -1
View File
@@ -87,4 +87,4 @@ __all__ = [
# Aliases for tests
"_extract_section",
"_truncate_text",
]
]
+7 -7
View File
@@ -1,17 +1,17 @@
"""Backward compatibility shim - import from analysis.risk_classifier instead."""
from analysis.risk_classifier import (
RiskClassifier,
RiskAssessment,
ValidationRecommendations,
AssessmentFlags,
ComplexityAnalysis,
ScopeAnalysis,
IntegrationAnalysis,
InfrastructureAnalysis,
IntegrationAnalysis,
KnowledgeAnalysis,
RiskAnalysis,
AssessmentFlags,
load_risk_assessment,
RiskAssessment,
RiskClassifier,
ScopeAnalysis,
ValidationRecommendations,
get_validation_requirements,
load_risk_assessment,
)
__all__ = [
+3 -3
View File
@@ -6,11 +6,11 @@ Standalone runners for various Auto Claude capabilities.
Each runner can be invoked from CLI or programmatically.
"""
from .spec_runner import main as run_spec
from .roadmap_runner import main as run_roadmap
from .ai_analyzer_runner import main as run_ai_analyzer
from .ideation_runner import main as run_ideation
from .insights_runner import main as run_insights
from .ai_analyzer_runner import main as run_ai_analyzer
from .roadmap_runner import main as run_roadmap
from .spec_runner import main as run_spec
__all__ = [
"run_spec",
+1 -1
View File
@@ -4,7 +4,7 @@ AI-Enhanced Project Analyzer Package
A modular system for running AI-powered analysis on codebases using Claude Agent SDK.
"""
from .models import AnalysisResult, AnalyzerType
from .runner import AIAnalyzerRunner
from .models import AnalyzerType, AnalysisResult
__all__ = ["AIAnalyzerRunner", "AnalyzerType", "AnalysisResult"]
@@ -3,7 +3,6 @@ Data models and type definitions for AI analyzer.
"""
from dataclasses import dataclass
from datetime import datetime
from enum import Enum
from typing import Any
@@ -7,7 +7,6 @@ from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING
from debug import debug
from ui import muted, print_status
from .models import RoadmapPhaseResult
@@ -16,7 +16,6 @@ from ui import Icons, box, icon, muted, print_section, print_status
from .competitor_analyzer import CompetitorAnalyzer
from .executor import AgentExecutor, ScriptExecutor
from .graph_integration import GraphHintsProvider
from .models import RoadmapPhaseResult
from .phases import DiscoveryPhase, FeaturesPhase, ProjectIndexPhase
+1 -1
View File
@@ -14,7 +14,7 @@ from debug import (
debug_success,
debug_warning,
)
from ui import muted, print_status
from ui import print_status
from .models import RoadmapPhaseResult
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from security.scan_secrets instead."""
from security.scan_secrets import *
from security.scan_secrets import * # noqa: F403
+1 -1
View File
@@ -1,2 +1,2 @@
"""Backward compatibility shim - import from security module instead."""
from security import *
from security import * # noqa: F403

Some files were not shown because too many files have changed in this diff Show More