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>
This commit is contained in:
AirPlan
2026-06-12 15:56:44 +08:00
commit 6130478c96
73 changed files with 10622 additions and 0 deletions

169
commands/eng.md Executable file
View File

@@ -0,0 +1,169 @@
---
description: "AirPlan eng - scheduler engine, dispatches isolated workers, never codes directly"
argument-hint: "[run|status|plan|dispatch|monitor|merge|intervene]"
allowed-tools: "[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 (默认) — 一次完整调度步骤
```bash
python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub status
```
然后:
- 无活跃波次 → 执行 dispatch 流程(见下方 dispatch 段)
- 有活跃 Worker → 执行 monitor不要盲目重新派发
- 就绪结果出现时merge through `--sub merge --result <path>`
### status
```bash
python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub status
```
### plan
```bash
python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub plan --todo AirPlan/todo.md
```
### dispatch
```bash
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
```bash
python "$HOME/plugins/airplan/scripts/airplan.py" --mode eng --project . --sub merge --result <result-json>
```
### intervene
```bash
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 或用户决策阻塞时停止