✨ feat(drone): add internal module routing system for drone commands

- introduce drone module registry with metadata and command routing
- add seedgo as a registered internal drone module with adapter
- update drone CLI to route commands to modules or branches by @target
- enhance `drone systems` to list registered modules with descriptions
- provide module help integration alongside branch help

✨ feat(seedgo): create drone adapter for seedgo module commands
- implement handle_command forwarding to seedgo CLI subprocess
- provide get_help function with command-specific help text
- support commands: check, audit, list, init with options and examples

✨ feat(seedgo): add __main__.py to support `python -m seedgo` execution

✨ feat(seedgo plugin): add drone-compliance plugin to verify drone adapter compliance
- checks existence of drone_adapter.py and required interface elements
- validates presence of DRONE_MODULE dict, handle_command(), and get_help()
- reports compliance results with pass/fail and score with detailed checks
- skips non-target packages and handles syntax errors gracefully

✅ test(drone modules): add comprehensive tests for drone module registry and routing
- test listing, info retrieval, command routing, and help retrieval
- test CLI integration for `drone systems` and `drone @seedgo` commands
- verify module priority over branch routing and error handling

✅ test(seedgo drone compliance): add tests for drone-compliance plugin
- test passing cases with proper adapter and interface
- test failures for missing adapter, metadata, or functions
- test warnings for missing get_help function
- test skipping non-target packages and file-not-found cases
- test handling of syntax errors in adapter files
This commit is contained in:
AIOSAI
2026-03-02 22:44:41 -08:00
parent ea39879faf
commit 2435a70c79
8 changed files with 933 additions and 14 deletions
+76 -14
View File
@@ -7,9 +7,10 @@ Usage:
drone Show available commands
drone --help Show help
drone --version Show version
drone systems List registered branches
drone systems List registered branches and modules
drone @branch command [args] Route command to branch
drone @branch --help Show help for branch
drone @module command [args] Route command to internal module
drone @branch --help Show help for branch or module
Zero external dependencies — stdlib only (sys).
"""
@@ -26,22 +27,30 @@ from aipass.drone import (
list_branches,
route_command,
)
from aipass.drone.modules import (
is_module,
list_modules,
get_module_info,
route_module_command,
get_module_help,
)
_HELP_TEXT = """\
drone — AIPass branch command router
drone — AIPass command router
Usage:
drone Show this help
drone --help Show this help
drone --version Show version
drone systems List registered branches
drone @branch command [args] Route command to branch
drone @branch --help Show help for branch
drone systems List registered branches and modules
drone @target command [args] Route command to branch or module
drone @target --help Show help for branch or module
Examples:
drone systems
drone @seedgo audit src/
drone @seedgo check src/myfile.py
drone @flow status
drone @flow run --verbose
drone @flow --help
"""
@@ -82,23 +91,49 @@ def main() -> None:
def _cmd_systems() -> None:
"""Handle `drone systems` — list registered branches."""
"""Handle `drone systems` — list registered branches and modules."""
branches = list_branches()
if not branches:
print("No branches registered.")
modules = list_modules()
if not branches and not modules:
print("No branches or modules registered.")
sys.exit(0)
print(f"Registered branches ({len(branches)}):")
for name in sorted(branches):
print(f" {name}")
if modules:
print(f"Modules ({len(modules)}):")
for name in modules:
info = get_module_info(name)
if info:
print(f" @{name} {info.description}")
else:
print(f" @{name} (not available)")
if branches:
print()
if branches:
print(f"Branches ({len(branches)}):")
for name in sorted(branches):
print(f" {name}")
sys.exit(0)
def _cmd_branch(args: list[str]) -> None:
"""Handle `drone @branch command [args]` or `drone @branch --help`."""
"""Handle `drone @target command [args]` or `drone @target --help`.
Checks internal modules first (e.g. @seedgo), then falls back
to branch registry for external branches.
"""
target = args[0]
rest = args[1:]
module_name = target.lstrip("@")
# Check if this is a registered internal module
if is_module(module_name):
_cmd_module(module_name, rest)
return
# Fall through to branch routing
# drone @branch --help
if not rest or rest == ["--help"]:
try:
@@ -133,3 +168,30 @@ def _cmd_branch(args: list[str]) -> None:
if result.stderr:
print(result.stderr, end="", file=sys.stderr)
sys.exit(result.exit_code)
def _cmd_module(name: str, args: list[str]) -> None:
"""Handle routing to an internal module (e.g. @seedgo)."""
# drone @module --help (or no args)
if not args or args == ["--help"]:
help_text = get_module_help(name)
if help_text:
print(help_text, end="")
else:
print(f"No help available for @{name}.")
sys.exit(0)
command = args[0]
cmd_args = args[1:] if len(args) > 1 else None
try:
result = route_module_command(name, command, cmd_args)
except (ImportError, AttributeError) as exc:
print(f"drone: module @{name} is registered but not available: {exc}", file=sys.stderr)
sys.exit(1)
if result.get("stdout"):
print(result["stdout"], end="")
if result.get("stderr"):
print(result["stderr"], end="", file=sys.stderr)
sys.exit(result.get("exit_code", 0))