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>
This commit is contained in:
AIOSAI
2026-03-10 01:26:42 -07:00
co-authored by Claude Opus 4.6
parent 09e759a8a4
commit babedd9c64
589 changed files with 17140 additions and 24881 deletions
+116 -2
View File
@@ -3,13 +3,127 @@
**Purpose:** Multi-mode backup with Google Drive integration
**Module:** `aipass.backup`
**Created:** 2026-03-07
**Citizen Class:** birthright
**Citizen Class:** builder
**Last Updated:** 2026-03-08
---
## Overview
Birthright citizen — minimal presence with identity and memory.
Builder citizen — full 3-layer architecture with identity and memory.
Provides automated file protection through snapshot backups, versioned backups,
and Google Drive synchronization. The entry point routes commands to four
specialized modules: `backup_core`, `google_drive_sync`, `integrations`, and
`reauth_drive`.
---
## Architecture
```
backup/
├── __init__.py
├── README.md
├── apps/
│ ├── backup.py # Entry point (CLI) — drone @backup
│ ├── modules/
│ │ ├── backup_core.py # Core backup operations (snapshot, versioned)
│ │ ├── google_drive_sync.py # Google Drive sync orchestration
│ │ ├── integrations.py # Cross-module integration commands
│ │ └── reauth_drive.py # Google Drive re-authentication
│ ├── handlers/
│ │ ├── config/
│ │ │ └── config_handler.py # Configuration management
│ │ ├── diff/
│ │ │ ├── diff_generator.py # Diff generation between backups
│ │ │ ├── version_manager.py # Version tracking
│ │ │ └── vscode_integration.py # VS Code diff viewer integration
│ │ ├── json/
│ │ │ ├── backup_info_handler.py # Backup info JSON read/write
│ │ │ ├── backup_metadata_builder.py # Metadata construction
│ │ │ ├── changelog_handler.py # Changelog JSON management
│ │ │ ├── drive_sync_json.py # Drive sync state tracking
│ │ │ ├── json_handler.py # Generic JSON utilities
│ │ │ └── statistics_handler.py # Backup statistics
│ │ ├── models/
│ │ │ └── backup_models.py # Data models for backup objects
│ │ ├── operations/
│ │ │ ├── drive_sync_client.py # Google Drive API client
│ │ │ ├── drive_sync_ops.py # Drive sync implementation
│ │ │ ├── file_cleanup.py # Old backup cleanup
│ │ │ ├── file_operations.py # File copy/move operations
│ │ │ ├── file_scanner.py # File discovery and filtering
│ │ │ ├── integration_ops.py # Integration operation logic
│ │ │ └── path_builder.py # Backup path construction
│ │ ├── reporting/
│ │ │ └── report_formatter.py # Backup report formatting
│ │ └── utils/
│ │ ├── backup_timestamps.py # Timestamp utilities
│ │ ├── reauth_handler.py # Re-auth implementation
│ │ └── system_utils.py # System-level utilities
│ ├── extensions/ # Extension point (placeholder)
│ ├── json_templates/ # JSON template files
│ └── plugins/ # Plugin point (placeholder)
├── backup_json/ # JSON tracking data
├── artifacts/ # Backup artifacts
├── docs/ # Documentation
├── tests/ # Test suite
└── tools/ # Branch verification utilities
```
---
## Commands / Usage
```bash
drone @backup # Introspection — list discovered modules
drone @backup --help # Show full help
drone @backup --version # Show version
drone @backup --all # Full backup cycle: snapshot -> versioned -> drive-sync
drone @backup snapshot # Create a system snapshot backup
drone @backup versioned # Create a versioned backup
drone @backup drive-test # Test Google Drive connectivity
drone @backup drive-sync # Sync backups to Google Drive
drone @backup drive-sync --test # Run a small test sync to verify integration
drone @backup drive-stats # Show Drive file tracker statistics
drone @backup drive-clear-tracker # Clear Drive file tracker cache
```
**Options:**
| Flag | Description |
|------|-------------|
| `--verbose`, `-v` | Extra diagnostic output |
| `--dry-run` | Preview what would happen, execute nothing |
| `--note NOTE` | Add a backup note/description |
| `--project NAME` | Project name for Drive sync (default: AIPass) |
| `--force` | Force sync all files (ignore change tracker) |
| `--limit N` | Limit drive-sync to first N files |
---
## Integration Points
### Depends On
- `rich` — Console output and formatting
- Python stdlib (`sys`, `argparse`, `logging`, `pathlib`)
### Provides To
- All modules — automated file protection, snapshot and versioned backups
- Google Drive — cloud backup synchronization
- Other branches — backup artifacts via `backup_json/` and `artifacts/`
---
## Modules
| Module | Purpose |
|--------|---------|
| `backup_core` | Core backup operations — snapshot and versioned backup creation |
| `google_drive_sync` | Google Drive synchronization — upload, track, and manage cloud backups |
| `integrations` | Cross-module integration commands and coordination |
| `reauth_drive` | Google Drive re-authentication when credentials expire |
---
+8 -23
View File
@@ -1,21 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: backup.py - Backup System Entry Point
# Date: 2025-11-22
# Version: 1.3.0
# Category: core/backup
#
# CHANGELOG (Max 5 entries):
# - v1.3.0 (2026-03-06): Adapted for AIPass public repo
# * Removed shebang, sys.path manipulation, prax/cli imports
# * Replaced get_modules() with explicit relative imports
# * Uses standard logging and rich console
# - v1.2.0 (2026-02-22): Seed CLI flags standard: --version, backup all command
# - v1.1.0 (2025-11-22): Fixed META header - correct filename, category, and standards
# - v1.0.0 (2025-11-08): Initial version - modular architecture
#
# CODE STANDARDS:
# - Handlers implement logic, modules orchestrate
# =================== AIPass ====================
# Name: backup.py
# Description: Entry point CLI for drone @backup
# Version: 1.0.0
# Created: 2026-03-08
# Modified: 2026-03-08
# =============================================
"""
@@ -28,14 +16,11 @@ Main handles routing, modules implement functionality.
# Standard library imports
import sys
import argparse
import logging
from pathlib import Path
from typing import Any, List
from rich.console import Console
logger = logging.getLogger(__name__)
console = Console()
from aipass.cli.apps.modules import console
from aipass.prax import logger
# Explicit module imports (replaces dynamic discover_modules)
from aipass.backup.apps.modules import backup_core, google_drive_sync, integrations, reauth_drive
@@ -1,29 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: config_handler.py - Backup system configuration and patterns
# Date: 2025-11-23
# =================== AIPass ====================
# Name: config_handler.py
# Description: Backup system configuration and patterns
# Version: 2.0.2
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v2.0.2 (2026-03-06): Adapted for AIPass public repo
# * Removed shebang and sys.path manipulation
# * Cleared CLI_TRACKING_PATTERNS (hardcoded internal paths removed)
# - v2.0.1 (2025-11-23): Added ignore patterns for log/data JSON files
# * Enabled *_data.json pattern to ignore backup_core_data.json
# * Enabled *_log.json pattern to ignore backup_core_log.json, drone_log.json
# * Enabled snapshot_backup.json pattern
# * Prevents frequent-change files from being backed up every run
# - v2.0.0 (2025-11-16): Seed standard extraction from archive
# * All configuration constants and patterns
# * Helper functions for pattern matching and filtering
# * Pure configuration - no complex logic
# - v1.0.0 (2025-10-14): Initial extraction from backup.py
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-23
# Modified: 2026-03-09
# =============================================
"""
@@ -1,22 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: diff_generator.py - Unified diff generation with binary detection
# Date: 2025-11-16
# =================== AIPass ====================
# Name: diff_generator.py
# Description: Unified diff generation with binary detection
# Version: 2.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v2.0.0 (2025-11-16): Extracted from backup_diff.py
# * Diff generation functionality
# * Binary file detection
# * Unified diff content generation
# * Updated imports to new handler locations
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-16
# Modified: 2026-03-09
# =============================================
"""
@@ -1,22 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: version_manager.py - Version discovery and management
# Date: 2025-11-16
# =================== AIPass ====================
# Name: version_manager.py
# Description: Version discovery and management
# Version: 2.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v2.0.0 (2025-11-16): Extracted from backup_diff.py
# * Version file discovery functionality
# * Versioned file listing
# * Support for file-organized structure
# * Updated imports to new handler locations
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-16
# Modified: 2026-03-09
# =============================================
"""
@@ -30,11 +17,11 @@ Supports version listing and filtering.
# IMPORTS
# =============================================
import logging
from aipass.prax import logger
from pathlib import Path
from typing import Dict, List, Optional
logger = logging.getLogger(__name__)
# logger imported from aipass.prax
# Import from handlers
from aipass.backup.apps.handlers.utils.system_utils import safe_print
@@ -1,22 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: vscode_integration.py - VS Code diff viewer integration
# Date: 2025-11-16
# =================== AIPass ====================
# Name: vscode_integration.py
# Description: VS Code diff viewer integration
# Version: 2.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v2.0.0 (2025-11-16): Extracted from backup_diff.py
# * VS Code diff viewer integration
# * File comparison logic
# * Baseline vs current comparison
# * Updated imports to new handler locations
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-16
# Modified: 2026-03-09
# =============================================
"""
@@ -33,10 +20,10 @@ Supports baseline vs current and version-to-version comparisons.
import sys
import os
import subprocess
import logging
from aipass.prax import logger
from pathlib import Path
logger = logging.getLogger(__name__)
# logger imported from aipass.prax
# Import from handlers
from aipass.backup.apps.handlers.utils.system_utils import safe_print
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: backup_info_handler.py - Backup state and statistics
# Date: 2025-11-16
# =================== AIPass ====================
# Name: backup_info_handler.py
# Description: Backup state and statistics
# Version: 1.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-16): Initial extraction from backup_core.py
# * load_backup_info() - Load mode-specific state
# * save_backup_info() - Persist backup state
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-16
# Modified: 2026-03-09
# =============================================
"""
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: backup_metadata_builder.py - Backup metadata construction
# Date: 2025-11-18
# =================== AIPass ====================
# Name: backup_metadata_builder.py
# Description: Backup metadata construction
# Version: 1.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
# * Extracted backup_info creation logic
# * Handles mode-specific metadata formatting
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-18
# Modified: 2026-03-09
# =============================================
"""
@@ -1,21 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: changelog_handler.py - Backup changelog management
# Date: 2025-11-16
# =================== AIPass ====================
# Name: changelog_handler.py
# Description: Backup changelog management
# Version: 1.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-16): Initial extraction from backup_core.py
# * load_changelog() - Load persistent changelog
# * save_changelog_entry() - Add new entry
# * display_previous_comments() - Show history
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-16
# Modified: 2026-03-09
# =============================================
"""
@@ -35,17 +23,12 @@ Functions:
# =============================================
import json
import logging
from aipass.prax import logger
import datetime
from pathlib import Path
from typing import Dict
logger = logging.getLogger(__name__)
from rich.console import Console
# Initialize console for output
console = Console()
# logger imported from aipass.prax
# =============================================
# CHANGELOG OPERATIONS
@@ -65,8 +48,7 @@ def load_changelog(changelog_file: Path) -> Dict:
with open(changelog_file, 'r', encoding='utf-8', errors='replace') as f:
return json.load(f)
except Exception as e:
console.print(f"[red]Error loading changelog: {e}[/red]")
logger.warning(f"Error loading changelog: {e}")
logger.error(f"Error loading changelog: {e}")
return {"entries": []}
@@ -98,7 +80,6 @@ def save_changelog_entry(changelog_file: Path, note: str, mode: str,
logger.info(f"[changelog_handler] Saved changelog entry: {note[:50]}")
return True
except Exception as e:
console.print(f"[red]Error saving changelog entry: {e}[/red]")
logger.error(f"[changelog_handler] Error saving changelog: {e}")
return False
@@ -115,14 +96,10 @@ def display_previous_comments(changelog_file: Path, mode_name: str):
entries = changelog.get("entries", [])
if not entries:
console.print(f"[yellow]No previous {mode_name} backup comments found.[/yellow]")
logger.warning(f"No previous {mode_name} backup comments found.")
return
from rich.panel import Panel
console.print()
console.print(Panel(f"PREVIOUS {mode_name.upper()} BACKUP COMMENTS",
style="bold cyan",
border_style="cyan"))
logger.info(f"PREVIOUS {mode_name.upper()} BACKUP COMMENTS")
# Show last 10 entries (most recent first)
recent_entries = entries[-10:]
@@ -133,21 +110,20 @@ def display_previous_comments(changelog_file: Path, mode_name: str):
mode_info = entry.get('mode', 'unknown')
# Handle encoding issues in notes
note = str(entry['note']).encode('ascii', errors='replace').decode('ascii')
console.print(f"[bright_blue]{i:2d}.[/bright_blue] [{formatted_time}] [green][{mode_info}][/green] {note}")
logger.info(f"{i:2d}. [{formatted_time}] [{mode_info}] {note}")
except Exception as e:
console.print(f"[bright_blue]{i:2d}.[/bright_blue] [red][ERROR] Failed to display entry: {e}[/red]")
logger.error(f"{i:2d}. [ERROR] Failed to display entry: {e}")
if len(entries) > 10:
console.print(f"\n[dim]... and {len(entries) - 10} older entries[/dim]")
console.print()
logger.info(f"... and {len(entries) - 10} older entries")
except FileNotFoundError:
console.print(f"[yellow]No previous {mode_name} backup comments found.[/yellow]")
logger.warning(f"No previous {mode_name} backup comments found.")
except PermissionError as e:
console.print(f"[yellow]Warning: Cannot read backup history - permission denied: {e}[/yellow]")
console.print("[yellow]Continuing with backup...[/yellow]")
logger.warning(f"Cannot read backup history - permission denied: {e}")
logger.warning("Continuing with backup...")
except Exception as e:
console.print(f"[yellow]Warning: Error displaying comments: {e}[/yellow]")
console.print("[yellow]Continuing with backup...[/yellow]")
logger.warning(f"Error displaying comments: {e}")
logger.warning("Continuing with backup...")
# =============================================
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: drive_sync_json.py - Google Drive Sync JSON Operations Handler
# Date: 2026-02-20
# =================== AIPass ====================
# Name: drive_sync_json.py
# Description: Google Drive Sync JSON Operations Handler
# Version: 1.0.0
# Category: backup_system/handlers/json
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2026-02-20): Extracted from google_drive_sync module
# * Moved JSON I/O functions to handler layer
# * Follows seed 3-layer architecture standards
#
# CODE STANDARDS:
# - Handlers must be independent and transportable
# - No prax imports (handler tier)
# - Pure file I/O operations
# Created: 2026-02-20
# Modified: 2026-03-09
# =============================================
"""
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: json_handler.py - JSON Auto-Creating Handler
# Date: 2025-11-22
# =================== AIPass ====================
# Name: json_handler.py
# Description: JSON Auto-Creating Handler
# Version: 3.1.0
# Category: backup_system/handlers/json
#
# CHANGELOG (Max 5 entries):
# - v3.1.0 (2026-01-31): Refactored to comply with error handling standards
# - v3.0.0 (2025-11-22): Updated to match Cortex template with all features
# - v2.0.0 (2025-11-16): Migrated to seed 3-layer architecture
# - v1.0.0 (2025-10-14): Initial implementation with auto-detection
#
# CODE STANDARDS:
# - Pure functions with proper error raising
# - No Prax imports (handler tier 3)
# Created: 2025-11-22
# Modified: 2026-03-09
# =============================================
import json
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: statistics_handler.py - Backup statistics tracking
# Date: 2025-11-18
# =================== AIPass ====================
# Name: statistics_handler.py
# Description: Backup statistics tracking
# Version: 1.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
# * Extracted update_data_file() statistics tracking
# * Handles runtime state and statistics updates
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-18
# Modified: 2026-03-09
# =============================================
"""
@@ -27,11 +16,11 @@ Manages backup operation statistics and runtime state persistence.
# IMPORTS
# =============================================
import logging
from aipass.prax import logger
import datetime
from pathlib import Path
logger = logging.getLogger(__name__)
# logger imported from aipass.prax
# Import handlers
from aipass.backup.apps.handlers.json.json_handler import load_json, save_json
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: backup_models.py - Backup system data models and structures
# Date: 2025-11-16
# =================== AIPass ====================
# Name: backup_models.py
# Description: Backup system data models and structures
# Version: 2.0.1
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v2.0.1 (2026-03-06): Adapted for AIPass public repo
# * Removed shebang and sys.path manipulation
# - v2.0.0 (2025-11-16): Migrated to seed 3-layer architecture
# - v1.0.0 (2025-10-14): Initial extraction from backup.py
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-16
# Modified: 2026-03-09
# =============================================
"""
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: drive_sync_client.py - Google Drive Sync Client Handler
# Date: 2026-02-20
# =================== AIPass ====================
# Name: drive_sync_client.py
# Description: Google Drive Sync Client Handler
# Version: 1.0.0
# Category: backup_system/handlers/operations
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2026-02-20): Extracted GoogleDriveSync class from module
# * Moved implementation to handler layer per seed 3-layer architecture
# * Module now delegates to this handler for all Drive operations
#
# CODE STANDARDS:
# - Handlers must be independent and transportable
# - No prax imports in class methods (handler tier)
# - Google API interactions isolated here
# Created: 2026-02-20
# Modified: 2026-03-09
# =============================================
"""
@@ -1,21 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: drive_sync_ops.py - Google Drive Sync Business Operations Handler
# Date: 2026-02-20
# =================== AIPass ====================
# Name: drive_sync_ops.py
# Description: Google Drive Sync Business Operations Handler
# Version: 1.0.0
# Category: backup_system/handlers/operations
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2026-02-20): Extracted from google_drive_sync module
# * Moved get_status, clear_file_tracker, show_file_tracker_stats,
# test_drive_sync to handler layer
# * Follows seed 3-layer architecture standards
#
# CODE STANDARDS:
# - Handlers must be independent and transportable
# - No prax imports (handler tier)
# - Delegates to json handler for file operations
# Created: 2026-02-20
# Modified: 2026-03-09
# =============================================
"""
@@ -1,29 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: file_cleanup.py - File deletion operations
# Date: 2025-11-23
# =================== AIPass ====================
# Name: file_cleanup.py
# Description: File deletion operations
# Version: 1.0.2
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.2 (2025-11-23): Added dry-run support for cleanup operations
# * Added dry_run parameter to cleanup_deleted_files()
# * Shows "Would delete" messages instead of actually deleting in dry-run
# * All three passes (directories, files, empty dirs) respect dry-run mode
# - v1.0.1 (2025-11-23): CRITICAL BUG FIX - respect exceptions in empty dir cleanup
# * Third pass now checks should_ignore() before removing empty directories
# * Prevents deletion of empty template directories
# * Added source_dir mapping to check exceptions properly
# * Only removes empty dirs if source doesn't exist OR should be ignored
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
# * Extracted file deletion logic for dynamic mode
# * Handles cleanup of deleted source files
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-23
# Modified: 2026-03-09
# =============================================
"""
@@ -36,11 +16,11 @@ Handles cleanup of backup files when source files are deleted.
# IMPORTS
# =============================================
import logging
from aipass.prax import logger
from pathlib import Path
from typing import Callable
logger = logging.getLogger(__name__)
# logger imported from aipass.prax
from aipass.backup.apps.handlers.utils.system_utils import temporarily_writable, safe_print
from aipass.backup.apps.handlers.models.backup_models import BackupResult
@@ -1,40 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: file_operations.py - Core backup file operations
# Date: 2025-11-23
# =================== AIPass ====================
# Name: file_operations.py
# Description: Core backup file operations
# Version: 2.0.4
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v2.0.4 (2025-11-23): Fix baseline snapshot messages for VS Code clickability
# * Changed baseline snapshot message from {baseline_name} to {baseline_path}
# * Users can now Ctrl+click on baseline paths to jump directly to files
# * Shows full path (e.g., /home/aipass/backups/project/README-baseline-2025-11-23.md)
# - v2.0.3 (2025-11-23): CRITICAL performance fix for versioned backup
# * Skip copying unchanged files (only copy if mtime differs)
# * Fixes 5s -> <1s regression (was copying all 5000+ files every time)
# * Added file_changed flag to track copy necessity
# * Only copy if is_new_file or file_changed
# - v2.0.2 (2025-11-23): Added per-file output to snapshot mode
# * Snapshot backup now shows each file as it's copied
# * Displays "Copied (new)" or "Copied (updated)" for each file
# * Matches the verbosity of versioned backup mode
# - v2.0.1 (2025-11-23): Fixed automatic VS Code diff opening
# * Removed automatic VS Code integration from copy_versioned_file()
# * Diffs are now created silently without opening in editor
# * VS Code integration still available via separate command
# - v2.0.0 (2025-11-16): Extraction from backup_operations.py
# * Extracted core file operations (lines 49-271)
# * copy_file_with_structure for snapshot mode
# * copy_versioned_file with baseline snapshots and diff generation
# * Extensive Linux permission handling with temporarily_writable()
# * Retry logic for filesystem errors
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-23
# Modified: 2026-03-09
# =============================================
"""
@@ -52,12 +21,12 @@ Functions:
# IMPORTS
# =============================================
import logging
from aipass.prax import logger
import shutil
import datetime
from pathlib import Path
logger = logging.getLogger(__name__)
# logger imported from aipass.prax
# Import from handlers modules
from aipass.backup.apps.handlers.utils.system_utils import temporarily_writable, safe_print
@@ -1,21 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: file_scanner.py - File system scanning operations
# Date: 2025-11-18
# =================== AIPass ====================
# Name: file_scanner.py
# Description: File system scanning operations
# Version: 1.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
# * Extracted file scanning logic (os.walk loops)
# * Handles file discovery with ignore patterns
# * Returns file list with metadata
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-18
# Modified: 2026-03-09
# =============================================
"""
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: integration_ops.py - Backup Integration Operations Handler
# Date: 2026-02-20
# =================== AIPass ====================
# Name: integration_ops.py
# Description: Backup Integration Operations Handler
# Version: 1.0.0
# Category: backup_system/handlers/operations
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2026-02-20): Extracted from integrations module
# * Moved sync_to_drive() and set_backup_readonly() to handler layer
# * Follows seed 3-layer architecture standards
#
# CODE STANDARDS:
# - Handlers must be independent and transportable
# - No prax imports (handler tier)
# - No cross-handler imports except within same domain
# Created: 2026-02-20
# Modified: 2026-03-09
# =============================================
"""
@@ -1,21 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: path_builder.py - Backup path construction
# Date: 2025-11-18
# =================== AIPass ====================
# Name: path_builder.py
# Description: Backup path construction
# Version: 1.0.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
# * Extracted path construction logic for versioned mode
# * Handles long filename hashing
# * Mode-specific path building
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-18
# Modified: 2026-03-09
# =============================================
"""
@@ -0,0 +1,87 @@
# =================== AIPass ====================
# Name: sync_test_ops.py
# Description: File operations for Drive sync test
# Version: 1.0.0
# Created: 2026-03-08
# Modified: 2026-03-09
# =============================================
"""
Sync Test File Operations Handler
Handles file system operations for the Drive sync test workflow:
- Creating test directory and test files
- Cleaning up test directory after test completes
"""
import shutil
from pathlib import Path
from datetime import datetime
from aipass.prax import logger
def create_sync_test_files(backup_root: Path) -> dict:
"""Create test directory and test files for Drive sync verification.
Args:
backup_root: Root backup directory (e.g., src/aipass/backup/)
Returns:
dict with keys:
- success (bool): Whether files were created
- test_dir (Path): Path to test directory
- file_count (int): Number of test files created
- error (str|None): Error message if failed
"""
try:
test_dir = backup_root / "backups" / "_sync_test"
test_dir.mkdir(parents=True, exist_ok=True)
test_files = {
"test_file_1.txt": "Hello from AIPass backup test",
"test_file_2.json": '{"test": true, "timestamp": "' + datetime.now().isoformat() + '"}',
"subdir/nested_file.txt": "Nested directory test",
"subdir/deep/deeper_file.md": "# Deep nested test\nVerifying folder structure",
}
for name, content in test_files.items():
path = test_dir / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content)
logger.info(f"[sync_test_ops] Created {len(test_files)} test files in {test_dir}")
return {
"success": True,
"test_dir": test_dir,
"file_count": len(test_files),
"error": None,
}
except Exception as e:
logger.error(f"[sync_test_ops] Failed to create test files: {e}")
return {
"success": False,
"test_dir": None,
"file_count": 0,
"error": str(e),
}
def cleanup_sync_test_dir(test_dir: Path) -> dict:
"""Remove the sync test directory and all contents.
Args:
test_dir: Path to test directory to remove
Returns:
dict with keys:
- success (bool): Whether cleanup succeeded
- error (str|None): Error message if failed
"""
try:
shutil.rmtree(test_dir, ignore_errors=True)
logger.info(f"[sync_test_ops] Cleaned up test directory: {test_dir}")
return {"success": True, "error": None}
except Exception as e:
logger.error(f"[sync_test_ops] Failed to cleanup test directory: {e}")
return {"success": False, "error": str(e)}
@@ -1,25 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: report_formatter.py - Backup result reporting
# Date: 2025-11-23
# =================== AIPass ====================
# Name: report_formatter.py
# Description: Backup result reporting
# Version: 1.1.0
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v1.1.0 (2025-11-23): Added dry-run statistics display
# * Added dry_run parameter to display_backup_results()
# * Shows "Would copy", "Would skip", "Would delete" in dry-run mode
# * Provides clear differentiation between dry-run and actual execution
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
# * Extracted statistics display formatting
# * Handles error/warning display
# * Formats skipped items reports
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-23
# Modified: 2026-03-09
# =============================================
"""
@@ -35,16 +19,15 @@ Formats and displays backup operation results, statistics, errors, and warnings.
import datetime
from pathlib import Path
from rich.console import Console
from aipass.prax import logger
from aipass.backup.apps.handlers.models.backup_models import BackupResult
console = Console()
# logger imported from aipass.prax
def _header(text):
console.print(f"\n[bold cyan]{'='*70}[/bold cyan]")
console.print(f"[bold cyan] {text}[/bold cyan]")
console.print(f"[bold cyan]{'='*70}[/bold cyan]")
from aipass.backup.apps.handlers.models.backup_models import BackupResult
logger.info(f"{'='*70}")
logger.info(f" {text}")
logger.info(f"{'='*70}")
# =============================================
# REPORT FORMATTING OPERATIONS
@@ -66,88 +49,77 @@ def display_backup_results(result: BackupResult, mode_config: dict, backup_path:
# Determine overall result status
if result.critical_errors:
status_style = "[bold red]"
status_icon = "!"
status_text = "FAILED"
elif result.errors > 0:
status_style = "[bold red]"
status_icon = "X"
status_text = "COMPLETED WITH ERRORS"
elif result.warnings:
status_style = "[bold yellow]"
status_icon = "!"
status_text = "COMPLETED WITH WARNINGS"
else:
status_style = "[bold green]"
status_icon = "OK"
status_text = "COMPLETED SUCCESSFULLY"
# Use _header for main status
console.print()
_header(f"{status_icon} {mode_config['name'].upper()} {status_text}")
console.print()
# Statistics Section
console.print("[bold cyan]STATISTICS:[/bold cyan]")
console.print(f" Files checked: [dim]{result.files_checked}[/dim]")
logger.info("STATISTICS:")
logger.info(f" Files checked: {result.files_checked}")
if dry_run:
# Dry-run mode: show "would be" language
console.print(f" Would copy: [bold]{result.files_copied}[/bold] files")
console.print(f" Would skip: [dim]{result.files_skipped}[/dim] files (unchanged)")
logger.info(f" Would copy: {result.files_copied} files")
logger.info(f" Would skip: {result.files_skipped} files (unchanged)")
if result.files_deleted > 0:
console.print(f" Would delete: [yellow]{result.files_deleted}[/yellow] files")
logger.warning(f" Would delete: {result.files_deleted} files")
else:
# Normal mode: show actual actions
console.print(f" Files copied: [bold]{result.files_copied}[/bold]")
logger.info(f" Files copied: {result.files_copied}")
if result.mode == 'versioned' and result.files_added > 0:
console.print(f" Files added: [green]{result.files_added}[/green] (new)")
console.print(f" Files skipped: [dim]{result.files_skipped}[/dim]")
logger.info(f" Files added: {result.files_added} (new)")
logger.info(f" Files skipped: {result.files_skipped}")
if result.mode == 'versioned' and result.files_deleted == 0:
console.print(f" Files deleted: [dim]{result.files_deleted}[/dim] [dim](cleanup disabled - keeps history)[/dim]")
logger.info(f" Files deleted: {result.files_deleted} (cleanup disabled - keeps history)")
else:
console.print(f" Files deleted: [red]{result.files_deleted}[/red]")
logger.info(f" Files deleted: {result.files_deleted}")
console.print(f" Errors: {status_style}{result.errors}[/]")
console.print(f" Warnings: [yellow]{len(result.warnings)}[/yellow]")
console.print(f" Duration: [blue]{duration.total_seconds():.2f}s[/blue]")
console.print(f" Location: [dim]{backup_path}[/dim]")
logger.info(f" Errors: {result.errors}")
logger.info(f" Warnings: {len(result.warnings)}")
logger.info(f" Duration: {duration.total_seconds():.2f}s")
logger.info(f" Location: {backup_path}")
# Display detailed error information
if result.critical_errors:
console.print()
console.print(f"[bold red]CRITICAL ERRORS ({len(result.critical_errors)}):[/bold red]")
console.print("-" * 40)
logger.error(f"CRITICAL ERRORS ({len(result.critical_errors)}):")
logger.info("-" * 40)
for i, error in enumerate(result.critical_errors, 1):
console.print(f" {i}. [red]{error}[/red]")
console.print()
console.print("[bold]RECOVERY SUGGESTIONS:[/bold]")
console.print(" - Check disk space and permissions")
console.print(" - Ensure backup destination is accessible")
console.print(" - Try running as administrator if permission issues")
console.print(" - Check if antivirus is blocking file operations")
logger.error(f" {i}. {error}")
logger.info("RECOVERY SUGGESTIONS:")
logger.info(" - Check disk space and permissions")
logger.info(" - Ensure backup destination is accessible")
logger.info(" - Try running as administrator if permission issues")
logger.info(" - Check if antivirus is blocking file operations")
elif result.error_details:
console.print()
console.print(f"[bold red]ERRORS ({len(result.error_details)}):[/bold red]")
console.print("-" * 40)
logger.error(f"ERRORS ({len(result.error_details)}):")
logger.info("-" * 40)
for i, error in enumerate(result.error_details[:10], 1):
console.print(f" {i}. [red]{error}[/red]")
logger.error(f" {i}. {error}")
if len(result.error_details) > 10:
console.print(f" [dim]... and {len(result.error_details) - 10} more errors[/dim]")
console.print()
console.print("[bold]SUGGESTIONS:[/bold]")
console.print(" - Some files may be in use - try closing applications")
console.print(" - Check file permissions on failed files")
logger.info(f" ... and {len(result.error_details) - 10} more errors")
logger.info("SUGGESTIONS:")
logger.info(" - Some files may be in use - try closing applications")
logger.info(" - Check file permissions on failed files")
if result.warnings:
console.print()
console.print(f"[bold yellow]WARNINGS ({len(result.warnings)}):[/bold yellow]")
console.print("-" * 40)
logger.warning(f"WARNINGS ({len(result.warnings)}):")
logger.info("-" * 40)
for i, warning in enumerate(result.warnings[:5], 1):
console.print(f" {i}. [yellow]{warning}[/yellow]")
logger.warning(f" {i}. {warning}")
if len(result.warnings) > 5:
console.print(f" [dim]... and {len(result.warnings) - 5} more warnings[/dim]")
logger.info(f" ... and {len(result.warnings) - 5} more warnings")
# Display project-specific skipped items
tracked_items = filter_tracked_items_func(skipped_items)
@@ -155,26 +127,24 @@ def display_backup_results(result: BackupResult, mode_config: dict, backup_path:
total_all_skipped = len(skipped_items["directories"]) + len(skipped_items["files"])
if total_tracked > 0:
console.print()
console.print(f"[bold cyan]NOTABLE SKIPPED ITEMS ({total_tracked}):[/bold cyan]")
console.print(f"[dim]Total ignored: {total_all_skipped}[/dim]")
console.print("-" * 50)
logger.info(f"NOTABLE SKIPPED ITEMS ({total_tracked}):")
logger.info(f"Total ignored: {total_all_skipped}")
logger.info("-" * 50)
if tracked_items["directories"]:
console.print(f"[bold]Directories ({len(tracked_items['directories'])}):[/bold]")
logger.info(f"Directories ({len(tracked_items['directories'])}):")
for i, dir_path in enumerate(sorted(tracked_items["directories"]), 1):
console.print(f" {i}. [dim]{dir_path}/[/dim]")
logger.info(f" {i}. {dir_path}/")
if tracked_items["files"]:
console.print(f"[bold]Files ({len(tracked_items['files'])}):[/bold]")
logger.info(f"Files ({len(tracked_items['files'])}):")
for i, file_path in enumerate(sorted(tracked_items["files"]), 1):
console.print(f" {i}. [dim]{file_path}[/dim]")
logger.info(f" {i}. {file_path}")
else:
console.print()
if total_all_skipped > 0:
console.print(f"[dim]No project-specific items skipped ({total_all_skipped} common items filtered)[/dim]")
logger.info(f"No project-specific items skipped ({total_all_skipped} common items filtered)")
else:
console.print("[dim]No items were skipped.[/dim]")
logger.info("No items were skipped.")
# =============================================
@@ -1,17 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: backup_timestamps.py - Tracks last-run timestamps for all backup modes
# Date: 2026-02-22
# =================== AIPass ====================
# Name: backup_timestamps.py
# Description: Tracks last-run timestamps for all backup modes
# Version: 1.0.0
# Category: handlers/utils
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2026-02-22): Initial version - show/update backup timestamps
#
# CODE STANDARDS:
# - Handler utility: no console output, returns data for module layer
# - JSON file at backups/backup_timestamps.json
# Created: 2026-02-22
# Modified: 2026-03-09
# =============================================
"""
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: reauth_handler.py - Google Drive Re-Authentication Handler
# Date: 2026-02-20
# =================== AIPass ====================
# Name: reauth_handler.py
# Description: Google Drive Re-Authentication Handler
# Version: 1.0.0
# Category: backup_system/handlers/utils
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2026-02-20): Extracted from reauth_drive.py module
# * Moved reauth() implementation to handler layer
# * Follows seed 3-layer architecture standards
#
# CODE STANDARDS:
# - Handlers must be independent and transportable
# - No prax imports (handler tier)
# - No cross-handler imports except within same domain
# Created: 2026-02-20
# Modified: 2026-03-09
# =============================================
"""
@@ -1,31 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: system_utils.py - Platform-aware file and console utilities
# Date: 2025-11-23
# =================== AIPass ====================
# Name: system_utils.py
# Description: Platform-aware file and console utilities
# Version: 2.1.1
# Category: handlers
#
# CHANGELOG (Max 5 entries):
# - v2.1.1 (2025-11-23): CRITICAL FIX - Switch to plain print() for clickability
# * Replaced console.print() with plain print() in safe_print()
# * Rich console truncates at 80 chars breaking long paths
# * Plain print() preserves full paths for terminal Ctrl+click
# - v2.1.0 (2025-11-23): Attempted fix with no_wrap parameter (insufficient)
# * Added no_wrap=True to console.print() but Rich still truncates
# * Identified Rich console 80-char limit as root cause
# - v2.0.0 (2025-11-16): Extracted to seed standards
# * Applied seed standards formatting and meta header
# * Preserved all logic from backup_utils v1.0.0
# - v1.1.0 (2025-11-22): Updated to seed Rich formatting standards
# - v1.0.0 (2025-11-18): Extracted from backup_core.py
# * Extracted system utilities
# * Cross-platform file operations
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Handlers must be independent and transportable
# - No cross-handler imports except within same domain
# Created: 2025-11-23
# Modified: 2026-03-09
# =============================================
"""
@@ -48,11 +26,11 @@ Key Functions:
import sys
import os
import stat
import logging
from aipass.prax import logger
from pathlib import Path
from contextlib import contextmanager
logger = logging.getLogger(__name__)
# logger imported from aipass.prax
# =============================================
# CONSTANTS
+7 -26
View File
@@ -1,25 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: backup_core.py - Main backup system orchestration module
# Date: 2025-11-23
# =================== AIPass ====================
# Name: backup_core.py
# Description: Main backup system orchestration module
# Version: 2.1.0
# Category: backup_system
#
# CHANGELOG (Max 5 entries):
# - v2.1.0 (2026-03-06): Adapted for AIPass public repo
# * Removed shebang, sys.path manipulation, prax/cli imports
# * Uses standard logging and rich console
# * Relative handler imports
# * JSON_DIR uses path relative to __file__
# - v2.0.4 (2025-11-23): CRITICAL FIX - Versioned dry-run accuracy
# - v2.0.3 (2025-11-23): Enhanced dry-run with accurate statistics
# - v2.0.2 (2025-11-23): CRITICAL FIX - Dry-run now shows proposed changes
# - v2.0.1 (2025-11-23): CRITICAL BUG FIX - Dry-run statistics counter
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Orchestrate workflows, delegate to handlers
# - Import handlers, never implement business logic
# Created: 2025-11-23
# Modified: 2026-03-09
# =============================================
"""
@@ -48,14 +32,11 @@ Architecture Pattern:
# Infrastructure
import sys
import datetime
import logging
from pathlib import Path
from typing import Dict
from rich.console import Console
logger = logging.getLogger(__name__)
console = Console()
from aipass.cli.apps.modules import console
from aipass.prax import logger
def _header(text):
@@ -1,24 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: google_drive_sync.py - Google Drive Integration for AIPass Backup System
# Date: 2025-10-30
# =================== AIPass ====================
# Name: google_drive_sync.py
# Description: Google Drive Integration for AIPass Backup System
# Version: 2.6.0
# Category: backup_system/modules
#
# CHANGELOG (Max 5 entries - remove oldest when adding new):
# - v2.6.0 (2026-03-06): Adapted for AIPass public repo
# * Removed shebang, sys.path manipulation, prax/cli imports
# * Uses standard logging and rich console
# * Relative handler imports, Google API deps wrapped in try/except
# - v2.5.0 (2026-02-22): Rich progress bar for drive-sync uploads, per-file progress callback
# - v2.4.0 (2026-02-21): Two-phase sync (prepare+upload), CLI visibility, dedup fix, --test mode
# - v2.3.2 (2026-02-10): Fixed deepcopy RuntimeError in _save_data during concurrent uploads
# - v2.2.0 (2026-02-10): Fixed SSL concurrency bug - per-thread credentials, retry with backoff, folder cache lock
#
# CODE STANDARDS:
# - Module orchestrates, handlers implement
# - CLI display (console.print) belongs here, not in handlers
# - Google API calls delegated to drive_sync_client handler
# Created: 2025-10-30
# Modified: 2026-03-09
# =============================================
"""
@@ -33,15 +18,10 @@ drive_sync_client handler for API operations.
# =============================================
import sys
import logging
from pathlib import Path
from datetime import datetime
from rich.console import Console
from rich.progress import Progress, BarColumn, TextColumn, TimeElapsedColumn, TimeRemainingColumn
logger = logging.getLogger(__name__)
console = Console()
from aipass.cli.apps.modules import console
from aipass.prax import logger
_BACKUP_ROOT = Path(__file__).resolve().parents[2] # src/aipass/backup/
@@ -103,6 +83,11 @@ except ImportError:
get_file_tracker_stats = None # type: ignore
_test_drive_connection = None # type: ignore
from aipass.backup.apps.handlers.operations.sync_test_ops import (
create_sync_test_files,
cleanup_sync_test_dir,
)
def _show_file_tracker_stats() -> bool:
"""Display file tracker statistics."""
@@ -163,34 +148,23 @@ def _test_drive_sync() -> bool:
def _run_sync_test() -> bool:
"""Run a small test sync to verify Drive integration."""
import shutil
console.print("[bold cyan]Drive Sync Test[/bold cyan]")
console.print()
# Create test files
test_dir = _BACKUP_ROOT / "backups" / "_sync_test"
test_dir.mkdir(parents=True, exist_ok=True)
# Create test files via handler
setup = create_sync_test_files(_BACKUP_ROOT)
if not setup["success"]:
console.print(f"[red]Failed to create test files: {setup['error']}[/red]")
return False
test_files = {
"test_file_1.txt": "Hello from AIPass backup test",
"test_file_2.json": '{"test": true, "timestamp": "' + datetime.now().isoformat() + '"}',
"subdir/nested_file.txt": "Nested directory test",
"subdir/deep/deeper_file.md": "# Deep nested test\nVerifying folder structure",
}
for name, content in test_files.items():
path = test_dir / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content)
console.print(f" Created {len(test_files)} test files in {test_dir}")
test_dir = setup["test_dir"]
console.print(f" Created {setup['file_count']} test files in {test_dir}")
# Run sync
sync = GoogleDriveSync()
if not sync.authenticate():
console.print("[red]Auth failed[/red]")
shutil.rmtree(test_dir, ignore_errors=True)
cleanup_sync_test_dir(test_dir)
return False
console.print(f"\nScanning...")
@@ -205,7 +179,7 @@ def _run_sync_test() -> bool:
if not folder_id:
error_msg = sync.last_error or "Unknown error"
console.print(f"[red]FAILED: {error_msg}[/red]")
shutil.rmtree(test_dir, ignore_errors=True)
cleanup_sync_test_dir(test_dir)
return False
console.print(f" Drive folder ready: AIPass_Test")
@@ -225,7 +199,7 @@ def _run_sync_test() -> bool:
if result.get("error"):
console.print(f"\n[red]FAILED: {result['error']}[/red]")
shutil.rmtree(test_dir, ignore_errors=True)
cleanup_sync_test_dir(test_dir)
return False
console.print()
@@ -243,8 +217,8 @@ def _run_sync_test() -> bool:
else:
console.print(f"[red]Dedup check failed: {len(files_to_upload2)} files flagged for re-upload[/red]")
# Cleanup local test dir
shutil.rmtree(test_dir, ignore_errors=True)
# Cleanup local test dir via handler
cleanup_sync_test_dir(test_dir)
console.print(f"\nCleaned up local test files")
console.print(f"[dim]Test Drive folder 'AIPass_Test' left on Drive for inspection[/dim]")
@@ -423,6 +397,28 @@ def handle_command(args) -> bool:
# CLI/EXECUTION
# =============================================
def print_introspection():
"""Display module introspection info."""
console.print()
console.print("google_drive_sync Module")
console.print("Orchestrates Google Drive backup sync with two-phase upload pipeline")
console.print()
console.print("Connected Handlers:")
console.print(" handlers/operations/")
console.print(" - drive_sync_client.py (GoogleDriveSync — Drive API client and upload engine)")
console.print(" - drive_sync_ops.py (clear_file_tracker — reset sync tracker cache)")
console.print(" - drive_sync_ops.py (get_file_tracker_stats — tracker statistics)")
console.print(" - drive_sync_ops.py (test_drive_connection — connectivity verification)")
console.print(" - sync_test_ops.py (create_sync_test_files — generate test fixtures)")
console.print(" - sync_test_ops.py (cleanup_sync_test_dir — remove test fixtures)")
console.print(" handlers/json/")
console.print(" - drive_sync_json.py (load_config — read module config JSON)")
console.print(" - drive_sync_json.py (load_data — read module data JSON)")
console.print(" handlers/utils/")
console.print(" - backup_timestamps.py (get_timestamps, update_timestamp, format_age — backup timing)")
console.print()
if __name__ == "__main__":
import argparse
@@ -550,4 +546,4 @@ EXAMPLES:
sys.exit(0)
else:
console.print("Google Drive sync test failed")
sys.exit(1)
sys.exit(1)
+22 -25
View File
@@ -1,24 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: integrations.py - External integrations and backup protection
# Date: 2025-11-29
# =================== AIPass ====================
# Name: integrations.py
# Description: External integrations and backup protection
# Version: 2.1.0
# Category: backup_system
#
# CHANGELOG (Max 5 entries):
# - v2.1.0 (2026-03-06): Adapted for AIPass public repo
# * Removed shebang, sys.path manipulation, prax/cli imports
# * Uses standard logging and rich console
# * Relative handler imports, GoogleDriveSync via sibling module
# - v2.0.1 (2025-11-29): UX FIX - Import error and missing help output
# - v2.0.0 (2025-11-16): Created seed-compliant layout module
# - v1.1.0 (2025-10-30): Original backup_integrations features
# - v1.0.0 (2025-10-14): Initial extraction
#
# CODE STANDARDS:
# - Follow seed 3-layer architecture
# - Orchestrate workflows, delegate to handlers
# - Import handlers, never implement business logic
# Created: 2025-11-29
# Modified: 2026-03-09
# =============================================
"""
@@ -45,13 +30,10 @@ Architecture Pattern:
import sys
import os
import stat
import logging
from pathlib import Path
from rich.console import Console
logger = logging.getLogger(__name__)
console = Console()
from aipass.cli.apps.modules import console
from aipass.prax import logger
def _header(text):
@@ -278,6 +260,21 @@ def print_help():
safe_print("="*70)
safe_print("")
def print_introspection():
"""Display module introspection info."""
console.print()
console.print("integrations Module")
console.print("External integrations and backup protection (Drive sync, read-only)")
console.print()
console.print("Connected Handlers:")
console.print(" handlers/utils/")
console.print(" - system_utils.py (safe_print — terminal-safe output wrapper)")
console.print(" handlers/operations/")
console.print(" - integration_ops.py (sync_to_drive — Drive upload orchestration)")
console.print(" - integration_ops.py (set_backup_readonly — read-only permission setter)")
console.print()
if __name__ == "__main__":
"""Display help when module is run directly."""
import sys as _sys
+19 -21
View File
@@ -1,20 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: reauth_drive.py - Google Drive Re-Authentication Module
# Date: 2026-02-21
# =================== AIPass ====================
# Name: reauth_drive.py
# Description: Google Drive Re-Authentication Module
# Version: 1.2.0
# Category: backup_system
#
# CHANGELOG (Max 5 entries):
# - v1.2.0 (2026-03-06): Adapted for AIPass public repo
# * Removed shebang, sys.path manipulation, prax/cli imports
# * Uses standard logging and rich console
# * Relative handler imports, Google API deps wrapped in try/except
# - v1.1.0 (2026-02-21): Fixed handle_command() signature (command, args) → (args)
# - v1.0.0 (2026-02-20): Initial version - standalone reauth utility
#
# CODE STANDARDS:
# - Handlers implement logic, modules orchestrate
# Created: 2026-02-21
# Modified: 2026-03-09
# =============================================
"""
@@ -26,13 +15,10 @@ Delegates implementation to reauth_handler.
"""
import sys
import logging
from pathlib import Path
from rich.console import Console
logger = logging.getLogger(__name__)
console = Console()
from aipass.cli.apps.modules import console
from aipass.prax import logger
# Handler imports
from aipass.backup.apps.handlers.utils.reauth_handler import reauth as _run_reauth
@@ -139,6 +125,18 @@ def _execute_reauth() -> bool:
return success
def print_introspection():
"""Display module introspection info."""
console.print()
console.print("reauth_drive Module")
console.print("Google Drive re-authentication via console OAuth flow")
console.print()
console.print("Connected Handlers:")
console.print(" handlers/utils/")
console.print(" - reauth_handler.py (reauth — OAuth credential refresh and re-auth)")
console.print()
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] in ['--help', '-h', 'help']:
print_help()