Files
AirPlan-V2/commands/eng.md
AirPlan 6130478c96 feat: AirPlan V2 — 全专家插件强制路由 + 事件系统规范化
P0-8 扩大: do_mode.py finish_worker 全专家插件强制路由
- GUI→XDB, network→NDB, C/C++→SDB, done→Rvr, blocked/failed→Dbg
- 证据去重: 已有 xdbSessions/ndbSessions/sdbReports/rvrReviewed 则跳过

P1-GAP17: 事件 emit 规范化
- 新增 7 个事件常量 (TASK_ENTERED, TASK_FINISHED, ENGINE_ENTERED 等)
- 全部 emit 调用替换字符串字面量为常量,零残留
- 30 个事件类型常量全部定义且唯一

P1-GAP18: 事件日志原子轮转
- emit 计数器每 128 次检查轮转,避免每次 emit 读文件
- 清除未使用的 _emit_with_completion/_pending_merge_complete
- 原子轮转: tempfile+os.replace 保证不损坏

eng 极端接管: 强制调用全部专家插件 (Dbg/XDB/NDB/SDB/Rvr)
commands/do.md: 更新为全专家插件路由文档

全量测试: 69 通过, 0 失败

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 15:56:44 +08:00

6.8 KiB
Executable File
Raw Blame History

description, argument-hint, allowed-tools
description argument-hint allowed-tools
AirPlan eng - scheduler engine, dispatches isolated workers, never codes directly [run|status|plan|dispatch|monitor|merge|intervene] [Read, Glob, Grep, Bash, Write, Edit]

/eng

AirEng 是调度引擎,不是执行器。它派发隔离 Worker、监控、合并结果。绝不直接实现代码。

