Files
AIPass/src/aipass/drone/apps/modules/resolver.py
T
AIOSAIandClaude Opus 4.6 babedd9c64 feat(system): seedgo v2 operational, full system audit, 14/15 branches at 99%
Three days of intensive work bringing seedgo to full operational status
and driving all branches through comprehensive standards compliance.

Seedgo v2.0.0:
- 22 checkers active (up from 20), standards pack fully operational
- New introspection standard researched from Dev-Pass, FPLAN-0017 open
- Bypass system for false positives (.seedgo config)
- Standards query and audit commands fully functional

System-wide audit (FPLAN-0016):
- All 14 auditable branches at 99%+ compliance
- CLI imports standardized across all branches (console from cli.apps.modules)
- handle_command(command, args) → bool contract added to all modules
- print_help() function naming fixed for checker pattern matching
- Handler extraction: large modules split, file I/O moved to handler layer
- New handlers created across ai_mail, backup, daemon, flow, skills, spawn, seedgo

Branch-specific highlights:
- ai_mail: email.py split 840→420 lines, 4 new handlers
- flow: dplan_flow.py 688→591 lines, 4 new handlers
- seedgo: massive restructure — standards moved to handlers/aipass_standards/,
  old standards/ tree removed, bypass system added, diagnostics module
- commons: database module added, CLI imports fixed
- skills: 5 handle_commands added, help function renamed
- trigger: error reporter handler, handle_command routing
- All branches: consistent architecture, clean drone routing

Culture doc (CLAUDE.md) added — documents AIPass philosophy, identity,
memory system, and collaboration principles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 01:26:42 -07:00

175 lines
5.4 KiB
Python

# =================== AIPass ====================
# Name: resolver.py
# Description: Branch resolution logic for symbolic @branch names
# Version: 1.0.0
# Created: 2026-03-09
# Modified: 2026-03-09
# =============================================
"""
Branch resolution logic.
Thin orchestrator for resolving symbolic @branch names to paths and metadata.
Delegates registry access to the handler layer.
"""
from typing import Any, Dict, List, Optional
from aipass.prax import logger
from aipass.drone.apps.handlers.exceptions import BranchNotFoundError
from aipass.drone.apps.handlers.registry_handler import (
load_registry,
get_all_branches,
get_branch_by_name,
)
def handle_command(command: str, args: List[str]) -> bool:
"""Route resolver commands to handler functions.
Args:
command: The command string (e.g. "resolve", "exists", "info", "list")
args: List of arguments for the command
Returns:
True if command succeeded, False otherwise
"""
if command == "resolve":
if not args:
logger.warning("resolver resolve requires a branch name")
return False
path = resolve_branch(args[0])
logger.info("%s -> %s", args[0], path)
return True
if command == "exists":
if not args:
logger.warning("resolver exists requires a branch name")
return False
logger.info("%s exists: %s", args[0], branch_exists(args[0]))
return True
if command == "info":
if not args:
logger.warning("resolver info requires a branch name")
return False
info = get_branch_info(args[0])
logger.info("Branch info: %s", info)
return True
if command == "list":
branches = list_branches()
for name in branches:
logger.info(" %s", name)
return True
logger.warning("resolver: unknown command '%s'", command)
return False
def print_help() -> None:
"""Print help for the resolver module."""
from aipass.cli.apps.modules import console
console.print("resolver — Branch resolution logic")
console.print()
console.print("Commands:")
console.print(" resolve <branch> Resolve branch name to path")
console.print(" exists <branch> Check if branch exists")
console.print(" info <branch> Get branch metadata")
console.print(" list List all branches")
def print_introspection():
"""Display module introspection info."""
try:
from aipass.cli.apps.modules.display import console
except ImportError:
from rich.console import Console
console = Console()
console.print()
console.print("resolver Module")
console.print("Branch resolution logic — resolves symbolic @branch names to paths and metadata.")
console.print()
console.print("Connected Handlers:")
console.print(" handlers/")
console.print(" - registry_handler.py (load_registry — load and parse AIPASS_REGISTRY.json)")
console.print(" - registry_handler.py (get_all_branches — list branches with optional filters)")
console.print(" - registry_handler.py (get_branch_by_name — look up a single branch)")
console.print(" - exceptions.py (BranchNotFoundError — raised when branch not in registry)")
console.print()
def normalize_branch_name(symbolic_name: str) -> str:
"""Normalize a symbolic branch name. Strips @ prefix if present."""
if symbolic_name.startswith("@"):
return symbolic_name[1:]
return symbolic_name
def normalize_branch_arg(target: str) -> str:
"""Normalize @branch argument: strip @ prefix, lowercase."""
return target.lstrip("@").lower()
def resolve_branch(symbolic_name: str) -> str:
"""Resolve a symbolic branch name to its absolute path.
Args:
symbolic_name: Branch name with or without @ prefix
Returns:
Absolute path to branch directory as string
Raises:
BranchNotFoundError: If branch not in registry
RegistryNotFoundError: If registry file missing
"""
registry = load_registry()
name = normalize_branch_name(symbolic_name).lower()
branch = registry.get("branches", {}).get(name)
if branch is None:
raise BranchNotFoundError(
f"Branch '{symbolic_name}' not found in registry"
)
return branch["path"]
def branch_exists(symbolic_name: str) -> bool:
"""Check if a branch exists in the registry."""
name = normalize_branch_name(symbolic_name).lower()
branch = get_branch_by_name(name)
return branch is not None
def get_branch_info(symbolic_name: str) -> Dict[str, Any]:
"""Get full metadata for a branch.
Raises:
BranchNotFoundError: If branch not in registry
"""
registry = load_registry()
name = normalize_branch_name(symbolic_name).lower()
branch = registry.get("branches", {}).get(name)
if branch is None:
raise BranchNotFoundError(
f"Branch '{symbolic_name}' not found in registry"
)
return branch
def list_branches(
branch_type: Optional[str] = None,
status: str = "active",
) -> List[str]:
"""List all registered branches, optionally filtered by type and status.
Returns:
List of branch names with @ prefix
"""
branches = get_all_branches(branch_type=branch_type, status=status)
return [f"@{branch['name']}" for branch in branches]