feat(system): feat(drone): add merge, smart-sync, and fix plugins to devpulse_ops (#149)

Co-authored-by: @devpulse <devpulse@aipass>
This commit is contained in:
AIPass
2026-03-30 16:18:07 -07:00
committed by GitHub
co-authored by @devpulse
parent 4b6b3cf665
commit c9b7feaf0c
7 changed files with 1203 additions and 3 deletions
+152 -2
View File
@@ -28,7 +28,7 @@ DRONE_MODULE = {
"description": "Git workflow — PR, status, sync, lock management",
}
_COMMANDS = ("pr", "status", "sync", "lock", "unlock", "system-pr")
_COMMANDS = ("pr", "status", "sync", "lock", "unlock", "system-pr", "merge", "smart-sync", "fix")
def _detect_branch_dir() -> tuple[str, Path] | None:
@@ -83,6 +83,12 @@ def handle_command(command: str | None = None, args: list[str] | None = None) ->
if command == "system-pr":
return _handle_system_pr(args)
if command == "merge":
return _handle_merge(args)
if command == "smart-sync":
return _handle_smart_sync(args)
if command == "fix":
return _handle_fix(args)
if command == "pr":
return _handle_pr(args)
if command == "status":
@@ -149,6 +155,129 @@ def _handle_system_pr(args: list[str]) -> dict:
}
def _handle_merge(args: list[str]) -> dict:
"""Handle the merge subcommand (devpulse-only)."""
if not args:
return {
"stdout": "",
"stderr": "Usage: drone @git merge <PR#>",
"exit_code": 1,
}
pr_number = args[0]
try:
from aipass.drone.apps.plugins.devpulse_ops.auth import verify_caller
from aipass.drone.apps.plugins.devpulse_ops.merge_plugin import merge_pr
except ImportError as exc:
logger.error("Failed to import devpulse_ops merge plugin: %s", exc)
return {
"stdout": "",
"stderr": f"devpulse_ops plugin not available: {exc}",
"exit_code": 1,
}
try:
caller = verify_caller()
except PermissionError as exc:
logger.error("merge authorization failed: %s", exc)
return {
"stdout": "",
"stderr": str(exc),
"exit_code": 1,
}
result = merge_pr(pr_number, caller)
if result["success"]:
return {
"stdout": result["message"],
"stderr": "",
"exit_code": 0,
}
return {
"stdout": "",
"stderr": result["message"],
"exit_code": 1,
}
def _handle_smart_sync(args: list[str]) -> dict:
"""Handle the smart-sync subcommand (devpulse-only)."""
try:
from aipass.drone.apps.plugins.devpulse_ops.auth import verify_caller
from aipass.drone.apps.plugins.devpulse_ops.sync_plugin import smart_sync
except ImportError as exc:
logger.error("Failed to import devpulse_ops sync plugin: %s", exc)
return {
"stdout": "",
"stderr": f"devpulse_ops plugin not available: {exc}",
"exit_code": 1,
}
try:
caller = verify_caller()
except PermissionError as exc:
logger.error("smart-sync authorization failed: %s", exc)
return {
"stdout": "",
"stderr": str(exc),
"exit_code": 1,
}
result = smart_sync(caller)
if result["success"]:
return {
"stdout": result["message"],
"stderr": "",
"exit_code": 0,
}
return {
"stdout": "",
"stderr": result["message"],
"exit_code": 1,
}
def _handle_fix(args: list[str]) -> dict:
"""Handle the fix subcommand (devpulse-only)."""
try:
from aipass.drone.apps.plugins.devpulse_ops.auth import verify_caller
from aipass.drone.apps.plugins.devpulse_ops.fix_plugin import fix_git_state
except ImportError as exc:
logger.error("Failed to import devpulse_ops fix plugin: %s", exc)
return {
"stdout": "",
"stderr": f"devpulse_ops plugin not available: {exc}",
"exit_code": 1,
}
try:
caller = verify_caller()
except PermissionError as exc:
logger.error("fix authorization failed: %s", exc)
return {
"stdout": "",
"stderr": str(exc),
"exit_code": 1,
}
result = fix_git_state(caller)
if result["success"]:
return {
"stdout": result["message"],
"stderr": "",
"exit_code": 0,
}
return {
"stdout": "",
"stderr": result["message"],
"exit_code": 1,
}
def _handle_pr(args: list[str]) -> dict:
"""Handle the PR subcommand."""
if not args:
@@ -296,6 +425,21 @@ def get_help(command: str | None = None) -> str:
" Stages all tracked changes, creates a disposable feature branch,\n"
" and opens a PR. Requires devpulse passport authorization.\n"
)
if command == "merge":
return (
"git merge <PR#> — Squash-merge a PR and sync local main (devpulse only)\n"
" Runs gh pr merge --squash --delete-branch, then git pull --rebase.\n"
)
if command == "smart-sync":
return (
"git smart-sync — Fetch origin and rebase if behind (devpulse only)\n"
" Detects divergence and rebases safely; aborts on conflict.\n"
)
if command == "fix":
return (
"git fix — Detect and fix common broken git states (devpulse only)\n"
" Fixes stuck rebases, detached HEAD, diverged branches, dirty index.\n"
)
return (
"git — Git workflow: PR, status, sync, lock management\n"
@@ -303,6 +447,9 @@ def get_help(command: str | None = None) -> str:
"Commands:\n"
" pr <description> Create a PR with scoped changes\n"
" system-pr <desc> Create a system-wide PR (devpulse only)\n"
" merge <PR#> Squash-merge a PR (devpulse only)\n"
" smart-sync Fetch + rebase if behind (devpulse only)\n"
" fix Fix broken git states (devpulse only)\n"
" status Show git status for your branch\n"
" sync Checkout main and pull\n"
" lock Check lock status\n"
@@ -325,8 +472,11 @@ def get_introspective() -> str:
" plugins/devpulse_ops/\n"
" - auth.py (verify_caller — passport-based authorization)\n"
" - pr_plugin.py (create_system_pr — system-wide PR workflow)\n"
" - merge_plugin.py (merge_pr — squash-merge PR + sync)\n"
" - sync_plugin.py (smart_sync — fetch + rebase if behind)\n"
" - fix_plugin.py (fix_git_state — detect/fix broken states)\n"
"\n"
"Commands: pr, system-pr, status, sync, lock, unlock\n"
"Commands: pr, system-pr, merge, smart-sync, fix, status, sync, lock, unlock\n"
)