Linting and test fixes
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from core.agent instead."""
|
||||
from core.agent import *
|
||||
from core.agent import * # noqa: F403
|
||||
|
||||
@@ -8,7 +8,6 @@ Handles session memory storage using dual-layer approach:
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from debug import (
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from analysis.analyzer instead."""
|
||||
from analysis.analyzer import *
|
||||
from analysis.analyzer import * # noqa: F403
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from analysis.analyzers instead."""
|
||||
from analysis.analyzers import *
|
||||
from analysis.analyzers import * # noqa: F403
|
||||
|
||||
@@ -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__ = [
|
||||
|
||||
@@ -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:
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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
|
||||
|
||||
+53
-1640
File diff suppressed because it is too large
Load Diff
@@ -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',
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from spec.critique instead."""
|
||||
from spec.critique import *
|
||||
from spec.critique import * # noqa: F403
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from core.debug instead."""
|
||||
from core.debug import *
|
||||
from core.debug import * # noqa: F403
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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,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,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,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from integrations.linear.updater instead."""
|
||||
from integrations.linear.updater import *
|
||||
from integrations.linear.updater import * # noqa: F403
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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,
|
||||
):
|
||||
"""
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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,
|
||||
):
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from .types import ChangeType, SemanticChange, TaskSnapshot
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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,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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
Utility functions for implementation planner.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from implementation_plan import Verification, VerificationType
|
||||
|
||||
|
||||
@@ -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,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from core.progress instead."""
|
||||
from core.progress import *
|
||||
from core.progress import * # noqa: F403
|
||||
|
||||
@@ -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,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,2 +1,2 @@
|
||||
"""Backward compatibility shim - import from prompts_pkg.prompts instead."""
|
||||
from prompts_pkg.prompts import *
|
||||
from prompts_pkg.prompts import * # noqa: F403
|
||||
|
||||
@@ -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
@@ -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,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,
|
||||
)
|
||||
|
||||
@@ -87,4 +87,4 @@ __all__ = [
|
||||
# Aliases for tests
|
||||
"_extract_section",
|
||||
"_truncate_text",
|
||||
]
|
||||
]
|
||||
|
||||
@@ -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__ = [
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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,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,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
Reference in New Issue
Block a user