#!/usr/bin/env python3 """ AirPlan V2 — 统一 CLI 入口。 V1 的 8 个独立插件合并为一个命令,通过 --mode 参数路由到对应子模式。 用法: airplan --mode arc --project [--todo ] airplan --mode eng --project [--sub enter|status|plan|dispatch|monitor|merge|run|intervene] airplan --mode do --project --task-id airplan --mode dbg --project [--task-id ] airplan --mode sdb --project [--backend cppcheck|clang-tidy|clippy|go-vet|tsc] [--target ] airplan --mode ctx --project [--sub now|status|pause|init] airplan --mode dep --project --task-id --host [--binary ] airplan --mode tst --project --task-id [--framework ] airplan --mode sec --project --task-id [--scan-path ] airplan --mode rvr --project --task-id """ from __future__ import annotations import argparse import sys from pathlib import Path def _add_lib_path() -> None: root = Path(__file__).resolve().parents[1] lib_path = root / "lib" if str(lib_path) not in sys.path: sys.path.insert(0, str(lib_path)) _add_lib_path() from air_runtime.project_bootstrap import ensure_project_bootstrap def _run_arc(args) -> None: from air_runtime.modes.arc_mode import main as arc_main arc_main(args) def _run_eng(args) -> None: from air_runtime.modes.eng_mode import main as eng_main eng_main(args) def _run_do(args) -> None: from air_runtime.modes.do_mode import main as do_main do_main(args) def _run_dbg(args) -> None: from air_runtime.modes.dbg_mode import main as dbg_main dbg_main(args) def _run_xdb(args) -> None: from air_runtime.modes.xdb_mode import main as xdb_main xdb_main(args) def _run_sdb(args) -> None: from air_runtime.modes.sdb_mode import main as sdb_main sdb_main(args) def _run_ndb(args) -> None: from air_runtime.modes.ndb_mode import main as ndb_main ndb_main(args) def _run_ctx(args) -> None: from air_runtime.modes.ctx_mode import main as ctx_main ctx_main(args) def _run_dep(args) -> None: from air_runtime.modes.dep_mode import main as dep_main dep_main(args) def _run_tst(args) -> None: from air_runtime.modes.tst_mode import main as tst_main tst_main(args) def _run_sec(args) -> None: from air_runtime.modes.sec_mode import main as sec_main sec_main(args) def _run_rvr(args) -> None: from air_runtime.modes.rvr_mode import main as rvr_main rvr_main(args) def _run_eng_orchestrator(args) -> None: from air_runtime.modes.eng_orchestrator import main as eng_orch_main eng_orch_main(args) MODE_ROUTER = { "arc": _run_arc, "eng": _run_eng, "do": _run_do, "dbg": _run_dbg, "xdb": _run_xdb, "sdb": _run_sdb, "ndb": _run_ndb, "ctx": _run_ctx, "dep": _run_dep, "tst": _run_tst, "sec": _run_sec, "rvr": _run_rvr, "eng_orchestrator": _run_eng_orchestrator, } MODE_HELP = { "arc": "架构规划器 — 分析依赖、写集冲突、产出执行计划", "eng": "调度引擎 — 波次派发、监控、合并、修复编排", "do": "任务执行器 — 单任务切片执行与结果生成", "dbg": "调试器 — 7步调试工作流、根因分析、修复回滚", "xdb": "GUI验证器 — 截图取证、GUI操作验证", "sdb": "静态分析器 — 多语言静态分析、diff模式", "ndb": "网络调试器 — 抓包分析、TLS解密", "ctx": "上下文管理器 — 压缩、Token估算、锁检测", "dep": "部署器 — SSH远程构建、部署、systemd管理", "tst": "测试运行器 — 统一测试执行与结果报告", "sec": "安全扫描器 — 敏感数据检测与脱敏", "rvr": "需求审查器 — 交付物与需求一致性验证", } def parse_args(argv: list[str] | None = None) -> argparse.Namespace: parser = argparse.ArgumentParser( description="AirPlan V2 — 统一制品驱动开发调度器", formatter_class=argparse.RawDescriptionHelpFormatter, epilog="\n".join(f" {k:6s} {v}" for k, v in MODE_HELP.items()), ) parser.add_argument("--mode", choices=list(MODE_ROUTER.keys()), required=True, help="子模式选择") parser.add_argument("--project", default=".", help="项目根目录 (默认: .)") parser.add_argument("--sub", default="", help="子模式内的二级操作(如 eng 的 enter|status|plan 等)") parser.add_argument("--todo", default="", help="todo.md 路径(arc/eng 使用)") parser.add_argument("--task-id", default="", help="任务 ID(do/dbg/xdb/sdb/ndb/dep/tst/sec/rvr 使用)") parser.add_argument("--result", default="", help="Worker result.json 路径(eng merge 使用)") parser.add_argument("--dispatch-group", default="", help="派发组名(eng dispatch 使用)") parser.add_argument("--host", default="", help="远程主机(dep 使用)") parser.add_argument("--binary", default="", help="本地二进制路径(dep 使用)") parser.add_argument("--framework", default="", help="测试框架(tst 使用)") parser.add_argument("--scan-path", default="", help="扫描路径(sec 使用)") parser.add_argument("--sec-mode", default="blocking", choices=["advisory", "blocking"], help="安全扫描模式(sec 使用): advisory(只报告)/ blocking(阻止合并)") parser.add_argument("--backend", default="", help="静态分析后端(sdb 使用): cppcheck|clang-tidy|clippy|go-vet|tsc") parser.add_argument("--target", default="", help="分析目标路径(sdb 使用)") parser.add_argument("--prefer", default="auto", help="截图后端偏好(xdb 使用): kms|xvfb|fallback|auto") parser.add_argument("--output", default="", help="截图输出文件名(xdb 使用,默认 screenshot.png)") parser.add_argument("--task-text", default="", help="任务描述文本(do 使用,用于 UI 任务检测和路由)") return parser.parse_args(argv) def main(argv: list[str] | None = None) -> None: args = parse_args(argv) project_root = Path(args.project).expanduser().resolve() ensure_project_bootstrap(project_root) handler = MODE_ROUTER.get(args.mode) if handler is None: print(f"Unknown mode: {args.mode}", file=sys.stderr) print(f"Available modes: {', '.join(MODE_ROUTER.keys())}", file=sys.stderr) sys.exit(1) handler(args) if __name__ == "__main__": main()