- Strip all 31 stale seedgo bypasses, re-evaluate from zero (10 legitimate kept) - Create json_handler + wire 9 handler/module files (json_structure 0→100%) - Add test_devpulse.py (17 tests: CLI routing, module discovery, error resilience) - Add conftest fixtures: mock_logger, mock_json_handler - Fix devpulse.py: add print_help(), feedback.py: META block + introspection - README: fix stale content, update test count 130→236, add json/ handler - Global prompt: remove secrets path, collapse duplicates, add branch_json breadcrumb - Delete init pollution: aipass/status/ dir (15 files), 2 stale per-branch global prompts - Seedgo: add README content accuracy checks (test count + dead links, 26 tests) - Prax: fix _parse_agent_activity() reverse iteration (thinking entries hidden) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
161 lines
5.0 KiB
Python
161 lines
5.0 KiB
Python
# =================== AIPass ====================
|
|
# Name: devpulse.py
|
|
# Description: Entry point for devpulse branch — auto-discovers modules
|
|
# Version: 1.0.0
|
|
# Created: 2026-03-07
|
|
# Modified: 2026-05-15
|
|
# =============================================
|
|
|
|
"""
|
|
DEVPULSE Branch - Main Orchestrator
|
|
|
|
Auto-discovery architecture:
|
|
- Scans modules/ directory for .py files with handle_command()
|
|
- Routes commands to discovered modules automatically
|
|
- No manual imports or routing needed
|
|
"""
|
|
|
|
import sys
|
|
import importlib
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from aipass.prax import logger
|
|
from aipass.cli.apps.modules import err_console
|
|
|
|
console = err_console
|
|
|
|
# =============================================================================
|
|
# MODULE DISCOVERY
|
|
# =============================================================================
|
|
|
|
MODULES_DIR = Path(__file__).parent / "modules"
|
|
|
|
|
|
def discover_modules() -> list[Any]:
|
|
"""Auto-discover modules in modules/ directory."""
|
|
modules = []
|
|
|
|
if not MODULES_DIR.exists():
|
|
return modules
|
|
|
|
for file_path in MODULES_DIR.glob("*.py"):
|
|
if file_path.name.startswith("_"):
|
|
continue
|
|
|
|
# Try package import first, fall back to relative import
|
|
module_names = [
|
|
f"aipass.devpulse.apps.modules.{file_path.stem}",
|
|
f"apps.modules.{file_path.stem}",
|
|
]
|
|
|
|
loaded = False
|
|
for module_name in module_names:
|
|
try:
|
|
module = importlib.import_module(module_name)
|
|
if hasattr(module, "handle_command"):
|
|
modules.append(module)
|
|
loaded = True
|
|
break
|
|
except (ImportError, ModuleNotFoundError) as e:
|
|
logger.info(f"[DEVPULSE] Module {module_name} not found: {e}")
|
|
continue
|
|
except Exception as e:
|
|
logger.error(f"[DEVPULSE] Failed to load module {module_name}: {e}")
|
|
loaded = True
|
|
break
|
|
|
|
if not loaded:
|
|
logger.error(f"[DEVPULSE] Could not import module {file_path.stem}")
|
|
|
|
return modules
|
|
|
|
|
|
def print_introspection():
|
|
"""Print branch introspection — discovered modules and capabilities."""
|
|
modules = discover_modules()
|
|
console.print("[bold cyan]DEVPULSE[/bold cyan] — Orchestration Hub")
|
|
console.print(f" Modules discovered: {len(modules)}")
|
|
for module in modules:
|
|
name = module.__name__.split(".")[-1]
|
|
desc = (module.__doc__ or "").strip().split("\n")[0] if module.__doc__ else "No description"
|
|
console.print(f" {name:20} {desc}")
|
|
|
|
|
|
def print_help():
|
|
"""Print CLI help — usage instructions and available commands."""
|
|
modules = discover_modules()
|
|
console.print("[bold cyan]DEVPULSE[/bold cyan] — Usage")
|
|
console.print()
|
|
console.print(" drone @devpulse <command> [args...]")
|
|
console.print()
|
|
console.print("[bold]COMMANDS:[/bold]")
|
|
for module in modules:
|
|
name = module.__name__.split(".")[-1]
|
|
desc = (module.__doc__ or "").strip().split("\n")[0] if module.__doc__ else "No description"
|
|
console.print(f" {name:20} {desc}")
|
|
console.print()
|
|
console.print("[bold]FLAGS:[/bold]")
|
|
console.print(" --help, -h Show this help message")
|
|
console.print(" --version, -V Show version")
|
|
|
|
|
|
def route_command(command: str, args: list[str], modules: list[Any]) -> bool:
|
|
"""Route command to appropriate module."""
|
|
for module in modules:
|
|
try:
|
|
if module.handle_command(command, args):
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"[DEVPULSE] Module {module.__name__} error: {e}")
|
|
return False
|
|
|
|
|
|
# =============================================================================
|
|
# HANDLER SECURITY GUARD
|
|
# =============================================================================
|
|
|
|
|
|
def handle_command(command: str, args: list) -> bool:
|
|
"""Entry point for drone routing. Guards against cross-branch misuse."""
|
|
caller = Path.cwd().name
|
|
if caller != "devpulse" and not any(p.name == "devpulse" for p in Path.cwd().parents):
|
|
logger.warning(f"[DEVPULSE] Cross-branch call from {caller} — use ai_mail instead")
|
|
|
|
return _handle_command(command, args)
|
|
|
|
|
|
def _handle_command(command: str, args: list) -> bool:
|
|
"""Internal command handler."""
|
|
modules = discover_modules()
|
|
|
|
if command in ["--help", "-h", "help"]:
|
|
print_help()
|
|
return True
|
|
|
|
if command in ["--version", "-V"]:
|
|
console.print("devpulse 1.0.0")
|
|
return True
|
|
|
|
return route_command(command, args, modules)
|
|
|
|
|
|
# =============================================================================
|
|
# MAIN ENTRY POINT
|
|
# =============================================================================
|
|
|
|
|
|
def main():
|
|
"""Main entry point - routes commands or shows help."""
|
|
args = sys.argv[1:]
|
|
|
|
if len(args) == 0:
|
|
print_introspection()
|
|
return 0
|
|
|
|
return 0 if _handle_command(args[0], args[1:]) else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|