Files
AIPass/src/aipass/spawn/apps/modules/delete.py
T
8c3ad2657c feat(spawn): seedgo compliance cleanup — 93% to 98% (#68)
* fix(ai_mail): resolve relative mailbox_path bug + archive dead handlers

Fix get_user_by_email() and get_all_users() returning relative mailbox_path
values from registry instead of absolute paths (causing doubled paths in reply).
Added path resolution matching get_current_user() pattern.

Archive 7 unused handler files to apps/.archive/ (gitignored):
- pending_work.py — planned feature, never wired
- lock_utils.py — superseded by inbox_lock.py
- data_ops.py — consumer (error_monitor) was archived
- config_generator.py, users/load.py, registry/validate.py — scaffolded, never used
- trigger/error_handler.py — superseded by trigger branch's event system

Added test_user_paths.py (13 tests) covering absolute path resolution.

Co-Authored-By: @ai_mail <ai_mail@aipass>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(spawn): seedgo compliance cleanup — 93% to 98%

Archive legacy files (dev.local.md, ai_mail.local/, .seed/). Update META
Modified dates on 22 files. Update README architecture tree and freshness.
Fix 15 Pyright unused warnings. Add introspection no-args gates to 6
modules. Wire json_handler + log_operation to 15 operational files. Add
seedgo bypass for 5 pure data files and log_structure. Remove deprecated
dev.local.md from builder template.

Co-Authored-By: @spawn <spawn@aipass>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: @ai_mail <ai_mail@aipass>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: @spawn <spawn@aipass>
2026-03-17 16:44:50 -07:00

139 lines
4.4 KiB
Python

# =================== AIPass ====================
# Name: delete.py
# Description: Branch deletion — thin CLI layer for archive and deregister
# Version: 1.1.0
# Created: 2026-03-07
# Modified: 2026-03-14
# =============================================
"""Delete orchestrator for branch lifecycle management.
Thin CLI module that parses arguments and delegates to the delete handler.
All implementation logic lives in apps/handlers/delete_ops.py.
"""
from aipass.prax import logger
# CLI service: from cli.apps.modules import console (via aipass namespace)
from aipass.cli.apps.modules import console, error, warning
from aipass.spawn.apps.handlers.delete_ops import delete_branch
from aipass.spawn.apps.handlers.json import json_handler
def print_introspection():
"""Display module introspection info."""
console.print()
console.print("delete Module")
console.print("Branch deletion — archive directory and deregister from AIPASS_REGISTRY")
console.print()
console.print("Connected Handlers:")
console.print(" handlers/")
console.print(" - delete_ops.py (delete_branch — resolve path, archive, remove from registry)")
console.print()
# =============================================================================
# DRONE ROUTING
# =============================================================================
def handle_command(command: str, args: list) -> bool:
"""Handle commands routed by the entry point.
Args:
command: The command string (e.g. "delete")
args: List of arguments for the command
Returns:
True if command was handled, False otherwise.
"""
if command != "delete":
return False
# No args → introspection
if not args:
print_introspection()
return True
return handle_delete(args) == 0
# =============================================================================
# PUBLIC API
# =============================================================================
def handle_delete(args: list[str]) -> int:
"""Parse args and execute delete.
Args patterns:
["@branch"] -> delete with confirmation prompt
["--yes", "@branch"] -> skip confirmation
["--dry-run", "@branch"] -> preview only
Returns exit code (0=success, 1=failure).
"""
if not args:
warning("Usage: drone @spawn delete <@branch> [--yes] [--dry-run]")
console.print()
console.print(" [green]@branch[/green] Branch to archive and deregister")
console.print(" [green]--yes[/green] Skip confirmation prompt")
console.print(" [green]--dry-run[/green] Preview what would happen without changes")
return 1
dry_run = "--dry-run" in args
skip_confirm = "--yes" in args
# Filter out flags to find the target
targets = [a for a in args if not a.startswith("--")]
if not targets:
error("specify a branch name (e.g. @api)")
return 1
branch_name = targets[0].lstrip("@").lower()
try:
result = delete_branch(
branch_name,
confirm=not skip_confirm,
dry_run=dry_run,
)
except Exception as exc:
logger.error(f"[delete] Unexpected error deleting {branch_name}: {exc}")
error(f"Error deleting {branch_name}: {exc}")
return 1
if result.get("success"):
json_handler.log_operation("branch_deleted", data={"branch": branch_name})
_print_summary(result, dry_run)
return 0 if result.get("success") else 1
# =============================================================================
# OUTPUT HELPERS
# =============================================================================
def _print_summary(result: dict, dry_run: bool) -> None:
"""Print a rich summary of the delete operation."""
branch = result.get("branch", "unknown")
success = result.get("success", False)
mode = "[dim](dry-run)[/dim] " if dry_run else ""
console.print()
if success:
console.print(f"[green]Delete {mode}{branch}[/green]")
else:
error(f"Delete FAILED {mode}{branch}")
archive_path = result.get("archive_path", "")
if archive_path:
console.print(f" Archive: {archive_path}")
console.print(f" Registry updated: {result.get('registry_updated', False)}")
err_msg = result.get("error", "")
if err_msg:
error(err_msg)
console.print()