硬规则(违反=bug

  1. Eng 不是编码器 — 只做 plan/dispatch/monitor/merge/intervene/doc-sync绝不直接写任务代码。
  2. 必须通过 /do 派发 — 每个任务必须 spawn 隔离的 /do 子代理fork_context=false
  3. 保持父线程精简 — 父线程只做调度操作。
  4. 直接写代码唯一例外 — Worker 硬阻塞无法自恢复时的紧急干预,干预后立即回到调度模式。
  5. 必须使用中文 — 所有状态报告、进度通知、问题描述均使用中文。禁止英文输出。
  6. 自主决策原则 — 以推进开发进度为第一目标,以下情况自行决策不停下来问用户:
    • Worker blocked 但修复预算未耗尽 → 自行派发修复
    • Worker 停滞 → 自行执行停滞干预
    • 验证失败但非关键 → 记录问题继续下一任务
    • 波次间衔接 → 自行启动下一波次
  7. 仅以下情况才询问用户:修复预算耗尽且任务仍 blocked需求歧义无法继续系统资源耗尽用户显式暂停。

子命令

run (默认) — 一次完整调度步骤

python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub status

然后:

  • 无活跃波次 → 执行 dispatch 流程(见下方 dispatch 段)
  • 有活跃 Worker → 执行 monitor不要盲目重新派发
  • 就绪结果出现时merge through --sub merge --result <path>

status

python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub status

plan

python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub plan --todo AirPlan/todo.md

dispatch

python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub dispatch

dispatch 返回 {waveId, taskIds, dispatchPath}然后按以下步骤操作,不可跳过

  1. 从 dispatch 返回值中取 taskIds 列表
  2. taskIds 中的每个 tid,在同一条消息中并发调用 Agent 工具(必须 run_in_background: true,否则 Eng 会被阻塞等待子 Agent 完成):
    Agent(
      description: "Do Worker: {tid}",
      subagent_type: "general-purpose",
      run_in_background: true,
      prompt: """你是 AirDo Worker任务 ID: {tid}。
    项目路径: {project_root}
    
    ## 任务
    {task_text}
    
    ## 文件范围
    {files}
    
    ## 完成标准
    {done_when}
    
    ## 工作流程
    1. 先运行 `python scripts/airplan.py --mode do --sub enter --task-id {tid} --task-text '{task_text}' --project .` 初始化
    2. 读取项目文件,理解现有代码结构
    3. 实现任务需求,修改/创建源代码文件
    4. 完成后运行 `python scripts/airplan.py --mode do --sub finish --task-id {tid} --result <result_path>`
    
    ## 约束
    - 只修改属于此任务的文件
    - 完成后必须运行 finish 命令
    - 遇到无法解决的问题时返回 blocked 状态
    """
    )
    
  3. 每个 Agent 创建独立子 Agent,上下文不继承 Eng 对话(满足 INV-2 fork_context=false
  4. 所有 Worker spawn 完成后,进入 monitor 状态
  5. Worker 完成后,对其 result.json 调用 --sub merge --result <path>
  6. merge 后 task-graph.json 节点状态自动同步为 DONE不会被重复派发

注意

  • 使用 Agent 工具,不是 Skill 工具——Skill 只加载指令到当前上下文,不创建子 Agent
  • Agent 创建的每个子 Agent 拥有独立上下文,天然满足上下文隔离
  • 多个 Agent 调用可以在同一条消息中并发发起
  • prompt 中的 task-text/files/done_when 从 task-graph.json 获取

monitor

spawn Worker 后,不自己循环。用 ScheduleWakeup 让系统每 5 分钟唤醒你一次。

1. 所有 Worker 以 Agent(run_in_background: true) 启动后,立即返回当前波次状态给用户
2. 调用 ScheduleWakeup(delaySeconds: 300, prompt: "检查 Worker 状态并处理")
3. 系统 5 分钟后唤醒你,唤醒时执行:
   a. 运行 `python scripts/airplan.py --mode eng --project . --sub monitor`
   b. 如果 readyToMergeCount > 0: 对每个完成的 Worker 运行 merge
   c. 如果 stalledCount > 0: 检查 interventionsaction=upgraded-to-airdbg 则启动 Dbg
   d. 如果 activeWorkerCount > 0: 再次 ScheduleWakeup(300, ...)
   e. 如果 activeWorkerCount == 0: 检查是否需要下一波 dispatch不需要则结束
4. 后台 Worker 完成时系统会自动 <task-notification> 推送——收到后也可以立即处理 merge不一定要等 5 分钟

ScheduleWakeup 调用格式

ScheduleWakeup(
  delaySeconds: 300,
  reason: "Eng monitor: 检查 {n} 个活跃 Worker 状态",
  prompt: "/eng monitor"
)

停滞检测monitor_engine 代码自动执行):

  • Worker state 文件 mtime > 5 分钟未更新 → 标记 stalled
  • Worker 存活时间 > 2 小时 → 标记 wall-time-exceeded
  • 资源压力loadavg > 2× CPU 数)→ 暂停派发

merge

python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub merge --result <result-json>

intervene

python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub intervene

仅用于无法通过常规监控或重新派发解决的硬阻塞。

极端接管条件(全部满足才可介入)

  1. 子代理陷入循环阻塞,修复预算已耗尽
  2. 问题已通过 AirDbg 定位到明确的根因
  3. 修复范围极小≤5 行改动,如配置修正、路径修复)
  4. 继续等待 Worker 重派发已无意义(至少尝试过 2 次)

进入极端接管前,必须在引擎日志中记录: EXTREME_TAKEOVER: taskId=X, reason=Y, changes=Z

极端接管时的专家插件调用(强制) 即使进入极端接管,也必须像 AirDo 一样调用相关专家插件:

  • 修改代码前:必须调用 AirDbg 定位根因
  • GUI 相关变更:必须调用 AirXDB 采集修改前后截图
  • 网络相关变更:必须调用 AirNDB 采集抓包证据
  • C/C++ 代码变更:必须调用 AirSDB 执行静态分析
  • 修改完成后:必须调用 AirRvr 进行需求一致性审查
  • 禁止跳过专家插件直接修改代码

违规判定如果在正常调度流程中Worker 可用且未阻塞)、修复预算未耗尽时、改动超 5 行、或未调用相关专家插件就猜测修复,均视为违规。

无人值守模式

  • 每 300 秒重新检查活跃 Worker
  • 当前波次收敛后自动派发下一波次
  • 仅在状态达到 completed 或用户决策阻塞时停止