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:
106
lib/air_runtime/partial_replanner.py
Normal file
106
lib/air_runtime/partial_replanner.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""
|
||||
局部重规划 — P1-21 仅重新生成受 ADR 变更影响的任务子集。
|
||||
替代全量重规划,保留未受影响任务的接口约束。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode, PlanDelta
|
||||
|
||||
|
||||
@dataclass
|
||||
class Interface:
|
||||
"""未受影响任务暴露的公共接口约束。"""
|
||||
task_id: str
|
||||
write_set: list[str] = field(default_factory=list)
|
||||
adr_refs: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ReplanContext:
|
||||
"""受影响任务的上下文信息,供 Arc 局部重规划使用。"""
|
||||
task_id: str
|
||||
task: str
|
||||
files_dirs: str
|
||||
done_when: str
|
||||
write_set: list[str] = field(default_factory=list)
|
||||
adr_refs: list[str] = field(default_factory=list)
|
||||
status: str = ""
|
||||
|
||||
|
||||
class PartialReplanner:
|
||||
"""仅重新生成受 ADR 变更影响的任务子集。
|
||||
|
||||
与 incremental_replan_mode 的区别:
|
||||
- incremental_replan_mode: 全量重建 DAG 再 diff
|
||||
- PartialReplanner: 只对受影响部分重新规划,保留稳定接口约束
|
||||
"""
|
||||
|
||||
def replan(self, graph: TaskGraph, invalidated_ids: list[str],
|
||||
new_adr_path: Path | None = None) -> PlanDelta:
|
||||
"""局部重规划:仅生成受影响任务的替代任务。
|
||||
|
||||
Args:
|
||||
graph: 当前任务图(已包含 INVALIDATED 标记)
|
||||
invalidated_ids: 被 ADR 变更级联失效的任务 ID 列表
|
||||
new_adr_path: 新 ADR 文件路径(可选,供 Arc 参考)
|
||||
"""
|
||||
delta = PlanDelta()
|
||||
|
||||
# 1. 收集受影响任务的上下文
|
||||
affected_context = self._collect_affected_context(graph, invalidated_ids)
|
||||
|
||||
# 2. 提取未受影响任务的稳定接口
|
||||
stable_interfaces = self._extract_stable_interfaces(graph, set(invalidated_ids))
|
||||
|
||||
# 3. 生成局部重规划指令文件(供 Arc 读取)
|
||||
replan_request = {
|
||||
"type": "partial-replan",
|
||||
"invalidatedTaskIds": invalidated_ids,
|
||||
"affectedContext": [ctx.__dict__ for ctx in affected_context],
|
||||
"stableInterfaces": [iface.__dict__ for iface in stable_interfaces],
|
||||
"newAdrPath": str(new_adr_path) if new_adr_path else None,
|
||||
}
|
||||
|
||||
# 4. 构建增量 delta
|
||||
# removed_tasks 已在 invalidate_by_adr 中填充
|
||||
# added_tasks 留空——由 Arc 读取 replan-request.json 后生成新任务
|
||||
delta.replan_request = replan_request
|
||||
|
||||
return delta
|
||||
|
||||
def _collect_affected_context(self, graph: TaskGraph,
|
||||
invalidated_ids: list[str]) -> list[ReplanContext]:
|
||||
"""收集受影响任务的上下文。"""
|
||||
contexts = []
|
||||
for tid in invalidated_ids:
|
||||
node = graph.nodes.get(tid)
|
||||
if node:
|
||||
contexts.append(ReplanContext(
|
||||
task_id=node.id,
|
||||
task=node.task,
|
||||
files_dirs=node.files_dirs,
|
||||
done_when=node.done_when,
|
||||
write_set=list(node.write_set),
|
||||
adr_refs=list(node.adr_refs),
|
||||
status=node.status,
|
||||
))
|
||||
return contexts
|
||||
|
||||
def _extract_stable_interfaces(self, graph: TaskGraph,
|
||||
invalidated_ids: set) -> list[Interface]:
|
||||
"""提取未受影响 DONE 任务的接口约束,确保重规划不破坏依赖。"""
|
||||
interfaces = []
|
||||
for nid, node in graph.nodes.items():
|
||||
if nid not in invalidated_ids and node.status == "DONE":
|
||||
if node.write_set or node.adr_refs:
|
||||
interfaces.append(Interface(
|
||||
task_id=node.id,
|
||||
write_set=list(node.write_set),
|
||||
adr_refs=list(node.adr_refs),
|
||||
))
|
||||
return interfaces
|
||||
Reference in New Issue
Block a user